@zenrows/mcp 1.0.7 → 1.1.1
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 +23 -1
- package/dist/server.js +5 -0
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
+
import { cors } from "hono/cors";
|
|
2
3
|
import { serve } from "@hono/node-server";
|
|
3
4
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
4
5
|
import { createServer } from "./server.js";
|
|
5
6
|
// ─── app ──────────────────────────────────────────────────────────────────────
|
|
6
7
|
const app = new Hono();
|
|
8
|
+
// CORS — required for browser-side MCP clients (Claude.ai, Cursor web, etc.)
|
|
9
|
+
// All origins allowed: the API key is the auth mechanism, not the origin.
|
|
10
|
+
app.use(cors({
|
|
11
|
+
origin: "*",
|
|
12
|
+
allowMethods: ["GET", "POST", "OPTIONS"],
|
|
13
|
+
allowHeaders: ["Authorization", "Content-Type", "Accept", "Mcp-Session-Id"],
|
|
14
|
+
exposeHeaders: ["WWW-Authenticate", "Mcp-Session-Id"],
|
|
15
|
+
maxAge: 86_400,
|
|
16
|
+
}));
|
|
7
17
|
function extractApiKey(req) {
|
|
8
18
|
const auth = req.headers.get("authorization");
|
|
9
19
|
if (auth) {
|
|
@@ -13,12 +23,24 @@ function extractApiKey(req) {
|
|
|
13
23
|
}
|
|
14
24
|
return new URL(req.url).searchParams.get("apikey") ?? undefined;
|
|
15
25
|
}
|
|
26
|
+
const AUTH_SERVER = process.env.OAUTH_AUTH_SERVER ?? "https://app.zenrows.com";
|
|
27
|
+
app.get("/.well-known/oauth-authorization-server", (c) => c.json({
|
|
28
|
+
issuer: AUTH_SERVER,
|
|
29
|
+
authorization_endpoint: `${AUTH_SERVER}/oauth/mcp/authorize`,
|
|
30
|
+
token_endpoint: `${AUTH_SERVER}/oauth/mcp/token`,
|
|
31
|
+
response_types_supported: ["code"],
|
|
32
|
+
grant_types_supported: ["authorization_code"],
|
|
33
|
+
code_challenge_methods_supported: ["S256"],
|
|
34
|
+
token_endpoint_auth_methods_supported: ["none"],
|
|
35
|
+
}));
|
|
16
36
|
app.all("/mcp", async (c) => {
|
|
17
37
|
const apiKey = extractApiKey(c.req.raw);
|
|
18
38
|
if (!apiKey) {
|
|
19
39
|
return c.json({
|
|
20
40
|
error: "Missing API key. Use Authorization: Bearer <key> header or ?apikey=<key> query param.",
|
|
21
|
-
}, 401
|
|
41
|
+
}, 401, {
|
|
42
|
+
"WWW-Authenticate": `Bearer realm="${AUTH_SERVER}", resource_metadata="https://mcp.zenrows.com/.well-known/oauth-authorization-server"`,
|
|
43
|
+
});
|
|
22
44
|
}
|
|
23
45
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
24
46
|
sessionIdGenerator: undefined, // stateless — no session tracking between requests
|
package/dist/server.js
CHANGED
|
@@ -11,6 +11,11 @@ export function createServer(apiKey) {
|
|
|
11
11
|
});
|
|
12
12
|
// ─── scrape ────────────────────────────────────────────────────────────────
|
|
13
13
|
server.registerTool("scrape", {
|
|
14
|
+
annotations: {
|
|
15
|
+
title: "Scrape Webpage",
|
|
16
|
+
readOnlyHint: true,
|
|
17
|
+
destructiveHint: false,
|
|
18
|
+
},
|
|
14
19
|
description: `Scrape any webpage and return its content using ZenRows.
|
|
15
20
|
|
|
16
21
|
Use this tool to fetch webpage content for analysis. By default it returns clean
|