The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.
Commit db345778
db34577898cfMerged
aryaamin <[email protected]> · 2 months ago · 4 files · ~4 modified
Description
fix: restart OAuth for unauthenticated MCP clients
Details
- Commit
- db34577898cf
- Parent
- 90ba0b085978
api/mcp.tsmodifiedView file
@@ -82,12 +82,40 @@
8282
};8383
}8484
85-
const handler = withMcpAuth(mcp, verifyToken, {85+
const resourceMetadataPath = '/.well-known/oauth-protected-resource/mcp';86+
87+
const authenticatedHandler = withMcpAuth(mcp, verifyToken, {8688
required: true,87-
resourceMetadataPath: '/.well-known/oauth-protected-resource',89+
resourceMetadataPath,8890
...(process.env.OPENCLASP_MCP_URL8991
? { resourceUrl: new URL(process.env.OPENCLASP_MCP_URL).origin }9092
: {}),9193
});9294
95+
async function handler(request: Request): Promise<Response> {96+
const response = await authenticatedHandler(request);97+
if (response.status !== 401 || request.headers.get('authorization')?.trim()) return response;98+
99+
// A missing credential is an authentication discovery challenge, not an invalid token.100+
// Cursor's V2 MCP client treats `invalid_token` while auth is still unknown as a101+
// transient connection failure instead of starting OAuth.102+
const configuredResource = process.env.OPENCLASP_MCP_URL;103+
const publicOrigin = configuredResource104+
? new URL(configuredResource).origin105+
: new URL(request.url).origin;106+
const headers = new Headers(response.headers);107+
headers.set(108+
'www-authenticate',109+
`Bearer resource_metadata="${new URL(resourceMetadataPath, publicOrigin).href}"`,110+
);111+
headers.set('cache-control', 'no-store');112+
headers.delete('content-length');113+
headers.delete('content-type');114+
return new Response(null, {115+
status: response.status,116+
statusText: response.statusText,117+
headers,118+
});119+
}120+
93121
export { handler as GET, handler as POST };api/oauth-protected-resource.tsmodifiedView file
Loading diff…
tests/hosted-auth.test.tsmodifiedView file
Loading diff…
vercel.jsonmodifiedView file
Loading diff…