{"record":{"id":"11517b84fe48c7ef","repo":"different-ai/openwork","slug":"mcp-resource-rejected-the-synthetic-access-token-w","errorCode":null,"errorMessage":"MCP resource rejected the synthetic access token with HTTP ${initializeRawResponse.status}","messagePattern":"MCP resource rejected the synthetic access token with HTTP (.+?)","errorType":"exception","errorClass":"ProbeFailure","httpStatus":null,"severity":"error","filePath":"packages/enterprise-mcp-mock-server/src/testing/probe.ts","lineNumber":738,"sourceCode":"      origin: baseUrl.origin,\n    }\n    startedAt = Date.now()\n    const initializeRawResponse = await fetchStep(mcpUrl, {\n        method: \"POST\",\n        headers: rpcHeaders,\n        body: JSON.stringify({\n          jsonrpc: \"2.0\",\n          id: 1,\n          method: \"initialize\",\n          params: {\n            protocolVersion: scenario.protocol.version,\n            capabilities: {},\n            clientInfo: { name: \"enterprise-mcp-probe\", version: \"0.1.0\" },\n          },\n        }),\n      }, \"MCP_INITIALIZE\", overallDeadline)\n    if (initializeRawResponse.status === 401 || initializeRawResponse.status === 403) {\n      throw new ProbeFailure(\n        \"AUTH_RESOURCE_VALIDATION\",\n        initializeRawResponse.status === 403 ? \"oauth_insufficient_scope\" : \"oauth_wrong_audience\",\n        `MCP resource rejected the synthetic access token with HTTP ${initializeRawResponse.status}`,\n      )\n    }\n    const initializeResponse = await expectOk(initializeRawResponse, \"MCP_INITIALIZE\")\n    sessionId = initializeResponse.headers.get(\"mcp-session-id\") ?? \"\"\n    negotiatedProtocolHeader = initializeResponse.headers.get(\"mcp-protocol-version\") ?? scenario.protocol.version\n    const initializeEnvelope = await parseRpc(initializeResponse, \"MCP_INITIALIZE\")\n    if (initializeEnvelope.error) {\n      const versionEvidence = z.object({ supportedVersions: z.array(z.string()).min(1) }).safeParse(initializeEnvelope.error.data)\n      throw versionEvidence.success || initializeEnvelope.error.message === \"Unsupported MCP protocol version\"\n        ? new ProbeFailure(\"MCP_VERSION\", \"mcp_version\", initializeEnvelope.error.message)\n        : new ProbeFailure(\"MCP_INITIALIZE\", \"mcp_initialize\", initializeEnvelope.error.message)\n    }\n    if (initializeEnvelope.id !== 1) {\n      throw new ProbeFailure(\"MCP_INITIALIZE\", \"mcp_initialize\", \"Initialize response JSON-RPC id did not match the request\")\n    }","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/enterprise-mcp-mock-server/src/testing/probe.ts#L720-L756","documentation":"During MCP_INITIALIZE, the probe sends an initialize JSON-RPC request with the freshly obtained access token. If the MCP resource server rejects it with 401 or 403, the probe classifies it as AUTH_RESOURCE_VALIDATION: 403 maps to subcode oauth_insufficient_scope and 401 to oauth_wrong_audience. The message embeds the HTTP status: `\"MCP resource rejected the synthetic access token with HTTP ${initializeRawResponse.status}\"`. This means the token was issued but does not satisfy the resource server's audience or scope requirements.","triggerScenarios":"initializeRawResponse.status is 401 or 403 when POSTing the MCP initialize request with `authorization: Bearer ${accessToken}` at probe.ts:734-740.","commonSituations":"Authorization server issuing tokens with the wrong `aud` (not equal to the MCP URL passed as the `resource` parameter); token missing the scopes the MCP resource requires; resource-server token-validation middleware (audience/scope checks) tightened while the mock AS lagged behind; clock skew making the token seem invalid.","solutions":["Ensure the token request includes resource: <mcpUrl> and that the AS embeds that audience in the access token so the resource server's 401 audience check passes.","For 403, add the required scopes to scenario.oauth.authorizationScopes (or grant them on the AS side) so the token carries the scopes the MCP resource enforces.","Compare the resource server's token-validation config (issuer, audience, required scopes) with the mock AS's issued claims and reconcile the two."],"exampleFix":"// before\nauthorizeUrl.searchParams.set(\"scope\", \"read\") // resource requires mcp:tools\n// after\nauthorizeUrl.searchParams.set(\"scope\", \"read mcp:tools\")","handlingStrategy":"validation","validationCode":"// decode the access token JWT and check claims before calling initialize\nconst claims = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64url').toString())\nif (claims.aud !== mcpUrl) throw new Error(`token aud ${claims.aud} != resource ${mcpUrl}`)\nif (!requiredScopes.every(s => (claims.scope ?? '').split(' ').includes(s))) throw new Error('token missing required scopes')","typeGuard":null,"tryCatchPattern":"try {\n  await probeEnterpriseMcpMockServer(scenario)\n} catch (e) {\n  if (e instanceof ProbeFailure && e.message.includes('rejected the synthetic access token with HTTP 403')) {\n    console.error('insufficient scope: add required scopes to scenario.oauth.authorizationScopes', e)\n  } else if (e instanceof ProbeFailure && e.message.includes('with HTTP 401')) {\n    console.error('wrong audience: pass resource=<mcpUrl> in the token request', e)\n  } else throw e\n}","preventionTips":["Always pass the MCP URL as the resource/audience parameter in token requests.","Keep the resource server's required scopes in sync with scenario.oauth.authorizationScopes.","Verify issued token claims (aud, scope, iss) against the resource server's validation config in CI."],"tags":["oauth","mcp","access-token","audience","insufficient-scope"],"backgroundTag":"oauth-insufficient-scope","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}