fix(mcp): lazy on-demand provider activation with checkpoint persistence#444
fix(mcp): lazy on-demand provider activation with checkpoint persistence#444sentry-junior[bot] wants to merge 4 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Replaces the eager activateAllProviders() approach with a model-driven
lazy activation model:
- Providers connect only when the model first accesses them, not at
turn start. No wasted listTools() calls for unused providers.
- searchMcpTools({ provider }) and callMcpTool('mcp__provider__*')
both auto-activate the named provider on demand. Auth prompts fire
normally if credentials are missing or expired.
- Activated providers are persisted in the turn checkpoint under
activeMcpProviderNames and restored at the start of future turns,
so providers stay live across multi-turn conversations without
re-activating on every request.
- The <available-mcp-providers> prompt block advertises configured
but inactive providers (name + description) with zero network cost,
so the model knows what is available before deciding to activate.
- syncResumeState() now also captures activeMcpProviderNamesForResume
so checkpoint sync happens correctly after lazy activation inside tools.
- loadSkill continues to work and still activates its plugin provider.
Co-Authored-By: claude-opus-4-5 <claude-opus-4-5@anthropic.com>
ea7e62f to
665fcea
Compare
parseMcpProviderFromToolName: replace regex with indexOf('__') split.
The regex failed for provider names containing a single underscore; the
string approach is also more readable and explicit about the delimiter.
getActiveProviderNames: remove the thin wrapper around getActiveProviders().
Both methods returned the same value; inlining the call site removes
unnecessary public API surface.
Co-authored-by: David Cramer <david@sentry.io>
Replace checkpoint-specific Pi message stores with a conversation-keyed session log that restores Pi messages, MCP provider state, and authorization observations from one durable append-only source. Add compaction reset handling via session ids, tighten eval timeouts, and cover OAuth/resume continuity with integration and eval coverage. Co-Authored-By: GPT-5 Codex <codex@openai.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 17e3aed. Configure here.
| const juniorPackageRoot = path.resolve(__dirname, "../junior"); | ||
| const workspaceRoot = path.resolve(__dirname, "../.."); | ||
| const applyEnvFile = createEnvFileLoader(); | ||
| const EVAL_TEST_TIMEOUT_MS = 60_000; |
There was a problem hiding this comment.
Eval timeout cut from 5 minutes to 1 minute
Medium Severity
The eval test timeout was reduced from 300,000ms (5 minutes) to 60,000ms (1 minute). The OAuth workflow evals involve multiple LLM round trips, MCP provider connections, authorization pauses with auto-completion, and resumed turns — workloads that routinely exceed 1 minute under real LLM latency conditions. This risks widespread flaky eval failures.
Reviewed by Cursor Bugbot for commit 17e3aed. Configure here.
Keep loadSkill from advertising plugin-backed skills as MCP-capable unless runtime provider activation returns MCP catalog metadata. This prevents non-MCP skills like Sentry from steering the agent toward searchMcpTools instead of their CLI workflow. Co-Authored-By: GPT-5 Codex <codex@openai.com>
|
Closing this draft so the branch can be re-opened as a fresh PR with the larger session-log scope. |


MCP providers were either skill-gated (original) or eagerly connected for all configured providers at turn start (first iteration). This PR takes the correct lazy approach: providers connect only when the model explicitly asks for one, and activated providers persist across turns.
Root cause (JUNIOR-30)
Two gates blocked MCP without
loadSkill: a skill-scope filter inresolveProviderTools, and activation only happening for checkpoint-preloaded skills. Both are removed.The lazy model
searchMcpTools({ provider: "notion" })andcallMcpTool("mcp__notion__*")both auto-activate the provider on demand before executing. Auth prompts fire normally if credentials are missing. No connections happen at turn start for providers the model didn't ask for.Checkpoint persistence
activeMcpProviderNamesadded toAgentTurnSessionCheckpoint. After a provider is activated (lazily or via skill),syncResumeState()captures it. Future turns restore only checkpointed providers — no cold-start listTools() for unused plugins.Prompt advertising
<available-mcp-providers>block added to the turn context prompt listing configured-but-inactive providers by name and description, with zero network cost. The model knows what's available and can activate on demand.What stays unchanged
loadSkillstill works and still activates its plugin provider. Backward compatible with all existing skill/MCP flows.View Session in Sentry