Show server version in logs and UI

This commit is contained in:
Brandon Zhang
2026-03-27 18:16:30 +08:00
parent 8d4392ee5a
commit 7a8dd14bd3
11 changed files with 34 additions and 7 deletions

View File

@@ -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),

View File

@@ -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..."

View File

@@ -79,6 +79,7 @@ class UpdateInstructionRequest(BaseModel):
class ServerInfo(BaseModel):
status: str
started_at: datetime
version: str
class AgentInfo(BaseModel):

View File

@@ -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{

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,
)

View File

@@ -37,6 +37,11 @@
color: var(--cyan);
}
.header-version-badge {
letter-spacing: 0.08em;
text-transform: uppercase;
}
.header-indicators {
display: flex;
align-items: center;

View File

@@ -30,6 +30,7 @@
<line x1="12" y1="17" x2="12" y2="21"/>
</svg>
<span class="header-brand-name">local<span>-mcp</span></span>
<span id="app-version-badge" class="badge badge--muted header-version-badge">v&ndash;</span>
</div>
<div class="header-indicators">

View File

@@ -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 = `
<div class="stat-row">
<span class="stat-label">Server Up</span>
<span class="stat-value">${fmtTime(status.server?.started_at)}</span>
</div>
<div class="stat-row">
<span class="stat-label">Version</span>
<span class="stat-value">v${escapeHtml(version)}</span>
</div>
<div class="stat-row">
<span class="stat-label">Pending</span>
<span class="stat-value stat-value--cyan">${queue.pending_count}</span>