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
20 changes: 10 additions & 10 deletions src/utils/tools-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { getActorOutput } from '../tools/get-actor-output.js';
import { addTool } from '../tools/helpers.js';
import { getActorsAsTools, toolCategories, toolCategoriesEnabledByDefault } from '../tools/index.js';
import type { Input, InternalTool, InternalToolArgs, ToolCategory, ToolEntry } from '../types.js';
import { doesMcpClientSupportDynamicTools } from './mcp-clients.js';
import { getExpectedToolsByCategories } from './tools.js';

// Lazily-computed cache of internal tools by name to avoid circular init issues.
Expand All @@ -41,7 +40,7 @@ function getInternalToolByNameMap(): Map<string, ToolEntry> {
export async function loadToolsFromInput(
input: Input,
apifyClient: ApifyClient,
initializeRequestData?: InitializeRequest,
_initializeRequestData?: InitializeRequest,
): Promise<ToolEntry[]> {
// Helpers for readability
const normalizeSelectors = (value: Input['tools']): (string | ToolCategory)[] | undefined => {
Expand Down Expand Up @@ -108,7 +107,7 @@ export async function loadToolsFromInput(
} // else: selectors provided but none are actors => do not load defaults

// Compose final tool list
let result: ToolEntry[] = [];
const result: ToolEntry[] = [];

// Internal tools
if (selectorsProvided) {
Expand Down Expand Up @@ -142,15 +141,16 @@ export async function loadToolsFromInput(
result.push(getActorOutput);
}

// TEMP: for now we disable this swapping logic as the add-actor tool was misbehaving in some clients
// Handle client capabilities logic for 'actors' category to swap call-actor for add-actor
// if client supports dynamic tools.
const selectorContainsCallActor = selectors?.some((s) => s === HelperTools.ACTOR_CALL);
if (doesMcpClientSupportDynamicTools(initializeRequestData) && hasCallActor && !selectorContainsCallActor) {
// Remove call-actor
result = result.filter((entry) => entry.tool.name !== HelperTools.ACTOR_CALL);
// Replace with add-actor if not already present
if (!hasAddActorTool) result.push(addTool);
}
// const selectorContainsCallActor = selectors?.some((s) => s === HelperTools.ACTOR_CALL);
// if (doesMcpClientSupportDynamicTools(initializeRequestData) && hasCallActor && !selectorContainsCallActor) {
// // Remove call-actor
// result = result.filter((entry) => entry.tool.name !== HelperTools.ACTOR_CALL);
// // Replace with add-actor if not already present
// if (!hasAddActorTool) result.push(addTool);
// }

// De-duplicate by tool name for safety
const seen = new Set<string>();
Expand Down
34 changes: 28 additions & 6 deletions tests/integration/suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -979,23 +979,45 @@ export function createIntegrationTestsSuite(
expect(tools.tools.length).toBeGreaterThan(0);
});

it.runIf(options.transport === 'streamable-http')('should swap call-actor for add-actor when client supports dynamic tools', async () => {
// TEMP: this logic is currently disabled, see src/utils/tools-loader.ts
// it.runIf(options.transport === 'streamable-http')('should swap call-actor for add-actor when client supports dynamic tools', async () => {
// client = await createClientFn({ clientName: 'Visual Studio Code', tools: ['actors'] });
// const names = getToolNames(await client.listTools());

// // should not contain call-actor but should contain add-actor
// expect(names).not.toContain('call-actor');
// expect(names).toContain('add-actor');

// await client.close();
// });
// it.runIf(options.transport === 'streamable-http')(
// `should swap call-actor for add-actor when client supports dynamic tools for default tools`, async () => {
// client = await createClientFn({ clientName: 'Visual Studio Code' });
// const names = getToolNames(await client.listTools());

// // should not contain call-actor but should contain add-actor
// expect(names).not.toContain('call-actor');
// expect(names).toContain('add-actor');

// await client.close();
// });
it.runIf(options.transport === 'streamable-http')('should NOT swap call-actor for add-actor even when client supports dynamic tools', async () => {
client = await createClientFn({ clientName: 'Visual Studio Code', tools: ['actors'] });
const names = getToolNames(await client.listTools());

// should not contain call-actor but should contain add-actor
expect(names).not.toContain('call-actor');
expect(names).toContain('add-actor');
expect(names).toContain('call-actor');
expect(names).not.toContain('add-actor');

await client.close();
});
it.runIf(options.transport === 'streamable-http')(`should swap call-actor for add-actor when client supports dynamic tools for default tools`, async () => {
it.runIf(options.transport === 'streamable-http')(`should NOT swap call-actor for add-actor even when client supports dynamic tools for default tools`, async () => {
client = await createClientFn({ clientName: 'Visual Studio Code' });
const names = getToolNames(await client.listTools());

// should not contain call-actor but should contain add-actor
expect(names).not.toContain('call-actor');
expect(names).toContain('add-actor');
expect(names).toContain('call-actor');
expect(names).not.toContain('add-actor');

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