"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContextInjectionServer = void 0;
const http_1 = __importDefault(require("http"));
const config_service_1 = require("./services/config.service");
const context_service_1 = require("./services/context.service");
const port_1 = require("./utils/port");
/**
* MCP Server for context injection
*/
class ContextInjectionServer {
/**
* Initialize the server
* @param configPath - Path to the configuration file
*/
constructor(configPath) {
this.server = null;
this.actualPort = null;
this.configService = new config_service_1.ConfigService(configPath);
const config = this.configService.getConfig();
// Initialize context service with Knowledge Graph reference settings
this.contextService = new context_service_1.ContextService(config.contextPath, config.knowledgeGraphReference, config.knowledgeGraphReferenceText);
}
/**
* Start the server
* @param options - Server start options
*/
async start(options) {
const config = this.configService.getConfig();
const preferredPort = config.port;
try {
// Attempt to find an available port
let port = preferredPort;
// Check if preferred port is in use
const pid = await (0, port_1.findProcessUsingPort)(port);
if (pid) {
// If process is found using the port
if (options?.forceKill) {
console.log(`Port ${port} is in use by process ${pid}. Attempting to kill it...`);
const killed = await (0, port_1.killProcess)(pid);
if (!killed) {
console.warn(`Could not kill process ${pid}. Trying to find another available port...`);
port = await (0, port_1.findAvailablePort)(preferredPort + 1);
}
}
else {
console.log(`Port ${port} is in use. Trying to find another available port...`);
port = await (0, port_1.findAvailablePort)(preferredPort + 1);
}
}
this.actualPort = port;
// Create HTTP server
this.server = http_1.default.createServer((req, res) => {
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// Handle preflight requests
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
// Handle context injection requests
if (req.method === 'POST' && req.url === '/inject-context') {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
try {
const requestData = JSON.parse(body);
this.handleContextInjection(requestData, res);
}
catch (error) {
console.error('Error processing request:', error instanceof Error ? error.message : String(error));
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: 'Invalid request',
message: error instanceof Error ? error.message : 'Unknown error'
}));
}
});
}
else if (req.method === 'GET' && req.url === '/health') {
// Health check endpoint
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
}
else if (req.method === 'GET' && req.url === '/status') {
// Server status endpoint
this.handleStatusRequest(res);
}
else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not found' }));
}
});
// Set up error handling for the server
this.server.on('error', (error) => {
if (error.code === 'EADDRINUSE') {
console.error(`Port ${port} is already in use. Server could not start.`);
console.log('Please try starting the server again or specify a different port.');
}
else {
console.error('Server error:', error);
}
});
// Start listening on the selected port
this.server.listen(port, () => {
console.log(`Context Injection MCP Server running on port ${port}`);
console.log(`Health check available at http://localhost:${port}/health`);
if (port !== preferredPort) {
console.log(`Note: Originally configured port ${preferredPort} was in use, using port ${port} instead.`);
// Update the config with the new port for future use
this.configService.updateConfig({ port });
}
if (config.knowledgeGraphReference) {
console.log('Knowledge Graph Reference is ENABLED');
}
});
}
catch (error) {
console.error('Failed to start server:', error instanceof Error ? error.message : String(error));
}
}
/**
* Get the actual port the server is running on
* @returns The port number or null if server is not running
*/
getPort() {
return this.actualPort;
}
/**
* Handle server status request
* @param res - HTTP response object
*/
handleStatusRequest(res) {
const config = this.configService.getConfig();
const statusResponse = {
status: 'ok',
knowledgeGraphReference: config.knowledgeGraphReference,
port: config.port,
autoInject: config.autoInject,
triggerKeywords: config.triggerKeywords,
contextPath: config.contextPath
};
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(statusResponse));
}
/**
* Handle context injection request
* @param requestData - Request data
* @param res - HTTP response object
*/
async handleContextInjection(requestData, res) {
const config = this.configService.getConfig();
const { message } = requestData;
if (!message) {
const response = {
injected: false,
error: 'Message is required'
};
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
return;
}
try {
// Check if we should inject context
const shouldInject = config.autoInject ||
this.contextService.shouldInjectContext(message, config.triggerKeywords);
if (shouldInject) {
// Get context with optional Knowledge Graph reference
const contextText = await this.contextService.formatContextForInjection();
const response = {
injected: true,
contextText,
modifiedMessage: `${contextText}\n\nUser's original message: ${message}`
};
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
console.log('Context injected into conversation');
}
else {
const response = {
injected: false,
originalMessage: message
};
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
}
}
catch (error) {
// Handle errors gracefully
console.error('Error during context injection:', error instanceof Error ? error.message : String(error));
const response = {
injected: false,
error: `Failed to inject context: ${error instanceof Error ? error.message : String(error)}`,
originalMessage: message
};
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(response));
}
}
/**
* Stop the server
*/
stop() {
if (this.server) {
this.server.close();
console.log('Server stopped');
}
}
}
exports.ContextInjectionServer = ContextInjectionServer;
//# sourceMappingURL=server.js.map