Skip to content

Commit 9d8d69a

Browse files
committed
Memory for each Actor is limited to 4GB.
Free users have an 8GB limit, 128MB needs to be allocated for running `Actors-MCP-Server`.
1 parent 5bdc9be commit 9d8d69a

File tree

7 files changed

+35
-11
lines changed

7 files changed

+35
-11
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ For example it can:
1919
- use [Instagram Scraper](https://apify.com/apify/instagram-scraper) to scrape Instagram posts, profiles, places, photos, and comments
2020
- use [RAG Web Browser](https://apify.com/apify/web-scraper) to search the web, scrape the top N URLs, and return their content
2121

22-
To interact with the Apify MCP server, you can use MCP clients such as [Claude Desktop](https://claude.ai/download), [Superinference.ai](https://superinterface.ai/), or [LibreChat](https://www.librechat.ai/).
22+
23+
To interact with the Apify MCP server, you can use MCP clients such as [Claude Desktop](https://claude.ai/download), [LibreChat](https://www.librechat.ai/), or other [MCP clients](https://glama.ai/mcp/clients).
2324
Additionally, you can use simple example clients found in the [examples](https://github.com/apify/actor-mcp-server/tree/main/src/examples) directory.
2425

2526
When you have Actors integrated with the MCP server, you can ask:
@@ -29,6 +30,10 @@ When you have Actors integrated with the MCP server, you can ask:
2930
- "Provide a step-by-step guide on using the Model Context Protocol with source URLs."
3031
- "What Apify Actors I can use?"
3132

33+
The following image shows how the Apify MCP server interacts with the Apify platform and AI clients:
34+
35+
![Actors-MCP-server](https://raw.githubusercontent.com/apify/actors-mcp-server/refs/heads/master/docs/actors-mcp-server.png)
36+
3237
In the future, we plan to load Actors dynamically and provide Apify's dataset and key-value store as resources.
3338
See the [Roadmap](#-roadmap-january-2025) for more details.
3439

@@ -311,11 +316,14 @@ Upon launching, the Inspector will display a URL that you can access in your bro
311316
To limit the context size the properties in the `input schema` are pruned and description is truncated to 200 characters.
312317
Enum fields and titles are truncated to max 50 options.
313318

319+
Memory for each Actor is limited to 4GB.
320+
Free users have an 8GB limit, 128MB needs to be allocated for running `Actors-MCP-Server`.
321+
314322
If you need other features or have any feedback, please [submit an issue](https://console.apify.com/actors/3ox4R101TgZz67sLr/issues) in Apify Console to let us know.
315323

316324
# 🚀 Roadmap (January 2025)
317325

318-
- Document examples for [Superinference.ai](https://superinterface.ai/) and [LibreChat](https://www.librechat.ai/).
326+
- Document examples for [LibreChat](https://www.librechat.ai/).
319327
- Provide tools to search for Actors and load them as needed.
320328
- Add Apify's dataset and key-value store as resources.
321329
- Add tools such as Actor logs and Actor runs for debugging.

src/actorDefinition.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Ajv } from 'ajv';
22
import { ApifyClient } from 'apify-client';
33

4-
import { MAX_DESCRIPTION_LENGTH, MAX_ENUM_LENGTH } from './const.js';
4+
import { MAX_DESCRIPTION_LENGTH, MAX_ENUM_LENGTH, MAX_MEMORY_MBYTES } from './const.js';
55
import { log } from './logger.js';
6-
import type { ActorDefinitionWithDesc, Tool, SchemaProperties } from './types.js';
6+
import type { ActorDefinitionWithDesc, SchemaProperties, Tool } from './types.js';
77

88
/**
99
* Get actor input schema by actor name.
@@ -44,6 +44,7 @@ async function fetchActorDefinition(actorFullName: string): Promise<ActorDefinit
4444
const actorDefinitions = buildDetails?.actorDefinition as ActorDefinitionWithDesc;
4545
actorDefinitions.description = actor.description || '';
4646
actorDefinitions.name = actorFullName;
47+
actorDefinitions.defaultRunOptions = actor.defaultRunOptions;
4748
return actorDefinitions;
4849
}
4950
return null;
@@ -108,12 +109,14 @@ export async function getActorsAsTools(actors: string[]): Promise<Tool[]> {
108109
result.input.properties = shortenProperties(properties);
109110
}
110111
try {
112+
const memoryMbytes = result.defaultRunOptions?.memoryMbytes || MAX_MEMORY_MBYTES;
111113
tools.push({
112114
name: result.name.replace('/', '_'),
113115
actorName: result.name,
114116
description: result.description,
115117
inputSchema: result.input || {},
116118
ajvValidate: ajv.compile(result.input || {}),
119+
memoryMbytes: memoryMbytes > MAX_MEMORY_MBYTES ? MAX_MEMORY_MBYTES : memoryMbytes,
117120
});
118121
} catch (validationError) {
119122
log.error(`Failed to compile AJV schema for actor: ${result.name}. Error: ${validationError}`);

src/const.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export const HEADER_READINESS_PROBE = 'x-apify-container-server-readiness-probe'
55

66
export const MAX_ENUM_LENGTH = 50;
77
export const MAX_DESCRIPTION_LENGTH = 200;
8+
// Limit memory to 4GB for Actors. Free users have 8 GB limit, but we need to reserve some memory for Actors-MCP-Server too
9+
export const MAX_MEMORY_MBYTES = 4096;
810

911
export const USER_AGENT_ORIGIN = 'Origin/mcp-server';
1012

src/examples/client_sse.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ async def run() -> None:
4343
print("No tools available!")
4444
return
4545

46+
print("\n\nCall tool")
4647
result = await session.call_tool("apify/rag-web-browser", { "query": "example.com", "maxResults": 3 })
47-
print("Tools Call Result:")
48+
print("Tools call result:")
4849

4950
for content in result.content:
5051
print(content)

src/main.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { parse } from 'querystring';
33

44
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
55
import { Actor } from 'apify';
6+
import type { ActorCallOptions } from 'apify-client';
67
import type { Request, Response } from 'express';
78
import express from 'express';
89

9-
import { HEADER_READINESS_PROBE, Routes } from './const.js';
10+
import { HEADER_READINESS_PROBE, MAX_MEMORY_MBYTES, Routes } from './const.js';
1011
import { processInput } from './input.js';
1112
import { log } from './logger.js';
1213
import { ApifyMcpServer } from './server.js';
@@ -115,6 +116,7 @@ if (STANDBY_MODE) {
115116
if (input && !input.debugActor && !input.debugActorInput) {
116117
await Actor.fail('If you need to debug a specific actor, please provide the debugActor and debugActorInput fields in the input');
117118
}
118-
await mcpServer.callActorGetDataset(input.debugActor!, input.debugActorInput!);
119+
const options = { memory: MAX_MEMORY_MBYTES } as ActorCallOptions;
120+
await mcpServer.callActorGetDataset(input.debugActor!, input.debugActorInput!, options);
119121
await Actor.exit();
120122
}

src/server.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
77
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
88
import type { ApifyClientOptions } from 'apify';
99
import { Actor } from 'apify';
10+
import type { ActorCallOptions } from 'apify-client';
1011
import { ApifyClient } from 'apify-client';
1112
import type { AxiosRequestConfig } from 'axios';
1213

@@ -65,11 +66,16 @@ export class ApifyMcpServer {
6566
* If the `APIFY_IS_AT_HOME` the dataset items are pushed to the Apify dataset.
6667
*
6768
* @param {string} actorName - The name of the actor to call.
69+
* @param {ActorCallOptions} callOptions - The options to pass to the actor.
6870
* @param {unknown} input - The input to pass to the actor.
6971
* @returns {Promise<object[]>} - A promise that resolves to an array of dataset items.
7072
* @throws {Error} - Throws an error if the `APIFY_TOKEN` is not set
7173
*/
72-
public async callActorGetDataset(actorName: string, input: unknown): Promise<object[]> {
74+
public async callActorGetDataset(
75+
actorName: string,
76+
input: unknown,
77+
callOptions: ActorCallOptions | undefined = undefined,
78+
): Promise<object[]> {
7379
if (!process.env.APIFY_TOKEN) {
7480
throw new Error('APIFY_TOKEN is required but not set. Please set it as an environment variable');
7581
}
@@ -80,7 +86,7 @@ export class ApifyMcpServer {
8086
const client = new ApifyClient({ ...options, token: process.env.APIFY_TOKEN });
8187
const actorClient = client.actor(actorName);
8288

83-
const results = await actorClient.call(input);
89+
const results = await actorClient.call(input, callOptions);
8490
const dataset = await client.dataset(results.defaultDatasetId).listItems();
8591
log.info(`Actor ${actorName} finished with ${dataset.items.length} items`);
8692

@@ -149,7 +155,7 @@ export class ApifyMcpServer {
149155
}
150156

151157
try {
152-
const items = await this.callActorGetDataset(tool.actorName, args);
158+
const items = await this.callActorGetDataset(tool.actorName, args, { memory: tool.memoryMbytes } as ActorCallOptions);
153159
const content = items.map((item) => {
154160
const text = JSON.stringify(item).slice(0, ACTOR_OUTPUT_MAX_CHARS_PER_ITEM);
155161
return text.length === ACTOR_OUTPUT_MAX_CHARS_PER_ITEM

src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ValidateFunction } from 'ajv';
2-
import type { ActorDefinition } from 'apify-client';
2+
import type { ActorDefaultRunOptions, ActorDefinition } from 'apify-client';
33

44
export type Input = {
55
actors: string[] | string;
@@ -9,6 +9,7 @@ export type Input = {
99

1010
export interface ActorDefinitionWithDesc extends ActorDefinition {
1111
description: string;
12+
defaultRunOptions: ActorDefaultRunOptions
1213
}
1314

1415
export interface Tool {
@@ -17,6 +18,7 @@ export interface Tool {
1718
description: string;
1819
inputSchema: object;
1920
ajvValidate: ValidateFunction;
21+
memoryMbytes: number;
2022
}
2123

2224
export interface SchemaProperties {

0 commit comments

Comments
 (0)