// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { CallToolRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { ClientOptions } from '@stainless-api/pylon-internal'; import Pylon from '@stainless-api/pylon-internal'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; import getAgenticHelpTool from './get-agentic-help-tool'; import { McpOptions } from './options'; import { HandlerFunction, McpTool } from './types'; export { McpOptions } from './options'; export { ClientOptions } from '@stainless-api/pylon-internal'; export const newMcpServer = () => new McpServer( { name: 'stainless_api_pylon_internal_api', version: '0.1.0-alpha.33', }, { capabilities: { tools: {}, logging: {} } }, ); // Create server instance export const server = newMcpServer(); /** * Initializes the provided MCP Server with the given tools and handlers. * If not provided, the default client, tools and handlers will be used. */ export function initMcpServer(params: { server: Server | McpServer; clientOptions?: ClientOptions; mcpOptions?: McpOptions; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; const logAtLevel = (level: 'debug' | 'info' | 'warning' | 'error') => (message: string, ...rest: unknown[]) => { void server.sendLoggingMessage({ level, data: { message, rest }, }); }; const logger = { debug: logAtLevel('debug'), info: logAtLevel('info'), warn: logAtLevel('warning'), error: logAtLevel('error'), }; let client = new Pylon({ logger, ...params.clientOptions, defaultHeaders: { ...params.clientOptions?.defaultHeaders, 'X-Stainless-MCP': 'true', }, }); const providedTools = selectTools(params.mcpOptions); const toolMap = Object.fromEntries(providedTools.map((mcpTool) => [mcpTool.tool.name, mcpTool])); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: providedTools.map((mcpTool) => mcpTool.tool), }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const mcpTool = toolMap[name]; if (!mcpTool) { throw new Error(`Unknown tool: ${name}`); } return executeHandler(mcpTool.handler, client, args); }); server.setRequestHandler(SetLevelRequestSchema, async (request) => { const { level } = request.params; switch (level) { case 'debug': client = client.withOptions({ logLevel: 'debug' }); break; case 'info': client = client.withOptions({ logLevel: 'info' }); break; case 'notice': case 'warning': client = client.withOptions({ logLevel: 'warn' }); break; case 'error': client = client.withOptions({ logLevel: 'error' }); break; default: client = client.withOptions({ logLevel: 'off' }); break; } return {}; }); } /** * Selects the tools to include in the MCP Server based on the provided options. */ export function selectTools(options?: McpOptions): McpTool[] { const includedTools = [codeTool()]; if (options?.includeDocsTools ?? true) { includedTools.push(docsSearchTool); } if (options?.includeGetAgenticHelpTool) { includedTools.push(getAgenticHelpTool); } return includedTools; } /** * Runs the provided handler with the given client and arguments. */ export async function executeHandler( handler: HandlerFunction, client: Pylon, args: Record | undefined, ) { return await handler(client, args || {}); } export const readEnv = (env: string): string | undefined => { if (typeof (globalThis as any).process !== 'undefined') { return (globalThis as any).process.env?.[env]?.trim(); } else if (typeof (globalThis as any).Deno !== 'undefined') { return (globalThis as any).Deno.env?.get?.(env)?.trim(); } return; }; export const readEnvOrError = (env: string): string => { let envValue = readEnv(env); if (envValue === undefined) { throw new Error(`Environment variable ${env} is not set`); } return envValue; }; export const requireValue = (value: T | undefined, description: string): T => { if (value === undefined) { throw new Error(`Missing required value: ${description}`); } return value; };