Skip to content

Commit 5e9eb91

Browse files
committed
feat: add client for /mcp endpoint
1 parent 3cf3e09 commit 5e9eb91

File tree

3 files changed

+118
-4
lines changed

3 files changed

+118
-4
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3+
import type { CallToolRequest, ListToolsRequest } from '@modelcontextprotocol/sdk/types.js';
4+
import {
5+
CallToolResultSchema,
6+
ListToolsResultSchema,
7+
LoggingMessageNotificationSchema,
8+
} from '@modelcontextprotocol/sdk/types.js';
9+
10+
import log from '@apify/log';
11+
12+
log.setLevel(log.LEVELS.DEBUG);
13+
14+
async function main(): Promise<void> {
15+
// Create a new client with streamable HTTP transport
16+
const client = new Client({
17+
name: 'example-client',
18+
version: '1.0.0',
19+
});
20+
21+
const transport = new StreamableHTTPClientTransport(
22+
new URL('http://localhost:3000/mcp'),
23+
);
24+
25+
// Connect the client using the transport and initialize the server
26+
await client.connect(transport);
27+
log.debug('Connected to MCP server');
28+
29+
// Set up notification handlers for server-initiated messages
30+
client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => {
31+
log.debug(`Notification received: ${notification.params.level} - ${notification.params.data}`);
32+
});
33+
34+
// List and call tools
35+
await listTools(client);
36+
37+
await callSearchTool(client);
38+
await callActor(client);
39+
40+
// Keep the connection open to receive notifications
41+
log.debug('\nKeeping connection open to receive notifications. Press Ctrl+C to exit.');
42+
}
43+
44+
async function listTools(client: Client): Promise<void> {
45+
try {
46+
const toolsRequest: ListToolsRequest = {
47+
method: 'tools/list',
48+
params: {},
49+
};
50+
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
51+
log.debug(`Tools available, count: ${toolsResult.tools.length}`);
52+
for (const tool of toolsResult.tools) {
53+
log.debug(`Tool: ${tool.name}, Description: ${tool.description}`);
54+
}
55+
if (toolsResult.tools.length === 0) {
56+
log.debug('No tools available from the server');
57+
}
58+
} catch (error) {
59+
log.error(`Tools not supported by this server (${error})`);
60+
}
61+
}
62+
63+
async function callSearchTool(client: Client): Promise<void> {
64+
try {
65+
const searchRequest: CallToolRequest = {
66+
method: 'tools/call',
67+
params: {
68+
name: 'search',
69+
arguments: { search: 'rag web browser', limit: 1 },
70+
},
71+
};
72+
const searchResult = await client.request(searchRequest, CallToolResultSchema);
73+
log.debug('Search result:');
74+
searchResult.content.forEach((item) => {
75+
if (item.type === 'text') {
76+
log.debug(`\t${item.text}`);
77+
}
78+
});
79+
} catch (error) {
80+
log.error(`Error calling greet tool: ${error}`);
81+
}
82+
}
83+
84+
async function callActor(client: Client): Promise<void> {
85+
try {
86+
log.debug('\nCalling Actor...');
87+
const actorRequest: CallToolRequest = {
88+
method: 'tools/call',
89+
params: {
90+
name: 'apify/rag-web-browser',
91+
arguments: { query: 'apify mcp server' },
92+
},
93+
};
94+
const actorResult = await client.request(actorRequest, CallToolResultSchema);
95+
log.debug('Actor results:');
96+
actorResult.content.forEach((item) => {
97+
if (item.type === 'text') {
98+
log.debug(`- ${item.text}`);
99+
}
100+
});
101+
} catch (error) {
102+
log.error(`Error calling Actor: ${error}`);
103+
}
104+
}
105+
106+
main().catch((error: unknown) => {
107+
log.error('Error running MCP client:', error as Error);
108+
process.exit(1);
109+
});

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@
55

66
import { ActorsMcpServer } from './mcp-server.js';
77

8-
// eslint-disable-next-line import/no-default-export
9-
export default ActorsMcpServer;
8+
export { ActorsMcpServer };

src/main.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@ import { processInput } from './actor/input.js';
1212
import { createExpressApp } from './actor/server.js';
1313
import type { Input } from './actor/types';
1414
import { ActorsMcpServer } from './mcp-server.js';
15-
import { actorDefinitionTool, addTool, callActorGetDataset, removeTool, searchTool } from './tools/index.js';
15+
import {
16+
actorDefinitionTool,
17+
addTool,
18+
callActorGetDataset,
19+
removeTool,
20+
searchTool,
21+
} from './tools/index.js';
1622

1723
const STANDBY_MODE = Actor.getEnv().metaOrigin === 'STANDBY';
1824

1925
await Actor.init();
2026

2127
const HOST = Actor.isAtHome() ? process.env.ACTOR_STANDBY_URL as string : 'http://localhost';
22-
const PORT = Actor.isAtHome() ? Number(process.env.ACTOR_STANDBY_PORT) : 3001;
28+
const PORT = Actor.isAtHome() ? Number(process.env.ACTOR_STANDBY_PORT) : 3000;
2329

2430
if (!process.env.APIFY_TOKEN) {
2531
log.error('APIFY_TOKEN is required but not set in the environment variables.');

0 commit comments

Comments
 (0)