Build MCP node bridge and adapters
## Original requirement (verbatim, epic 13348)
Deep research all third party integrations in Lovable (Connect) and implement all of them.
Ensure the highest level of code reuse, abstract out any generic code across all integrations. Users need an easy way to connect. Documentation must be as detailed as in Lovable or better.
If something needs to be done on the partner website (e.g. register an app) and it can only be done by human create a follow up task per third party with exact step by step of what user needs to do). Mark it as user only task to set up but the runner will validate it was done correctly.
You can refactor anything to make working with creds more robust.
## Settled inputs
Full PRD and architecture: the epic's `prd` and `architecture` artifacts (Task 13348 BA, Task 13349 Architect). Section numbers below (§3.2 item 6, AC2.3, …) refer to them. They are settled: realize them, do not reopen them. Operator decisions O1–O6 and D1–D8 bind.
## This child's scope
C4b, architecture §5 (node half). Build against the launch contract pinned in §5 (parallel with C4a).
- `AcpLaunchContext` (`apps/jaahd/agents/base.py`) gains `mcp_connections: tuple[McpConnection, ...] = ()`, frozen dataclass {name ^[a-z0-9_]{1,40}$, credential_path, url (https), transport streamable_http|sse}; the executor copies it from the decision's `mcp_connections` (absent field = empty).
- `apps/jaahd/mcp_bridge.py`, run as `python3 -m jaahd.mcp_bridge --credential <path> --url <url> --transport <t>`: stdio MCP server forwarding to the remote server over streamable HTTP or SSE; fetches the token per request batch through the task's credential socket (`credential.get`), re-fetches on 401, logs nothing of headers or bodies.
- Adapters add one stdio entry `mcp_<name>` per connection beside `control`: Claude (`claude.py`) and Codex (ACP session `mcpServers`, never the account-level `mcp_servers.*` table). Antigravity and Pi are NOT wired.
- `supports_remote_mcp` in `AgentProvider.capabilities` (`apps/jaahd/agent_providers.py`): true for Claude and Codex, false for Antigravity and Pi.
- `acp/launch.py` `validate_secrets` stays: no credential in MCP env.
- Mind mem-32955: files under apps/jaahd ship in the community-edition mirror; do not backtick a repo path the mirror lacks.
Credentials & reach:
- MCP on dev (linked project lists tools; transcript grep for the token) — deferred (MCP half): no MCP vendor or test-bearer credential exists, operator chose unit tests only (O6); proven by C4b unit tests. Console half verified via `org/console/dev-login`
- Unit tests, `./dc check quick`, `tools/check_context.py` — verified (no credential)
Out of scope (PRD §6, verbatim, plus what NOT to touch):
- No app-user connectors (per-end-user OAuth, connector gateway for published apps).
- No "Managed by Jaah" vendor keys or credit billing; no change to `apps/api/app/billing/`.
- No per-vendor API client libraries or MCP tool wrappers built by Jaah (except where the vendor's own hosted MCP server is the connector).
- No Lovable action-approval UI (allow once/always).
- No change to runner auth to model providers (`account_auth.py`, `Account` table) or to login/sign-in OAuth (`routes/login_oauth.py`).
- No change to NodeVault crypto semantics (`credential_crypto.py` encryption tiers) beyond what a refactor needs to keep behaviour identical.
- Do not break existing rows: every existing credential type and every existing row keeps working; migrations additive (two-release overlap rule).
- Supabase/project-backend and git-sync are not new work; Figma plugin/.fig upload out.
- Never write a credential value into a task, doc, log or PR.
- Do NOT file Tasks (no licence): the human-only OAuth registration tasks are filed outside this child.
- Antigravity and Pi per-session MCP isolation (a named follow-up, not this child).
Done means:
- AC4.2 (jaahd) An MCP connection is attached to a runner session only when the session's project has linked it; other projects' runners never see it. — jaahd unit test: a launch with `mcp_connections` includes `mcp_<name>`; a launch without does not; two concurrent Claude/Codex sessions with different connections do not see each other's server (per-session isolation).
- AC4.3 Works for every runner agent adapter that supports MCP; adapters without MCP support show "not supported by <agent>". — adapter tests per agent: Claude and Codex add the bridge entry; Antigravity's and Pi's launches add no `mcp_*` server and their capability is false.
- AC4.4 No MCP secret is written into the worktree, transcript or logs (fetched through the broker). — redaction test: with a fake token returned by the credential socket, grep the generated adapter config, the bridge's log output and env for the token → nothing; bridge re-fetches on a mocked 401. Dev transcript grep deferred (see Credentials & reach).
- AC1.5 `./dc check quick` green and `tools/check_context.py` green on this PR — the gate output cited in the PR body.
Outcome
Built the MCP node bridge: per-session mcp_<name> stdio servers for Claude, DeepSeek and Codex, none for Antigravity and Pi, and the supports_remote_mcp flag. Quick gate green. PR #7875 merged (9e615c8); Jaah Deploy succeeded. Deferred: Claude subscription (legacy runtime) and MicroVM runs get no MCP links yet. Memory: none applied.
Artifacts
Activity
- Draft
- Ready
- Runner started
- Runner ended (done)