Completes Fase 9's "consolidar MCP" half: the daemon now serves its own MCP endpoint at /mcp, exposing every semantic-routes operation as an MCP tool against the daemon's authoritative graph, and the old Electron-local MCP server is retired since it's now redundant. New: src/main/frontend/worker/mcp_server.cljs The CF-Worker's own MCP endpoint (deps/db-sync/worker/entry.mjs) generates its tools from the OpenAPI document via @cloudflare/codemode's openApiMcpServer, a package that only exists inside Cloudflare Workers, plus a pile of ChatGPT-App-specific tooling (asset image resources, upload_asset, Cognito protected-resource metadata) this daemon has no use for -- none of that ports to Node. So this registers one tool per operation by hand instead, using @modelcontextprotocol/sdk directly, the same pattern electron/mcp_server.cljs already used for its own 6 tools (registerTool with an explicit title/description/inputSchema/handler) -- just generated from semantic-routes' operation table and operation-docs (now public) instead of writing 35 one-off registrations by hand, so the MCP tool surface can't drift from the HTTP routes or the OpenAPI document. Each tool's Zod input shape is assembled from path params (auto-derived from the route's :param segments) plus a per-operation-id map of the extra query/body fields; a handful of shared fragments (pagination, time filters, the recursive block-tree shape, property-value/task-status selectors) cover the repetition across list/create/update operations. Each tool's handler makes a loopback HTTP call to this same daemon's own /v1/semantic/* route, forwarding the /mcp request's own Authorization header -- reusing the already-tested HTTP-layer logic (repo-error validation, lock-owner assertion, response shaping) instead of a second request path directly against the thread-api. Session/transport plumbing (handle-post/get/delete-request, the transports-by-session-id map) is adapted from electron/mcp_server.cljs's Fastify-based version: that one gets req/res already unwrapped-to-Node-primitives via `.raw` with the body pre-parsed by Fastify; this one is called straight from the daemon's own raw http.createServer callback, so req/res already are what StreamableHTTPServerTransport wants, and the body needs parsing here instead. No separate auth check either -- the daemon's existing bearer-token check on every route (request-authorized? in db_worker_node.cljs) already gates /mcp before this is reached. Wires POST/GET/DELETE /mcp into db_worker_node.cljs's make-server cond chain, alongside the existing /v1/semantic/* branch. Dependencies: adds @modelcontextprotocol/sdk and zod (zod/v3 -- the SDK doesn't work with zod 4's default export, same constraint electron/mcp_server.cljs already worked around) to the root package.json; previously only resources/package.json (Electron's own bundle) had them. Retired: electron/mcp_server.cljs and its wiring (electron/server.cljs's initialize-mcp-routes, its 3 POST/GET/DELETE /mcp route registrations, the :mcp-enabled? config field; components/server.cljs's "copy MCP URL" popup link; components/settings.cljs's entire AI settings tab, which had nothing in it besides the MCP-server toggle). Electron already talks to the daemon (Fase 3) rather than driving itself locally, so a second, separately-configured MCP surface bolted onto Electron's own local automation API server (which otherwise stays -- /api is a distinct, still-used concern) was redundant with the daemon's new one. Removed the 4 associated i18n keys (server/mcp-url-copied, settings/ai, settings.ai/enable-mcp-server[-desc]) from all ~26 locale dicts. New: src/test/frontend/worker/mcp_server_test.cljs Connects a real @modelcontextprotocol/sdk client over HTTP to a live daemon's /mcp endpoint: lists all registered tools, round-trips createPage/getPage and a recursive captureToToday block tree, and checks a tool call against a nonexistent page surfaces as MCP error content rather than throwing. 4 tests, 11 assertions. Verification: all 5 shadow-cljs targets compile with 0 warnings. Full `bb dev:test` run: the only failures are the same 7 pre-existing, sandboxed-network-related persist_db_test.cljs failures already documented in the Fase 8 and Fase 9 (1/N) commits -- identical test names, identical ECONNREFUSED/Invalid URL errors. Every other shard, including all three daemon-HTTP worker test files sharing one test.js process (db_worker_node_test.cljs, semantic_test.cljs, mcp_server_test.cljs), passes clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
347 KiB
347 KiB