server.js•2.27 kB
import express from "express";
import cors from "cors";
import bodyParser from "body-parser";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { config, validateConfig } from './config.js';
import { TwentyAPIClient } from './api/client.js';
import { getAllTools, executeTool } from './tools/index.js';
import { setupRoutes } from './routes/index.js';
import { logger } from './utils/logger.js';
export class TwentyCRMServer {
constructor() {
validateConfig();
this.apiClient = new TwentyAPIClient();
this.server = new Server(
{
name: config.name,
version: config.version,
},
{
capabilities: {
tools: {},
},
}
);
this.setupMCPHandlers();
}
setupMCPHandlers() {
// MCP Protocol: List tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: getAllTools()
};
});
// MCP Protocol: Call tool
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
logger.debug(`CallTool request received:`, { name, args });
try {
const result = await executeTool(name, args, this.apiClient);
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2)
}
]
};
} catch (error) {
logger.error(`CallTool error:`, error.message);
return {
content: [
{
type: "text",
text: `Error: ${error.message}`
}
],
isError: true
};
}
});
}
async run() {
const app = express();
app.use(cors());
app.use(bodyParser.json());
// Setup all REST routes
setupRoutes(app, this.apiClient);
app.listen(config.port, "0.0.0.0", () => {
logger.info(`Twenty CRM MCP server running on http://0.0.0.0:${config.port}`);
logger.info(`Base URL: ${config.baseUrl}`);
logger.info(`API Key configured: ${!!config.apiKey}`);
});
}
}