@zenrows/mcp 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +29 -3
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -24,25 +24,51 @@ function extractApiKey(req) {
|
|
|
24
24
|
return new URL(req.url).searchParams.get("apikey") ?? undefined;
|
|
25
25
|
}
|
|
26
26
|
const AUTH_SERVER = process.env.OAUTH_AUTH_SERVER ?? "https://app.zenrows.com";
|
|
27
|
+
const MCP_SERVER = process.env.MCP_SERVER ?? "https://mcp.zenrows.com";
|
|
28
|
+
app.get("/mcp/.well-known/oauth-authorization-server", (c) => c.redirect("/.well-known/oauth-authorization-server", 301));
|
|
29
|
+
// RFC 9728 — OAuth Protected Resource Metadata
|
|
30
|
+
// MCP clients fetch this first to discover the authorization server(s) for this resource.
|
|
31
|
+
app.get("/.well-known/oauth-protected-resource", (c) => c.json({
|
|
32
|
+
resource: MCP_SERVER,
|
|
33
|
+
authorization_servers: [MCP_SERVER],
|
|
34
|
+
bearer_methods_supported: ["header", "query"],
|
|
35
|
+
scopes_supported: [],
|
|
36
|
+
}));
|
|
37
|
+
// RFC 8414 — OAuth Authorization Server Metadata
|
|
38
|
+
// Issuer must match the URL of the server serving this document (MCP_SERVER, not AUTH_SERVER),
|
|
39
|
+
// because the MCP server acts as an authorization server proxy for client discovery purposes.
|
|
27
40
|
app.get("/.well-known/oauth-authorization-server", (c) => c.json({
|
|
28
|
-
issuer:
|
|
41
|
+
issuer: MCP_SERVER,
|
|
29
42
|
authorization_endpoint: `${AUTH_SERVER}/oauth/mcp/authorize`,
|
|
30
43
|
token_endpoint: `${AUTH_SERVER}/oauth/mcp/token`,
|
|
44
|
+
registration_endpoint: `${MCP_SERVER}/register`,
|
|
31
45
|
response_types_supported: ["code"],
|
|
32
46
|
grant_types_supported: ["authorization_code"],
|
|
33
47
|
code_challenge_methods_supported: ["S256"],
|
|
34
48
|
token_endpoint_auth_methods_supported: ["none"],
|
|
35
49
|
}));
|
|
50
|
+
// RFC 7591 — Dynamic Client Registration
|
|
51
|
+
// MCP clients (Claude.ai, Cursor, etc.) register themselves before initiating OAuth.
|
|
52
|
+
// Since ZenRows API keys are the real auth mechanism, client registration is stateless —
|
|
53
|
+
// we echo back a stable client_id derived from the request (or the one the client provides).
|
|
54
|
+
app.post("/register", async (c) => {
|
|
55
|
+
const body = await c.req.json().catch(() => ({}));
|
|
56
|
+
return c.json({
|
|
57
|
+
client_id: body.client_id ?? crypto.randomUUID(),
|
|
58
|
+
client_id_issued_at: Math.floor(Date.now() / 1000),
|
|
59
|
+
...body,
|
|
60
|
+
}, 201);
|
|
61
|
+
});
|
|
36
62
|
app.all("/mcp", async (c) => {
|
|
37
63
|
const apiKey = extractApiKey(c.req.raw);
|
|
38
64
|
if (!apiKey) {
|
|
39
65
|
return c.json({
|
|
40
66
|
error: "Missing API key. Use Authorization: Bearer <key> header or ?apikey=<key> query param.",
|
|
41
67
|
}, 401, {
|
|
42
|
-
"WWW-Authenticate": `Bearer realm="${AUTH_SERVER}", resource_metadata="
|
|
68
|
+
"WWW-Authenticate": `Bearer realm="${AUTH_SERVER}", resource_metadata="${MCP_SERVER}/.well-known/oauth-protected-resource"`,
|
|
43
69
|
// CloudFront strips WWW-Authenticate — add Link header as RFC 8615 fallback
|
|
44
70
|
// so MCP clients can still discover the OAuth server
|
|
45
|
-
"Link":
|
|
71
|
+
"Link": `<${MCP_SERVER}/.well-known/oauth-protected-resource>; rel="oauth-protected-resource"`,
|
|
46
72
|
});
|
|
47
73
|
}
|
|
48
74
|
const transport = new WebStandardStreamableHTTPServerTransport({
|