leanix-pathfinder-mcp-server
Version:
MCP Server for LeanIX Pathfinder API - Enterprise Architecture Management Platform
225 lines • 9.06 kB
JavaScript
#!/usr/bin/env node
import express from 'express';
import cors from 'cors';
import { LeanIXClient } from './client.js';
// Express app
const app = express();
app.use(cors());
app.use(express.json());
// Initialize LeanIX client
let leanixClient = null;
function initializeClient() {
if (!leanixClient) {
const config = {
baseUrl: process.env.LEANIX_BASE_URL || '',
clientId: process.env.LEANIX_CLIENT_ID || '',
clientSecret: process.env.LEANIX_CLIENT_SECRET || '',
workspaceId: process.env.LEANIX_WORKSPACE_ID,
};
if (!config.baseUrl || !config.clientId || !config.clientSecret) {
throw new Error('Missing required LeanIX configuration. Please set LEANIX_BASE_URL, LEANIX_CLIENT_ID, and LEANIX_CLIENT_SECRET environment variables.');
}
leanixClient = new LeanIXClient(config);
}
return leanixClient;
}
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
version: '1.0.0',
service: 'LeanIX Pathfinder REST API'
});
});
// Get suggestions
app.post('/api/suggestions', async (req, res) => {
try {
const client = initializeClient();
const { q, count = 5, object = 'factSheet', perType = false, useCaseId } = req.body;
if (!q) {
return res.status(400).json({ error: 'Search query (q) is required' });
}
const queryParams = new URLSearchParams({
q,
count: count.toString(),
object,
perType: perType.toString()
});
if (useCaseId)
queryParams.append('useCaseId', useCaseId);
const response = await client.get(`/services/pathfinder/v1/suggestions?${queryParams}`);
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// List fact sheets
app.post('/api/factsheets', async (req, res) => {
try {
const client = initializeClient();
const { ids, types, pageSize, cursor, relations } = req.body;
const queryParams = new URLSearchParams();
if (ids)
queryParams.append('ids', ids);
if (types)
queryParams.append('types', types);
if (pageSize)
queryParams.append('pageSize', pageSize.toString());
if (cursor)
queryParams.append('cursor', cursor);
if (relations)
queryParams.append('relations', relations);
const response = await client.get(`/services/pathfinder/v1/factSheets?${queryParams}`);
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Get specific fact sheet
app.post('/api/factsheet', async (req, res) => {
try {
const client = initializeClient();
const { id, version } = req.body;
if (!id) {
return res.status(400).json({ error: 'Fact sheet ID is required' });
}
const queryParams = version ? `?version=${version}` : '';
const response = await client.get(`/services/pathfinder/v1/factSheets/${id}${queryParams}`);
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Create fact sheet
app.post('/api/factsheet/create', async (req, res) => {
try {
const client = initializeClient();
const { factSheet } = req.body;
if (!factSheet || !factSheet.name || !factSheet.type) {
return res.status(400).json({ error: 'FactSheet with name and type is required' });
}
const response = await client.post('/services/pathfinder/v1/factSheets', { body: factSheet });
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Update fact sheet
app.put('/api/factsheet/:id', async (req, res) => {
try {
const client = initializeClient();
const { id } = req.params;
const { factSheet, relationTypes } = req.body;
if (!factSheet) {
return res.status(400).json({ error: 'FactSheet data is required' });
}
const queryParams = relationTypes ? `?relationTypes=${relationTypes}` : '';
const response = await client.put(`/services/pathfinder/v1/factSheets/${id}${queryParams}`, { body: factSheet });
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Delete fact sheet
app.delete('/api/factsheet/:id', async (req, res) => {
try {
const client = initializeClient();
const { id } = req.params;
const { comment } = req.body;
const body = comment ? { comment } : undefined;
const response = await client.delete(`/services/pathfinder/v1/factSheets/${id}`, { body });
res.json({ message: `Fact sheet ${id} deleted successfully`, data: response.data });
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Execute GraphQL query
app.post('/api/graphql', async (req, res) => {
try {
const client = initializeClient();
const { query, variables, operationName } = req.body;
if (!query) {
return res.status(400).json({ error: 'GraphQL query is required' });
}
const graphqlRequest = {
query,
variables: variables || {},
operationName: operationName || null,
};
const response = await client.post('/services/pathfinder/v1/graphql', { body: graphqlRequest });
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// List bookmarks
app.post('/api/bookmarks', async (req, res) => {
try {
const client = initializeClient();
const { bookmarkType, pageSize, cursor } = req.body;
const queryParams = new URLSearchParams();
if (bookmarkType)
queryParams.append('bookmarkType', bookmarkType);
if (pageSize)
queryParams.append('pageSize', pageSize.toString());
if (cursor)
queryParams.append('cursor', cursor);
const response = await client.get(`/services/pathfinder/v1/bookmarks?${queryParams}`);
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Get data model
app.get('/api/models', async (req, res) => {
try {
const client = initializeClient();
const { workspaceId, useCaseId } = req.query;
const queryParams = new URLSearchParams();
if (workspaceId)
queryParams.append('workspaceId', workspaceId);
if (useCaseId)
queryParams.append('useCaseId', useCaseId);
const response = await client.get(`/services/pathfinder/v1/models?${queryParams}`);
res.json(response.data);
}
catch (error) {
const statusCode = error.response?.status || 500;
const errorMessage = error.response?.data?.errorMessage || error.message || 'Unknown error occurred';
res.status(statusCode).json({ error: errorMessage });
}
});
// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`🚀 LeanIX Pathfinder REST API Server started on port ${port}`);
console.log(`📊 Health check: http://localhost:${port}/health`);
console.log(`📖 API endpoints available at: http://localhost:${port}/api/*`);
});
export default app;
//# sourceMappingURL=rest-api-server.js.map