From 7a8dd14bd3348bfcaf2ad0b901f97991835dbda3 Mon Sep 17 00:00:00 2001 From: Brandon Zhang Date: Fri, 27 Mar 2026 18:16:30 +0800 Subject: [PATCH] Show server version in logs and UI --- app/api/routes_status.py | 2 ++ app/config.py | 1 + app/models.py | 1 + go-server/internal/api/status.go | 2 ++ go-server/internal/config/config.go | 5 ++++- go-server/internal/mcp/handler.go | 2 +- go-server/main.go | 3 ++- main.py | 9 +++++---- static/css/layout.css | 5 +++++ static/index.html | 1 + static/js/status.js | 10 ++++++++++ 11 files changed, 34 insertions(+), 7 deletions(-) diff --git a/app/api/routes_status.py b/app/api/routes_status.py index 3bc5aca..f438b7e 100644 --- a/app/api/routes_status.py +++ b/app/api/routes_status.py @@ -11,6 +11,7 @@ from datetime import datetime, timezone from fastapi import APIRouter from fastapi.responses import StreamingResponse +from app.config import APP_VERSION from app.models import ( AgentInfo, HealthResponse, @@ -49,6 +50,7 @@ def get_status(): server=ServerInfo( status="up", started_at=status_service.server_started_at(), + version=APP_VERSION, ), agent=agent_info, queue=QueueCounts(**counts), diff --git a/app/config.py b/app/config.py index 7ac8607..444d1ba 100644 --- a/app/config.py +++ b/app/config.py @@ -9,6 +9,7 @@ import os from dataclasses import dataclass, field +APP_VERSION = "1.0.0" DEFAULT_EMPTY_RESPONSE = "call this tool `get_user_request` again to fetch latest user input..." diff --git a/app/models.py b/app/models.py index bc57bd2..b188df0 100644 --- a/app/models.py +++ b/app/models.py @@ -79,6 +79,7 @@ class UpdateInstructionRequest(BaseModel): class ServerInfo(BaseModel): status: str started_at: datetime + version: str class AgentInfo(BaseModel): diff --git a/go-server/internal/api/status.go b/go-server/internal/api/status.go index 5b38ab7..2732dec 100644 --- a/go-server/internal/api/status.go +++ b/go-server/internal/api/status.go @@ -4,6 +4,7 @@ import ( "net/http" "time" + "github.com/local-mcp/local-mcp-go/internal/config" "github.com/local-mcp/local-mcp-go/internal/models" ) @@ -57,6 +58,7 @@ func handleStatus(stores Stores) http.HandlerFunc { "server": map[string]any{ "status": "up", "started_at": serverStartTime.Format(time.RFC3339Nano), + "version": config.AppVersion, }, "agent": agent, "queue": map[string]any{ diff --git a/go-server/internal/config/config.go b/go-server/internal/config/config.go index c4cc456..54eb8a1 100644 --- a/go-server/internal/config/config.go +++ b/go-server/internal/config/config.go @@ -6,7 +6,10 @@ import ( "strconv" ) -const DefaultEmptyResponse = "call this tool `get_user_request` again to fetch latest user input..." +const ( + AppVersion = "1.0.0" + DefaultEmptyResponse = "call this tool `get_user_request` again to fetch latest user input..." +) // Config holds all runtime configuration values for local-mcp. type Config struct { diff --git a/go-server/internal/mcp/handler.go b/go-server/internal/mcp/handler.go index 67b0cf7..176b8aa 100644 --- a/go-server/internal/mcp/handler.go +++ b/go-server/internal/mcp/handler.go @@ -53,7 +53,7 @@ func New( broker *events.Broker, ) *Handler { h := &Handler{ - MCP: server.NewMCPServer("local-mcp", "1.0.0"), + MCP: server.NewMCPServer("local-mcp", config.AppVersion), instStore: instStore, settStore: settStore, agentStore: agentStore, diff --git a/go-server/main.go b/go-server/main.go index 73f2dd4..fd691c9 100644 --- a/go-server/main.go +++ b/go-server/main.go @@ -122,6 +122,7 @@ func main() { mcpURL := fmt.Sprintf("http://%s/mcp", addr) slog.Info("local-mcp-go ready", + "version", config.AppVersion, "http", httpURL, "mcp", mcpURL, "stateless", cfg.MCPStateless, @@ -131,7 +132,7 @@ func main() { if runtime.GOOS == "windows" { fmt.Println() fmt.Println("╔══════════════════════════════════════════════════════════╗") - fmt.Printf("║ local-mcp-go ready on port %s%-24s║\n", port, "") + fmt.Printf("║ local-mcp-go v%-6s ready on port %s%-14s║\n", config.AppVersion, port, "") fmt.Println("║ ║") fmt.Printf("║ Web UI: %-46s║\n", httpURL) fmt.Printf("║ MCP: %-46s║\n", mcpURL) diff --git a/main.py b/main.py index 9952455..dcda162 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,7 @@ from fastapi.staticfiles import StaticFiles from app.api import routes_config, routes_instructions, routes_status from app.api.auth import TokenAuthMiddleware -from app.config import settings +from app.config import APP_VERSION, settings from app.database import init_db from app.logging_setup import configure_logging from app.mcp_server import mcp, mcp_asgi_app @@ -37,11 +37,12 @@ logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): # Startup - logger.info("local-mcp starting up – initialising database …") + logger.info("local-mcp v%s starting up – initialising database …", APP_VERSION) init_db(settings.db_path) await instruction_service.init_wakeup() logger.info( - "local-mcp ready http://%s:%d | MCP http://%s:%d/mcp (stateless=%s)", + "local-mcp v%s ready http://%s:%d | MCP http://%s:%d/mcp (stateless=%s)", + APP_VERSION, settings.host, settings.http_port, settings.host, settings.http_port, settings.mcp_stateless, @@ -57,7 +58,7 @@ def create_app() -> FastAPI: app = FastAPI( title="local-mcp", description="Localhost MCP server with instruction queue management UI", - version="1.0.0", + version=APP_VERSION, lifespan=lifespan, ) diff --git a/static/css/layout.css b/static/css/layout.css index bd9c2eb..3e9e843 100644 --- a/static/css/layout.css +++ b/static/css/layout.css @@ -37,6 +37,11 @@ color: var(--cyan); } +.header-version-badge { + letter-spacing: 0.08em; + text-transform: uppercase; +} + .header-indicators { display: flex; align-items: center; diff --git a/static/index.html b/static/index.html index 576fed7..31ee5de 100644 --- a/static/index.html +++ b/static/index.html @@ -30,6 +30,7 @@ local-mcp + v–
diff --git a/static/js/status.js b/static/js/status.js index 9584837..75e86a3 100644 --- a/static/js/status.js +++ b/static/js/status.js @@ -58,6 +58,7 @@ function updateHeaderLeds(serverOnline, status) { function renderStatusPanel(status) { const el = document.getElementById('status-panel-body'); + const versionBadge = document.getElementById('app-version-badge'); if (!el || !status) return; const agent = status.agent ?? {}; @@ -65,12 +66,21 @@ function renderStatusPanel(status) { pending_count: status.queue?.pending_count ?? 0, consumed_count: status.queue?.consumed_count ?? 0, }; + const version = status.server?.version || '–'; + + if (versionBadge) { + versionBadge.textContent = `v${version}`; + } el.innerHTML = `
Server Up ${fmtTime(status.server?.started_at)}
+
+ Version + v${escapeHtml(version)} +
Pending ${queue.pending_count}