index.js•6.42 kB
#!/usr/bin/env node
/**
* Web Proxy MCP Server
* Main entry point for the Model Context Protocol server
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
McpError,
ErrorCode
} from '@modelcontextprotocol/sdk/types.js';
import { TargetManager } from './src/proxy/target-manager.js';
import { ProxyServerWithSSL } from './src/proxy/proxy-server-ssl.js';
import { TrafficAnalyzer } from './src/traffic/traffic-analyzer.js';
import { BrowserSetup } from './src/setup/browser-setup.js';
import { SSLManager } from './src/ssl/ssl-manager.js';
import { ToolHandlers } from './src/tools/tool-handlers.js';
import { TOOLS, getToolNames } from './src/tools/tool-definitions.js';
class WebProxyMCPServer {
constructor() {
this.server = new Server(
{
name: 'web-proxy-mcp',
version: '1.0.0'
},
{
capabilities: {
tools: {}
}
}
);
// Initialize components
this.targetManager = new TargetManager();
this.trafficAnalyzer = new TrafficAnalyzer({
enablePersistence: true,
persistenceFile: './data/traffic-log.json',
maxEntries: 5000
});
this.sslManager = new SSLManager();
this.proxyServer = new ProxyServerWithSSL(this.targetManager, this.trafficAnalyzer, this.sslManager);
this.browserSetup = new BrowserSetup(this.targetManager);
this.toolHandlers = new ToolHandlers(
this.proxyServer,
this.targetManager,
this.browserSetup,
this.trafficAnalyzer,
this.sslManager
);
this._setupHandlers();
}
/**
* Setup MCP request handlers
* @private
*/
_setupHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: Object.entries(TOOLS).map(([name, tool]) => ({
name,
description: tool.description,
inputSchema: tool.inputSchema
}))
};
});
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
const result = await this.toolHandlers.handleTool(name, args || {});
if (result.isError) {
throw new McpError(
ErrorCode.InternalError,
result.error
);
}
return result;
} catch (error) {
console.error(`Tool error [${name}]:`, error.message);
throw new McpError(
ErrorCode.InternalError,
`Tool execution failed: ${error.message}`
);
}
});
// Handle server errors
this.server.onerror = (error) => {
console.error('[MCP Server Error]:', error);
};
process.on('SIGINT', async () => {
console.log('\\n🛑 Shutting down Web Proxy MCP Server...');
await this.shutdown();
process.exit(0);
});
}
/**
* Initialize server and load data
*/
async initialize() {
try {
console.log('🚀 Initializing Web Proxy MCP Server...');
// Load persisted data
await this.targetManager.loadTargets();
await this.trafficAnalyzer.loadPersistedEntries();
await this.sslManager.initialize();
// Add some default targets for testing
await this._addDefaultTargets();
console.log(`✅ Server initialized successfully`);
console.log(`📊 Loaded targets: ${this.targetManager.getStats().total}`);
console.log(`📈 Loaded traffic entries: ${this.trafficAnalyzer.getEntryCount()}`);
console.log(`🔒 SSL Manager: ${this.sslManager.getCAStatus().currentCA}`);
console.log(`🔧 Available tools: ${getToolNames().length}`);
} catch (error) {
console.error('❌ Failed to initialize server:', error.message);
throw error;
}
}
/**
* Start the MCP server
*/
async start() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.log('🔌 Web Proxy MCP Server connected via stdio');
console.log('📡 Ready to receive MCP requests');
}
/**
* Shutdown server and cleanup
*/
async shutdown() {
try {
// Stop proxy server if running
if (this.proxyServer.isRunning()) {
await this.proxyServer.stop();
}
// Save data
await this.targetManager.saveTargets();
console.log('✅ Shutdown complete');
} catch (error) {
console.error('❌ Error during shutdown:', error.message);
}
}
/**
* Add default targets for testing
* @private
*/
async _addDefaultTargets() {
const defaultTargets = [
{
domain: 'httpbin.org',
description: 'HTTP testing service for proxy verification',
enabled: true,
captureHeaders: true,
captureBody: false
},
{
domain: 'jsonplaceholder.typicode.com',
description: 'JSON API testing service',
enabled: true,
captureHeaders: true,
captureBody: true
},
{
domain: 'example.com',
description: 'Example domain for testing',
enabled: false,
captureHeaders: true,
captureBody: false
}
];
for (const target of defaultTargets) {
this.targetManager.addTarget(
target.domain,
target.description,
{
enabled: target.enabled,
captureHeaders: target.captureHeaders,
captureBody: target.captureBody
}
);
}
console.log(`📋 Added ${defaultTargets.length} default targets`);
}
}
/**
* Main execution
*/
async function main() {
try {
const server = new WebProxyMCPServer();
await server.initialize();
await server.start();
} catch (error) {
console.error('💥 Fatal error:', error.message);
process.exit(1);
}
}
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
console.error('💥 Uncaught Exception:', error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('💥 Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
// Start the server
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}
export { WebProxyMCPServer };