vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
116 lines (113 loc) • 5.51 kB
JavaScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import dotenv from "dotenv";
import logger from "./logger.js";
import './tools/index.js';
import './services/request-processor/index.js';
import { getAllTools, executeTool } from './services/routing/toolRegistry.js';
import { addInteraction } from './services/state/sessionState.js';
import { getUnifiedSecurityConfig } from "./tools/vibe-task-manager/security/unified-security-config.js";
dotenv.config();
export function createServer(loadedConfigParam) {
logger.info({
receivedConfig: loadedConfigParam,
hasMapping: Boolean(loadedConfigParam.llm_mapping),
mappingKeys: loadedConfigParam.llm_mapping ? Object.keys(loadedConfigParam.llm_mapping) : [],
mappingValues: loadedConfigParam.llm_mapping
}, 'createServer received config object.');
try {
const unifiedSecurityConfig = getUnifiedSecurityConfig();
unifiedSecurityConfig.initializeFromMCPConfig(loadedConfigParam);
logger.info('Unified security configuration initialized from MCP client config');
}
catch (error) {
logger.warn({ err: error }, 'Failed to initialize unified security configuration from MCP client config');
}
const server = new McpServer({
name: "vibe-coder-mcp",
version: "1.0.0"
}, {
instructions: `
Vibe Coder MCP server provides tools for development automation:
1. Fullstack Starter Kit - Generates custom full-stack project starter kits
2. Research - Performs deep research using Perplexity Sonar
3. Generate Rules - Creates project-specific development rules
4. Generate PRD - Creates comprehensive product requirements documents
5. Generate User Stories - Creates detailed user stories
6. Generate Task List - Creates detailed development task lists
All generated artifacts are stored in structured directories.
`
});
logger.info('MCP Server initialized');
logger.info('Registering tools from Tool Registry...');
const allToolDefinitions = getAllTools();
if (allToolDefinitions.length === 0) {
logger.warn('No tools found in the registry. Ensure tools register themselves via imports.');
}
for (const definition of allToolDefinitions) {
logger.debug(`Registering tool "${definition.name}" with MCP server.`);
server.tool(definition.name, definition.description, definition.inputSchema, async (params, extra) => {
logger.debug({ configInHandler: loadedConfigParam }, 'Tool handler closure using config object.');
let sessionId = 'placeholder-session-id';
let transportType = 'unknown';
if (extra && typeof extra === 'object') {
if ('sessionId' in extra && typeof extra.sessionId === 'string') {
sessionId = extra.sessionId;
}
else if ('req' in extra && extra.req && typeof extra.req === 'object') {
const req = extra.req;
if (req.query && req.query.sessionId) {
sessionId = req.query.sessionId;
}
else if (req.body && req.body.session_id) {
sessionId = req.body.session_id;
}
else if (req.headers && req.headers['x-session-id']) {
sessionId = req.headers['x-session-id'];
}
}
if ('transportType' in extra && typeof extra.transportType === 'string') {
transportType = extra.transportType;
}
}
if (sessionId === 'placeholder-session-id') {
sessionId = 'stdio-session';
transportType = 'stdio';
logger.warn({ toolName: definition.name }, "Using stdio session ID. SSE notifications will be limited to polling.");
}
const context = {
sessionId,
transportType
};
logger.debug({ toolName: definition.name, sessionId: context.sessionId, transportType: context.transportType }, "Server handler executing tool with context");
let executionConfig;
try {
const configToCopy = {
...loadedConfigParam,
llm_mapping: loadedConfigParam.llm_mapping || {}
};
executionConfig = JSON.parse(JSON.stringify(configToCopy));
logger.debug({ configForExecution: executionConfig }, 'Deep copied config for executeTool call.');
}
catch (copyError) {
logger.error({ err: copyError }, 'Failed to deep copy config in handler. Using original reference (may cause issues).');
executionConfig = loadedConfigParam;
}
const result = await executeTool(definition.name, params, executionConfig, context);
const responseWithTimestamp = {
...result,
timestamp: Date.now(),
};
addInteraction(sessionId, {
toolCall: {
name: definition.name,
params: params,
timestamp: Date.now()
},
response: responseWithTimestamp,
});
return result;
});
}
logger.info(`Registered ${allToolDefinitions.length} tools dynamically with MCP server.`);
return server;
}