MCP KDL: add upstream MCP proxy grants for guarded passthroughs #214

Closed
opened 2026-07-10 03:24:29 +00:00 by coilyco-ops · 2 comments
Member

Context

Kai wants a Grubhub MCP that is a guarded passthrough to a private Playwright MCP: sticky personal Grubhub auth, Grubhub-only browsing, read-only by policy, and no semantic Grubhub API layer.

The deploy/service shape should be authored in coilyco-bridge/deploy and the runtime proxy behavior should live in ward-mcp, but the core KDL/specgen belongs in cli-guard so ward-mcp stays a consumer.

Desired cli-guard work

  • Extend the MCP KDL/specgen grammar to express an upstream MCP proxy grant.
  • Keep deny-by-absence as the default: only explicitly granted upstream tools appear on the served MCP surface.
  • Support exact upstream tool mapping, for example proxy browser_snapshot -> upstream playwright tool browser_snapshot.
  • Pull or carry through upstream tool input schema so generated MCP tools keep the Playwright-shaped contract.
  • Add simple guard primitives for v1: allow/deny regexes over string arguments such as url, target, element, text, and key.
  • Support a post-call guard hook shape that can inspect at least returned text/content for URL or forbidden-state checks.

Non-goals for v1

  • No browser-policy language that understands arbitrary DOM semantics.
  • No semantic Grubhub layer.
  • No composition/action DSL beyond what the proxy path needs.

Acceptance sketch

A ward-mcp consumer can write a .mcp.kdl surface that exposes a small allowlisted subset of Playwright MCP tools, with generated schemas preserved and unknown upstream tools omitted from the served MCP surface.

## Context Kai wants a Grubhub MCP that is a guarded passthrough to a private Playwright MCP: sticky personal Grubhub auth, Grubhub-only browsing, read-only by policy, and no semantic Grubhub API layer. The deploy/service shape should be authored in coilyco-bridge/deploy and the runtime proxy behavior should live in ward-mcp, but the core KDL/specgen belongs in cli-guard so ward-mcp stays a consumer. ## Desired cli-guard work * Extend the MCP KDL/specgen grammar to express an upstream MCP proxy grant. * Keep deny-by-absence as the default: only explicitly granted upstream tools appear on the served MCP surface. * Support exact upstream tool mapping, for example proxy browser_snapshot -> upstream playwright tool browser_snapshot. * Pull or carry through upstream tool input schema so generated MCP tools keep the Playwright-shaped contract. * Add simple guard primitives for v1: allow/deny regexes over string arguments such as url, target, element, text, and key. * Support a post-call guard hook shape that can inspect at least returned text/content for URL or forbidden-state checks. ## Non-goals for v1 * No browser-policy language that understands arbitrary DOM semantics. * No semantic Grubhub layer. * No composition/action DSL beyond what the proxy path needs. ## Acceptance sketch A ward-mcp consumer can write a .mcp.kdl surface that exposes a small allowlisted subset of Playwright MCP tools, with generated schemas preserved and unknown upstream tools omitted from the served MCP surface.
Author
Member

WARDED_WORKFLOW: reservation-held

reservation details

Holder: launch intent for container engineer-codex-cli-guard-214 on host kais-macbook-pro-2.local.

Accepted by ward agent --harness codex (reserved 2026-07-14T08:56:27Z). Concurrent ward agent runs are blocked until this intent becomes visible or the intent is released. The stale-intent fallback is still TTL-bounded (3h TTL). --override-reservation overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh. That is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

run seed context — what this run is carrying (ward#609)
  • Resolved: coilyco-flight-deck/cli-guard#214 · branch issue-214 · harness codex · workflow pull-request-and-merge
  • Run: engineer-codex-cli-guard-214 · ward v0.672.0 · dispatched 2026-07-14T08:56:25Z
  • Comment thread: 0 included in the pre-flight read, 0 stripped (ward's own automated comments).

Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.672.0).

— Codex, via ward agent

<!-- ward-agent-reservation --> WARDED_WORKFLOW: reservation-held <details><summary>reservation details</summary> Holder: launch intent for container `engineer-codex-cli-guard-214` on host `kais-macbook-pro-2.local`. Accepted by `ward agent --harness codex` (reserved 2026-07-14T08:56:27Z). Concurrent `ward agent` runs are blocked until this intent becomes visible or the intent is released. The stale-intent fallback is still TTL-bounded (3h TTL). `--override-reservation` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh**. That is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <details><summary>run seed context — what this run is carrying (ward#609)</summary> - **Resolved:** `coilyco-flight-deck/cli-guard#214` · branch `issue-214` · harness `codex` · workflow `pull-request-and-merge` - **Run:** `engineer-codex-cli-guard-214` · ward `v0.672.0` · dispatched `2026-07-14T08:56:25Z` - **Comment thread:** 0 included in the pre-flight read, 0 stripped (ward's own automated comments). Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.672.0). </details> </details> <!-- ward-agent-signature --> — Codex, via `ward agent`
Author
Member

WARDED_WORKFLOW: #228

details

workflow: pull-request-and-merge; review summary: review gate skipped by ~/.ward/config.yaml default
felt: the parser change was direct, and the only friction was repo-local cache pressure during validation.
confidence: high
surprises: the full repo test suite hit unrelated environment-sensitive failures, but the touched package and pre-commit gate passed.
follow-ups: none

WARDED_WORKFLOW: https://forgejo.coilysiren.me/coilyco-flight-deck/cli-guard/pulls/228 <details><summary>details</summary> workflow: pull-request-and-merge; review summary: review gate skipped by ~/.ward/config.yaml default felt: the parser change was direct, and the only friction was repo-local cache pressure during validation. confidence: high surprises: the full repo test suite hit unrelated environment-sensitive failures, but the touched package and pre-commit gate passed. follow-ups: none </details>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/cli-guard#214
No description provided.