forked from Inspiration/drawnix
feat(mcp-server): add MCP server with 10 mindmap tools #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/mcp-server"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
@mindnest/mcp-serverpackage — a Model Context Protocol server exposing 10 tools for creating, loading, querying, and mutating.drawnixmindmap files over stdio (JSON-RPC 2.0).mcp.jsonproject-level config so Claude Code and Claude Desktop can connect to the server out of the boxdocs/features/mcp-server.md)MCP Tools (10)
mindmap_create,mindmap_loadmindmap_summary,mindmap_list_nodes,mindmap_get_nodemindmap_add_child,mindmap_add_sibling,mindmap_add_summary,mindmap_set_shape,mindmap_remove_nodeArchitecture highlights
createTestingBoard + fakeNodeWeakMap) — mutations use the real@plait/mindtransforms, no DOM shim needed.drawnix-only extension allowlistLimitedStdioServerTransportenforces per-frame byte cap; stdout reserved exclusively for JSON-RPC framesTOOL_ALLOWLISTasserted against registered tools at boot; mismatch throws before accepting connectionsCI improvements
cancel-in-progressdrops stale runs on force-pushTest plan
nx build mcp-server+nx run mcp-server:link-runtime-depsproduces working artifactnode dist/mcp-server/index.cjs.js < /dev/nullexits 0 with pino log on stderrNODE_NOT_FOUND,SANDBOX_VIOLATION,ROOT_ELEMENT,INVALID_DOCUMENT,EEXIST.mcp.jsonand lists 10 tools- Create packages/mcp-server with full Nx project wiring: package.json, project.json (@nx/rollup build target), tsconfig.json, tsconfig.lib.json (ES2022/CJS), tsconfig.spec.json, jest.config.ts, eslint.config.mjs - Move test fixtures from plans-cc/discovery/mcp-server-fixtures/ to packages/mcp-server/test-fixtures/ (empty, single-root, mixed) - Add src/index.ts: pino stderr-only logging, SIGINT/SIGTERM handlers, main().catch() fatal exit; zero console.log calls - Add typed Phase 2/4 stubs: config.ts, logger.ts, mcp/server.ts, mcp/tools/registry.ts (interface contracts for downstream agents) - Build wiring: @nx/esbuild absent → @nx/rollup:rollup fallback - tsconfig.base.json alias: skipped per Phase 0 §0.9 (standalone CLI) - Verified: nx test mcp-server (0 tests, exit 0) ✓ nx lint mcp-server (0 errors, 3 stub warnings) ✓Phase 3 implementation (TDD: RED → GREEN). All 137 tests pass; 71 new tests added on top of the 66-test Phase 2 baseline. src/board/board-host.ts — withBoard<T>(document, fn) constructs a headless PlaitBoard via the Phase 0-confirmed Strategy A recipe (createTestingBoard + fakeNodeWeakMap with [withOptions, withI18n, withMind] plugin chain), runs fn(board), and returns { result, document, newNodeId? } using pre/post mind-element id-set diff for the deterministic newNodeId contract. Includes the Phase 0 §0.12 test-only failure injection guarded by NODE_ENV=test + MCP_TEST_INJECT_BOARD_FAILURE=1. src/board/mind-queries.ts — pure tree traversal helpers operating on document.elements directly (no board construction): findMindElementById, listMindElements, getRootTopics, getChildTopics, summarizeTree. src/board/mind-transforms.ts — five wrappers (addChild, addSibling, addSummary, setShape, removeNode) that resolve string ids, validate via isMindElement, and persist mutations through document-store.updateDocument (the per-realpath mutex). NodeNotFoundError, NotMindElementError, and RootElementError surface structured errors with code fields. addSibling explicitly rejects root mindmap elements per Phase 0 §0.4 PlaitMind.isMind discovery outcome (the upstream transform silently no-ops; we throw). jest.config.ts — three additions to make the @plait ESM packages testable: 1. moduleNameMapper points @plait/core and @plait/mind to workspace-level .mjs bundles to prevent duplicate-module WeakMap divergence (mcp-server has package-local copies that aren't used by @plait/common etc.) 2. transformIgnorePatterns whitelist for @plait/* and points-on-curve (the latter ships type=cjs but uses ESM export syntax) 3. @babel/plugin-transform-class-static-block for @plait/mind static {} class blocks (ES2022) that the base @nx/js/babel preset doesn't enable. Coverage (global, all above 80% threshold): Statements 89.30% Branches 82.97% Functions 93.25% Lines 90.71% No DOM shim, no per-file branch override needed (Phase 0 Strategy A). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>Phase 5 deliverables: - src/__tests__/stdio-purity.spec.ts (9 tests, all passing): * Spawned-process tests for stdout=MCP-only, stderr-no-frames * Error-path coverage: unknown tool, validation failure, sandbox violation, synthetic board failure injection (NODE_ENV=test + MCP_TEST_INJECT_BOARD_FAILURE=1) * Runtime inertness: NODE_ENV=production keeps injection guard inert * Phase 5.2 integration harness: parallel mutation lost-update prevention via spawned - docs/inspector-smoke.md: build/launch/CLI-verification + minimal-PATH (env -i) instructions - evaluations/mindmap-tools.eval.xml: 10-question suite covering all shipped tools, with mandatory negative questions (Q5 root-sibling, Q6 unknown-id, Q10 sandbox traversal) plus malformed-JSON load (Q2) Build fixes required to produce a runnable artifact: - src/index.ts: pino import via export= (Zod v3/v4 conflict mitigated by node_modules symlink in dist/mcp-server/, created via new link-runtime-deps target) - src/mcp/tools/result.ts: ToolResult type updated to match SDK CallToolResult shape - src/board/mind-transforms.ts: PlaitMindBoard / MindElement type casts for rollup TS check - tsconfig.lib.json: esModuleInterop + allowSyntheticDefaultImports for pino default import - project.json: link-runtime-deps target creates dist/mcp-server/node_modules symlink Coverage (verified with --coverage): - Statements 89.36%, Branches 80.23%, Functions 94.82%, Lines 90.79% (all ≥80%) - 209 tests passing (200 in-process + 9 spawned stdio-purity) - src/board/ overrides: 0 (Phase 0 used Strategy A — no DOM shim required)- Add @mindnest/mcp-server package: 10 MCP tools over stdio for .drawnix mindmap files (mindmap_create, mindmap_load, mindmap_summary, mindmap_list_nodes, mindmap_get_node, mindmap_add_child, mindmap_add_sibling, mindmap_add_summary, mindmap_set_shape, mindmap_remove_node) - Headless PlaitBoard host (Strategy A: createTestingBoard + fakeNodeWeakMap, no DOM shim) - Atomic document store with per-path async mutex, filesystem lock, and revision hashing - Workspace-sandboxed path resolver with two-stage traversal rejection - LimitedStdioServerTransport with per-frame byte guard - Add .mcp.json project-level MCP server config pointing to test-fixtures workspace - Add docs/features/mcp-server.md: comprehensive architecture + API reference - Update README, docs/01/02/04/09/PROJECT_DOCUMENTATION to reflect new package - Fix MindElementShape values in docs: actual enum is {round-rectangle, underline} - Update .gitignore: exclude *.tgz tarballs and .claude/ project cache