leanix-pathfinder-mcp-server
Version:
MCP Server for LeanIX Pathfinder API - Enterprise Architecture Management Platform
332 lines • 11.3 kB
JavaScript
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