fix(mcp): restore cloud-snapshot mode for Recce Summary agent (DRC-3384)#1359
Conversation
`recce mcp-server` collapsed two distinct cloud paths into a single live
CloudBackend branch. Setting RECCE_SESSION_ID (the Recce Summary agent's
contract) routed into the live-session spawn (POST /api/v2/sessions/{id}/
instance) and 401'd before the MCP server could start, breaking GitLab
summary generation in production.
Split mcp-server into three explicit modes:
- cloud-session (public) `--cloud --session <id>`
CloudBackend proxies tool calls to a live Recce Cloud session.
- cloud-snapshot (internal) `RECCE_SESSION_ID` / `RECCE_SNAPSHOT_ID` env
CloudStateLoader downloads the state file from S3 and the MCP server
runs locally against that snapshot. Used by the Recce Summary agent.
- local (default) no flags / no env
Capture --cloud / --session BEFORE patch_derived_args() so explicit
cloud-session can still be told apart from env-driven cloud-snapshot
after the helper promotes session_id to cloud=True. Reset cloud=False
before run_mcp_server() in non-session paths so the legacy snapshot
flow doesn't take the CloudBackend branch.
Tests updated:
- cloud-snapshot via RECCE_SESSION_ID env -> state loader, no live spawn
- cloud-session via --cloud --session -> CloudBackend, no state loader
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Kent Huang <kent@infuseai.io>
Codecov Report❌ Patch coverage is
... and 4 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Code Review: PR #1359Files reviewed: 2 ( Validation ResultsPass A: Correctness & Logic — PASSTraced the three-mode dispatch end-to-end:
Pass C: Cross-Reference Consistency — PASS
Pass D: Error Handling & Edge Cases — PASS
Pass E: Test Coverage & Quality — PASS with NOTE
Pass F: Diff-Specific Checks — PASS
Pass G: Performance — N/ACLI startup path; no hot loops or query changes. Pass H: Async/Concurrency — N/A
Verification Results
Verdict: GOAll validation passes clean. Notes
What I could not verify
What I looked for and did not find
|
There was a problem hiding this comment.
Pull request overview
This PR restores the intended “cloud-snapshot” behavior for recce mcp-server when invoked by the Recce Summary agent via RECCE_SESSION_ID, while preserving an explicit “cloud-session” mode for end users (--cloud --session <id>). It prevents env-driven snapshot runs from incorrectly taking the live CloudBackend branch (and failing early with a 401 before MCP starts).
Changes:
- Split MCP startup logic into explicit modes (cloud-session vs cloud-snapshot vs local) by capturing explicit flags before
patch_derived_args(). - Route env-driven snapshot startup through
create_state_loader_by_args()and forcecloud=Falsewhen callingrun_mcp_serverto avoid CloudBackend. - Add/adjust CLI tests to validate snapshot-via-env uses a state loader and explicit cloud-session skips it.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
recce/cli.py |
Introduces explicit mode detection for mcp-server, routes snapshot mode through cloud state loader, and prevents accidental CloudBackend activation. |
tests/test_cli.py |
Adds coverage for env-driven cloud-snapshot behavior and explicit --cloud --session cloud-session behavior. |
Code Review: PR #1359Files reviewed: 2 ( Summary of approachIndependently traced the dispatch logic for every legal input combination, verified the production caller of the cloud-snapshot path, and re-ran the full CLI test suite. This is a fresh adversarial read; not a re-statement of the prior review. Validation ResultsPass A: Correctness & Logic — PASSTraced 9 input combinations end-to-end against the new dispatch:
Order-of-operations is critical and correct:
Pass B: Security — PASSNo secrets logged. Pass C: Cross-Reference Consistency — PASS
Pass D: Error Handling & Edge Cases — PASS
Pass E: Test Coverage & Quality — PASS with NOTE
Pass F: Diff-Specific Checks — PASS
Pass G: Performance — N/ACLI startup path; no hot loops, queries, or memory concerns. Pass H: Async/Concurrency — N/A
Verification Results
Production caller verificationThe recce mcp-server --sse --debug 2> /dev/null &with Verdict: GONo BLOCKERs, no ISSUEs. The dispatcher is correct on all combinations I traced, the production caller is exercised by the cloud-snapshot path, the full CLI suite passes, and lint is clean. Notes
What I could not verify
What I looked for and did not find
|
even-wei
left a comment
There was a problem hiding this comment.
Claude Code Review (re-review at user's request): No critical issues found. Dispatcher is correct on all 9 traced combinations; production caller (recce_ai_summary_entrypoint) confirmed to use the cloud-snapshot path. 4 NOTEs about help-text UX, session_id forwarding, missing negative test, and a behavior tightening — all non-blocking. See review comment for details.
Summary
recce mcp-serverhad collapsed two distinct cloud paths into a single liveCloudBackendbranch. WithRECCE_SESSION_IDin the environment (the contract used by the Recce Summary agent), the server tried to spawn a live cloud instance viaPOST /api/v2/sessions/{id}/instanceand 401'd before MCP could start — breaking GitLab summary generation in production (DRC-3384).This PR splits
mcp-serverinto three explicit modes:--cloud --session <id>CloudBackendproxies tool calls to a live Recce Cloud sessionRECCE_SESSION_ID/RECCE_SNAPSHOT_IDenvCloudStateLoaderdownloads state file from S3, served as a local MCP. Used by the Recce Summary agent.Root cause
patch_derived_args()promotessession_id(which Click reads fromRECCE_SESSION_IDvia the hidden--session-idoption) tocloud=True. After e7b7f81 addedCloudBackend, the env-driven flag also routed into the live-session branch — but the Recce Summary agent only has snapshot artifacts, not a running cloud instance, so the spawn call 401'd.Fix
--cloud/--sessionflags beforepatch_derived_args()so explicit cloud-session can still be told apart from env-driven cloud-snapshot afterward.create_state_loader_by_args(legacy path) and resetkwargs[\"cloud\"] = Falsebeforerun_mcp_serverso it does not take theCloudBackendbranch.Test plan
tests/test_cli.py::TestCommandMCPServer— all 6 tests passtest_cmd_mcp_server_cloud_snapshot_mode_via_env_var:RECCE_SESSION_ID→ state loader, no live spawntest_cmd_mcp_server_cloud_session_mode_skips_state_loader:--cloud --session→CloudBackend, no state loadertests/test_cli.pysuite passes (21 tests)recce mcp-server --sse --debugwithRECCE_SESSION_IDset should printLoading Recce state from cloud snapshot (...)and start an SSE server (noPOST /instancecall)recce mcp-server --cloud --session <id>still spawns a live cloud sessionRelated
feat(mcp): add cloud-mode support for recce mcp-server, DRC-3345)🤖 Generated with Claude Code