@bycrawl/mcp 0.4.1 → 0.5.0
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/README.md +20 -0
- package/build/client.js +5 -1
- package/build/client.js.map +1 -1
- package/build/oauth/callback.d.ts +6 -0
- package/build/oauth/callback.js +75 -0
- package/build/oauth/callback.js.map +1 -0
- package/build/oauth/crypto.d.ts +6 -0
- package/build/oauth/crypto.js +29 -0
- package/build/oauth/crypto.js.map +1 -0
- package/build/oauth/provider.d.ts +14 -0
- package/build/oauth/provider.js +125 -0
- package/build/oauth/provider.js.map +1 -0
- package/build/oauth/store.d.ts +43 -0
- package/build/oauth/store.js +66 -0
- package/build/oauth/store.js.map +1 -0
- package/build/oauth/user-keys.d.ts +6 -0
- package/build/oauth/user-keys.js +89 -0
- package/build/oauth/user-keys.js.map +1 -0
- package/build/server.js +2 -2
- package/build/server.js.map +1 -1
- package/build/tools/dcard.js +6 -14
- package/build/tools/dcard.js.map +1 -1
- package/build/tools/facebook.js +21 -8
- package/build/tools/facebook.js.map +1 -1
- package/build/tools/gmaps.d.ts +2 -0
- package/build/tools/gmaps.js +13 -0
- package/build/tools/gmaps.js.map +1 -0
- package/build/tools/instagram.js +5 -5
- package/build/tools/instagram.js.map +1 -1
- package/build/tools/job104.js +3 -3
- package/build/tools/job104.js.map +1 -1
- package/build/tools/linkedin.js +9 -9
- package/build/tools/linkedin.js.map +1 -1
- package/build/tools/reddit.js +16 -5
- package/build/tools/reddit.js.map +1 -1
- package/build/tools/system.js +2 -1
- package/build/tools/system.js.map +1 -1
- package/build/tools/threads.js +8 -8
- package/build/tools/threads.js.map +1 -1
- package/build/tools/tiktok.js +8 -8
- package/build/tools/tiktok.js.map +1 -1
- package/build/tools/x.js +5 -5
- package/build/tools/x.js.map +1 -1
- package/build/tools/youtube.js +5 -7
- package/build/tools/youtube.js.map +1 -1
- package/build/transport-http.js +146 -66
- package/build/transport-http.js.map +1 -1
- package/package.json +6 -6
- package/build/tools/xiaohongshu.d.ts +0 -2
- package/build/tools/xiaohongshu.js +0 -31
- package/build/tools/xiaohongshu.js.map +0 -1
package/build/transport-http.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { resolve, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
2
5
|
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
|
|
3
6
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
7
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
8
|
import { createServer } from "./server.js";
|
|
6
9
|
import { apiContextStorage } from "./api-context.js";
|
|
7
|
-
const PORT = parseInt(process.env.PORT ?? "
|
|
10
|
+
const PORT = parseInt(process.env.PORT ?? "8080", 10);
|
|
8
11
|
const HOST = process.env.HOST ?? "0.0.0.0";
|
|
12
|
+
const OAUTH_ENABLED = !!process.env.SUPABASE_URL;
|
|
9
13
|
// Session TTL: clean up sessions idle for more than 30 minutes
|
|
10
14
|
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
11
15
|
const sessions = {};
|
|
@@ -20,7 +24,7 @@ setInterval(() => {
|
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
}, 60_000); // check every minute
|
|
23
|
-
// --- API key helpers ---
|
|
27
|
+
// --- API key helpers (legacy mode) ---
|
|
24
28
|
function extractApiKey(req) {
|
|
25
29
|
const bearer = req.headers.authorization;
|
|
26
30
|
if (bearer?.startsWith("Bearer "))
|
|
@@ -50,93 +54,169 @@ function getSession(sessionId) {
|
|
|
50
54
|
entry.lastActivity = Date.now();
|
|
51
55
|
return entry;
|
|
52
56
|
}
|
|
57
|
+
// --- MCP request handler (shared between OAuth and legacy modes) ---
|
|
58
|
+
async function handleMcpPost(req, res, apiKey) {
|
|
59
|
+
const maskedKey = apiKey.slice(0, 12) + "...";
|
|
60
|
+
console.log(`[MCP POST] apiKey=${maskedKey} sessionId=${req.headers["mcp-session-id"] ?? "(none)"}`);
|
|
61
|
+
await withApiKey(apiKey, async () => {
|
|
62
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
63
|
+
// Existing session
|
|
64
|
+
if (sessionId) {
|
|
65
|
+
const entry = getSession(sessionId);
|
|
66
|
+
if (entry) {
|
|
67
|
+
console.log(`[MCP POST] existing session ${sessionId}, body method=${req.body?.method}`);
|
|
68
|
+
await entry.transport.handleRequest(req, res, req.body);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
console.log(`[MCP POST] session ${sessionId} not found in ${Object.keys(sessions).length} active sessions`);
|
|
72
|
+
}
|
|
73
|
+
// New session (must be initialize request)
|
|
74
|
+
if (!sessionId && isInitializeRequest(req.body)) {
|
|
75
|
+
console.log(`[MCP POST] new session (initialize)`);
|
|
76
|
+
const transport = new StreamableHTTPServerTransport({
|
|
77
|
+
sessionIdGenerator: () => randomUUID(),
|
|
78
|
+
onsessioninitialized: (sid) => {
|
|
79
|
+
sessions[sid] = { transport, lastActivity: Date.now() };
|
|
80
|
+
console.log(`[MCP POST] session initialized: ${sid}`);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
transport.onclose = () => {
|
|
84
|
+
const sid = transport.sessionId;
|
|
85
|
+
if (sid && sessions[sid])
|
|
86
|
+
delete sessions[sid];
|
|
87
|
+
};
|
|
88
|
+
const server = createServer();
|
|
89
|
+
await server.connect(transport);
|
|
90
|
+
await transport.handleRequest(req, res, req.body);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
console.log(`[MCP POST] bad request — no session, not initialize. body=${JSON.stringify(req.body).slice(0, 200)}`);
|
|
94
|
+
res.status(400).json({
|
|
95
|
+
jsonrpc: "2.0",
|
|
96
|
+
error: { code: -32000, message: "Bad Request: No valid session ID provided" },
|
|
97
|
+
id: null,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function handleMcpGet(req, res) {
|
|
102
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
103
|
+
const entry = getSession(sessionId);
|
|
104
|
+
if (!sessionId || !entry) {
|
|
105
|
+
res.status(400).json({ error: "Invalid or missing session ID" });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await entry.transport.handleRequest(req, res);
|
|
109
|
+
}
|
|
110
|
+
async function handleMcpDelete(req, res) {
|
|
111
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
112
|
+
const entry = getSession(sessionId);
|
|
113
|
+
if (!sessionId || !entry) {
|
|
114
|
+
res.status(400).json({ error: "Invalid or missing session ID" });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await entry.transport.handleRequest(req, res);
|
|
118
|
+
}
|
|
119
|
+
// --- Start server ---
|
|
53
120
|
export async function startHttp() {
|
|
54
121
|
const app = createMcpExpressApp({ host: HOST });
|
|
122
|
+
// Trust first proxy (Zeabur / reverse proxy) — required for express-rate-limit
|
|
123
|
+
app.set("trust proxy", 1);
|
|
55
124
|
// Health check (no auth needed)
|
|
56
125
|
app.get("/health", (_req, res) => {
|
|
57
126
|
res.json({ status: "ok" });
|
|
58
127
|
});
|
|
59
|
-
//
|
|
128
|
+
// Favicon for MCP Directory listing
|
|
129
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
130
|
+
const faviconPath = resolve(__dirname, "../static/favicon.png");
|
|
131
|
+
let faviconBuf;
|
|
132
|
+
try {
|
|
133
|
+
faviconBuf = readFileSync(faviconPath);
|
|
134
|
+
}
|
|
135
|
+
catch { }
|
|
136
|
+
if (faviconBuf) {
|
|
137
|
+
app.get("/favicon.ico", (_req, res) => {
|
|
138
|
+
res.set("Content-Type", "image/png").set("Cache-Control", "public, max-age=86400").send(faviconBuf);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (OAUTH_ENABLED) {
|
|
142
|
+
await mountOAuth(app);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
mountLegacy(app);
|
|
146
|
+
}
|
|
147
|
+
// Catch-all: any other route → 404 JSON
|
|
148
|
+
app.use((_req, res, _next) => {
|
|
149
|
+
res.status(404).json({ error: "Not found" });
|
|
150
|
+
});
|
|
151
|
+
app.listen(PORT, HOST, () => {
|
|
152
|
+
const mode = OAUTH_ENABLED ? "OAuth" : "API key";
|
|
153
|
+
console.log(`ByCrawl MCP HTTP server listening on http://${HOST}:${PORT}/mcp (${mode} mode)`);
|
|
154
|
+
});
|
|
155
|
+
// Graceful shutdown
|
|
156
|
+
process.on("SIGINT", async () => {
|
|
157
|
+
console.log("Shutting down...");
|
|
158
|
+
for (const sid of Object.keys(sessions)) {
|
|
159
|
+
await sessions[sid].transport.close().catch(() => { });
|
|
160
|
+
delete sessions[sid];
|
|
161
|
+
}
|
|
162
|
+
process.exit(0);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// --- Legacy mode (Bearer sk_byc_xxx / x-bycrawl-api-key header) ---
|
|
166
|
+
function mountLegacy(app) {
|
|
60
167
|
app.post("/mcp", async (req, res) => {
|
|
61
168
|
const apiKey = requireApiKey(req, res);
|
|
62
169
|
if (!apiKey)
|
|
63
170
|
return;
|
|
64
|
-
await
|
|
65
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
66
|
-
// Existing session
|
|
67
|
-
if (sessionId) {
|
|
68
|
-
const entry = getSession(sessionId);
|
|
69
|
-
if (entry) {
|
|
70
|
-
await entry.transport.handleRequest(req, res, req.body);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// New session (must be initialize request)
|
|
75
|
-
if (!sessionId && isInitializeRequest(req.body)) {
|
|
76
|
-
const transport = new StreamableHTTPServerTransport({
|
|
77
|
-
sessionIdGenerator: () => randomUUID(),
|
|
78
|
-
onsessioninitialized: (sid) => {
|
|
79
|
-
sessions[sid] = { transport, lastActivity: Date.now() };
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
transport.onclose = () => {
|
|
83
|
-
const sid = transport.sessionId;
|
|
84
|
-
if (sid && sessions[sid])
|
|
85
|
-
delete sessions[sid];
|
|
86
|
-
};
|
|
87
|
-
const server = createServer();
|
|
88
|
-
await server.connect(transport);
|
|
89
|
-
await transport.handleRequest(req, res, req.body);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
res.status(400).json({
|
|
93
|
-
jsonrpc: "2.0",
|
|
94
|
-
error: { code: -32000, message: "Bad Request: No valid session ID provided" },
|
|
95
|
-
id: null,
|
|
96
|
-
});
|
|
97
|
-
});
|
|
171
|
+
await handleMcpPost(req, res, apiKey);
|
|
98
172
|
});
|
|
99
|
-
// GET /mcp — SSE stream (server-to-client notifications)
|
|
100
173
|
app.get("/mcp", async (req, res) => {
|
|
101
174
|
const apiKey = requireApiKey(req, res);
|
|
102
175
|
if (!apiKey)
|
|
103
176
|
return;
|
|
104
|
-
|
|
105
|
-
const entry = getSession(sessionId);
|
|
106
|
-
if (!sessionId || !entry) {
|
|
107
|
-
res.status(400).json({ error: "Invalid or missing session ID" });
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
await entry.transport.handleRequest(req, res);
|
|
177
|
+
await handleMcpGet(req, res);
|
|
111
178
|
});
|
|
112
|
-
// DELETE /mcp — End session
|
|
113
179
|
app.delete("/mcp", async (req, res) => {
|
|
114
180
|
const apiKey = requireApiKey(req, res);
|
|
115
181
|
if (!apiKey)
|
|
116
182
|
return;
|
|
117
|
-
|
|
118
|
-
const entry = getSession(sessionId);
|
|
119
|
-
if (!sessionId || !entry) {
|
|
120
|
-
res.status(400).json({ error: "Invalid or missing session ID" });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
await entry.transport.handleRequest(req, res);
|
|
183
|
+
await handleMcpDelete(req, res);
|
|
124
184
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
185
|
+
}
|
|
186
|
+
// --- OAuth mode (JWT + backward-compat plain API keys) ---
|
|
187
|
+
async function mountOAuth(app) {
|
|
188
|
+
const { mcpAuthRouter } = await import("@modelcontextprotocol/sdk/server/auth/router.js");
|
|
189
|
+
const { requireBearerAuth } = await import("@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js");
|
|
190
|
+
const { ByCrawlOAuthProvider } = await import("./oauth/provider.js");
|
|
191
|
+
const { oauthCallbackHandler } = await import("./oauth/callback.js");
|
|
192
|
+
const EXTERNAL_URL = process.env.EXTERNAL_URL;
|
|
193
|
+
const provider = new ByCrawlOAuthProvider();
|
|
194
|
+
const issuerUrl = new URL(EXTERNAL_URL);
|
|
195
|
+
const resourceServerUrl = new URL("/mcp", EXTERNAL_URL);
|
|
196
|
+
const resourceMetadataUrl = `${EXTERNAL_URL}/.well-known/oauth-protected-resource/mcp`;
|
|
197
|
+
// Mount OAuth endpoints (authorize, token, register, revoke, metadata)
|
|
198
|
+
app.use(mcpAuthRouter({
|
|
199
|
+
provider,
|
|
200
|
+
issuerUrl,
|
|
201
|
+
resourceServerUrl,
|
|
202
|
+
resourceName: "ByCrawl MCP",
|
|
203
|
+
}));
|
|
204
|
+
// Supabase Auth callback (after Google login)
|
|
205
|
+
app.get("/oauth/callback/:nonce", oauthCallbackHandler);
|
|
206
|
+
// Bearer auth middleware for /mcp routes
|
|
207
|
+
const bearerAuth = requireBearerAuth({ verifier: provider, resourceMetadataUrl });
|
|
208
|
+
app.post("/mcp", bearerAuth, async (req, res) => {
|
|
209
|
+
console.log(`[OAuth /mcp POST] auth.clientId=${req.auth?.clientId} auth.extra=${JSON.stringify(req.auth?.extra)}`);
|
|
210
|
+
const apiKey = req.auth.extra.apiKey;
|
|
211
|
+
await handleMcpPost(req, res, apiKey);
|
|
128
212
|
});
|
|
129
|
-
app.
|
|
130
|
-
console.log(`
|
|
213
|
+
app.get("/mcp", bearerAuth, async (req, res) => {
|
|
214
|
+
console.log(`[OAuth /mcp GET] auth.clientId=${req.auth?.clientId}`);
|
|
215
|
+
await handleMcpGet(req, res);
|
|
131
216
|
});
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
for (const sid of Object.keys(sessions)) {
|
|
136
|
-
await sessions[sid].transport.close().catch(() => { });
|
|
137
|
-
delete sessions[sid];
|
|
138
|
-
}
|
|
139
|
-
process.exit(0);
|
|
217
|
+
app.delete("/mcp", bearerAuth, async (req, res) => {
|
|
218
|
+
console.log(`[OAuth /mcp DELETE] auth.clientId=${req.auth?.clientId}`);
|
|
219
|
+
await handleMcpDelete(req, res);
|
|
140
220
|
});
|
|
141
221
|
}
|
|
142
222
|
//# sourceMappingURL=transport-http.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-http.js","sourceRoot":"","sources":["../src/transport-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"transport-http.js","sourceRoot":"","sources":["../src/transport-http.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bycrawl/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for ByCrawl — query 9+ social media platforms (Threads, X, Facebook, Reddit, LinkedIn,
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "MCP server for ByCrawl — query 9+ social media platforms (Threads, X, Facebook, Reddit, LinkedIn, TikTok, Instagram, YouTube) from AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"bycrawl-mcp": "./build/index.js"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"test": "vitest run",
|
|
19
19
|
"test:smoke": "vitest run tests/smoke.test.ts",
|
|
20
20
|
"test:smoke-http": "vitest run tests/smoke-http.test.ts",
|
|
21
|
-
"test:unit": "vitest run tests/client.unit.test.ts",
|
|
21
|
+
"test:unit": "vitest run tests/client.unit.test.ts tests/oauth.unit.test.ts",
|
|
22
22
|
"test:integration": "vitest run tests/platforms/",
|
|
23
23
|
"test:integration:slow": "INCLUDE_SLOW=true vitest run tests/platforms/",
|
|
24
24
|
"test:watch": "vitest"
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"facebook",
|
|
33
33
|
"reddit",
|
|
34
34
|
"linkedin",
|
|
35
|
-
|
|
36
|
-
"tiktok",
|
|
35
|
+
"tiktok",
|
|
37
36
|
"instagram",
|
|
38
37
|
"ai",
|
|
39
38
|
"claude",
|
|
@@ -46,8 +45,9 @@
|
|
|
46
45
|
"homepage": "https://bycrawl.com",
|
|
47
46
|
"license": "MIT",
|
|
48
47
|
"dependencies": {
|
|
49
|
-
"@modelcontextprotocol/sdk": "
|
|
48
|
+
"@modelcontextprotocol/sdk": ">=1.12.1 <2.0.0",
|
|
50
49
|
"express": "^5.1.0",
|
|
50
|
+
"jose": "^6.0.0",
|
|
51
51
|
"zod": "^3.24.2"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { bycrawlGet } from "../client.js";
|
|
3
|
-
export function registerXiaohongshuTools(server) {
|
|
4
|
-
server.tool("xiaohongshu_search_notes", "Search Xiaohongshu (RED) notes by keyword", {
|
|
5
|
-
keyword: z.string().describe("Search keyword"),
|
|
6
|
-
page: z.number().optional().describe("Page number (starts at 1)"),
|
|
7
|
-
sort: z.enum(["general", "time_descending", "popularity_descending"]).optional().describe("Sort order"),
|
|
8
|
-
}, async ({ keyword, page, sort }) => bycrawlGet("/xiaohongshu/notes/search", { keyword, page, sort }));
|
|
9
|
-
server.tool("xiaohongshu_get_note", "Get a Xiaohongshu note (post) by ID", { noteId: z.string().describe("Xiaohongshu note ID") }, async ({ noteId }) => bycrawlGet(`/xiaohongshu/notes/${noteId}`));
|
|
10
|
-
server.tool("xiaohongshu_get_note_comments", "Get comments on a Xiaohongshu note", {
|
|
11
|
-
noteId: z.string().describe("Xiaohongshu note ID"),
|
|
12
|
-
cursor: z.string().optional().describe("Pagination cursor"),
|
|
13
|
-
}, async ({ noteId, cursor }) => bycrawlGet(`/xiaohongshu/notes/${noteId}/comments`, { cursor }));
|
|
14
|
-
server.tool("xiaohongshu_get_comment_replies", "Get replies (sub-comments) for a specific comment on a Xiaohongshu note", {
|
|
15
|
-
noteId: z.string().describe("Xiaohongshu note ID"),
|
|
16
|
-
commentId: z.string().describe("Parent comment ID"),
|
|
17
|
-
cursor: z.string().optional().describe("Pagination cursor"),
|
|
18
|
-
}, async ({ noteId, commentId, cursor }) => bycrawlGet(`/xiaohongshu/notes/${noteId}/comments/${commentId}/replies`, { cursor }));
|
|
19
|
-
server.tool("xiaohongshu_search_users", "Search Xiaohongshu users by keyword", {
|
|
20
|
-
keyword: z.string().describe("Search keyword"),
|
|
21
|
-
page: z.number().optional().describe("Page number (starts at 1)"),
|
|
22
|
-
}, async ({ keyword, page }) => bycrawlGet("/xiaohongshu/users/search", { keyword, page }));
|
|
23
|
-
server.tool("xiaohongshu_get_user", "Get a Xiaohongshu user profile by ID", { userId: z.string().describe("Xiaohongshu user ID") }, async ({ userId }) => bycrawlGet(`/xiaohongshu/users/${userId}`));
|
|
24
|
-
server.tool("xiaohongshu_get_user_notes", "Get notes posted by a Xiaohongshu user", {
|
|
25
|
-
userId: z.string().describe("Xiaohongshu user ID"),
|
|
26
|
-
cursor: z.string().optional().describe("Pagination cursor"),
|
|
27
|
-
}, async ({ userId, cursor }) => bycrawlGet(`/xiaohongshu/users/${userId}/notes`, { cursor }));
|
|
28
|
-
server.tool("xiaohongshu_get_feed", "Get Xiaohongshu discovery feed", { cursor: z.string().optional().describe("Pagination cursor") }, async ({ cursor }) => bycrawlGet("/xiaohongshu/feed", { cursor }));
|
|
29
|
-
server.tool("xiaohongshu_resolve_share_url", "Resolve a Xiaohongshu share URL to get note/user data", { url: z.string().describe("Xiaohongshu share URL") }, async ({ url }) => bycrawlGet("/xiaohongshu/share/resolve", { url }));
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=xiaohongshu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"xiaohongshu.js","sourceRoot":"","sources":["../../src/tools/xiaohongshu.ts"],"names":[],"mappings":"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"}
|