feat: log MCP tool list + descriptions on startup

main.py lifespan now enumerates every MCP tool with its description at
startup so operators can see at a glance what the server exposes.

The auto-generated '### Responses:' suffix that fastapi-mcp appends to
each tool description is truncated before logging to keep the startup
log scannable.

Docstrings added to all 12 route handlers in server.py so the MCP tool
descriptions are meaningful (without them, fastapi-mcp would emit empty
descriptions). Each route now carries a summary + description used by
the auto-generated OpenAPI schema.
This commit is contained in:
Claude
2026-06-24 17:50:30 +08:00
parent 093e51a9c2
commit ff9dea0ba7
2 changed files with 111 additions and 17 deletions
+25 -5
View File
@@ -1,29 +1,49 @@
# coding=utf-8
"""
@Time :2026/6/24
@Author :tao.chen
@Author :tao.chen
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI
from spark_executor import app as spark_executor_app
from common.factory import init_mcp_server
from common.logging import logger
from spark_executor import app as spark_executor_app
@asynccontextmanager
async def lifespan(app: "FastAPI"):
logger.info(f"Startup {app.title}")
spark_executor_mcp = init_mcp_server(spark_executor_app)
spark_executor_mcp.mount_http(app, mount_path="/spark-executor-mcp")
logger.info(f"include {spark_executor_app.title}, version {spark_executor_app.version}")
logger.info(
f"MCP server mounted at /spark-executor-mcp "
f"(source: {spark_executor_app.title} v{spark_executor_app.version})"
)
# Enumerate every MCP tool + its description so operators can see at a
# glance what the server exposes (useful for debugging / change review).
tools = spark_executor_mcp.tools
logger.info(f"MCP tools registered ({len(tools)}):")
for i, tool in enumerate(tools, 1):
desc = (tool.description or "").strip()
# fastapi-mcp appends an auto-generated "### Responses: ..." block to
# every tool description; drop it so the startup log stays scannable.
if "### Responses" in desc:
desc = desc.split("### Responses", 1)[0].rstrip()
# Collapse internal newlines / extra spaces into one line.
desc = " ".join(desc.split())
logger.info(f" {i:>2}. {tool.name} - {desc}")
yield
logger.info(f"Shutdown {app.title}")
app = FastAPI(title="Main App", lifespan=lifespan)
app = FastAPI(title="Main App", lifespan=lifespan)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)