@sigyl-dev/cli
Version:
Official Sigyl CLI for installing and managing MCP packages. Zero-config installation for public packages, secure API-based authentication.
165 lines (154 loc) ⢠6.68 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.integrateWithExpress = integrateWithExpress;
const chalk_1 = __importDefault(require("chalk"));
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const ora_1 = __importDefault(require("ora"));
const express_scanner_1 = require("../lib/express-scanner");
const logger_1 = require("../logger");
async function integrateWithExpress(options) {
const spinner = (0, ora_1.default)("Analyzing Express application...").start();
try {
// Scan Express app for endpoints
const scanner = new express_scanner_1.ExpressScanner(options.directory);
const endpoints = await scanner.scanForEndpoints();
if (endpoints.length === 0) {
spinner.fail("No Express endpoints found!");
console.log(chalk_1.default.yellow("Make sure your Express app has route definitions"));
return;
}
spinner.text = `Generating integration code for ${endpoints.length} endpoints...`;
// Generate integration code
await generateIntegrationCode(endpoints, options);
spinner.succeed("MCP integration generated successfully!");
console.log(chalk_1.default.green("š Integration ready!"));
console.log(chalk_1.default.blue("\nš Next steps:"));
if (!options.autoAdd) {
console.log(chalk_1.default.gray("1. Add this line to your Express app:"));
console.log(chalk_1.default.cyan(` import { addMCPEndpoints } from './${options.outDir}/integration'`));
console.log(chalk_1.default.cyan(` addMCPEndpoints(app)`));
console.log(chalk_1.default.gray("\n2. Start your Express app normally:"));
console.log(chalk_1.default.cyan(" npm start"));
console.log(chalk_1.default.gray("\n3. Test with MCP Inspector:"));
console.log(chalk_1.default.cyan(` sigyl inspect http://localhost:3000${options.endpoint || '/mcp'}`));
console.log(chalk_1.default.yellow("\nā¹ļø To change the Express API address/port, set the APP_BASE_URL environment variable when running the generated MCP server. Example:"));
console.log(chalk_1.default.cyan(" APP_BASE_URL=http://myhost:4000 node server.js"));
}
else {
console.log(chalk_1.default.gray("ā
Integration automatically added to your Express app"));
console.log(chalk_1.default.gray("Start your app and visit /mcp endpoint"));
}
}
catch (error) {
spinner.fail("Integration failed");
throw error;
}
}
async function generateIntegrationCode(endpoints, options) {
// Ensure output directory exists
if (!(0, node_fs_1.existsSync)(options.outDir)) {
(0, node_fs_1.mkdirSync)(options.outDir, { recursive: true });
}
const endpoint = options.endpoint || '/mcp';
const integrationCode = `/**
* MCP Integration for Express App
* Auto-generated integration code that adds MCP endpoints to your existing Express application.
*
* This provides a single-server solution with zero network overhead.
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"
import { z } from "zod"
import type { Express, Request, Response } from "express"
interface MCPIntegrationOptions {
endpoint?: string
autoScan?: boolean
}
export function addMCPEndpoints(app: Express, options: MCPIntegrationOptions = {}) {
const mcpEndpoint = options.endpoint || '${endpoint}'
// Create MCP server instance
const createMCPServer = () => {
const server = new McpServer({
name: "express-mcp-integration",
version: "1.0.0",
})
${generateToolsCode(endpoints)}
return server.server
}
// Add MCP endpoint to Express app
app.post(mcpEndpoint, async (req: Request, res: Response) => {
try {
const server = createMCPServer()
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined })
res.on('close', () => {
transport.close()
server.close()
})
await server.connect(transport)
await transport.handleRequest(req, res, req.body)
} catch (error) {
console.error('MCP endpoint error:', error)
res.status(500).json({ error: 'Internal server error' })
}
})
console.log(\`š§ MCP endpoints added at \${mcpEndpoint}\`)
return app
}
// Export individual tools for advanced usage
${endpoints.map((endpoint, i) => `export const tool${i + 1} = "${generateToolName(endpoint)}"`).join('\n')}
`;
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(options.outDir, "integration.ts"), integrationCode);
(0, logger_1.verboseLog)("Generated integration.ts");
// Generate package.json updates
const packageUpdates = {
dependencies: {
"@modelcontextprotocol/sdk": "^1.10.1",
"zod": "^3.22.0"
}
};
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(options.outDir, "package-updates.json"), JSON.stringify(packageUpdates, null, 2));
console.log(chalk_1.default.yellow("š¦ Don't forget to install new dependencies:"));
console.log(chalk_1.default.gray("npm install @modelcontextprotocol/sdk zod"));
}
function generateToolsCode(endpoints) {
return endpoints.map(endpoint => {
const toolName = generateToolName(endpoint);
return `
// ${endpoint.method.toUpperCase()} ${endpoint.path}
server.tool(
"${toolName}",
"${endpoint.description || `${endpoint.method} ${endpoint.path}`}",
{
// Tool schema would go here based on endpoint analysis
},
async (args) => {
// Direct function call - no HTTP overhead!
// Implementation would call the actual Express route handler
return { content: [{ type: "text", text: "Tool result" }] }
}
)`;
}).join('\n');
}
function generateToolName(endpoint) {
// Same logic as existing CLI
const method = endpoint.method.toLowerCase();
const pathParts = endpoint.path
.split('/')
.filter((part) => part && part !== '')
.map((part) => {
if (part.startsWith(':')) {
return 'By' + part.slice(1).charAt(0).toUpperCase() + part.slice(2);
}
return part
.replace(/[-_]/g, ' ')
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
});
return method + pathParts.join('');
}
//# sourceMappingURL=integrate.js.map