@bycrawl/mcp 0.1.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 ADDED
@@ -0,0 +1,66 @@
1
+ # @bycrawl/mcp
2
+
3
+ MCP server for [ByCrawl](https://bycrawl.com) — query 8 social media platforms from AI agents like Claude and Cursor.
4
+
5
+ **Supported platforms:** Threads, X/Twitter, Facebook, Reddit, LinkedIn, Xiaohongshu (RED), TikTok, Instagram
6
+
7
+ ## Setup
8
+
9
+ ### Claude Code
10
+
11
+ ```bash
12
+ claude mcp add bycrawl -- npx -y @bycrawl/mcp
13
+ ```
14
+
15
+ Then set your API key:
16
+
17
+ ```bash
18
+ claude mcp add bycrawl -e BYCRAWL_API_KEY=sk_byc_xxx -- npx -y @bycrawl/mcp
19
+ ```
20
+
21
+ ### Claude Desktop / Cursor
22
+
23
+ Add to your MCP config:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "bycrawl": {
29
+ "command": "npx",
30
+ "args": ["-y", "@bycrawl/mcp"],
31
+ "env": {
32
+ "BYCRAWL_API_KEY": "sk_byc_xxx"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ## Tools (41)
40
+
41
+ | Platform | Tools | Examples |
42
+ |----------|-------|---------|
43
+ | Threads | 7 | Search posts, get user profile, public feed |
44
+ | X/Twitter | 4 | Search tweets, get user timeline |
45
+ | Facebook | 4 | Get page, search posts, get post by URL |
46
+ | Reddit | 5 | Get subreddit, search posts, get user |
47
+ | LinkedIn | 6 | Get company, search jobs, get post |
48
+ | Xiaohongshu | 9 | Search notes, get comments, resolve share URL |
49
+ | TikTok | 4 | Get video, browse by category |
50
+ | Instagram | 1 | Search hashtags |
51
+ | System | 1 | Health check |
52
+
53
+ ## API Key
54
+
55
+ Get your API key at [bycrawl.com](https://bycrawl.com).
56
+
57
+ ## Environment Variables
58
+
59
+ | Variable | Required | Default | Description |
60
+ |----------|----------|---------|-------------|
61
+ | `BYCRAWL_API_KEY` | Yes | — | Your ByCrawl API key |
62
+ | `BYCRAWL_API_URL` | No | `https://api.bycrawl.com` | API base URL (for self-hosting) |
63
+
64
+ ## License
65
+
66
+ MIT
@@ -0,0 +1,8 @@
1
+ type McpContent = {
2
+ content: Array<{
3
+ type: "text";
4
+ text: string;
5
+ }>;
6
+ };
7
+ export declare function bycrawlGet(path: string, params?: Record<string, string | number | boolean | undefined | null>): Promise<McpContent>;
8
+ export {};
@@ -0,0 +1,24 @@
1
+ const API_URL = process.env.BYCRAWL_API_URL ?? "https://api.bycrawl.com";
2
+ const API_KEY = process.env.BYCRAWL_API_KEY ?? "";
3
+ export async function bycrawlGet(path, params) {
4
+ try {
5
+ const url = new URL(path, API_URL);
6
+ if (params) {
7
+ for (const [k, v] of Object.entries(params)) {
8
+ if (v != null && v !== "")
9
+ url.searchParams.set(k, String(v));
10
+ }
11
+ }
12
+ const res = await fetch(url, {
13
+ headers: { "x-api-key": API_KEY },
14
+ signal: AbortSignal.timeout(120_000),
15
+ });
16
+ const body = await res.text();
17
+ return { content: [{ type: "text", text: body }] };
18
+ }
19
+ catch (err) {
20
+ const message = err instanceof Error ? err.message : String(err);
21
+ return { content: [{ type: "text", text: JSON.stringify({ error: message }) }] };
22
+ }
23
+ }
24
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,yBAAyB,CAAC;AACzE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;AAIlD,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,MAAqE;IAErE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;oBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE;YACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;SACrC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { registerThreadsTools } from "./tools/threads.js";
5
+ import { registerXTools } from "./tools/x.js";
6
+ import { registerFacebookTools } from "./tools/facebook.js";
7
+ import { registerRedditTools } from "./tools/reddit.js";
8
+ import { registerLinkedinTools } from "./tools/linkedin.js";
9
+ import { registerXiaohongshuTools } from "./tools/xiaohongshu.js";
10
+ import { registerTiktokTools } from "./tools/tiktok.js";
11
+ import { registerInstagramTools } from "./tools/instagram.js";
12
+ import { registerSystemTools } from "./tools/system.js";
13
+ const server = new McpServer({
14
+ name: "bycrawl",
15
+ version: "0.1.0",
16
+ });
17
+ registerThreadsTools(server);
18
+ registerXTools(server);
19
+ registerFacebookTools(server);
20
+ registerRedditTools(server);
21
+ registerLinkedinTools(server);
22
+ registerXiaohongshuTools(server);
23
+ registerTiktokTools(server);
24
+ registerInstagramTools(server);
25
+ registerSystemTools(server);
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ console.error("ByCrawl MCP server running on stdio");
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,cAAc,CAAC,MAAM,CAAC,CAAC;AACvB,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC/B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerFacebookTools(server: McpServer): void;
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerFacebookTools(server) {
4
+ server.tool("facebook_get_page", "Get Facebook page profile by username", { username: z.string().describe("Facebook page username") }, async ({ username }) => bycrawlGet(`/facebook/users/${username}`));
5
+ server.tool("facebook_get_page_posts", "Get Facebook page posts by username", { username: z.string().describe("Facebook page username") }, async ({ username }) => bycrawlGet(`/facebook/users/${username}/posts`));
6
+ server.tool("facebook_get_post", "Get a Facebook post by URL (supports posts, reels, videos, share links)", { url: z.string().describe("Facebook post URL") }, async ({ url }) => bycrawlGet("/facebook/posts", { url }));
7
+ server.tool("facebook_search_posts", "Search public Facebook posts by keyword", {
8
+ query: z.string().describe("Search keyword"),
9
+ count: z.number().optional().describe("Number of results (max 5)"),
10
+ cursor: z.string().optional().describe("Pagination cursor"),
11
+ }, async ({ query, count, cursor }) => bycrawlGet("/facebook/posts/search", { q: query, count, cursor }));
12
+ }
13
+ //# sourceMappingURL=facebook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facebook.js","sourceRoot":"","sources":["../../src/tools/facebook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,uCAAuC,EACvC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,EAC3D,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAClE,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,qCAAqC,EACrC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,EAC3D,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,mBAAmB,QAAQ,QAAQ,CAAC,CACxE,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,yEAAyE,EACzE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,EACjD,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,CAAC,CAC1D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,yCAAyC,EACzC;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAClE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KAC5D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,wBAAwB,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACtG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerInstagramTools(server: McpServer): void;
@@ -0,0 +1,6 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerInstagramTools(server) {
4
+ server.tool("instagram_search_tags", "Search Instagram hashtags by keyword", { query: z.string().describe("Hashtag to search") }, async ({ query }) => bycrawlGet("/instagram/tags/search", { q: query }));
5
+ }
6
+ //# sourceMappingURL=instagram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instagram.js","sourceRoot":"","sources":["../../src/tools/instagram.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,sCAAsC,EACtC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,EACnD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,wBAAwB,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CACxE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerLinkedinTools(server: McpServer): void;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerLinkedinTools(server) {
4
+ server.tool("linkedin_get_company", "Get LinkedIn company profile", { companyId: z.string().describe("Company ID or vanity name (e.g. 'microsoft')") }, async ({ companyId }) => bycrawlGet(`/linkedin/companies/${companyId}`));
5
+ server.tool("linkedin_get_company_jobs", "Get job listings for a LinkedIn company", {
6
+ companyId: z.string().describe("Company ID or vanity name"),
7
+ count: z.number().optional().describe("Number of jobs (max 100)"),
8
+ offset: z.number().optional().describe("Pagination offset"),
9
+ }, async ({ companyId, count, offset }) => bycrawlGet(`/linkedin/companies/${companyId}/jobs`, { count, offset }));
10
+ server.tool("linkedin_search_jobs", "Search LinkedIn job listings by keyword", {
11
+ query: z.string().describe("Search keywords (e.g. 'software engineer')"),
12
+ location: z.string().optional().describe("Location filter (e.g. 'San Francisco')"),
13
+ count: z.number().optional().describe("Number of results (max 100)"),
14
+ offset: z.number().optional().describe("Pagination offset"),
15
+ }, async ({ query, location, count, offset }) => bycrawlGet("/linkedin/jobs/search", { query, location, count, offset }));
16
+ server.tool("linkedin_get_job", "Get a LinkedIn job posting by ID", { jobId: z.string().describe("LinkedIn job ID") }, async ({ jobId }) => bycrawlGet(`/linkedin/jobs/${jobId}`));
17
+ server.tool("linkedin_get_post", "Get a LinkedIn post by ID", { postId: z.string().describe("LinkedIn post or article ID") }, async ({ postId }) => bycrawlGet(`/linkedin/posts/${postId}`));
18
+ server.tool("linkedin_get_user", "Get LinkedIn user profile by username", { username: z.string().describe("LinkedIn username or profile URL slug") }, async ({ username }) => bycrawlGet(`/linkedin/users/${username}`));
19
+ }
20
+ //# sourceMappingURL=linkedin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linkedin.js","sourceRoot":"","sources":["../../src/tools/linkedin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,8BAA8B,EAC9B,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC,EAAE,EAClF,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,uBAAuB,SAAS,EAAE,CAAC,CACxE,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,2BAA2B,EAC3B,yCAAyC,EACzC;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QACjE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KAC5D,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,uBAAuB,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAC/G,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,yCAAyC,EACzC;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACxE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QAClF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACpE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KAC5D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACtH,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,kCAAkC,EAClC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EACjD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAC3D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,2BAA2B,EAC3B,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,EAC9D,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAC9D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,uCAAuC,EACvC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC,EAAE,EAC1E,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAClE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRedditTools(server: McpServer): void;
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerRedditTools(server) {
4
+ server.tool("reddit_get_subreddit", "Get subreddit info by name", { name: z.string().describe("Subreddit name (without r/)") }, async ({ name }) => bycrawlGet(`/reddit/subreddits/${name}`));
5
+ server.tool("reddit_get_subreddit_posts", "Get posts from a subreddit", {
6
+ name: z.string().describe("Subreddit name (without r/)"),
7
+ sort: z.enum(["hot", "new", "top", "rising"]).optional().describe("Sort order"),
8
+ count: z.number().optional().describe("Number of posts (max 100)"),
9
+ }, async ({ name, sort, count }) => bycrawlGet(`/reddit/subreddits/${name}/posts`, { sort, count }));
10
+ server.tool("reddit_search_posts", "Search Reddit posts by keyword", {
11
+ query: z.string().describe("Search query"),
12
+ sort: z.enum(["relevance", "hot", "top", "new", "comments"]).optional().describe("Sort order"),
13
+ count: z.number().optional().describe("Number of results (max 100)"),
14
+ }, async ({ query, sort, count }) => bycrawlGet("/reddit/posts/search", { q: query, sort, count }));
15
+ server.tool("reddit_get_post", "Get a Reddit post by ID", { postId: z.string().describe("Reddit post ID") }, async ({ postId }) => bycrawlGet(`/reddit/posts/${postId}`));
16
+ server.tool("reddit_get_user", "Get Reddit user profile by username", { username: z.string().describe("Reddit username") }, async ({ username }) => bycrawlGet(`/reddit/users/${username}`));
17
+ }
18
+ //# sourceMappingURL=reddit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit.js","sourceRoot":"","sources":["../../src/tools/reddit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,4BAA4B,EAC5B,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,EAC5D,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAC7D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,4BAA4B,EAC5B,4BAA4B,EAC5B;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACxD,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC/E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACnE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,sBAAsB,IAAI,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CACjG,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,gCAAgC,EAChC;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC1C,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;KACrE,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,sBAAsB,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAChG,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,yBAAyB,EACzB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EACjD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAC5D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,qCAAqC,EACrC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EACpD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAChE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerSystemTools(server: McpServer): void;
@@ -0,0 +1,5 @@
1
+ import { bycrawlGet } from "../client.js";
2
+ export function registerSystemTools(server) {
3
+ server.tool("bycrawl_health", "Check ByCrawl API health status", {}, async () => bycrawlGet("/health"));
4
+ }
5
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/tools/system.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,iCAAiC,EACjC,EAAE,EACF,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerThreadsTools(server: McpServer): void;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerThreadsTools(server) {
4
+ server.tool("threads_search_posts", "Search Threads posts by keyword", { query: z.string().describe("Search keyword"), count: z.number().optional().describe("Number of results (max 25)") }, async ({ query, count }) => bycrawlGet("/threads/posts/search", { q: query, count }));
5
+ server.tool("threads_get_post", "Get a single Threads post by ID or shortcode", { postId: z.string().describe("Post ID or shortcode"), mode: z.enum(["full"]).optional().describe("Use 'full' for view counts") }, async ({ postId, mode }) => bycrawlGet(`/threads/posts/${postId}`, { mode }));
6
+ server.tool("threads_get_posts_batch", "Get multiple Threads posts by IDs (batch)", { ids: z.string().describe("Comma-separated post IDs or shortcodes"), mode: z.enum(["full"]).optional().describe("Use 'full' for view counts") }, async ({ ids, mode }) => bycrawlGet("/threads/posts", { ids, mode }));
7
+ server.tool("threads_search_users", "Search Threads users by username or name", { query: z.string().describe("Search query"), count: z.number().optional().describe("Number of results (max 25)") }, async ({ query, count }) => bycrawlGet("/threads/users/search", { q: query, count }));
8
+ server.tool("threads_get_user", "Get a Threads user profile by username", { username: z.string().describe("Username") }, async ({ username }) => bycrawlGet(`/threads/users/${username}`));
9
+ server.tool("threads_get_user_posts", "Get a Threads user's posts with pagination", {
10
+ userId: z.string().describe("Numeric user ID"),
11
+ cursor: z.string().optional().describe("Pagination cursor"),
12
+ count: z.number().optional().describe("Number of results"),
13
+ }, async ({ userId, cursor, count }) => bycrawlGet(`/threads/users/${userId}/posts`, { cursor, count }));
14
+ server.tool("threads_get_public_feed", "Get Threads public For You feed", {
15
+ cursor: z.string().optional().describe("Pagination cursor"),
16
+ count: z.number().optional().describe("Number of items"),
17
+ country: z.string().optional().describe("Country code (default: TW)"),
18
+ }, async ({ cursor, count, country }) => bycrawlGet("/threads/feed/public", { cursor, count, country }));
19
+ }
20
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/tools/threads.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerTiktokTools(server: McpServer): void;
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerTiktokTools(server) {
4
+ server.tool("tiktok_get_video", "Get TikTok video metadata by video ID", { videoId: z.string().describe("TikTok video ID") }, async ({ videoId }) => bycrawlGet(`/tiktok/videos/${videoId}`));
5
+ server.tool("tiktok_get_user", "Get TikTok user info and recent videos", {
6
+ username: z.string().describe("TikTok username"),
7
+ count: z.number().optional().describe("Number of recent videos (max 50)"),
8
+ }, async ({ username, count }) => bycrawlGet(`/tiktok/users/${username}`, { count }));
9
+ server.tool("tiktok_get_user_videos", "Get TikTok user's video list", {
10
+ username: z.string().describe("TikTok username"),
11
+ count: z.number().optional().describe("Number of videos (max 50)"),
12
+ }, async ({ username, count }) => bycrawlGet(`/tiktok/users/${username}/videos`, { count }));
13
+ server.tool("tiktok_get_category_videos", "Browse TikTok videos by category", {
14
+ category: z.string().optional().describe("Category name (e.g. Food, Dance, Comedy). Omit for trending"),
15
+ count: z.number().optional().describe("Number of videos (max 50)"),
16
+ }, async ({ category, count }) => bycrawlGet("/tiktok/categories", { category, count }));
17
+ }
18
+ //# sourceMappingURL=tiktok.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiktok.js","sourceRoot":"","sources":["../../src/tools/tiktok.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,uCAAuC,EACvC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EACnD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAC/D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,wCAAwC,EACxC;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;KAC1E,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAClF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,8BAA8B,EAC9B;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACnE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,QAAQ,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CACzF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,4BAA4B,EAC5B,kCAAkC,EAClC;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;QACvG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACnE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CACrF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerXTools(server: McpServer): void;
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import { bycrawlGet } from "../client.js";
3
+ export function registerXTools(server) {
4
+ server.tool("x_get_user", "Get X/Twitter user profile by username", { username: z.string().describe("X username") }, async ({ username }) => bycrawlGet(`/x/users/${username}`));
5
+ server.tool("x_get_user_posts", "Get X/Twitter user's timeline tweets", {
6
+ username: z.string().describe("X username"),
7
+ count: z.number().optional().describe("Number of tweets (max 40)"),
8
+ cursor: z.string().optional().describe("Pagination cursor"),
9
+ }, async ({ username, count, cursor }) => bycrawlGet(`/x/users/${username}/posts`, { count, cursor }));
10
+ server.tool("x_get_post", "Get a single X/Twitter post (tweet) by ID", { postId: z.string().describe("Tweet ID") }, async ({ postId }) => bycrawlGet(`/x/posts/${postId}`));
11
+ server.tool("x_search_posts", "Search X/Twitter posts by keyword", {
12
+ query: z.string().describe("Search query"),
13
+ count: z.number().optional().describe("Number of tweets (10-100)"),
14
+ cursor: z.string().optional().describe("Pagination cursor"),
15
+ product: z.enum(["Top", "Latest"]).optional().describe("Search tab: Top or Latest"),
16
+ }, async ({ query, count, cursor, product }) => bycrawlGet("/x/posts/search", { q: query, count, cursor, product }));
17
+ }
18
+ //# sourceMappingURL=x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x.js","sourceRoot":"","sources":["../../src/tools/x.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,cAAc,CAAC,MAAiB;IAC9C,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,wCAAwC,EACxC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,EAC/C,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,QAAQ,EAAE,CAAC,CAC3D,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,sCAAsC,EACtC;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC3C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAClE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KAC5D,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,QAAQ,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACnG,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,2CAA2C,EAC3C,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,EAC3C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,MAAM,EAAE,CAAC,CACvD,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,mCAAmC,EACnC;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAClE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAC3D,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACpF,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,iBAAiB,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CACjH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerXiaohongshuTools(server: McpServer): void;
@@ -0,0 +1,31 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xiaohongshu.js","sourceRoot":"","sources":["../../src/tools/xiaohongshu.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@bycrawl/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for ByCrawl — query 8 social media platforms (Threads, X, Facebook, Reddit, LinkedIn, Xiaohongshu, TikTok, Instagram) from AI agents",
5
+ "type": "module",
6
+ "bin": {
7
+ "bycrawl-mcp": "./build/index.js"
8
+ },
9
+ "files": [
10
+ "build"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsx src/index.ts",
15
+ "test": "vitest run",
16
+ "test:smoke": "vitest run tests/smoke.test.ts",
17
+ "test:unit": "vitest run tests/client.unit.test.ts",
18
+ "test:integration": "vitest run tests/platforms/",
19
+ "test:integration:slow": "INCLUDE_SLOW=true vitest run tests/platforms/",
20
+ "test:watch": "vitest"
21
+ },
22
+ "keywords": [
23
+ "mcp",
24
+ "model-context-protocol",
25
+ "social-media",
26
+ "threads",
27
+ "twitter",
28
+ "facebook",
29
+ "reddit",
30
+ "linkedin",
31
+ "xiaohongshu",
32
+ "tiktok",
33
+ "instagram",
34
+ "ai",
35
+ "claude",
36
+ "cursor"
37
+ ],
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/SignalsurfAi/bycrawl-mcp"
41
+ },
42
+ "homepage": "https://bycrawl.com",
43
+ "license": "MIT",
44
+ "dependencies": {
45
+ "@modelcontextprotocol/sdk": "^1.12.1",
46
+ "zod": "^3.24.2"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.13.10",
50
+ "tsx": "^4.19.3",
51
+ "typescript": "^5.8.2",
52
+ "vitest": "^4.0.18"
53
+ },
54
+ "packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b"
55
+ }