@apify/actors-mcp-server 0.1.1-beta.0 → 0.1.1-beta.2

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.
Files changed (47) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +2 -0
  3. package/dist/actorDefinition.d.ts +14 -0
  4. package/dist/actorDefinition.d.ts.map +1 -0
  5. package/dist/actorDefinition.js +83 -0
  6. package/dist/actorDefinition.js.map +1 -0
  7. package/dist/const.d.ts +13 -0
  8. package/dist/const.d.ts.map +1 -0
  9. package/dist/const.js +19 -0
  10. package/dist/const.js.map +1 -0
  11. package/dist/examples/clientSse.d.ts +8 -0
  12. package/dist/examples/clientSse.d.ts.map +1 -0
  13. package/dist/examples/clientSse.js +80 -0
  14. package/dist/examples/clientSse.js.map +1 -0
  15. package/dist/examples/clientStdio.d.ts +8 -0
  16. package/dist/examples/clientStdio.d.ts.map +1 -0
  17. package/dist/examples/clientStdio.js +66 -0
  18. package/dist/examples/clientStdio.js.map +1 -0
  19. package/dist/examples/clientStdioChat.d.ts +23 -0
  20. package/dist/examples/clientStdioChat.d.ts.map +1 -0
  21. package/dist/examples/clientStdioChat.js +201 -0
  22. package/dist/examples/clientStdioChat.js.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +30 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/input.d.ts +8 -0
  28. package/dist/input.d.ts.map +1 -0
  29. package/dist/input.js +14 -0
  30. package/dist/input.js.map +1 -0
  31. package/dist/logger.d.ts +3 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +4 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/main.d.ts +2 -0
  36. package/dist/main.d.ts.map +1 -0
  37. package/dist/main.js +104 -0
  38. package/dist/main.js.map +1 -0
  39. package/dist/server.d.ts +31 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +129 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/types.d.ts +18 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +4 -2
@@ -0,0 +1,201 @@
1
+ /* eslint-disable no-console */
2
+ /**
3
+ * Create a simple chat client that connects to the Model Context Protocol server using the stdio transport.
4
+ * Based on the user input, the client sends a query to the MCP server, retrieves results and processes them.
5
+ *
6
+ * You can expect the following output:
7
+ *
8
+ * MCP Client Started!
9
+ * Type your queries or 'quit|q|exit' to exit.
10
+ * You: Find to articles about AI agent and return URLs
11
+ * [internal] Received response from Claude: [{"type":"text","text":"I'll search for information about AI agents
12
+ * and provide you with a summary."},{"type":"tool_use","id":"tool_01He9TkzQfh2979bbeuxWVqM","name":"search",
13
+ * "input":{"query":"what are AI agents definition capabilities applications","maxResults":2}}]
14
+ * [internal] Calling tool: {"name":"search","arguments":{"query":"what are AI agents definition ...
15
+ * I can help analyze the provided content about AI agents.
16
+ * This appears to be crawled content from AWS and IBM websites explaining what AI agents are.
17
+ * Let me summarize the key points:
18
+ */
19
+ import { execSync } from 'child_process';
20
+ import path from 'path';
21
+ import * as readline from 'readline';
22
+ import { fileURLToPath } from 'url';
23
+ import { Anthropic } from '@anthropic-ai/sdk';
24
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
25
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
26
+ import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
27
+ import dotenv from 'dotenv';
28
+ const filename = fileURLToPath(import.meta.url);
29
+ const dirname = path.dirname(filename);
30
+ dotenv.config({ path: path.resolve(dirname, '../../.env') });
31
+ const REQUEST_TIMEOUT = 120_000; // 2 minutes
32
+ const MAX_TOKENS = 2048; // Maximum tokens for Claude response
33
+ // const CLAUDE_MODEL = 'claude-3-5-sonnet-20241022'; // the most intelligent model
34
+ // const CLAUDE_MODEL = 'claude-3-5-haiku-20241022'; // a fastest model
35
+ const CLAUDE_MODEL = 'claude-3-haiku-20240307'; // a fastest and most compact model for near-instant responsiveness
36
+ const DEBUG = true;
37
+ const DEBUG_SERVER_PATH = path.resolve(dirname, '../../dist/index.js');
38
+ const NODE_PATH = execSync('which node').toString().trim();
39
+ dotenv.config(); // Load environment variables from .env
40
+ class MCPClient {
41
+ anthropic;
42
+ client = new Client({
43
+ name: 'example-client',
44
+ version: '0.1.0',
45
+ }, {
46
+ capabilities: {}, // Optional capabilities
47
+ });
48
+ tools = [];
49
+ constructor() {
50
+ this.anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
51
+ }
52
+ /**
53
+ * Start the server using node and provided server script path.
54
+ * Connect to the server using stdio transport and list available tools.
55
+ */
56
+ async connectToServer(serverArgs) {
57
+ const transport = new StdioClientTransport({
58
+ command: NODE_PATH,
59
+ args: serverArgs,
60
+ env: { APIFY_TOKEN: process.env.APIFY_TOKEN || '' },
61
+ });
62
+ await this.client.connect(transport);
63
+ const response = await this.client.listTools();
64
+ this.tools = response.tools.map((x) => ({
65
+ name: x.name,
66
+ description: x.description,
67
+ input_schema: x.inputSchema,
68
+ }));
69
+ console.log('Connected to server with tools:', this.tools.map((x) => x.name));
70
+ }
71
+ /**
72
+ * Process LLM response and check whether it contains any tool calls.
73
+ * If a tool call is found, call the tool and return the response and save the results to messages with type: user.
74
+ * If the tools response is too large, truncate it to the limit.
75
+ */
76
+ async processMsg(response, messages) {
77
+ for (const content of response.content) {
78
+ if (content.type === 'text') {
79
+ messages.push({ role: 'assistant', content: content.text });
80
+ }
81
+ else if (content.type === 'tool_use') {
82
+ await this.handleToolCall(content, messages);
83
+ }
84
+ }
85
+ return messages;
86
+ }
87
+ /**
88
+ * Call the tool and return the response.
89
+ */
90
+ async handleToolCall(content, messages, toolCallCount = 0) {
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ const params = { name: content.name, arguments: content.input };
93
+ console.log(`[internal] Calling tool (count: ${toolCallCount}): ${JSON.stringify(params)}`);
94
+ let results;
95
+ try {
96
+ results = await this.client.callTool(params, CallToolResultSchema, { timeout: REQUEST_TIMEOUT });
97
+ if (results.content instanceof Array && results.content.length !== 0) {
98
+ const text = results.content.map((x) => x.text);
99
+ messages.push({ role: 'user', content: `Tool result: ${text.join('\n\n')}` });
100
+ }
101
+ else {
102
+ messages.push({ role: 'user', content: `No results retrieved from ${params.name}` });
103
+ }
104
+ }
105
+ catch (error) {
106
+ messages.push({ role: 'user', content: `Error calling tool: ${params.name}, error: ${error}` });
107
+ }
108
+ // Get next response from Claude
109
+ const nextResponse = await this.anthropic.messages.create({
110
+ model: CLAUDE_MODEL,
111
+ max_tokens: MAX_TOKENS,
112
+ messages,
113
+ tools: this.tools, // eslint-disable-line @typescript-eslint/no-explicit-any
114
+ });
115
+ for (const c of nextResponse.content) {
116
+ if (c.type === 'text') {
117
+ messages.push({ role: 'assistant', content: c.text });
118
+ }
119
+ else if (c.type === 'tool_use' && toolCallCount < 3) {
120
+ return await this.handleToolCall(c, messages, toolCallCount + 1);
121
+ }
122
+ }
123
+ return messages;
124
+ }
125
+ /**
126
+ * Process user query by sending it to the server and returning the response.
127
+ * Also, process any tool calls.
128
+ */
129
+ async processQuery(query, messages) {
130
+ messages.push({ role: 'user', content: query });
131
+ const response = await this.anthropic.messages.create({
132
+ model: CLAUDE_MODEL,
133
+ max_tokens: MAX_TOKENS,
134
+ messages,
135
+ tools: this.tools, // eslint-disable-line @typescript-eslint/no-explicit-any
136
+ });
137
+ console.log('[internal] Received response from Claude:', JSON.stringify(response.content));
138
+ return await this.processMsg(response, messages);
139
+ }
140
+ /**
141
+ * Create a chat loop that reads user input from the console and sends it to the server for processing.
142
+ */
143
+ async chatLoop() {
144
+ const rl = readline.createInterface({
145
+ input: process.stdin,
146
+ output: process.stdout,
147
+ prompt: 'You: ',
148
+ });
149
+ console.log("MCP Client Started!\nType your queries or 'quit|q|exit' to exit.");
150
+ rl.prompt();
151
+ let lastPrintMessage = 0;
152
+ const messages = [];
153
+ rl.on('line', async (input) => {
154
+ const v = input.trim().toLowerCase();
155
+ if (v === 'quit' || v === 'q' || v === 'exit') {
156
+ rl.close();
157
+ return;
158
+ }
159
+ try {
160
+ await this.processQuery(input, messages);
161
+ for (let i = lastPrintMessage + 1; i < messages.length; i++) {
162
+ if (messages[i].role === 'assistant') {
163
+ console.log('CLAUDE:', messages[i].content);
164
+ }
165
+ else if (messages[i].role === 'user') {
166
+ console.log('USER:', messages[i].content.slice(0, 500), '...');
167
+ }
168
+ else {
169
+ console.log('CLAUDE[thinking]:', messages[i].content);
170
+ }
171
+ }
172
+ lastPrintMessage += messages.length;
173
+ }
174
+ catch (error) {
175
+ console.error('Error processing query:', error);
176
+ }
177
+ rl.prompt();
178
+ });
179
+ }
180
+ }
181
+ async function main() {
182
+ const client = new MCPClient();
183
+ if (process.argv.length < 3) {
184
+ if (DEBUG) {
185
+ process.argv.push(DEBUG_SERVER_PATH);
186
+ }
187
+ else {
188
+ console.error('Usage: node <path_to_server_script>');
189
+ process.exit(1);
190
+ }
191
+ }
192
+ try {
193
+ await client.connectToServer(process.argv.slice(2));
194
+ await client.chatLoop();
195
+ }
196
+ catch (error) {
197
+ console.error('Error:', error);
198
+ }
199
+ }
200
+ main().catch(console.error);
201
+ //# sourceMappingURL=clientStdioChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientStdioChat.js","sourceRoot":"","sources":["../../src/examples/clientStdioChat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * This script initializes and starts the Apify MCP server using the Stdio transport.
3
+ *
4
+ * Usage:
5
+ * node <script_name> --actors=<actor1,actor2,...>
6
+ *
7
+ * Command-line arguments:
8
+ * --actors - A comma-separated list of actor full names to add to the server.
9
+ *
10
+ * Example:
11
+ * node index.js --actors=apify/google-search-scraper,apify/instagram-scraper
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * This script initializes and starts the Apify MCP server using the Stdio transport.
3
+ *
4
+ * Usage:
5
+ * node <script_name> --actors=<actor1,actor2,...>
6
+ *
7
+ * Command-line arguments:
8
+ * --actors - A comma-separated list of actor full names to add to the server.
9
+ *
10
+ * Example:
11
+ * node index.js --actors=apify/google-search-scraper,apify/instagram-scraper
12
+ */
13
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
+ import minimist from 'minimist';
15
+ import { ApifyMcpServer } from './server.js';
16
+ const argv = minimist(process.argv.slice(2));
17
+ const argActors = argv.actors?.split(',').map((actor) => actor.trim()) || [];
18
+ async function main() {
19
+ const server = new ApifyMcpServer();
20
+ await (argActors.length !== 0
21
+ ? server.addToolsFromActors(argActors)
22
+ : server.addToolsFromDefaultActors());
23
+ const transport = new StdioServerTransport();
24
+ await server.connect(transport);
25
+ }
26
+ main().catch((error) => {
27
+ console.error('Server error:', error); // eslint-disable-line no-console
28
+ process.exit(1);
29
+ });
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;AAErF,KAAK,UAAU,IAAI;IACf,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IACpC,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC;QACtC,CAAC,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,iCAAiC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Input } from './types.js';
2
+ /**
3
+ * Process input parameters, split actors string into an array
4
+ * @param originalInput
5
+ * @returns input
6
+ */
7
+ export declare function processInput(originalInput: Partial<Input>): Promise<Input>;
8
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAQhF"}
package/dist/input.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Process input parameters, split actors string into an array
3
+ * @param originalInput
4
+ * @returns input
5
+ */
6
+ export async function processInput(originalInput) {
7
+ const input = originalInput;
8
+ // actors can be a string or an array of strings
9
+ if (input.actors && typeof input.actors === 'string') {
10
+ input.actors = input.actors.split(',').map((format) => format.trim());
11
+ }
12
+ return input;
13
+ }
14
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,aAA6B;IAC5D,MAAM,KAAK,GAAG,aAAsB,CAAC;IAErC,gDAAgD;IAChD,IAAI,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnD,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAa,CAAC;IAC9F,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { log } from 'apify';
2
+ export { log };
3
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI5B,OAAO,EAAE,GAAG,EAAE,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,4 @@
1
+ import { log } from 'apify';
2
+ log.setLevel(log.LEVELS.DEBUG);
3
+ export { log };
4
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAE/B,OAAO,EAAE,GAAG,EAAE,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/dist/main.js ADDED
@@ -0,0 +1,104 @@
1
+ import { parse } from 'querystring';
2
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
3
+ import { Actor } from 'apify';
4
+ import express from 'express';
5
+ import { Routes } from './const.js';
6
+ import { processInput } from './input.js';
7
+ import { log } from './logger.js';
8
+ import { ApifyMcpServer } from './server.js';
9
+ await Actor.init();
10
+ const STANDBY_MODE = Actor.getEnv().metaOrigin === 'STANDBY';
11
+ const HOST = Actor.isAtHome() ? process.env.ACTOR_STANDBY_URL : 'http://localhost';
12
+ const PORT = Actor.isAtHome() ? process.env.ACTOR_STANDBY_PORT : 3001;
13
+ const app = express();
14
+ const mcpServer = new ApifyMcpServer();
15
+ let transport;
16
+ const HELP_MESSAGE = `Connect to the server with GET request to ${HOST}/sse?token=YOUR-APIFY-TOKEN`
17
+ + ` and then send POST requests to ${HOST}/message?token=YOUR-APIFY-TOKEN`;
18
+ /**
19
+ * Process input parameters and update tools
20
+ * If URL contains query parameter actors, add tools from actors, otherwise add tools from default actors
21
+ * @param url
22
+ */
23
+ async function processParamsAndUpdateTools(url) {
24
+ const params = parse(url.split('?')[1] || '');
25
+ delete params.token;
26
+ log.debug(`Received input parameters: ${JSON.stringify(params)}`);
27
+ const input = await processInput(params);
28
+ if (input.actors) {
29
+ await mcpServer.addToolsFromActors(input.actors);
30
+ }
31
+ else {
32
+ log.debug(`Server is running in STANDBY mode with the following Actors (tools): ${mcpServer.getToolNames()}.
33
+ To use different Actors, provide them in query parameter "actors" or include them in the Actor Task input.`);
34
+ }
35
+ }
36
+ app.route(Routes.ROOT)
37
+ .get(async (req, res) => {
38
+ try {
39
+ log.info(`Received GET message at: ${req.url}`);
40
+ await processParamsAndUpdateTools(req.url);
41
+ res.status(200).json({ message: `Actor is using Model Context Protocol. ${HELP_MESSAGE}` }).end();
42
+ }
43
+ catch (error) {
44
+ log.error(`Error in GET ${Routes.ROOT} ${error}`);
45
+ res.status(500).json({ message: 'Internal Server Error' }).end();
46
+ }
47
+ })
48
+ .head((_req, res) => {
49
+ res.status(200).end();
50
+ });
51
+ app.route(Routes.SSE)
52
+ .get(async (req, res) => {
53
+ try {
54
+ log.info(`Received GET message at: ${req.url}`);
55
+ await processParamsAndUpdateTools(req.url);
56
+ transport = new SSEServerTransport(Routes.MESSAGE, res);
57
+ await mcpServer.connect(transport);
58
+ }
59
+ catch (error) {
60
+ log.error(`Error in GET ${Routes.SSE}: ${error}`);
61
+ res.status(500).json({ message: 'Internal Server Error' }).end();
62
+ }
63
+ });
64
+ app.route(Routes.MESSAGE)
65
+ .post(async (req, res) => {
66
+ try {
67
+ log.info(`Received POST message at: ${req.url}`);
68
+ if (transport) {
69
+ await transport.handlePostMessage(req, res);
70
+ }
71
+ else {
72
+ res.status(400).json({
73
+ message: 'Server is not connected to the client. '
74
+ + 'Connect to the server with GET request to /sse endpoint',
75
+ });
76
+ }
77
+ }
78
+ catch (error) {
79
+ log.error(`Error in POST ${Routes.MESSAGE}: ${error}`);
80
+ res.status(500).json({ message: 'Internal Server Error' }).end();
81
+ }
82
+ });
83
+ // Catch-all for undefined routes
84
+ app.use((req, res) => {
85
+ res.status(404).json({ message: `There is nothing at route ${req.method} ${req.originalUrl}. ${HELP_MESSAGE}` }).end();
86
+ });
87
+ const input = await processInput((await Actor.getInput()) ?? {});
88
+ log.info(`Loaded input: ${JSON.stringify(input)} `);
89
+ if (STANDBY_MODE) {
90
+ log.info('Actor is running in the STANDBY mode.');
91
+ await mcpServer.addToolsFromDefaultActors();
92
+ app.listen(PORT, () => {
93
+ log.info(`The Actor web server is listening for user requests at ${HOST}`);
94
+ });
95
+ }
96
+ else {
97
+ log.info('Actor is not designed to run in the NORMAL model (use this mode only for debugging purposes)');
98
+ if (input && !input.debugActor && !input.debugActorInput) {
99
+ await Actor.fail('If you need to debug a specific actor, please provide the debugActor and debugActorInput fields in the input');
100
+ }
101
+ await mcpServer.callActorGetDataset(input.debugActor, input.debugActorInput);
102
+ await Actor.exit();
103
+ }
104
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ import type { Tool } from './types';
4
+ /**
5
+ * Create Apify MCP server
6
+ */
7
+ export declare class ApifyMcpServer {
8
+ private server;
9
+ private tools;
10
+ constructor();
11
+ /**
12
+ * Calls an Apify actor and retrieves the dataset items.
13
+ *
14
+ * It requires the `APIFY_TOKEN` environment variable to be set.
15
+ * If the `APIFY_IS_AT_HOME` the dataset items are pushed to the Apify dataset.
16
+ *
17
+ * @param {string} actorName - The name of the actor to call.
18
+ * @param {unknown} input - The input to pass to the actor.
19
+ * @returns {Promise<object[]>} - A promise that resolves to an array of dataset items.
20
+ * @throws {Error} - Throws an error if the `APIFY_TOKEN` is not set
21
+ */
22
+ callActorGetDataset(actorName: string, input: unknown): Promise<object[]>;
23
+ addToolsFromActors(actors: string[]): Promise<void>;
24
+ addToolsFromDefaultActors(): Promise<void>;
25
+ updateTools(tools: Tool[]): void;
26
+ getToolNames(): string[];
27
+ private setupErrorHandling;
28
+ private setupToolHandlers;
29
+ connect(transport: Transport): Promise<void>;
30
+ }
31
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAc/E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC;;GAEG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAoB;;IAmBjC;;;;;;;;;;OAUG;IACU,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBzE,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE;IAKnC,yBAAyB;IAI/B,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IAOhC,YAAY,IAAI,MAAM,EAAE;IAI/B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;IAuCnB,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAGrD"}
package/dist/server.js ADDED
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Model Context Protocol (MCP) server for Apify Actors
4
+ */
5
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
7
+ import { Actor } from 'apify';
8
+ import { ApifyClient } from 'apify-client';
9
+ import { getActorsAsTools } from './actorDefinition.js';
10
+ import { ACTOR_OUTPUT_MAX_CHARS_PER_ITEM, ACTOR_OUTPUT_TRUNCATED_MESSAGE, defaults, SERVER_NAME, SERVER_VERSION, } from './const.js';
11
+ import { log } from './logger.js';
12
+ /**
13
+ * Create Apify MCP server
14
+ */
15
+ export class ApifyMcpServer {
16
+ server;
17
+ tools;
18
+ constructor() {
19
+ this.server = new Server({
20
+ name: SERVER_NAME,
21
+ version: SERVER_VERSION,
22
+ }, {
23
+ capabilities: {
24
+ tools: {},
25
+ },
26
+ });
27
+ this.tools = new Map();
28
+ this.setupErrorHandling();
29
+ this.setupToolHandlers();
30
+ }
31
+ /**
32
+ * Calls an Apify actor and retrieves the dataset items.
33
+ *
34
+ * It requires the `APIFY_TOKEN` environment variable to be set.
35
+ * If the `APIFY_IS_AT_HOME` the dataset items are pushed to the Apify dataset.
36
+ *
37
+ * @param {string} actorName - The name of the actor to call.
38
+ * @param {unknown} input - The input to pass to the actor.
39
+ * @returns {Promise<object[]>} - A promise that resolves to an array of dataset items.
40
+ * @throws {Error} - Throws an error if the `APIFY_TOKEN` is not set
41
+ */
42
+ async callActorGetDataset(actorName, input) {
43
+ if (!process.env.APIFY_TOKEN) {
44
+ throw new Error('APIFY_TOKEN is required but not set. Please set it as an environment variable');
45
+ }
46
+ try {
47
+ log.info(`Calling actor ${actorName} with input: ${JSON.stringify(input)}`);
48
+ const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
49
+ const actorClient = client.actor(actorName);
50
+ const results = await actorClient.call(input);
51
+ const dataset = await client.dataset(results.defaultDatasetId).listItems();
52
+ log.info(`Actor ${actorName} finished with ${dataset.items.length} items`);
53
+ if (process.env.APIFY_IS_AT_HOME) {
54
+ await Actor.pushData(dataset.items);
55
+ log.info(`Pushed ${dataset.items.length} items to the dataset`);
56
+ }
57
+ return dataset.items;
58
+ }
59
+ catch (error) {
60
+ log.error(`Error calling actor: ${error}. Actor: ${actorName}, input: ${JSON.stringify(input)}`);
61
+ throw new Error(`Error calling actor: ${error}`);
62
+ }
63
+ }
64
+ async addToolsFromActors(actors) {
65
+ const tools = await getActorsAsTools(actors);
66
+ this.updateTools(tools);
67
+ }
68
+ async addToolsFromDefaultActors() {
69
+ await this.addToolsFromActors(defaults.actors);
70
+ }
71
+ updateTools(tools) {
72
+ for (const tool of tools) {
73
+ this.tools.set(tool.name, tool);
74
+ log.info(`Added/Updated tool: ${tool.name}`);
75
+ }
76
+ }
77
+ getToolNames() {
78
+ return Array.from(this.tools.keys());
79
+ }
80
+ setupErrorHandling() {
81
+ this.server.onerror = (error) => {
82
+ console.error('[MCP Error]', error); // eslint-disable-line no-console
83
+ };
84
+ process.on('SIGINT', async () => {
85
+ await this.server.close();
86
+ process.exit(0);
87
+ });
88
+ }
89
+ setupToolHandlers() {
90
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
91
+ return { tools: Array.from(this.tools.values()) };
92
+ });
93
+ /**
94
+ * Handles the request to call a tool.
95
+ * @param {object} request - The request object containing tool name and arguments.
96
+ * @throws {Error} - Throws an error if the tool is unknown or arguments are invalid.
97
+ */
98
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
99
+ const { name, arguments: args } = request.params;
100
+ // Anthropic can't handle '/' in tool names. The replace is only necessary when calling the tool from stdio clients.
101
+ const tool = this.tools.get(name) || this.tools.get(name.replace('/', '_'));
102
+ if (!tool) {
103
+ throw new Error(`Unknown tool: ${name}`);
104
+ }
105
+ log.info(`Validate arguments for tool: ${tool.name} with arguments: ${JSON.stringify(args)}`);
106
+ if (!tool.ajvValidate(args)) {
107
+ throw new Error(`Invalid arguments for tool ${tool.name}: args: ${JSON.stringify(args)} error: ${JSON.stringify(tool?.ajvValidate.errors)}`);
108
+ }
109
+ try {
110
+ const items = await this.callActorGetDataset(tool.actorName, args);
111
+ const content = items.map((item) => {
112
+ const text = JSON.stringify(item).slice(0, ACTOR_OUTPUT_MAX_CHARS_PER_ITEM);
113
+ return text.length === ACTOR_OUTPUT_MAX_CHARS_PER_ITEM
114
+ ? { type: 'text', text: `${text} ... ${ACTOR_OUTPUT_TRUNCATED_MESSAGE}` }
115
+ : { type: 'text', text };
116
+ });
117
+ return { content };
118
+ }
119
+ catch (error) {
120
+ log.error(`Error calling tool: ${error}`);
121
+ throw new Error(`Error calling tool: ${error}`);
122
+ }
123
+ });
124
+ }
125
+ async connect(transport) {
126
+ await this.server.connect(transport);
127
+ }
128
+ }
129
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ValidateFunction } from 'ajv';
2
+ import type { ActorDefinition } from 'apify-client';
3
+ export type Input = {
4
+ actors: string[] | string;
5
+ debugActor?: string;
6
+ debugActorInput?: unknown;
7
+ };
8
+ export interface ActorDefinitionWithDesc extends ActorDefinition {
9
+ description: string;
10
+ }
11
+ export interface Tool {
12
+ name: string;
13
+ actorName: string;
14
+ description: string;
15
+ inputSchema: object;
16
+ ajvValidate: ValidateFunction;
17
+ }
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,KAAK,GAAG;IAChB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC5D,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,IAAI;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,gBAAgB,CAAC;CACjC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}