MCP probe: handle real-world 401 shapes + live snapshot tests#736
Merged
RhysSullivan merged 4 commits intomainfrom May 9, 2026
Merged
MCP probe: handle real-world 401 shapes + live snapshot tests#736RhysSullivan merged 4 commits intomainfrom
RhysSullivan merged 4 commits intomainfrom
Conversation
The body-shape gate rejected sentry.dev's 401 because its body is a
spec-compliant RFC 6750 OAuth error envelope (`{error:"invalid_token",
...}`), not JSON-RPC. Sentry advertises full RFC 9728/8414 metadata via
the `resource_metadata=` attribute of WWW-Authenticate, which is the
MCP authorization spec's mandated signal.
Accept `resource_metadata=` as sufficient for MCP+auth on 401, falling
back to the JSON-RPC body check only for bare Bearer challenges (the
cubic.dev / static-API-key path). Railway-style OAuth-protected
non-MCP endpoints still get rejected because they don't include
`resource_metadata=` and don't return JSON-RPC bodies.
Add an opt-in test that fires the canonical MCP `initialize` POST at
each of 11 real public MCP servers (Sentry, Stripe, Linear, Notion,
Atlassian, Zapier, Cubic, ref.tools, Hugging Face, DeepWiki, Context7),
captures the raw status / WWW-Authenticate / content-type / body
snippet alongside the resulting probe classification, and pins them as
vitest snapshots. Default test runs stay offline; opt in via
`MCP_PROBE_LIVE=1`. When a real server's behavior shifts the snapshot
diff makes the change reviewable, and `vitest -u` regenerates.
While running the live suite Atlassian failed: it omits
`resource_metadata=` from its WWW-Authenticate and returns an RFC 6750
Bearer error envelope (`{error:"invalid_token", ...}`) rather than
JSON-RPC. Add an OAuth-error-body accept path to probe-shape so 401 +
bare Bearer + RFC 6750 envelope classifies as MCP+auth, while the
GraphQL `{errors:[...]}` shape that motivated the body gate still
rejects.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | fcffb2c | Commit Preview URL Branch Preview URL |
May 09 2026, 08:28 AM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | fcffb2c | May 09 2026, 08:28 AM |
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/storage-core
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-google-discovery
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
Expand the live-fetch snapshot file from 11 to 29 servers, adding
Asana, Canva, Cloudflare bindings/observability/radar, Figma, GitHub
Copilot, Intercom, Neon, Netlify, PayPal, Replicate, Square, Supabase,
Tavily, Vercel, Webflow, Wix.
Several of those (Supabase, GitHub Copilot, Vercel, Neon, Tavily,
Replicate) carry RFC 6750 §3.1 `error=` / `error_description=`
auth-params on their Bearer challenge but no `resource_metadata=`, and
their bodies aren't always RFC 6750 either (Supabase returns
`{"message":"Unauthorized"}`). Add `error=` in the Bearer challenge
as another accept signal so wire-shape detection classifies them as
mcp+auth without needing the URL-token fallback.
…s coverage The wire-shape probe (`probeMcpEndpointShape`) only tells us "this is an MCP server" / "auth required". The UI flow in `AddMcpSource` then keys off `probeEndpoint`'s `requiresOAuth` and `supportsDynamicRegistration` to decide whether to show the OAuth popup. Capture those in the live snapshot too so a regression that breaks OAuth detection (vs. falling through to the credentials editor) shows up as a snapshot diff. The 24 OAuth servers now lock in `requiresOAuth: true` / `supportsDynamicRegistration: true` (GitHub Copilot is the lone DCR holdout); the API-key MCPs (Cubic, ref.tools) lock in the auth-required error message; the public MCPs (Hugging Face, DeepWiki, Context7) lock in `connected: true, requiresOAuth: false` with a tool count.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
resource_metadata=inWWW-Authenticateas a sufficient MCP+auth signal on 401, so spec-compliant OAuth-protected servers (Sentry, Stripe, Linear, Notion, Context7) are no longer rejected when their 401 body is RFC 6750 OAuth-shape rather than JSON-RPC.{error:"invalid_token",...}) on 401 + bareBearerfor servers that omitresource_metadata=(Atlassian). GraphQL-style{errors:[...]}401s still reject so non-MCP OAuth-protected APIs aren't misclassified.MCP_PROBE_LIVE=1) that POSTs the canonical MCPinitializeto 11 real public MCP servers (Sentry, Stripe, Linear, Notion, Atlassian, Zapier, Cubic, ref.tools, Hugging Face, DeepWiki, Context7), captures status/headers/body alongside the probe classification, and pins them as vitest snapshots so behavior shifts surface as reviewable diffs (-uregenerates).Test plan
bun run test— full suite passes with the live file skipped by defaultbun run lintandbun run typecheckcleanMCP_PROBE_LIVE=1 vitest run packages/plugins/mcp/src/sdk/probe-shape-real-servers.live.test.ts— all 11 live snapshots matchhttps://mcp.sentry.dev/mcp/into Add MCP Source still triggers the OAuth popuphttps://mcp.atlassian.com/v1/ssetriggers the OAuth popuphttps://www.cubic.dev/api/mcp(API-key MCP) is detected and surfaces as MCP+auth so user can paste credentials