| 21 | // surface/decision-space optimization; the backend still enforces scope, so a |
| 22 | // skipped tool is never the security boundary. |
| 23 | function gateRegistration(server: McpServer, allowed: ReadonlySet<string>): void { |
| 24 | const original = server.registerTool.bind(server) as (...a: unknown[]) => unknown; |
| 25 | server.registerTool = ((name: string, ...rest: unknown[]) => { |
| 26 | if (!allowed.has(name)) { |
| 27 | // Skip: not wired into the server's tool list. Returns undefined; the |
| 28 | // register*Tools callers don't use the return value. |
| 29 | return undefined as unknown as ReturnType<McpServer["registerTool"]>; |
| 30 | } |
| 31 | return original(name, ...rest) as ReturnType<McpServer["registerTool"]>; |
| 32 | }) as McpServer["registerTool"]; |
| 33 | } |
| 34 | |
| 35 | export function buildServer({ client, version = "0.1.0" }: BuildServerOptions): McpServer { |
| 36 | const server = new McpServer({ |