import { getAppState } from '@features/app-state/getAppState';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { isError } from '@shared/core/isError';
import { McpToolError } from '@shared/mcp-tool/McpToolError';
import { z, type ZodType, type ZodTypeDef } from 'zod';
import zodToJsonSchema from 'zod-to-json-schema';
/**
* Registers the tools with the MCP server
*/
export function registerTools(server: Server): void {
const appState = getAppState();
// const tool = createGetDeclarationDependentsMcpTool();
// Use tools from app config
const allTools = [...appState.tools];
// Register tool listing
server.setRequestHandler(ListToolsRequestSchema, () => ({
tools: [
...allTools.map((tool) => ({
name: tool.name,
description: tool.description,
inputSchema: zodToJsonSchema(tool.inputSchema as ZodType<unknown, ZodTypeDef, unknown>),
})),
],
}));
// Register tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
if (allTools.map((tool) => tool.name).includes(request.params.name)) {
const tool = allTools.find((t) => t.name === request.params.name);
if (!tool) {
throw new Error(`Unknown tool: ${request.params.name}`);
}
// Get the latest state to ensure we have the current mode
const currentState = getAppState();
// Check if the tool is enabled in the current mode
if (!tool.enabledInModes.includes(currentState.mode)) {
return {
isError: true,
content: [
{
type: 'text',
text: `Tool '${tool.name}' is not available in '${appState.mode}' mode.`,
},
],
};
}
const params = (tool.inputSchema as z.ZodObject<z.ZodRawShape>).parse(request.params.arguments);
console.error(request, params);
try {
const result = await tool.handler({ params, appState: getAppState() });
console.error(result);
if (isError(result)) {
return {
isError: true,
content: [
{
type: 'text',
text: result.message,
},
],
};
}
return {
isError: false,
content: result.map((content) => {
if (content.type === 'json') {
return {
type: 'text',
text: JSON.stringify(content.data, null, 2),
};
}
return content;
}),
};
} catch (error) {
if (error instanceof McpToolError) {
return {
isError: true,
content: [
{
type: 'text',
text: error.message,
},
],
};
}
// Log unexpected errors but return safe message
console.error('Unexpected error:', error);
return {
isError: true,
content: [
{
type: 'text',
text: 'An unexpected error occurred',
},
],
};
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
} catch (error) {
if (error instanceof z.ZodError) {
throw new Error(`Invalid input: ${JSON.stringify(error.errors)}`);
}
throw error;
}
});
}