Skip to content

Commit 0a707f4

Browse files
committed
better error handling and logging
1 parent aadbfa3 commit 0a707f4

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

src/mcp/server.ts

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
66
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
77
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
8-
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
8+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from '@modelcontextprotocol/sdk/types.js';
99
import type { ActorCallOptions } from 'apify-client';
1010

1111
import log from '@apify/log';
@@ -116,15 +116,14 @@ export class ActorsMcpServer {
116116
* @returns {object} - The response object containing the tools.
117117
*/
118118
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
119-
// TODO if there is actor-mcp as a tool, also list the tools from that Actor
120119
const tools = Array.from(this.tools.values()).map((tool) => (tool.tool));
121120
return { tools };
122121
});
123122

124123
/**
125124
* Handles the request to call a tool.
126125
* @param {object} request - The request object containing tool name and arguments.
127-
* @throws {Error} - Throws an error if the tool is unknown or arguments are invalid.
126+
* @throws {McpError} - based on the McpServer class code from the typescript MCP SDK
128127
*/
129128
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
130129
const { name, arguments: args } = request.params;
@@ -135,27 +134,47 @@ export class ActorsMcpServer {
135134

136135
// Validate token
137136
if (!apifyToken) {
138-
throw new Error('APIFY_TOKEN is required but not set in the environment variables or passed as a parameter.');
137+
const msg = 'APIFY_TOKEN is required. It must be set in the environment variables or passed as a parameter in the body.';
138+
log.error(msg);
139+
await this.server.sendLoggingMessage({ level: 'error', data: msg });
140+
throw new McpError(
141+
ErrorCode.InvalidParams,
142+
msg,
143+
);
139144
}
140145

141-
// TODO - log errors
142-
// TODO: handle errors better, server.sendLoggingMessage ( )
143-
// TODO - do not raise but return mcp errors
144146
// TODO - if connection is /mcp client will not receive notification on tool change
145147

146148
// Find tool by name or actor full name
147149
const tool = Array.from(this.tools.values())
148150
.find((t) => t.tool.name === name || (t.type === 'actor' && (t.tool as ActorTool).actorFullName === name));
149151
if (!tool) {
150-
await this.server.sendLoggingMessage({ level: 'info', data: `Unknown tool $\{name}, available tools ${this.getToolNames()}` });
151-
throw new Error(`Unknown tool: ${name}`);
152+
const msg = `Tool ${name} not found. Available tools: ${this.getToolNames().join(', ')}`;
153+
log.error(msg);
154+
await this.server.sendLoggingMessage({ level: 'error', data: msg });
155+
throw new McpError(
156+
ErrorCode.InvalidParams,
157+
msg,
158+
);
152159
}
153160
if (!args) {
154-
throw new Error(`Missing arguments for tool: ${name}`);
161+
const msg = `Missing arguments for tool ${name}`;
162+
log.error(msg);
163+
await this.server.sendLoggingMessage({ level: 'error', data: msg });
164+
throw new McpError(
165+
ErrorCode.InvalidParams,
166+
msg,
167+
);
155168
}
156169
log.info(`Validate arguments for tool: ${tool.tool.name} with arguments: ${JSON.stringify(args)}`);
157170
if (!tool.tool.ajvValidate(args)) {
158-
throw new Error(`Invalid arguments for tool ${tool.tool.name}: args: ${JSON.stringify(args)} error: ${JSON.stringify(tool?.tool.ajvValidate.errors)}`);
171+
const msg = `Invalid arguments for tool ${tool.tool.name}: args: ${JSON.stringify(args)} error: ${JSON.stringify(tool?.tool.ajvValidate.errors)}`;
172+
log.error(msg);
173+
await this.server.sendLoggingMessage({ level: 'error', data: msg });
174+
throw new McpError(
175+
ErrorCode.InvalidParams,
176+
msg,
177+
);
159178
}
160179

161180
try {
@@ -207,11 +226,23 @@ export class ActorsMcpServer {
207226
return { content };
208227
}
209228
} catch (error) {
210-
log.error(`Error calling tool: ${error}`);
211-
throw new Error(`Error calling tool: ${error}`);
229+
log.error(`Error calling tool ${name}: ${error}`);
230+
throw new McpError(
231+
ErrorCode.InternalError,
232+
`An error occurred while calling the tool.`,
233+
);
212234
}
213235

214-
throw new Error(`Tool ${name} is not implemented`);
236+
const msg = `Unknown tool: ${name}`;
237+
log.error(msg);
238+
await this.server.sendLoggingMessage({
239+
level: 'error',
240+
data: msg,
241+
});
242+
throw new McpError(
243+
ErrorCode.InvalidParams,
244+
msg,
245+
);
215246
});
216247
}
217248

0 commit comments

Comments
 (0)