Skip to content

Commit d973f17

Browse files
committed
Merge remote-tracking branch 'origin/master' into feat/progress-notification
2 parents 2ea7ef3 + 9a5c16a commit d973f17

File tree

17 files changed

+344
-264
lines changed

17 files changed

+344
-264
lines changed

.actor/ACTOR.md

Lines changed: 48 additions & 123 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@
33
All notable changes to this project will be documented in this file.
44

55
<!-- git-cliff-unreleased-start -->
6-
## 0.2.14 - **not yet released**
6+
## 0.2.15 - **not yet released**
7+
8+
### 🚀 Features
9+
10+
- Add video tutorial into the Actor README. Simplify README ([#175](https://github.com/apify/actors-mcp-server/pull/175)) ([3547521](https://github.com/apify/actors-mcp-server/commit/3547521e23bbf9a5d49cb75f8ff275e88dfe5be4)) by [@jirispilka](https://github.com/jirispilka), closes [#138](https://github.com/apify/actors-mcp-server/issues/138), [#148](https://github.com/apify/actors-mcp-server/issues/148)
11+
12+
13+
<!-- git-cliff-unreleased-end -->
14+
## [0.2.14](https://github.com/apify/actors-mcp-server/releases/tag/v0.2.14) (2025-07-17)
15+
16+
### 🚀 Features
17+
18+
- Add tool selection by feature param ([#172](https://github.com/apify/actors-mcp-server/pull/172)) ([f3b2e4f](https://github.com/apify/actors-mcp-server/commit/f3b2e4f1d204ab01cd0783bbc9930bfc2f84a539)) by [@MQ37](https://github.com/MQ37), closes [#166](https://github.com/apify/actors-mcp-server/issues/166)
719

820
### 🐛 Bug Fixes
921

1022
- Encode Actor input fields containing dots ([#170](https://github.com/apify/actors-mcp-server/pull/170)) ([8dbdc7b](https://github.com/apify/actors-mcp-server/commit/8dbdc7b53da50137fd118631404312c71d8f4381)) by [@MQ37](https://github.com/MQ37)
1123

1224

13-
<!-- git-cliff-unreleased-end -->
1425
## [0.2.13](https://github.com/apify/actors-mcp-server/releases/tag/v0.2.13) (2025-07-15)
1526

1627
### 🐛 Bug Fixes

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,17 @@ One of the powerful features of MCP with Apify is dynamic actor tooling – the
9494

9595
- Actor discovery and management: Search for Actors (`search-actors`), view details (`get-actor-details`), and dynamically add them (`add-actor`).
9696
- Apify documentation: Search Apify documentation (`search-apify-docs`) and fetch specific documents (`fetch-apify-docs`).
97-
- Built-in help tool: A static helper (`apify-actor-help-tool`) that returns usage info for the Apify MCP Server.
97+
- Actor runs (*): Get a list of your Actor runs (`get-actor-run-list`), specific run details (`get-actor-run`), and logs from a specific Actor run (`get-actor-log`).
98+
- Apify storage (*): Access datasets (`get-dataset`, `get-dataset-items`, `get-dataset-list`), key-value stores (`get-key-value-store`, `get-key-value-store-keys`, `get-key-value-store-record`, `get-key-value-store-records`), and their records.
99+
100+
**Note**: Helper tool categories marked with (*) are not enabled by default in the MCP server and must be explicitly enabled using the `tools` argument (either the `--tools` command line argument for the stdio server or the `?tools` URL query parameter for the remote MCP server). The `tools` argument is a comma-separated list of categories with the following possible values:
101+
102+
- `docs`: Search and fetch Apify documentation tools.
103+
- `runs`: Get Actor runs list, run details, and logs from a specific Actor run.
104+
- `storage`: Access datasets, key-value stores, and their records.
105+
- `preview`: Experimental tools in preview mode.
106+
107+
For example, to enable all tools, use `npx @apify/actors-mcp-server --tools docs,runs,storage,preview` or `https://mcp.apify.com/?tools=docs,runs,storage,preview`.
98108

99109
## Prompt & Resources
100110

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apify/actors-mcp-server",
3-
"version": "0.2.14",
3+
"version": "0.2.15",
44
"type": "module",
55
"description": "Model Context Protocol Server for Apify",
66
"engines": {

src/actor/server.ts

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,9 @@ import log from '@apify/log';
1313

1414
import { ActorsMcpServer } from '../mcp/server.js';
1515
import { parseInputParamsFromUrl } from '../mcp/utils.js';
16-
import { getActorsAsTools } from '../tools/actor.js';
1716
import { getHelpMessage, HEADER_READINESS_PROBE, Routes } from './const.js';
1817
import { getActorRunData } from './utils.js';
1918

20-
/**
21-
* Helper function to load tools and actors based on input parameters
22-
* @param mcpServer The MCP server instance
23-
* @param url The request URL to parse parameters from
24-
* @param apifyToken The Apify token for authentication
25-
*/
26-
async function loadToolsAndActors(mcpServer: ActorsMcpServer, url: string, apifyToken: string): Promise<void> {
27-
const input = parseInputParamsFromUrl(url);
28-
if (input.actors || input.enableAddingActors) {
29-
await mcpServer.loadToolsFromUrl(url, apifyToken);
30-
}
31-
if (!input.actors) {
32-
await mcpServer.loadDefaultActors(apifyToken);
33-
}
34-
}
35-
3619
export function createExpressApp(
3720
host: string,
3821
mcpServerOptions: {
@@ -85,13 +68,21 @@ export function createExpressApp(
8568
try {
8669
log.info(`Received GET message at: ${Routes.SSE}`);
8770
const mcpServer = new ActorsMcpServer(mcpServerOptions, false);
88-
// Load tools from Actor input for backwards compatibility
89-
if (mcpServerOptions.actors && mcpServerOptions.actors.length > 0) {
90-
const tools = await getActorsAsTools(mcpServerOptions.actors, process.env.APIFY_TOKEN as string);
91-
mcpServer.upsertTools(tools);
92-
}
93-
await loadToolsAndActors(mcpServer, req.url, process.env.APIFY_TOKEN as string);
9471
const transport = new SSEServerTransport(Routes.MESSAGE, res);
72+
73+
// Load MCP server tools
74+
const apifyToken = process.env.APIFY_TOKEN as string;
75+
const input = parseInputParamsFromUrl(req.url);
76+
if (input.actors || input.enableAddingActors || input.tools) {
77+
log.debug('[SSE] Loading tools from URL', { sessionId: transport.sessionId });
78+
await mcpServer.loadToolsFromUrl(req.url, apifyToken);
79+
}
80+
// Load default tools if no actors are specified
81+
if (!input.actors) {
82+
log.debug('[SSE] Loading default tools', { sessionId: transport.sessionId });
83+
await mcpServer.loadDefaultActors(apifyToken);
84+
}
85+
9586
transportsSSE[transport.sessionId] = transport;
9687
mcpServers[transport.sessionId] = mcpServer;
9788
await mcpServer.connect(transport);
@@ -164,13 +155,20 @@ export function createExpressApp(
164155
enableJsonResponse: false, // Use SSE response mode
165156
});
166157
const mcpServer = new ActorsMcpServer(mcpServerOptions, false);
167-
// Load tools from Actor input for backwards compatibility
168-
if (mcpServerOptions.actors && mcpServerOptions.actors.length > 0) {
169-
const tools = await getActorsAsTools(mcpServerOptions.actors, process.env.APIFY_TOKEN as string);
170-
mcpServer.upsertTools(tools);
171-
}
158+
172159
// Load MCP server tools
173-
await loadToolsAndActors(mcpServer, req.url, process.env.APIFY_TOKEN as string);
160+
const apifyToken = process.env.APIFY_TOKEN as string;
161+
const input = parseInputParamsFromUrl(req.url);
162+
if (input.actors || input.enableAddingActors || input.tools) {
163+
log.debug('[Streamable] Loading tools from URL', { sessionId: transport.sessionId });
164+
await mcpServer.loadToolsFromUrl(req.url, apifyToken);
165+
}
166+
// Load default tools if no actors are specified
167+
if (!input.actors) {
168+
log.debug('[Streamable] Loading default tools', { sessionId: transport.sessionId });
169+
await mcpServer.loadDefaultActors(apifyToken);
170+
}
171+
174172
// Connect the transport to the MCP server BEFORE handling the request
175173
await mcpServer.connect(transport);
176174

src/input.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44
import log from '@apify/log';
55

6-
import type { Input } from './types.js';
6+
import type { Input, ToolCategory } from './types.js';
77

88
/**
99
* Process input parameters, split Actors string into an array
@@ -30,7 +30,8 @@ export function processInput(originalInput: Partial<Input>): Input {
3030
input.enableAddingActors = input.enableAddingActors === true || input.enableAddingActors === 'true';
3131
}
3232

33-
// If beta present, set input.beta to true
34-
input.beta = input.beta !== undefined && (input.beta !== false && input.beta !== 'false');
33+
if (input.tools && typeof input.tools === 'string') {
34+
input.tools = input.tools.split(',').map((tool: string) => tool.trim()) as ToolCategory[];
35+
}
3536
return input;
3637
}

src/mcp/server.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
SERVER_NAME,
2424
SERVER_VERSION,
2525
} from '../const.js';
26-
import { addRemoveTools, betaTools, callActorGetDataset, defaultTools, getActorsAsTools } from '../tools/index.js';
26+
import { addRemoveTools, callActorGetDataset, defaultTools, getActorsAsTools, toolCategories } from '../tools/index.js';
2727
import { actorNameToToolName, decodeDotPropertyNames } from '../tools/utils.js';
2828
import type { ActorMcpTool, ActorTool, HelperTool, ToolEntry } from '../types.js';
2929
import { createProgressTracker } from '../utils/progress.js';
@@ -34,7 +34,6 @@ import { processParamsGetTools } from './utils.js';
3434
type ActorsMcpServerOptions = {
3535
enableAddingActors?: boolean;
3636
enableDefaultActors?: boolean;
37-
enableBeta?: boolean; // Enable beta features
3837
};
3938

4039
type ToolsChangedHandler = (toolNames: string[]) => void;
@@ -53,7 +52,6 @@ export class ActorsMcpServer {
5352
this.options = {
5453
enableAddingActors: options.enableAddingActors ?? true,
5554
enableDefaultActors: options.enableDefaultActors ?? true, // Default to true for backward compatibility
56-
enableBeta: options.enableBeta ?? false, // Disabled by default
5755
};
5856
this.server = new Server(
5957
{
@@ -79,10 +77,6 @@ export class ActorsMcpServer {
7977
this.enableDynamicActorTools();
8078
}
8179

82-
if (this.options.enableBeta) {
83-
this.upsertTools(betaTools, false);
84-
}
85-
8680
// Initialize automatically for backward compatibility
8781
this.initialize().catch((error) => {
8882
log.error('Failed to initialize server:', error);
@@ -173,7 +167,11 @@ export class ActorsMcpServer {
173167
const loadedTools = this.listAllToolNames();
174168
const actorsToLoad: string[] = [];
175169
const toolsToLoad: ToolEntry[] = [];
176-
const internalToolMap = new Map([...defaultTools, ...addRemoveTools, ...betaTools].map((tool) => [tool.tool.name, tool]));
170+
const internalToolMap = new Map([
171+
...defaultTools,
172+
...addRemoveTools,
173+
...Object.values(toolCategories).flat(),
174+
].map((tool) => [tool.tool.name, tool]));
177175

178176
for (const tool of toolNames) {
179177
// Skip if the tool is already loaded

src/mcp/utils.ts

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { createHash } from 'node:crypto';
22
import { parse } from 'node:querystring';
33

44
import { processInput } from '../input.js';
5-
import { addRemoveTools, betaTools, getActorsAsTools } from '../tools/index.js';
6-
import type { Input, ToolEntry } from '../types.js';
5+
import type { Input } from '../types.js';
6+
import { loadToolsFromInput } from '../utils/tools-loader.js';
77
import { MAX_TOOL_NAME_LENGTH, SERVER_ID_LENGTH } from './const.js';
88

99
/**
@@ -34,26 +34,14 @@ export function getProxyMCPServerToolName(url: string, toolName: string): string
3434
}
3535

3636
/**
37-
* Process input parameters and get tools
37+
* Process input parameters from URL and get tools
3838
* If URL contains query parameter `actors`, return tools from Actors otherwise return null.
3939
* @param url
4040
* @param apifyToken
4141
*/
4242
export async function processParamsGetTools(url: string, apifyToken: string) {
4343
const input = parseInputParamsFromUrl(url);
44-
let tools: ToolEntry[] = [];
45-
if (input.actors) {
46-
const actors = input.actors as string[];
47-
// Normal Actors as a tool
48-
tools = await getActorsAsTools(actors, apifyToken);
49-
}
50-
if (input.enableAddingActors) {
51-
tools.push(...addRemoveTools);
52-
}
53-
if (input.beta) {
54-
tools.push(...betaTools);
55-
}
56-
return tools;
44+
return await loadToolsFromInput(input, apifyToken);
5745
}
5846

5947
export function parseInputParamsFromUrl(url: string): Input {

src/stdio.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import { hideBin } from 'yargs/helpers';
2222

2323
import log from '@apify/log';
2424

25-
import { defaults } from './const.js';
2625
import { ActorsMcpServer } from './mcp/server.js';
27-
import { getActorsAsTools } from './tools/index.js';
26+
import { toolCategories } from './tools/index.js';
27+
import type { Input, ToolCategory } from './types.js';
28+
import { loadToolsFromInput } from './utils/tools-loader.js';
2829

2930
// Keeping this interface here and not types.ts since
3031
// it is only relevant to the CLI/STDIO transport in this file
@@ -36,7 +37,8 @@ interface CliArgs {
3637
enableAddingActors: boolean;
3738
/** @deprecated */
3839
enableActorAutoLoading: boolean;
39-
beta: boolean;
40+
/** Tool categories to include */
41+
tools?: string;
4042
}
4143

4244
// Configure logging, set to ERROR
@@ -47,24 +49,35 @@ const argv = yargs(hideBin(process.argv))
4749
.usage('Usage: $0 [options]')
4850
.option('actors', {
4951
type: 'string',
50-
describe: 'Comma-separated list of Actor full names to add to the server',
52+
describe: 'Comma-separated list of Actor full names to add to the server.',
5153
example: 'apify/google-search-scraper,apify/instagram-scraper',
5254
})
5355
.option('enable-adding-actors', {
5456
type: 'boolean',
5557
default: true,
56-
describe: 'Enable dynamically adding Actors as tools based on user requests',
58+
describe: 'Enable dynamically adding Actors as tools based on user requests.',
5759
})
5860
.option('enableActorAutoLoading', {
5961
type: 'boolean',
6062
default: true,
6163
hidden: true,
62-
describe: 'Deprecated: use enable-adding-actors instead',
64+
describe: 'Deprecated: use enable-adding-actors instead.',
6365
})
64-
.option('beta', {
65-
type: 'boolean',
66-
default: false,
67-
describe: 'Enable beta features',
66+
.options('tools', {
67+
type: 'string',
68+
describe: `Comma-separated list of specific tool categories to enable.
69+
70+
Available choices: ${Object.keys(toolCategories).join(', ')}
71+
72+
Tool categories are as follows:
73+
- docs: Search and fetch Apify documentation tools.
74+
- runs: Get Actor runs list, run details, and logs from a specific Actor run.
75+
- storage: Access datasets, key-value stores, and their records.
76+
- preview: Experimental tools in preview mode.
77+
78+
Note: Tools that enable you to search Actors from the Apify Store and get their details are always enabled by default.
79+
`,
80+
example: 'docs,runs,storage',
6881
})
6982
.help('help')
7083
.alias('h', 'help')
@@ -73,13 +86,14 @@ const argv = yargs(hideBin(process.argv))
7386
'To connect, set your MCP client server command to `npx @apify/actors-mcp-server`'
7487
+ ' and set the environment variable `APIFY_TOKEN` to your Apify API token.\n',
7588
)
76-
.epilogue('For more information, visit https://github.com/apify/actors-mcp-server')
89+
.epilogue('For more information, visit https://mcp.apify.com or https://github.com/apify/actors-mcp-server')
7790
.parseSync() as CliArgs;
7891

7992
const enableAddingActors = argv.enableAddingActors && argv.enableActorAutoLoading;
8093
const actors = argv.actors as string || '';
8194
const actorList = actors ? actors.split(',').map((a: string) => a.trim()) : [];
82-
const enableBeta = argv.beta;
95+
// Keys of the tool categories to enable
96+
const toolCategoryKeys = argv.tools ? argv.tools.split(',').map((t: string) => t.trim()) : [];
8397

8498
// Validate environment
8599
if (!process.env.APIFY_TOKEN) {
@@ -88,8 +102,18 @@ if (!process.env.APIFY_TOKEN) {
88102
}
89103

90104
async function main() {
91-
const mcpServer = new ActorsMcpServer({ enableAddingActors, enableDefaultActors: false, enableBeta });
92-
const tools = await getActorsAsTools(actorList.length ? actorList : defaults.actors, process.env.APIFY_TOKEN as string);
105+
const mcpServer = new ActorsMcpServer({ enableAddingActors, enableDefaultActors: false });
106+
107+
// Create an Input object from CLI arguments
108+
const input: Input = {
109+
actors: actorList.length ? actorList : [],
110+
enableAddingActors,
111+
tools: toolCategoryKeys as ToolCategory[],
112+
};
113+
114+
// Use the shared tools loading logic
115+
const tools = await loadToolsFromInput(input, process.env.APIFY_TOKEN as string, actorList.length === 0);
116+
93117
mcpServer.upsertTools(tools);
94118

95119
// Start server

0 commit comments

Comments
 (0)