Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export const SKYFIRE_PAY_ID_PROPERTY_DESCRIPTION = `Skyfire PAY token ID used fo

export const SKYFIRE_README_CONTENT = `The Apify MCP Server allows clients to interact with Apify Actors, storage, and documentation. Before running any Apify Actor, you need to set up a Skyfire PAY token for billing purposes. To set up the PAY token you need to use the create-pay-token tool from the Skyfire MCP server. The PAY token must be charged with a minimum of ${SKYFIRE_MIN_CHARGE_USD} USD to be valid.${SKYFIRE_SELLER_ID ? ` The Skyfire seller ID for Apify MCP server is "${SKYFIRE_SELLER_ID}".` : ''} When running an Actor using the call-actor tool, you must provide the Skyfire PAY token ID in the \`skyfire-pay-id\` input property. Similarly, when retrieving Actor output using the get-actor-output tool, you must also provide the same Skyfire PAY token ID in the \`skyfire-pay-id\` input property.`;

export const CALL_ACTOR_MCP_MISSING_TOOL_NAME_MSG = `When calling an MCP server Actor, you must specify the tool name in the actor parameter as "{actorName}:{toolName}" in the "actor" input property.`;

// Cache
export const ACTOR_CACHE_MAX_SIZE = 500;
export const ACTOR_CACHE_TTL_SECS = 30 * 60; // 30 minutes
Expand Down
6 changes: 3 additions & 3 deletions src/tools/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import log from '@apify/log';
import { ApifyClient } from '../apify-client.js';
import {
ACTOR_MAX_MEMORY_MBYTES,
CALL_ACTOR_MCP_MISSING_TOOL_NAME_MSG,
HelperTools,
RAG_WEB_BROWSER,
RAG_WEB_BROWSER_ADDITIONAL_DESC,
Expand Down Expand Up @@ -384,8 +385,7 @@ EXAMPLES:
// For definition resolution we always use token-based client; Skyfire is only for actual Actor runs
const apifyClientForDefinition = new ApifyClient({ token: apifyToken });
// Resolve MCP server URL
const needsMcpUrl = mcpToolName !== undefined || performStep === 'info';
const mcpServerUrlOrFalse = needsMcpUrl ? await getActorMcpUrlCached(baseActorName, apifyClientForDefinition) : false;
const mcpServerUrlOrFalse = await getActorMcpUrlCached(baseActorName, apifyClientForDefinition);
const isActorMcpServer = mcpServerUrlOrFalse && typeof mcpServerUrlOrFalse === 'string';

// Standby Actors, thus MCPs, are not supported in Skyfire mode
Expand Down Expand Up @@ -465,7 +465,7 @@ EXAMPLES:
// and does not provide the tool name.
const isMcpToolNameInvalid = mcpToolName === undefined || mcpToolName.trim().length === 0;
if (isActorMcpServer && isMcpToolNameInvalid) {
return buildMCPResponse([`When calling an MCP server Actor, you must specify the tool name in the actor parameter as "{actorName}:{toolName}" in the "actor" input property.`]);
return buildMCPResponse([CALL_ACTOR_MCP_MISSING_TOOL_NAME_MSG]);
}

// Handle MCP tool calls
Expand Down
22 changes: 21 additions & 1 deletion tests/integration/suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CallToolResultSchema, ToolListChangedNotificationSchema } from '@modelc
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';

import { ApifyClient } from '../../src/apify-client.js';
import { defaults, HelperTools } from '../../src/const.js';
import { CALL_ACTOR_MCP_MISSING_TOOL_NAME_MSG, defaults, HelperTools } from '../../src/const.js';
import { addTool } from '../../src/tools/helpers.js';
import { defaultTools, toolCategories } from '../../src/tools/index.js';
import { actorNameToToolName } from '../../src/tools/utils.js';
Expand Down Expand Up @@ -989,5 +989,25 @@ export function createIntegrationTestsSuite(

await client.close();
});

it.only('should return error message when tryging to call MCP server Actor without tool name in actor parameter', async () => {
client = await createClientFn({ tools: ['actors'] });

const response = await client.callTool({
name: 'call-actor',
arguments: {
actor: ACTOR_MCP_SERVER_ACTOR_NAME,
step: 'call',
input: { url: 'https://docs.apify.com' },
},
});

expect(response.content).toBeDefined();
const content = response.content as { text: string }[];
expect(content.length).toBeGreaterThan(0);
expect(content[0].text).toContain(CALL_ACTOR_MCP_MISSING_TOOL_NAME_MSG);

await client.close();
});
});
}