Skip to main content
Glama
server.ts3.71 kB
/** * Simple MCP Server for TeamCity * Direct implementation without complex abstractions */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import { info, debug as logDebug, error as logError } from '@/utils/logger'; import packageJson from '../package.json'; import { getConfig } from './config'; import { getAvailableTools, getMCPMode, getTool } from './tools'; /** * Create a simple MCP server */ export function createMCPServer(): Server { return createSimpleServer(); } export function createSimpleServer(): Server { // Server initialization const _config = getConfig(); // Load available tools to validate configuration getAvailableTools(); const server = new Server( { name: 'teamcity-mcp', version: packageJson.version, }, { capabilities: { tools: {}, prompts: undefined, resources: undefined, }, } ); // Register tool listing handler server.setRequestHandler(ListToolsRequestSchema, async () => { const currentTools = getAvailableTools(); // Get fresh list in case env changed // Listing tools in current mode info('MCP request: tools/list', { mode: getMCPMode(), count: currentTools.length }); const response = { tools: currentTools.map((tool) => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, })), }; logDebug('MCP response: tools/list', { count: response.tools.length, success: true }); return response; }); // Register tool execution handler server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; // Executing tool with arguments const started = Date.now(); info('MCP request: tools/call', { tool: name, args }); const tool = getTool(name); if (!tool) { // Unknown tool requested const availableTools = getAvailableTools(); logError('MCP error: unknown tool', undefined, { tool: name, available: availableTools.map((t) => t.name), mode: getMCPMode(), }); throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${name}. Available tools in ${getMCPMode().toUpperCase()} mode: ${availableTools.map((t) => t.name).join(', ')}` ); } try { const result = await tool.handler(args ?? {}); // Tool executed successfully // MCP SDK expects a specific format for tool responses const response = { content: result.content ?? [ { type: 'text', text: result.error ?? 'Tool executed successfully' }, ], }; const duration = Date.now() - started; const success = result?.success !== false; logDebug('MCP response: tools/call', { tool: name, success, duration, contentTypes: response.content?.map((c) => c.type), }); return response; } catch (error) { // Tool execution failed if (error instanceof McpError) { const duration = Date.now() - started; logError('MCP error: tool call', error, { tool: name, success: false, duration }); throw error; } const duration = Date.now() - started; logError('MCP error: tool call (unexpected)', error, { tool: name, success: false, duration, }); throw new McpError( ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : String(error)}` ); } }); return server; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Daghis/teamcity-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server