Expand description
Axum-based MCP daemon.
Endpoints:
POST /session— unauthenticated; mints{ session_id, token, cwd }.POST /mcp— authenticated JSON-RPC 2.0. Returns either plain JSON or an SSE stream depending on the method.GET /health— simple liveness probe.
Session auth headers (required on POST /mcp):
Authorization: Bearer <token>X-Construct-Session: <session_id>
POST /mcp dispatch:
initialize→ plain JSON response with server info + capabilities.tools/list→ plain JSON response listing all advertised tools.tools/call→ SSE stream. First emits zero or morenotifications/progressevents (forwarded from the tool’sexecute_with_progress), then one terminal JSON-RPC response event, thenevent: done.
Structs§
- AppState
- McpServer
Handle - Handle returned by
serve_onso tests can learn the bound port and shut the server down.
Functions§
- build_
router - Build the Axum router. Exposed for tests.
- cleanup_
discovery_ file - Remove the MCP discovery file on shutdown. Safe to call when the file doesn’t exist.
- default_
state - Build an
AppStatewith Construct’s baseline tool registry (no Config). - discovery_
path - Absolute path of the MCP discovery file (
~/.construct/mcp.json). - run_
daemon - Legacy blocking entry point retained for tests that want to boot the MCP server with only a workspace directory (no gateway AppState).
- serve_
on - Bind to
addr(use127.0.0.1:0for ephemeral) and serve the router. Returns once the server is listening. Writes no discovery file. - state_
from_ config - Build an
AppStateusing a loadedConfigso integrations with creds (Notion, Jira, Composio, Google Workspace, etc.) and the skills meta-tools get registered alongside the baseline. - state_
from_ runtime - Build an
AppStateusing a loadedConfigplus the gateway’s liveRuntimeHandles. This is the full-registry entry point used by the in-process daemon boot. - state_
with_ tools - Extend an existing
AppStatewith additional tools (used by tests). - write_
discovery_ file - Write the MCP discovery file atomically (tempfile + rename) so external
readers never observe a half-written JSON document. Payload shape is
{url, pid, started_at}— frozen by contract, do not change.