Skip to content

feat(agent-connect): mount MCP-over-HTTP at /mcp on the dashboard#12

Merged
Coding-Dev-Tools merged 1 commit into
feat/agent-connectfrom
feat/agent-connect-mcp
Jul 15, 2026
Merged

feat(agent-connect): mount MCP-over-HTTP at /mcp on the dashboard#12
Coding-Dev-Tools merged 1 commit into
feat/agent-connectfrom
feat/agent-connect-mcp

Conversation

@Coding-Dev-Tools

Copy link
Copy Markdown
Owner

What (stacked on #11)

MCP-native agents (Claude Code, Cursor, …) point one URL at the cloud instance — https://team.engraphis.com/mcp with a per-user bearer token — and reuse the same v2 store the dashboard reads. No local install. Team-gated (402) + member-authenticated (401), exactly like /api/remember.

This is the /mcp follow-up I deferred from #11. Base is feat/agent-connect (stacked) — rebase onto main and switch the base to main after #11 merges.

Changes

  • mcp_server.py: set_service(svc) injects the dashboard's MemoryService so the MCP tools share one writer (no second SQLite connection → no WAL database is locked contention — the exact problem mcp_server_http.py was written to avoid).
  • **dashboard_app.py\**: build the streamable-http ASGI app up front and give the app a **lifespan that initializes the MCP session manager** (a mounted sub-app's own lifespan does not run in Starlette → Task group is not initialized). Mount at /mcpwith the endpoint at/inside the sub-app so the prefix lines up. **Reset_session_managerpercreate_app()** so multiple apps in one process (tests) each get a fresh, runnable instance (run()` is once-per-instance).
  • _auth_gate: protect /mcp (Team license 402 + member token/cookie 401) before the existing /api/* logic. Disable MCP's DNS-rebinding host allowlist on the mounted instance — its default localhost-only allowlist would 421 a real domain like team.engraphis.com; the dashboard gate is the real auth boundary. The standalone mcp_server_http.py is unaffected (its own process).
  • docs/AGENT_CONNECT.md updated (/mcp now live + a config snippet) + CHANGELOG.

Tests

tests/test_agent_connect_mcp.py — 4 tests, speaking the streamable-http JSON-RPC protocol directly over the TestClient (no real socket): 401 without auth, 402 without a Team license, handshake + tools/list returns the engraphis tools, and tools/call engraphis_remember writes a memory that is immediately found via the dashboard's /api/recall (proves the shared single-writer store). Suite: 705 passed, 3 skipped, 0 failed. Ruff clean.

Trade-off flagged

Disabling MCP's host validation reduces defense-in-depth, but /mcp is already behind the dashboard's auth gate (Team license + per-user member token), so an attacker can't reach the MCP tools without a valid seat's token. Documented in AGENT_CONNECT.md.

Not in this PR

@Coding-Dev-Tools

Copy link
Copy Markdown
Owner Author

Council Gate Verdict — APPROVE

Risk level: high | Agreement: 1.0 | Council session: council-ec987560-e30b-48b7-ab14-63ddafe2e9e9

Per-model scores (rubric: correctness / safety / style / tests / complexity)

  • nvidia/nemotron-3-super-120b-a12b: APPROVE_WITH_NITS (overall 4.6) -- correctness=5.0, safety=4.0, style=5.0, tests=5.0, complexity=4.0
  • nvidia/llama-3.3-nemotron-super-49b-v1.5: APPROVE_WITH_NITS (overall 4.6) -- correctness=5.0, safety=4.0, style=5.0, tests=5.0, complexity=4.0
  • deepseek-v4-flash: APPROVE_WITH_NITS (overall 3.8) -- correctness=4.0, safety=3.0, style=4.0, tests=4.0, complexity=4.0
  • nvidia/nemotron-3-ultra-550b-a55b: APPROVE_WITH_NITS (overall 4.6) -- correctness=5.0, safety=4.0, style=5.0, tests=5.0, complexity=4.0

Engraphis reference

Council verdict persisted as mem_01KXJQE84M6VXJXPC7G665N8DC (workspace Coding-Dev-Tools). Also logged to security-council workspace as mem_01KXJQE859EMHAC4FSGEWXZHDG (auth/security PR).

Posted automatically by the council-gate PR review cron. Auth/security PRs are reviewed at risk_level=high.

@Coding-Dev-Tools Coding-Dev-Tools added the council-approved Council gate approved this PR (APPROVE / APPROVE_WITH_NITS) label Jul 15, 2026
MCP-native agents (Claude Code, Cursor, ...) point one URL at the cloud instance
(https://team.engraphis.com/mcp) with a per-user bearer token and reuse the same v2
store the dashboard reads — no local install. Team-gated (402) + member-authed (401),
exactly like /api/remember.

- mcp_server: set_service(svc) injects the dashboard's MemoryService so the MCP tools
  share ONE writer (no second SQLite connection -> no WAL lock contention).
- dashboard_app: build the streamable-http ASGI app up front and give the app a lifespan
  that initializes the MCP session manager (a mounted sub-app's own lifespan does not run
  in Starlette -> 'Task group is not initialized'); mount at /mcp with the endpoint at
  '/' inside the sub-app so the prefix lines up. The mcp import + session-manager build
  are fully inside a try so the dashboard still starts if the mcp extra is absent
  (MCP mount is genuinely optional). Reset _session_manager per create_app() so multiple
  apps in one process (tests) each get a fresh, runnable instance (run() is once-per-instance).
- _auth_gate: protect /mcp (Team license 402 + member token/cookie 401) before the
  existing /api/* logic; disable MCP's DNS-rebinding host allowlist on the mounted
  instance (default localhost-only would 421 a real domain like team.engraphis.com; the
  dashboard gate is the real auth boundary; standalone mcp_server_http is unaffected as
  its own process).
- v2_team.connect-info: mcp_over_http + mcp_url now reflect whether /mcp is mounted.
- docs/AGENT_CONNECT.md updated (/mcp now live + config snippet); CHANGELOG.
- tests/test_agent_connect_mcp.py: 5 tests (401, 402, handshake+tools/list,
  write-shares-dashboard-store, connect-info reports /mcp). Suite green (one pre-existing
  flaky inspector test fails under load but passes in isolation, on main too).
@Coding-Dev-Tools Coding-Dev-Tools force-pushed the feat/agent-connect-mcp branch from 7fb16f3 to 8ef6403 Compare July 15, 2026 11:19
@Coding-Dev-Tools Coding-Dev-Tools merged commit 01d5e00 into feat/agent-connect Jul 15, 2026
7 checks passed
@Coding-Dev-Tools Coding-Dev-Tools deleted the feat/agent-connect-mcp branch July 15, 2026 11:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

council-approved Council gate approved this PR (APPROVE / APPROVE_WITH_NITS)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant