Spaces:
Sleeping
Sleeping
File size: 1,774 Bytes
7dc28be | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | // FastMCP's default tools/list handler runs toJsonSchema() for every tool on every request.
// Hosts that poll tools/list frequently (or many concurrent sessions) then burn a full CPU core.
// We precompute the list once before stdio connects, then replace the handler to return that snapshot.
import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import type { FastMCP } from 'fastmcp';
import { toJsonSchema } from 'xsschema';
import { logger } from './logger.js';
type AddToolArg = Parameters<FastMCP['addTool']>[0];
export function collectToolsWhileRegistering(server: FastMCP, out: AddToolArg[]): void {
const add = server.addTool.bind(server);
(server as unknown as { addTool: (tool: AddToolArg) => void }).addTool = (tool) => {
out.push(tool);
add(tool);
};
}
export async function buildCachedToolsListPayload(tools: AddToolArg[]) {
return {
tools: await Promise.all(
tools.map(async (tool) => ({
annotations: tool.annotations,
description: tool.description,
inputSchema: tool.parameters
? await toJsonSchema(tool.parameters)
: {
additionalProperties: false,
properties: {},
type: 'object' as const,
},
name: tool.name,
}))
),
};
}
export function installCachedToolsListHandler(
server: FastMCP,
listPayload: Awaited<ReturnType<typeof buildCachedToolsListPayload>>
): void {
const session = server.sessions[0];
if (!session) {
logger.warn('No MCP session; skipping tools/list cache install.');
return;
}
session.server.setRequestHandler(ListToolsRequestSchema, async () => listPayload);
logger.debug(`Installed cached tools/list (${listPayload.tools.length} tools).`);
}
|