UNPKG

leanix-pathfinder-mcp-server

Version:

MCP Server for LeanIX Pathfinder API - Enterprise Architecture Management Platform

332 lines 11.3 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import express from 'express'; import cors from 'cors'; import { LeanIXClient } from './client.js'; const app = express(); app.use(cors()); app.use(express.json()); // Initialize LeanIX client const config = { baseUrl: process.env.LEANIX_BASE_URL || '', clientId: process.env.LEANIX_CLIENT_ID || '', clientSecret: process.env.LEANIX_CLIENT_SECRET || '' }; const client = new LeanIXClient(config); // Tool handling function async function handleToolCall(name, args) { switch (name) { case 'leanix_get_suggestions': { const { q, count = 5 } = args; const queryParams = client.buildQueryParams({ q, count }); const response = await client.get(`/services/pathfinder/v1/suggestions${queryParams}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_list_fact_sheets': { const { types, ids, relations, pageSize, cursor } = args; const queryParams = client.buildQueryParams({ types, ids, relations, pageSize, cursor }); const response = await client.get(`/services/pathfinder/v1/factSheets${queryParams}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_get_fact_sheet': { const { id } = args; const response = await client.get(`/services/pathfinder/v1/factSheets/${id}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_create_fact_sheet': { const { factSheet } = args; const response = await client.post('/services/pathfinder/v1/factSheets', factSheet); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_execute_graphql': { const { query, variables } = args; const response = await client.post('/services/pathfinder/v1/graphql', { query, variables }); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_list_bookmarks': { const { bookmarkType, pageSize, cursor } = args; const queryParams = client.buildQueryParams({ bookmarkType, pageSize, cursor }); const response = await client.get(`/services/pathfinder/v1/bookmarks${queryParams}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_get_data_model': { const { workspaceId } = args; const queryParams = client.buildQueryParams({ workspaceId }); const response = await client.get(`/services/pathfinder/v1/models/dataModel${queryParams}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } case 'leanix_get_meta_model': { const { factSheetType } = args; const queryParams = client.buildQueryParams({ factSheetType }); const response = await client.get(`/services/pathfinder/v1/models/metaModel${queryParams}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2) } ] }; } default: throw new Error(`Unknown tool: ${name}`); } } // Create MCP Server instance const server = new Server({ name: 'leanix-pathfinder-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, }); // Define core MCP tools for Copilot Studio const tools = [ { name: 'leanix_get_suggestions', description: 'Get search suggestions from LeanIX', inputSchema: { type: 'object', properties: { q: { type: 'string', description: 'Search query' }, count: { type: 'number', description: 'Number of results', default: 5 } }, required: ['q'] } }, { name: 'leanix_list_fact_sheets', description: 'List fact sheets with optional filtering', inputSchema: { type: 'object', properties: { types: { type: 'string', description: 'Comma-separated fact sheet types' }, pageSize: { type: 'number', description: 'Number of results per page' }, cursor: { type: 'string', description: 'Pagination cursor' } } } }, { name: 'leanix_get_fact_sheet', description: 'Get detailed information about a specific fact sheet', inputSchema: { type: 'object', properties: { id: { type: 'string', description: 'Fact sheet ID' } }, required: ['id'] } }, { name: 'leanix_create_fact_sheet', description: 'Create a new fact sheet', inputSchema: { type: 'object', properties: { factSheet: { type: 'object', properties: { name: { type: 'string', description: 'Fact sheet name' }, type: { type: 'string', description: 'Fact sheet type' }, displayName: { type: 'string', description: 'Display name' }, description: { type: 'string', description: 'Description' } }, required: ['name', 'type'] } }, required: ['factSheet'] } }, { name: 'leanix_execute_graphql', description: 'Execute a GraphQL query', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'GraphQL query string' }, variables: { type: 'object', description: 'Query variables' } }, required: ['query'] } }, { name: 'leanix_list_bookmarks', description: 'List all bookmarks', inputSchema: { type: 'object', properties: { bookmarkType: { type: 'string', description: 'Filter by bookmark type' }, pageSize: { type: 'number', description: 'Number of results per page' } } } }, { name: 'leanix_get_data_model', description: 'Get the data model for the workspace', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID' } } } }, { name: 'leanix_get_meta_model', description: 'Get the meta model', inputSchema: { type: 'object', properties: { factSheetType: { type: 'string', description: 'Filter by fact sheet type' } } } } ]; // Set up MCP server handlers server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Streamable MCP endpoint for Microsoft Copilot Studio app.post('/mcp', async (req, res) => { try { const { method, params, id } = req.body; // Handle MCP initialize request if (method === 'initialize') { return res.json({ jsonrpc: '2.0', id, result: { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'leanix-pathfinder-mcp-server', version: '1.0.0' } } }); } // Handle tools/list request if (method === 'tools/list') { return res.json({ jsonrpc: '2.0', id, result: { tools } }); } // Handle tools/call request if (method === 'tools/call') { try { const { name, arguments: args } = params; const toolResult = await handleToolCall(name, args); return res.json({ jsonrpc: '2.0', id, result: toolResult }); } catch (error) { return res.status(500).json({ jsonrpc: '2.0', id, error: { code: -32603, message: 'Internal error', data: error instanceof Error ? error.message : String(error) } }); } } // Handle unknown methods return res.status(400).json({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found' } }); } catch (error) { console.error('MCP endpoint error:', error); return res.status(500).json({ jsonrpc: '2.0', id: req.body.id, error: { code: -32603, message: 'Internal error', data: error instanceof Error ? error.message : String(error) } }); } }); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), version: '1.0.0', service: 'LeanIX Pathfinder Streamable MCP Server', transport: 'streamable' }); }); // Start the server const port = process.env.PORT || 3001; app.listen(port, () => { console.log(`🚀 LeanIX Pathfinder Streamable MCP Server running on port ${port}`); console.log(`📡 MCP endpoint: http://localhost:${port}/mcp`); console.log(`❤️ Health check: http://localhost:${port}/health`); console.log(`🔧 Ready for Microsoft Copilot Studio integration!`); }); export default app; //# sourceMappingURL=streamable-mcp-server.js.map