Skip to content

feat(engine): gateway transport (config + hand-rolled MCP client) - #14

Merged
Miyamura80 merged 1 commit into
mainfrom
claude/thin-engine-rescope
Aug 27, 2026
Merged

feat(engine): gateway transport (config + hand-rolled MCP client)#14
Miyamura80 merged 1 commit into
mainfrom
claude/thin-engine-rescope

Conversation

@Miyamura80

@Miyamura80 Miyamura80 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

First slice of the thin-engine re-scope: sealg becomes a thin transport that forwards tool calls to the SealGate gateway's per-user /mcp/{api_key}/ endpoint, where all policy / lethal-trifecta / PII enforcement lives. The binary carries no policy of its own.

This PR is additive — it adds the gateway transport module but does not yet wire it into the CLI surface, so nothing existing breaks. The follow-up slice rewires sealg call → the gateway, adds sealg list, and deletes the template's local demo commands.

Design context: dev-docs/architecture/multi-interface-design.md in edison-watch/edison-watch (§5A thin engine, §5B Centaur, B3 error mirroring).

Changes

  • crates/engine/src/gateway/config.rsGatewayConfig::from_env() resolves gateway coordinates from the environment (so the binary stays stateless and drops into any sandbox):
    • gateway URL (SEALGATE_URL, defaults to the dev endpoint — never a guessed prod host)
    • optional API key: present → embedded in the /mcp/{key}/ path; absent → keyless path, auth injected upstream (Centaur iron-proxy). Supports both credential models with no fork.
    • sealgate_secret_key header value, conversation id (SEALGATE_CONVERSATION_ID, falling back to Centaur's CENTAUR_THREAD_KEY), and a MITM CA bundle (SSL_CERT_FILE/REQUESTS_CA_BUNDLE/NODE_EXTRA_CA_CERTS) — reqwest+rustls does not read those automatically, so we load them or TLS fails behind an intercepting proxy.
    • written against a getter seam for deterministic tests.
  • crates/engine/src/gateway/client.rs — hand-rolled MCP Streamable-HTTP client (spec 2026-07-28), no rmcp dependency so the binary stays thin: initialize / tools_list / tools_call, Mcp-Session-Id capture, JSON + SSE response parsing, and JSON-RPC errors mapped to a variant that mirrors the MCP error shape verbatim (no bespoke taxonomy).
  • crates/engine/src/gateway/mod.rs + lib.rs — module wiring and re-exports.

Testing

  • Tests pass — cargo test -p engine gateway: 10 passed (env resolution, URL building, JSON/SSE/error parsing). The client's transport methods need a live gateway, so this slice unit-tests the pure pieces (config resolution, the response parser).
  • Linting — cargo fmt --check and cargo clippy -p engine clean locally. Full make ci runs here on CI.

Related Issues

None — tracked by the multi-interface design doc.


Generated by Claude Code


Summary by cubic

Turns sealg into a thin transport that forwards tool calls to the SealGate gateway's per-user /mcp/{api_key}/ endpoint, where all policy and PII enforcement lives. Additive only — the CLI surface is unchanged and nothing existing breaks.

  • GatewayConfig::from_env() reads gateway URL, API key, secret key, conversation id, and MITM CA bundle from the environment.
  • With an API key the path becomes /mcp/{key}/; without one, auth is injected upstream and the keyless path is used; conversation id falls back to CENTAUR_THREAD_KEY.
  • Adds a hand-rolled MCP Streamable HTTP client (initialize, tools/list, tools/call) with JSON and SSE parsing and no rmcp dependency.
  • CA bundle env vars are honored explicitly because reqwest+rustls does not read them, so TLS keeps working behind an intercepting proxy.
  • JSON-RPC errors mirror the MCP error shape so callers can map them to exit codes directly; 10 unit tests cover config resolution, URL building, and response parsing.

Written for commit ed6fd11. Summary will update on new commits.

Review in cubic

Additive first slice of the thin-engine re-scope. sealg forwards tool calls
to the SealGate gateway's per-user /mcp/{api_key}/ endpoint, where all policy
and trifecta enforcement lives; the binary carries none.

- gateway::config: GatewayConfig::from_env resolves gateway URL, optional API
  key (path vs upstream-injected auth), sealgate_secret_key, conversation id
  (SEALGATE_CONVERSATION_ID or CENTAUR_THREAD_KEY), and MITM CA bundle. Written
  against a getter seam for deterministic tests.
- gateway::client: hand-rolled MCP Streamable HTTP (2026-07-28) client -
  initialize/tools_list/tools_call, session-id capture, JSON + SSE response
  parsing, MCP-shaped errors mapped verbatim (design B3). No rmcp dep.
- 10 unit tests (env resolution, URL building, JSON/SSE/error parsing); fmt +
  clippy clean.

Not yet wired into the CLI surface; demo commands still present. Next slice
rewires 'sealg call' to the gateway, adds 'sealg list', deletes demo commands.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpwFmgQPfugKFF9zugay6Y
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@Miyamura80
Miyamura80 merged commit 221230a into main Aug 27, 2026
9 checks passed
@github-actions
github-actions Bot deleted the claude/thin-engine-rescope branch August 27, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants