Show server version in logs and UI
This commit is contained in:
@@ -11,6 +11,7 @@ from datetime import datetime, timezone
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
|
|
||||||
|
from app.config import APP_VERSION
|
||||||
from app.models import (
|
from app.models import (
|
||||||
AgentInfo,
|
AgentInfo,
|
||||||
HealthResponse,
|
HealthResponse,
|
||||||
@@ -49,6 +50,7 @@ def get_status():
|
|||||||
server=ServerInfo(
|
server=ServerInfo(
|
||||||
status="up",
|
status="up",
|
||||||
started_at=status_service.server_started_at(),
|
started_at=status_service.server_started_at(),
|
||||||
|
version=APP_VERSION,
|
||||||
),
|
),
|
||||||
agent=agent_info,
|
agent=agent_info,
|
||||||
queue=QueueCounts(**counts),
|
queue=QueueCounts(**counts),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import os
|
|||||||
from dataclasses import dataclass, field
|
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..."
|
DEFAULT_EMPTY_RESPONSE = "call this tool `get_user_request` again to fetch latest user input..."
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class UpdateInstructionRequest(BaseModel):
|
|||||||
class ServerInfo(BaseModel):
|
class ServerInfo(BaseModel):
|
||||||
status: str
|
status: str
|
||||||
started_at: datetime
|
started_at: datetime
|
||||||
|
version: str
|
||||||
|
|
||||||
|
|
||||||
class AgentInfo(BaseModel):
|
class AgentInfo(BaseModel):
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/local-mcp/local-mcp-go/internal/config"
|
||||||
"github.com/local-mcp/local-mcp-go/internal/models"
|
"github.com/local-mcp/local-mcp-go/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ func handleStatus(stores Stores) http.HandlerFunc {
|
|||||||
"server": map[string]any{
|
"server": map[string]any{
|
||||||
"status": "up",
|
"status": "up",
|
||||||
"started_at": serverStartTime.Format(time.RFC3339Nano),
|
"started_at": serverStartTime.Format(time.RFC3339Nano),
|
||||||
|
"version": config.AppVersion,
|
||||||
},
|
},
|
||||||
"agent": agent,
|
"agent": agent,
|
||||||
"queue": map[string]any{
|
"queue": map[string]any{
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import (
|
|||||||
"strconv"
|
"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.
|
// Config holds all runtime configuration values for local-mcp.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func New(
|
|||||||
broker *events.Broker,
|
broker *events.Broker,
|
||||||
) *Handler {
|
) *Handler {
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
MCP: server.NewMCPServer("local-mcp", "1.0.0"),
|
MCP: server.NewMCPServer("local-mcp", config.AppVersion),
|
||||||
instStore: instStore,
|
instStore: instStore,
|
||||||
settStore: settStore,
|
settStore: settStore,
|
||||||
agentStore: agentStore,
|
agentStore: agentStore,
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ func main() {
|
|||||||
mcpURL := fmt.Sprintf("http://%s/mcp", addr)
|
mcpURL := fmt.Sprintf("http://%s/mcp", addr)
|
||||||
|
|
||||||
slog.Info("local-mcp-go ready",
|
slog.Info("local-mcp-go ready",
|
||||||
|
"version", config.AppVersion,
|
||||||
"http", httpURL,
|
"http", httpURL,
|
||||||
"mcp", mcpURL,
|
"mcp", mcpURL,
|
||||||
"stateless", cfg.MCPStateless,
|
"stateless", cfg.MCPStateless,
|
||||||
@@ -131,7 +132,7 @@ func main() {
|
|||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
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.Println("║ ║")
|
||||||
fmt.Printf("║ Web UI: %-46s║\n", httpURL)
|
fmt.Printf("║ Web UI: %-46s║\n", httpURL)
|
||||||
fmt.Printf("║ MCP: %-46s║\n", mcpURL)
|
fmt.Printf("║ MCP: %-46s║\n", mcpURL)
|
||||||
|
|||||||
9
main.py
9
main.py
@@ -17,7 +17,7 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
|
|
||||||
from app.api import routes_config, routes_instructions, routes_status
|
from app.api import routes_config, routes_instructions, routes_status
|
||||||
from app.api.auth import TokenAuthMiddleware
|
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.database import init_db
|
||||||
from app.logging_setup import configure_logging
|
from app.logging_setup import configure_logging
|
||||||
from app.mcp_server import mcp, mcp_asgi_app
|
from app.mcp_server import mcp, mcp_asgi_app
|
||||||
@@ -37,11 +37,12 @@ logger = logging.getLogger(__name__)
|
|||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
# Startup
|
# 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)
|
init_db(settings.db_path)
|
||||||
await instruction_service.init_wakeup()
|
await instruction_service.init_wakeup()
|
||||||
logger.info(
|
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.host, settings.http_port,
|
settings.host, settings.http_port,
|
||||||
settings.mcp_stateless,
|
settings.mcp_stateless,
|
||||||
@@ -57,7 +58,7 @@ def create_app() -> FastAPI:
|
|||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="local-mcp",
|
title="local-mcp",
|
||||||
description="Localhost MCP server with instruction queue management UI",
|
description="Localhost MCP server with instruction queue management UI",
|
||||||
version="1.0.0",
|
version=APP_VERSION,
|
||||||
lifespan=lifespan,
|
lifespan=lifespan,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
color: var(--cyan);
|
color: var(--cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-version-badge {
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
.header-indicators {
|
.header-indicators {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
<line x1="12" y1="17" x2="12" y2="21"/>
|
<line x1="12" y1="17" x2="12" y2="21"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="header-brand-name">local<span>-mcp</span></span>
|
<span class="header-brand-name">local<span>-mcp</span></span>
|
||||||
|
<span id="app-version-badge" class="badge badge--muted header-version-badge">v–</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header-indicators">
|
<div class="header-indicators">
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ function updateHeaderLeds(serverOnline, status) {
|
|||||||
|
|
||||||
function renderStatusPanel(status) {
|
function renderStatusPanel(status) {
|
||||||
const el = document.getElementById('status-panel-body');
|
const el = document.getElementById('status-panel-body');
|
||||||
|
const versionBadge = document.getElementById('app-version-badge');
|
||||||
if (!el || !status) return;
|
if (!el || !status) return;
|
||||||
|
|
||||||
const agent = status.agent ?? {};
|
const agent = status.agent ?? {};
|
||||||
@@ -65,12 +66,21 @@ function renderStatusPanel(status) {
|
|||||||
pending_count: status.queue?.pending_count ?? 0,
|
pending_count: status.queue?.pending_count ?? 0,
|
||||||
consumed_count: status.queue?.consumed_count ?? 0,
|
consumed_count: status.queue?.consumed_count ?? 0,
|
||||||
};
|
};
|
||||||
|
const version = status.server?.version || '–';
|
||||||
|
|
||||||
|
if (versionBadge) {
|
||||||
|
versionBadge.textContent = `v${version}`;
|
||||||
|
}
|
||||||
|
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="stat-row">
|
<div class="stat-row">
|
||||||
<span class="stat-label">Server Up</span>
|
<span class="stat-label">Server Up</span>
|
||||||
<span class="stat-value">${fmtTime(status.server?.started_at)}</span>
|
<span class="stat-value">${fmtTime(status.server?.started_at)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-row">
|
||||||
|
<span class="stat-label">Version</span>
|
||||||
|
<span class="stat-value">v${escapeHtml(version)}</span>
|
||||||
|
</div>
|
||||||
<div class="stat-row">
|
<div class="stat-row">
|
||||||
<span class="stat-label">Pending</span>
|
<span class="stat-label">Pending</span>
|
||||||
<span class="stat-value stat-value--cyan">${queue.pending_count}</span>
|
<span class="stat-value stat-value--cyan">${queue.pending_count}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user