Skip to content

feat(runner): deliver gateway tools to Claude on Daytona via an in-sandbox stdio MCP shim#5244

Closed
mmabrouk wants to merge 5 commits into
big-agentsfrom
feat-in-sandbox-tool-mcp
Closed

feat(runner): deliver gateway tools to Claude on Daytona via an in-sandbox stdio MCP shim#5244
mmabrouk wants to merge 5 commits into
big-agentsfrom
feat-in-sandbox-tool-mcp

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Jul 12, 2026

Copy link
Copy Markdown
Member

Context

A Claude run on Daytona that carries any custom tool is refused up front. Tool execution over the file relay works there, but nothing inside the sandbox tells the harness which tools exist, so the fail-loud gate (#5047) blocks the whole combination. The harness we want people to use for real agents cannot use platform tools in the sandbox we want to be the default.

This PR delivers gateway and callback tools to Claude on Daytona through a small in-sandbox stdio MCP shim. The shim advertises the run's tools and turns each call into a relay request that the runner executes with its own credentials, so the sandbox never sees a secret. Design: docs/design/agent-workflows/projects/in-sandbox-tool-mcp/.

The one real risk, proven first

Warm reuse was the unproven part. After a sandbox parks to stopped and the engine reconnects, does the Claude ACP adapter respawn a dead stdio MCP subprocess on session/load? It does. Proven live on Daytona (spike-restart.md): the reload returned the same session, respawned the shim (pid 145 to 147) with a fresh initialize and tools/list. No cold fallback path needed.

Changes

  • The shim (tool-mcp-stdio.ts): newline-delimited JSON-RPC over stdio. tools/list serves the run's public specs from an uploaded file (schemas are unbounded, so a file, not an env value). tools/call writes a relay request and maps failures to tool errors. It exits loud on missing input.
  • Asset upload (tool-mcp-assets.ts): writes the shim bundle and specs into an ephemeral in-VM directory next to the relay dir, and fails loud rather than delivering a half-set.
  • The internal MCP entry (mcp.ts): a dedicated builder makes the stdio entry named agenta-tools. A user-declared MCP server may not claim that reserved name; it is refused when declared and again when the entry is built.
  • The gate (run-plan.ts): executable tools on Daytona now pass. Client tools on a remote sandbox still refuse loud (an explicit v1 cut), and non-Daytona remote providers stay fail-closed.
  • The relay execution guard (relay-guard.ts): the guard now runs for every harness, not just Pi. deny is enforced identically everywhere, so a forged relay file cannot run a deny-policy tool. One residual is documented and called out for your decision below.

No /run wire change. Pi and local-Claude delivery are unchanged.

Open decision for you: the ask residual

The review flagged this as exploitable, and I agree it needs your ruling. On a non-Pi harness the guard lets an ask-policy tool through, because Claude's own dialog is meant to gate it. But the relay directory is sandbox-writable, so a prompt-injected Claude could forge a request for an ask-protected tool and the runner would run it with no approval event. The hard deny boundary is not affected; this is only the ask path.

Two options: fail closed for non-Pi ask (safe, but ask-protected gateway tools become unavailable on Claude until a real grant exists), or keep the residual (functional, but accept the bypass risk). The full fix is a one-use grant recorded from the approval event, which is a separate project.

Acceptance (qa-slice2.md, live on the dev stack and Daytona EU)

Cell Result
Claude + local + gateway tool (regression) PASS, token echoed end to end
Pi + Daytona + gateway tool (regression) PASS, unchanged
Claude + Daytona + gateway tool, cold MECHANISM PASS: no refusal, shim uploaded and advertised, session created with the agenta-tools entry. The model turn then failed on Anthropic key credit, so the tool call itself did not run
Claude + Daytona + client tool PASS, loud refusal in 29ms, zero sandboxes created
Claude + Daytona + no tools PASS, shim path inert
Reserved name agenta-tools in user config PASS, refused
Warm reuse / stopped-VM restart (execution) Blocked on the same Anthropic credit; the restart mechanism is proven by the spike above

Sandbox hygiene verified twice: zero sandboxes left on the account.

Merge gate: do not merge until the credit-blocked cells run a real tool end to end on Claude and Daytona (cold, warm reuse, restart). What they need is Anthropic credit on the box's key, not Daytona (the Daytona sandboxes were created fine). status.md carries the same gate.

What to QA

Prerequisites: the dev stack with Daytona creds, a runner on this branch with both bundles rebuilt (pnpm run build:extension; the dev sidecar needs the fresh dist/ copied in before restart), and an Anthropic key with credit in the request.

  1. cd services/runner && pnpm test && pnpm run typecheck && pnpm run build:extension: suite green, both bundles built.
  2. POST /run with harness: claude, sandbox: daytona, and one callback tool pointing at an echo server that returns an unguessable token (exact request in qa-slice2.md).
  3. Expect: the run is accepted, the log shows the shim upload and "advertised via the in-sandbox stdio MCP shim", the reply contains the token, and the echo server was hit once.
  4. Send a second turn inside the idle window, and a third after the VM parks and restarts. The tool still runs.
  5. Edge cases: a client tool on the same path refuses loud; a user MCP server named agenta-tools is refused; a run with no tools uploads no shim.

Notes

  • Follow-up review fixes live in fix(runner): safe hardening from the stack review pass #5248 (top of the stack): correct ping and JSON-RPC error handling in the shim, faster asset upload, and two restored test cases.
  • v1 cuts (follow-ups in plan.md): client tools through the shim, Codex on Daytona, snapshot bake, Pi as an MCP client, and the ask-grant work above.

https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC

mmabrouk added 4 commits July 12, 2026 05:54
…ndbox stdio MCP shim

Slice 1 of in-sandbox-tool-mcp (docs/design/agent-workflows/projects/in-sandbox-tool-mcp/).
Today a Claude run on Daytona with any custom tool is refused up front
(REMOTE_TOOLS_UNSUPPORTED_MESSAGE): execution via the file relay is solved, but nothing
inside the sandbox advertises the tools to an MCP-client harness. This revives PR #4873
onto today's paths, consuming the relay client PR #5243 extracted.

- tools/tool-mcp-stdio.ts: a dependency-free stdio MCP shim (9.6 kB bundled) the harness's
  ACP adapter spawns inside the sandbox. NDJSON JSON-RPC; tools/list serves the run's
  public specs from a specs FILE; tools/call writes a relay request through the shared
  relay client (atomic publication, per-tool timeoutMs) and maps failures to isError
  results. Fail-loud exit 1 on missing env/specs. Env contract in tools/tool-mcp-env.ts:
  AGENTA_AGENT_TOOLS_RELAY_DIR + AGENTA_AGENT_TOOLS_PUBLIC_SPECS_FILE (a file, not an
  unbounded env value copied through four exec layers).
- engines/sandbox_agent/tool-mcp-assets.ts: bundle + specs upload, always-write (closes
  bundle-version skew in reused sandboxes), THROWS on missing bundle/failed upload on the
  path that requires the shim. Bundle override SANDBOX_AGENT_RELAY_MCP_BUNDLE.
- engines/sandbox_agent/mcp.ts: dedicated internal-entry constructor building the typeless
  ACP stdio shape named agenta-tools (claude_settings.py couples permission rules to it);
  McpServerStdio moved here out of mcp-bridge.ts; user-declared servers may not claim the
  reserved name; toAcpMcpServers still cannot emit stdio; user-stdio refusal unrelaxed.
- run-plan.ts: the remote-tools gate narrows - executable tools on Daytona pass (new
  toolMcpDir ephemeral sibling of the relay dir), client tools refuse loud with their own
  message, non-Daytona remote providers stay fail-closed.
- engines/sandbox_agent/relay-guard.ts: the relay execution guard now guards EVERY harness
  (review finding): allow/deny identical everywhere; ask consumes the Pi grant ledger on Pi
  and passes on MCP harnesses whose own dialog gates the call, with the forged-ask residual
  documented. Previously Claude relay records executed unguarded.
- The slice-0 restart spike locked the A2 transport: the pinned Claude ACP adapter
  (claude-agent-acp 0.22.2 in snapshot agenta-sandbox-pi) respawns the stdio MCP subprocess
  on the session/load path after a VM stop/restart (spike-restart.md in the workspace).

Tests: 25+ new (shim handler + real startToolRelay round trip incl. crash-after-write,
concurrency, stdout purity; assets fail-loud; three-layer session MCP pin; gate matrix;
non-Pi guard semantics). Suite 1054 passed / 4 known pre-existing failures; typecheck clean
for the slice; both bundles build with the forbidden-server-symbols gate.

Claude-Session: https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC
…internal MCP name

The engine half of the shim slice, split from the previous commit after a cross-lane
hunk-dependency snag (a formatting pass had touched the parallel Daytona-secret lane's
committed regions; reverted, insertions re-anchored):

- sandbox_agent.ts: upload the shim bundle + specs file on the Daytona non-Pi
  executable-tools path (fail-loud helper, deps-injectable) and pass the assets into
  buildSessionMcpServers; the relay execution guard is now built for EVERY harness via
  buildRelayExecutionGuard (allow/deny identical everywhere; ask consumes the Pi grant
  ledger on Pi and passes on MCP harnesses whose own dialog gates the call).
- mcp.ts: materialization-time reserved-name defense (assertNoReservedUserMcpName at the
  top of buildSessionMcpServers).
- run-plan.ts: declaration-time refusal of a user MCP server named agenta-tools, before
  any resource is created, plus its gate test.

Claude-Session: https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC
The three-layer test used the credentials wire field owned by the parallel Daytona-secret
work, so this lane's tip failed typecheck standalone. The layering pin is about WHICH
servers are delivered; auth delivery has its own tests. Also swap the 'no Bearer' assertion
for 'no user MCP url leaks into the internal entry'.

Claude-Session: https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC
…CP shim

The internal gateway-tool channel now has two transports (local loopback HTTP; the
in-sandbox stdio shim on Daytona): update the runner-to-MCP-server interface page (shim
env contract, SANDBOX_AGENT_RELAY_MCP_BUNDLE, reserved server name, narrowed remote gates,
the every-harness relay execution guard and its stated ask residual), the interface index
rows, the harness-adapters and mcp-models coupling notes, the permission-responder guard
note, the tools/ground-truth/claude-code narrative pages, and the operator env-var
inventory in running-the-agent.

Claude-Session: https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC
@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 12, 2026 8:15pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5590d4b6-b8d8-4892-98c1-e8f73459fcf1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 60.87% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: delivering gateway tools to Claude on Daytona via an in-sandbox stdio MCP shim.
Description check ✅ Passed The description is detailed and directly describes the shim, relay, gate, and reserved-name changes in the pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-in-sandbox-tool-mcp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mmabrouk

Copy link
Copy Markdown
Member Author

Self-review finder round (verification pass skipped per budget; treat as candidates for the Codex review):

  1. tool-mcp-stdio.ts ~L244: MCP ping answered with -32601 instead of the spec-required empty result. If a future Claude SDK health-checks stdio servers, the shim would be torn down. Live QA showed the current pin does not ping, so not blocking — fix before or at the credit-gated re-run.
  2. tool-mcp-stdio.ts: no -32700 response on unparseable stdin lines and initialize echoes the client's protocolVersion without negotiation (a 2025-03-26 client could legally send batches, which the loop drops silently). Same bucket as (1).
  3. relay-guard non-Pi ask passes without a grant — documented residual (deny is enforced; a forged relay file can fire an ask tool without a dialog on the MCP path). Follow-up: ask-grant parity by reflecting harness approvals into the ledger.
  4. Test-pin gaps: the plan→buildRelayExecutionGuard isPi wiring is only indirectly pinned; the client-ONLY (no executable tools) Daytona refusal lost its direct test (only the mixed case is pinned).
  5. Perf nit: uploadToolMcpAssets does 3 serial Daytona FS round trips per acquire and re-reads the static bundle each time — cache the bundle read, parallelize the two writes.
  6. Docs nit: services/runner/AGENTS.md + README still describe build:extension as emitting only the Pi extension.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
services/runner/src/engines/sandbox_agent/mcp.ts (1)

118-127: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Centralize the response-watch env name

AGENTA_AGENT_TOOLS_RELAY_RESPONSE_WATCH_ENABLED is duplicated in mcp.ts, pi-assets.ts, and relay-client.ts. Add a shared constant in tool-mcp-env.ts and reuse it on both sides so the kill switch can’t drift silently.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9291b848-7c61-404f-9d04-40a63d0c6607

📥 Commits

Reviewing files that changed from the base of the PR and between a1ec038 and 0fb9186.

📒 Files selected for processing (25)
  • docs/design/agent-workflows/documentation/adapters/claude-code.md
  • docs/design/agent-workflows/documentation/ground-truth.md
  • docs/design/agent-workflows/documentation/running-the-agent.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/cross-service/README.md
  • docs/design/agent-workflows/interfaces/cross-service/runner-to-mcp-server.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/in-service/mcp-models-and-resolution.md
  • docs/design/agent-workflows/interfaces/in-service/permission-responder.md
  • services/runner/scripts/build-extension.mjs
  • services/runner/src/engines/sandbox_agent.ts
  • services/runner/src/engines/sandbox_agent/mcp.ts
  • services/runner/src/engines/sandbox_agent/relay-guard.ts
  • services/runner/src/engines/sandbox_agent/run-plan.ts
  • services/runner/src/engines/sandbox_agent/tool-mcp-assets.ts
  • services/runner/src/tools/mcp-bridge.ts
  • services/runner/src/tools/tool-mcp-env.ts
  • services/runner/src/tools/tool-mcp-stdio.ts
  • services/runner/tests/unit/sandbox-agent-orchestration.test.ts
  • services/runner/tests/unit/sandbox-agent-run-plan.test.ts
  • services/runner/tests/unit/session-mcp-layering.test.ts
  • services/runner/tests/unit/tool-mcp-assets.test.ts
  • services/runner/tests/unit/tool-mcp-stdio.test.ts
  • services/runner/tests/unit/tool-relay-guard.test.ts

Comment on lines +447 to +458
Separately from the dialog gates, the relay re-checks every execute record with a runner-side
execution guard (`buildRelayExecutionGuard` in
`services/runner/src/engines/sandbox_agent/relay-guard.ts`), on EVERY harness: the relay dir is
sandbox-writable, so a forged request file proves nothing about any dialog having run.
`allow` passes and `deny` refuses identically everywhere. `ask` splits by harness: on Pi the
guard consumes a dialog-recorded execution grant, so a forged or replayed record for an `ask`
tool fails closed; on an MCP harness (Claude) the guard passes `ask`, because the harness's own
dialog gates the call before it reaches the shim and the runner holds no grant for it. The
stated residual: on the MCP path a forged relay file can still trigger an ask-tool without a
dialog; reflecting the harness approval into the grant ledger is a documented follow-up. The
hard deny boundary holds on every harness.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not ship the forged-ask execution bypass as a documented residual.

Because the relay directory is sandbox-writable and the non-Pi guard accepts ask without consuming an approval grant, a forged relay file can execute an ask-protected tool without a Claude dialog. Bind relay records to authenticated harness approvals or make the runner require a verifiable grant before execution.

Comment on lines +241 to +245
return {
jsonrpc: "2.0",
id,
error: { code: -32601, message: `method not found: ${method}` },
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and inspect the surrounding handler.
git ls-files services/runner/src/tools/tool-mcp-stdio.ts
echo '--- outline ---'
ast-grep outline services/runner/src/tools/tool-mcp-stdio.ts --view expanded || true
echo '--- targeted excerpt ---'
sed -n '1,340p' services/runner/src/tools/tool-mcp-stdio.ts | cat -n | sed -n '180,280p'

Repository: Agenta-AI/agenta

Length of output: 4939


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- repo ping references ---'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' '\bping\b|tools/list|initialize|jsonrpc' .

echo '--- package references for MCP / Claude SDK ---'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'mcp|claude|anthropic|acp' package.json pnpm-lock.yaml services web . || true

Repository: Agenta-AI/agenta

Length of output: 50373


🌐 Web query:

Model Context Protocol ping request empty result error code -32601 specification

💡 Result:

The Model Context Protocol (MCP) specifies that a ping request is a standard JSON-RPC 2.0 request with no parameters, used to verify connection health [1][2]. There is no "empty result error code" for a ping request. According to the protocol specification, a successful ping request MUST be answered by the receiver with an empty result object [2][3]. The correct response format is a JSON-RPC success response containing an empty JSON object as the result [2]: { "jsonrpc": "2.0", "id": "your-request-id", "result": {} } If a receiver fails to respond to a ping, it is typically treated as a connection timeout or failure, not as a specific error code [2]. MCP uses standard JSON-RPC 2.0 error codes (such as -32600 to -32603) for protocol-level failures and reserved ranges (-32020 to -32099) for defined specification errors, but these are not applicable to the successful completion of a ping [4][5][6]. If you encounter an error when sending a ping, it would be a standard JSON-RPC error response indicating a transport or protocol issue, rather than a specific "empty result error code" [4][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '162,260p' services/runner/tests/unit/tool-mcp-stdio.test.ts | cat -n

Repository: Agenta-AI/agenta

Length of output: 4079


Handle ping as a successful MCP response

ping currently falls through to -32601, but MCP expects an empty success result ({}). Add an explicit branch before the unknown-method fallback so liveness probes don’t treat the server as unhealthy.

Suggested handling
+  if (method === "ping") {
+    return { jsonrpc: "2.0", id, result: {} };
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return {
jsonrpc: "2.0",
id,
error: { code: -32601, message: `method not found: ${method}` },
};
if (method === "ping") {
return { jsonrpc: "2.0", id, result: {} };
}
return {
jsonrpc: "2.0",
id,
error: { code: -32601, message: `method not found: ${method}` },
};

@mmabrouk

mmabrouk commented Jul 12, 2026

Copy link
Copy Markdown
Member Author

Reviewed with Codex (high effort). Delivery works and the hard deny boundary is solid (a forged relay file cannot run a deny-policy tool).

The mechanical items are fixed in #5248: correct MCP ping, proper JSON-RPC errors, faster asset upload, two restored test cases, and the stale build docs.

One thing is yours to decide: the non-Pi ask residual. The relay directory is sandbox-writable, so a prompt-injected Claude could forge a request for an ask-protected tool and the runner would run it with no approval event. Fail closed (safe, but ask-protected gateway tools become unavailable on Claude until a real grant exists) or keep the residual (functional, accept the risk)? The tradeoff is in the PR body.

Comment thread services/runner/src/engines/sandbox_agent/relay-guard.ts
@mmabrouk mmabrouk added the needs-review Agent updated; awaiting Mahmoud's review label Jul 12, 2026
@mmabrouk mmabrouk marked this pull request as ready for review July 12, 2026 17:57
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. feature typescript labels Jul 12, 2026

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should accept the ask situation as is. In any case, in the future we will move from this relay mechanism to a real connection path between the sandbox and the runner, probably through a virtual network.

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mmabrouk mmabrouk added lgtm This PR has been approved by a maintainer and removed needs-review Agent updated; awaiting Mahmoud's review labels Jul 12, 2026
mmabrouk added a commit that referenced this pull request Jul 12, 2026
Addresses the mechanical review findings on #5243, #5244, and #5245 that carry
no design decision and need no live verification. Landed as one commit on top
of the stack because GitButler cannot retro-assign a new delta onto a lower
applied lane; each fix is mapped to its PR below.

Relay (#5243):
- relay.ts: bound every relay-file removal with a timeout so a hung daemon
  deletion can no longer wedge pickup, stale-sweep, or shutdown; a timed-out
  removal is treated as failed and the loop continues.
- relay-watch.ts: tie a safety-poll miss to the active watch generation so a
  later zero-exit of the same generation cannot erase it (the demotion counter
  now accumulates); validate the whole watch-window string instead of
  parseInt accepting partial garbage.

Shim (#5244):
- tool-mcp-stdio.ts: answer MCP 'ping' with an empty result; return -32700 on
  unparseable input and -32600 on an invalid request; document the
  at-least-once relay delivery contract. Protocol-version negotiation is left
  unchanged (that needs a live check).
- tool-mcp-assets.ts: cache the shim bundle by path and write bundle + specs
  concurrently, removing avoidable serial Daytona round trips.
- restored the direct client-only Daytona refusal test; pinned the Pi vs
  non-Pi ask guard wiring; updated the build:extension docs.

Continuation (#5245):
- tool-mcp-http.ts: authenticate before the method check so an unauthenticated
  GET/DELETE gets 401, not 405.
- added auth tests: unauthorized GET/DELETE, wrong scheme, empty and
  whitespace tokens, and that neither the callback executor nor the client
  relay runs on an unauthorized call.

Deferred (need a design decision or a live check, not in this commit): the
non-Pi ask authorization model (#5244), the bearer-in-argv delivery (#5245),
MCP protocol-version negotiation (#5244).

Claude-Session: https://claude.ai/code/session_0127AM79khCdvD2b8BG2joZL
@mmabrouk mmabrouk deleted the branch big-agents July 12, 2026 20:30
@mmabrouk mmabrouk closed this Jul 12, 2026
@mmabrouk mmabrouk changed the base branch from feat-event-driven-tool-relay to big-agents July 12, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files. typescript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant