@apify/actors-mcp-server 0.1.1-beta.1 → 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 (48) hide show
  1. package/dist/actorDefinition.d.ts +14 -0
  2. package/dist/actorDefinition.d.ts.map +1 -0
  3. package/{src/actorDefinition.ts → dist/actorDefinition.js} +8 -12
  4. package/dist/actorDefinition.js.map +1 -0
  5. package/dist/const.d.ts +13 -0
  6. package/dist/const.d.ts.map +1 -0
  7. package/{src/const.ts → dist/const.js} +7 -8
  8. package/dist/const.js.map +1 -0
  9. package/dist/examples/clientSse.d.ts +8 -0
  10. package/dist/examples/clientSse.d.ts.map +1 -0
  11. package/{src/examples/clientSse.ts → dist/examples/clientSse.js} +25 -45
  12. package/dist/examples/clientSse.js.map +1 -0
  13. package/dist/examples/clientStdio.d.ts +8 -0
  14. package/dist/examples/clientStdio.d.ts.map +1 -0
  15. package/{src/examples/clientStdio.ts → dist/examples/clientStdio.js} +5 -24
  16. package/dist/examples/clientStdio.js.map +1 -0
  17. package/dist/examples/clientStdioChat.d.ts +23 -0
  18. package/dist/examples/clientStdioChat.d.ts.map +1 -0
  19. package/{src/examples/clientStdioChat.ts → dist/examples/clientStdioChat.js} +37 -63
  20. package/dist/examples/clientStdioChat.js.map +1 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/{src/index.ts → dist/index.js} +2 -6
  24. package/dist/index.js.map +1 -0
  25. package/dist/input.d.ts +8 -0
  26. package/dist/input.d.ts.map +1 -0
  27. package/dist/input.js +14 -0
  28. package/dist/input.js.map +1 -0
  29. package/dist/logger.d.ts +3 -0
  30. package/dist/logger.d.ts.map +1 -0
  31. package/{src/logger.ts → dist/logger.js} +1 -2
  32. package/dist/logger.js.map +1 -0
  33. package/dist/main.d.ts +2 -0
  34. package/dist/main.d.ts.map +1 -0
  35. package/dist/main.js +104 -0
  36. package/dist/main.js.map +1 -0
  37. package/dist/server.d.ts +31 -0
  38. package/dist/server.d.ts.map +1 -0
  39. package/{src/server.ts → dist/server.js} +23 -47
  40. package/dist/server.js.map +1 -0
  41. package/{src/types.ts → dist/types.d.ts} +1 -3
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/package.json +3 -3
  46. package/src/examples/client_sse.py +0 -48
  47. package/src/input.ts +0 -16
  48. package/src/main.ts +0 -115
@@ -3,46 +3,31 @@
3
3
  * Model Context Protocol (MCP) server for Apify Actors
4
4
  */
5
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
- import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
7
6
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
8
7
  import { Actor } from 'apify';
9
8
  import { ApifyClient } from 'apify-client';
10
-
11
9
  import { getActorsAsTools } from './actorDefinition.js';
12
- import {
13
- ACTOR_OUTPUT_MAX_CHARS_PER_ITEM,
14
- ACTOR_OUTPUT_TRUNCATED_MESSAGE,
15
- defaults,
16
- SERVER_NAME,
17
- SERVER_VERSION,
18
- } from './const.js';
10
+ import { ACTOR_OUTPUT_MAX_CHARS_PER_ITEM, ACTOR_OUTPUT_TRUNCATED_MESSAGE, defaults, SERVER_NAME, SERVER_VERSION, } from './const.js';
19
11
  import { log } from './logger.js';
20
- import type { Tool } from './types';
21
-
22
12
  /**
23
13
  * Create Apify MCP server
24
14
  */
25
15
  export class ApifyMcpServer {
26
- private server: Server;
27
- private tools: Map<string, Tool>;
28
-
16
+ server;
17
+ tools;
29
18
  constructor() {
30
- this.server = new Server(
31
- {
32
- name: SERVER_NAME,
33
- version: SERVER_VERSION,
19
+ this.server = new Server({
20
+ name: SERVER_NAME,
21
+ version: SERVER_VERSION,
22
+ }, {
23
+ capabilities: {
24
+ tools: {},
34
25
  },
35
- {
36
- capabilities: {
37
- tools: {},
38
- },
39
- },
40
- );
26
+ });
41
27
  this.tools = new Map();
42
28
  this.setupErrorHandling();
43
29
  this.setupToolHandlers();
44
30
  }
45
-
46
31
  /**
47
32
  * Calls an Apify actor and retrieves the dataset items.
48
33
  *
@@ -54,7 +39,7 @@ export class ApifyMcpServer {
54
39
  * @returns {Promise<object[]>} - A promise that resolves to an array of dataset items.
55
40
  * @throws {Error} - Throws an error if the `APIFY_TOKEN` is not set
56
41
  */
57
- public async callActorGetDataset(actorName: string, input: unknown): Promise<object[]> {
42
+ async callActorGetDataset(actorName, input) {
58
43
  if (!process.env.APIFY_TOKEN) {
59
44
  throw new Error('APIFY_TOKEN is required but not set. Please set it as an environment variable');
60
45
  }
@@ -62,43 +47,37 @@ export class ApifyMcpServer {
62
47
  log.info(`Calling actor ${actorName} with input: ${JSON.stringify(input)}`);
63
48
  const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
64
49
  const actorClient = client.actor(actorName);
65
-
66
50
  const results = await actorClient.call(input);
67
51
  const dataset = await client.dataset(results.defaultDatasetId).listItems();
68
52
  log.info(`Actor ${actorName} finished with ${dataset.items.length} items`);
69
-
70
53
  if (process.env.APIFY_IS_AT_HOME) {
71
54
  await Actor.pushData(dataset.items);
72
55
  log.info(`Pushed ${dataset.items.length} items to the dataset`);
73
56
  }
74
57
  return dataset.items;
75
- } catch (error) {
58
+ }
59
+ catch (error) {
76
60
  log.error(`Error calling actor: ${error}. Actor: ${actorName}, input: ${JSON.stringify(input)}`);
77
61
  throw new Error(`Error calling actor: ${error}`);
78
62
  }
79
63
  }
80
-
81
- public async addToolsFromActors(actors: string[]) {
64
+ async addToolsFromActors(actors) {
82
65
  const tools = await getActorsAsTools(actors);
83
66
  this.updateTools(tools);
84
67
  }
85
-
86
- public async addToolsFromDefaultActors() {
68
+ async addToolsFromDefaultActors() {
87
69
  await this.addToolsFromActors(defaults.actors);
88
70
  }
89
-
90
- public updateTools(tools: Tool[]): void {
71
+ updateTools(tools) {
91
72
  for (const tool of tools) {
92
73
  this.tools.set(tool.name, tool);
93
74
  log.info(`Added/Updated tool: ${tool.name}`);
94
75
  }
95
76
  }
96
-
97
- public getToolNames(): string[] {
77
+ getToolNames() {
98
78
  return Array.from(this.tools.keys());
99
79
  }
100
-
101
- private setupErrorHandling(): void {
80
+ setupErrorHandling() {
102
81
  this.server.onerror = (error) => {
103
82
  console.error('[MCP Error]', error); // eslint-disable-line no-console
104
83
  };
@@ -107,12 +86,10 @@ export class ApifyMcpServer {
107
86
  process.exit(0);
108
87
  });
109
88
  }
110
-
111
- private setupToolHandlers(): void {
89
+ setupToolHandlers() {
112
90
  this.server.setRequestHandler(ListToolsRequestSchema, async () => {
113
91
  return { tools: Array.from(this.tools.values()) };
114
92
  });
115
-
116
93
  /**
117
94
  * Handles the request to call a tool.
118
95
  * @param {object} request - The request object containing tool name and arguments.
@@ -120,7 +97,6 @@ export class ApifyMcpServer {
120
97
  */
121
98
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
122
99
  const { name, arguments: args } = request.params;
123
-
124
100
  // Anthropic can't handle '/' in tool names. The replace is only necessary when calling the tool from stdio clients.
125
101
  const tool = this.tools.get(name) || this.tools.get(name.replace('/', '_'));
126
102
  if (!tool) {
@@ -130,7 +106,6 @@ export class ApifyMcpServer {
130
106
  if (!tool.ajvValidate(args)) {
131
107
  throw new Error(`Invalid arguments for tool ${tool.name}: args: ${JSON.stringify(args)} error: ${JSON.stringify(tool?.ajvValidate.errors)}`);
132
108
  }
133
-
134
109
  try {
135
110
  const items = await this.callActorGetDataset(tool.actorName, args);
136
111
  const content = items.map((item) => {
@@ -140,14 +115,15 @@ export class ApifyMcpServer {
140
115
  : { type: 'text', text };
141
116
  });
142
117
  return { content };
143
- } catch (error) {
118
+ }
119
+ catch (error) {
144
120
  log.error(`Error calling tool: ${error}`);
145
121
  throw new Error(`Error calling tool: ${error}`);
146
122
  }
147
123
  });
148
124
  }
149
-
150
- async connect(transport: Transport): Promise<void> {
125
+ async connect(transport) {
151
126
  await this.server.connect(transport);
152
127
  }
153
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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"}
@@ -1,16 +1,13 @@
1
1
  import type { ValidateFunction } from 'ajv';
2
2
  import type { ActorDefinition } from 'apify-client';
3
-
4
3
  export type Input = {
5
4
  actors: string[] | string;
6
5
  debugActor?: string;
7
6
  debugActorInput?: unknown;
8
7
  };
9
-
10
8
  export interface ActorDefinitionWithDesc extends ActorDefinition {
11
9
  description: string;
12
10
  }
13
-
14
11
  export interface Tool {
15
12
  name: string;
16
13
  actorName: string;
@@ -18,3 +15,4 @@ export interface Tool {
18
15
  inputSchema: object;
19
16
  ajvValidate: ValidateFunction;
20
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":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/actors-mcp-server",
3
- "version": "0.1.1-beta.1",
3
+ "version": "0.1.1-beta.2",
4
4
  "type": "module",
5
5
  "description": "Model Context Protocol Server for Apify Actors",
6
6
  "engines": {
@@ -11,8 +11,8 @@
11
11
  "actors-mcp-server": "dist/index.js"
12
12
  },
13
13
  "files": [
14
- "dist/**",
15
- "src/**",
14
+ "dist",
15
+ "!dist/*.tsbuildinfo",
16
16
  "LICENSE"
17
17
  ],
18
18
  "repository": {
@@ -1,48 +0,0 @@
1
- """
2
- Test Apify MCP Server using SSE client
3
-
4
- It is using python client as the typescript one does not support custom headers when connecting to the SSE server.
5
-
6
- Install python dependencies (assumes you have python installed):
7
- > pip install requests python-dotenv mcp
8
- """
9
-
10
- import asyncio
11
- import os
12
- from pathlib import Path
13
-
14
- import requests
15
- from dotenv import load_dotenv
16
- from mcp.client.session import ClientSession
17
- from mcp.client.sse import sse_client
18
-
19
- load_dotenv(Path(__file__).resolve().parent.parent.parent / ".env")
20
-
21
- MCP_SERVER_URL = "https://actors-mcp-server.apify.actor"
22
-
23
- HEADERS = {"Authorization": f"Bearer {os.getenv('APIFY_TOKEN')}"}
24
-
25
- async def run() -> None:
26
-
27
- print("Start MCP Server with Actors")
28
- r = requests.get(MCP_SERVER_URL, headers=HEADERS)
29
- print("MCP Server Response:", r.json(), end="\n\n")
30
-
31
- async with sse_client(url=f"{MCP_SERVER_URL}/sse", timeout=60, headers=HEADERS) as (read, write):
32
- async with ClientSession(read, write) as session:
33
- await session.initialize()
34
-
35
- tools = await session.list_tools()
36
- print("Available Tools:", tools, end="\n\n")
37
-
38
- if hasattr(tools, "tools") and not tools.tools:
39
- print("No tools available!")
40
- return
41
-
42
- result = await session.call_tool("apify/rag-web-browser", { "query": "example.com", "maxResults": 3 })
43
- print("Tools Call Result:")
44
-
45
- for content in result.content:
46
- print(content)
47
-
48
- asyncio.run(run())
package/src/input.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { Input } from './types.js';
2
-
3
- /**
4
- * Process input parameters, split actors string into an array
5
- * @param originalInput
6
- * @returns input
7
- */
8
- export async function processInput(originalInput: Partial<Input>): Promise<Input> {
9
- const input = originalInput as Input;
10
-
11
- // actors can be a string or an array of strings
12
- if (input.actors && typeof input.actors === 'string') {
13
- input.actors = input.actors.split(',').map((format: string) => format.trim()) as string[];
14
- }
15
- return input;
16
- }
package/src/main.ts DELETED
@@ -1,115 +0,0 @@
1
- import type { ParsedUrlQuery } from 'querystring';
2
- import { parse } from 'querystring';
3
-
4
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
5
- import { Actor } from 'apify';
6
- import type { Request, Response } from 'express';
7
- import express from 'express';
8
-
9
- import { Routes } from './const.js';
10
- import { processInput } from './input.js';
11
- import { log } from './logger.js';
12
- import { ApifyMcpServer } from './server.js';
13
- import type { Input } from './types.js';
14
-
15
- await Actor.init();
16
-
17
- const STANDBY_MODE = Actor.getEnv().metaOrigin === 'STANDBY';
18
- const HOST = Actor.isAtHome() ? process.env.ACTOR_STANDBY_URL : 'http://localhost';
19
- const PORT = Actor.isAtHome() ? process.env.ACTOR_STANDBY_PORT : 3001;
20
-
21
- const app = express();
22
-
23
- const mcpServer = new ApifyMcpServer();
24
- let transport: SSEServerTransport;
25
-
26
- const HELP_MESSAGE = `Connect to the server with GET request to ${HOST}/sse?token=YOUR-APIFY-TOKEN`
27
- + ` and then send POST requests to ${HOST}/message?token=YOUR-APIFY-TOKEN`;
28
-
29
- /**
30
- * Process input parameters and update tools
31
- * If URL contains query parameter actors, add tools from actors, otherwise add tools from default actors
32
- * @param url
33
- */
34
- async function processParamsAndUpdateTools(url: string) {
35
- const params = parse(url.split('?')[1] || '') as ParsedUrlQuery;
36
- delete params.token;
37
- log.debug(`Received input parameters: ${JSON.stringify(params)}`);
38
- const input = await processInput(params as Input);
39
- if (input.actors) {
40
- await mcpServer.addToolsFromActors(input.actors as string[]);
41
- } else {
42
- log.debug(`Server is running in STANDBY mode with the following Actors (tools): ${mcpServer.getToolNames()}.
43
- To use different Actors, provide them in query parameter "actors" or include them in the Actor Task input.`);
44
- }
45
- }
46
-
47
- app.route(Routes.ROOT)
48
- .get(async (req: Request, res: Response) => {
49
- try {
50
- log.info(`Received GET message at: ${req.url}`);
51
- await processParamsAndUpdateTools(req.url);
52
- res.status(200).json({ message: `Actor is using Model Context Protocol. ${HELP_MESSAGE}` }).end();
53
- } catch (error) {
54
- log.error(`Error in GET ${Routes.ROOT} ${error}`);
55
- res.status(500).json({ message: 'Internal Server Error' }).end();
56
- }
57
- })
58
- .head((_req: Request, res: Response) => {
59
- res.status(200).end();
60
- });
61
-
62
- app.route(Routes.SSE)
63
- .get(async (req: Request, res: Response) => {
64
- try {
65
- log.info(`Received GET message at: ${req.url}`);
66
- await processParamsAndUpdateTools(req.url);
67
- transport = new SSEServerTransport(Routes.MESSAGE, res);
68
- await mcpServer.connect(transport);
69
- } catch (error) {
70
- log.error(`Error in GET ${Routes.SSE}: ${error}`);
71
- res.status(500).json({ message: 'Internal Server Error' }).end();
72
- }
73
- });
74
-
75
- app.route(Routes.MESSAGE)
76
- .post(async (req: Request, res: Response) => {
77
- try {
78
- log.info(`Received POST message at: ${req.url}`);
79
- if (transport) {
80
- await transport.handlePostMessage(req, res);
81
- } else {
82
- res.status(400).json({
83
- message: 'Server is not connected to the client. '
84
- + 'Connect to the server with GET request to /sse endpoint',
85
- });
86
- }
87
- } catch (error) {
88
- log.error(`Error in POST ${Routes.MESSAGE}: ${error}`);
89
- res.status(500).json({ message: 'Internal Server Error' }).end();
90
- }
91
- });
92
-
93
- // Catch-all for undefined routes
94
- app.use((req: Request, res: Response) => {
95
- res.status(404).json({ message: `There is nothing at route ${req.method} ${req.originalUrl}. ${HELP_MESSAGE}` }).end();
96
- });
97
-
98
- const input = await processInput((await Actor.getInput<Partial<Input>>()) ?? ({} as Input));
99
- log.info(`Loaded input: ${JSON.stringify(input)} `);
100
-
101
- if (STANDBY_MODE) {
102
- log.info('Actor is running in the STANDBY mode.');
103
- await mcpServer.addToolsFromDefaultActors();
104
- app.listen(PORT, () => {
105
- log.info(`The Actor web server is listening for user requests at ${HOST}`);
106
- });
107
- } else {
108
- log.info('Actor is not designed to run in the NORMAL model (use this mode only for debugging purposes)');
109
-
110
- if (input && !input.debugActor && !input.debugActorInput) {
111
- await Actor.fail('If you need to debug a specific actor, please provide the debugActor and debugActorInput fields in the input');
112
- }
113
- await mcpServer.callActorGetDataset(input.debugActor!, input.debugActorInput!);
114
- await Actor.exit();
115
- }