init project
This commit is contained in:
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import express from 'express';
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
import { createServer } from '../server.js';
|
||||
import { processManager } from '../lib/processManager.js';
|
||||
import { browserManager } from '../tools/browser/index.js';
|
||||
import { dockerManager } from '../tools/docker/index.js';
|
||||
import { logger } from '../lib/logger.js';
|
||||
import { config } from '../config.js';
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
if (config.httpToken) {
|
||||
app.use((req, res, next) => {
|
||||
const auth = req.header('authorization');
|
||||
if (auth === `Bearer ${config.httpToken}`) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
res.status(401).json({ error: 'Unauthorized' });
|
||||
});
|
||||
}
|
||||
else if (config.httpHost !== '127.0.0.1' && config.httpHost !== 'localhost') {
|
||||
logger.error(`Refusing to bind to non-localhost host "${config.httpHost}" without MCP_HTTP_TOKEN set. ` +
|
||||
'Set MCP_HTTP_TOKEN, or bind to 127.0.0.1/localhost for unauthenticated local use.');
|
||||
process.exit(1);
|
||||
}
|
||||
const transports = new Map();
|
||||
app.post('/mcp', async (req, res) => {
|
||||
try {
|
||||
const sessionId = req.header('mcp-session-id');
|
||||
let transport = sessionId ? transports.get(sessionId) : undefined;
|
||||
if (!transport) {
|
||||
const server = createServer();
|
||||
transport = new StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => randomUUID(),
|
||||
onsessioninitialized: (id) => {
|
||||
transports.set(id, transport);
|
||||
logger.info(`http session initialized: ${id}`);
|
||||
},
|
||||
onsessionclosed: (id) => {
|
||||
transports.delete(id);
|
||||
logger.info(`http session closed: ${id}`);
|
||||
},
|
||||
});
|
||||
await server.connect(transport);
|
||||
}
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
}
|
||||
catch (error) {
|
||||
logger.error('error handling POST /mcp', { error: error instanceof Error ? error.message : error });
|
||||
if (!res.headersSent)
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
app.get('/mcp', async (req, res) => {
|
||||
const sessionId = req.header('mcp-session-id');
|
||||
const transport = sessionId ? transports.get(sessionId) : undefined;
|
||||
if (!transport) {
|
||||
res.status(400).send('Invalid or missing mcp-session-id');
|
||||
return;
|
||||
}
|
||||
await transport.handleRequest(req, res);
|
||||
});
|
||||
app.delete('/mcp', async (req, res) => {
|
||||
const sessionId = req.header('mcp-session-id');
|
||||
const transport = sessionId ? transports.get(sessionId) : undefined;
|
||||
if (!transport) {
|
||||
res.status(400).send('Invalid or missing mcp-session-id');
|
||||
return;
|
||||
}
|
||||
await transport.handleRequest(req, res);
|
||||
});
|
||||
app.get('/healthz', (_req, res) => {
|
||||
res.json({ status: 'ok', workspaceRoot: config.workspaceRoot });
|
||||
});
|
||||
const httpServer = app.listen(config.httpPort, config.httpHost, () => {
|
||||
logger.info(`web-dev-mcp HTTP server listening on http://${config.httpHost}:${config.httpPort}/mcp`);
|
||||
});
|
||||
async function shutdown(signal) {
|
||||
logger.info(`received ${signal}, shutting down`);
|
||||
processManager.stopAll();
|
||||
await browserManager.close();
|
||||
await dockerManager.cleanupAll();
|
||||
httpServer.close(() => process.exit(0));
|
||||
}
|
||||
process.on('SIGINT', () => void shutdown('SIGINT'));
|
||||
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
||||
//# sourceMappingURL=http.js.map
|
||||
Reference in New Issue
Block a user