MCP Server Internals
How the Leif FastMCP server is put together — tool registration, service lifecycle, annotations, output guards, and auth hardening (as of the June 2026 overhaul).
How the FastMCP server (leif-mcp.service on the Leif host) is wired
internally. This reflects the June 2026 overhaul
(leif#49); if behavior here
disagrees with the code, the code wins — start at src/mcp/server.py.
Tool registration
Registration is declarative: src/mcp/tools/__init__.py holds a table
mapping each tool module to a toolset group and the services its
register() needs. Modules import lazily, and the registered tool list is
derived from the running server rather than maintained by hand.
REGISTERED_TOOL_NAMESis an exact-equality snapshot enforced by tests — if a module adds or drops a tool without updating the snapshot, the suite fails in both directions.- Some tool groups only register when their feature flag is on
(
ENABLE_SONICWALL_LOGSforsonicwall_*,ENABLE_CLOUDFLAREforcf_*).expected_tool_names()accounts for these. MCP_TOOLSETS(comma-separated:business,core,google,infrastructure,msp,personal) limits which groups register. Unset means everything;MCP_TOOLSETS=coreboots roughly 87 tools instead of ~300.
Shared helpers live in src/mcp/tools/_common.py — one implementation of
JSON serialization, service resolution, enabled checks, and method
invocation. Tool modules do not construct integration clients
themselves; services come from the runtime container, and an
unconfigured integration returns a clean “not enabled” error.
Service lifecycle
initialize_runtime_services builds every service from an ordered factory
table with per-service failure isolation: if one integration’s
constructor throws (bad credentials, unreachable API), that slot is left
unconfigured and the server still boots. Outcomes land in
container.service_status.
Shutdown is symmetric — anything in the container exposing close() or
stop() gets shut down, so new services can’t be forgotten.
One config note: the RunPod SSH tools require RUNPOD_HOST in the
environment. There is deliberately no default host in source.
Annotations
Every tool carries MCP ToolAnnotations (readOnlyHint /
destructiveHint), assigned by explicit overrides plus name rules in
src/mcp/tools/annotations.py. Read-only tools (searches, reports,
status) are marked as such; destructive ones (delete_*, *_destroy,
arbitrary command execution, service restarts) are flagged so MCP clients
can make safer permission decisions. A handful of ambiguous names stay
unannotated on purpose rather than risk a wrong hint.
Output size guard
Serialized tool output is capped by MCP_TOOL_MAX_OUTPUT_CHARS (default
100,000 characters). Oversized payloads come back as a valid-JSON
truncation envelope with a preview and a hint to narrow the query, so a
single unbounded result can’t flood a client context window.
Auth
OAuth (for Claude.ai / Claude Code connections) is hardened:
- Access tokens, refresh tokens, and authorization codes are stored
sha256-hashed in
data/mcp/oauth_store.json; legacy plaintext entries migrate transparently on first use. - Expired credentials are pruned on every store write, and refresh-token / auth-code expiry is enforced on load.
- The consent page rate-limits failed access-code attempts: 5 per authorization request, 10 per IP per 15 minutes (HTTP 429).
Sessions and restarts
Streamable-HTTP sessions are stateful by default: after a leif-mcp
restart, old mcp-session-id values are invalid and clients get a 404
with X-MCP-Reinitialize: true until they re-initialize (Claude clients
do this automatically). Setting MCP_STATELESS_HTTP=true removes the
session table entirely, which eliminates the post-restart reconnect dance
at the cost of per-session state.
Already-connected clients cache the tool list at connect time — a newly deployed tool won’t appear in an existing session until it reconnects.
Environment variables
| Variable | Default | Effect |
|---|---|---|
MCP_TOOLSETS | all groups | Comma-separated toolset groups to register |
MCP_TOOL_MAX_OUTPUT_CHARS | 100000 | Output cap before the truncation envelope kicks in |
MCP_STATELESS_HTTP | false | Stateless streamable-http (no session table) |
ENABLE_SONICWALL_LOGS | off | Registers the sonicwall_* tools |
ENABLE_CLOUDFLARE | off | Registers the cf_* tools |
RUNPOD_HOST | unset | Required for the runpod_* SSH tools |
MCP_DEBUG_HTTP | false | Request/response logging (auth headers redacted) |
Related pages
- Architecture — where the MCP server sits in the bigger picture
- Leif / MCP unreachable — the runbook when nothing responds
- Tools — the curated tool catalog