initial-commit (#1)
CD / test (push) Successful in 21s
CD / Check changes (push) Successful in 31s
CD / Build and push (amd64) (push) Successful in 47s
CD / Build and push (arm64) (push) Successful in 3m6s
CD / Create manifest (push) Successful in 55s

Reviewed-on: #1
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
This commit was merged in pull request #1.
This commit is contained in:
2025-07-16 07:21:12 +02:00
committed by t.behrendt
parent 4b4d2c66d9
commit e2081a19b5
199 changed files with 28879 additions and 123 deletions
+98
View File
@@ -0,0 +1,98 @@
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import express from "express";
import pino from "pino";
import { z } from "zod";
import { outlineMcpFactory } from "./outline";
const sessionIdSchema = z.string().uuid();
async function main() {
const logger = pino({
level: "debug",
});
const transports: Record<string, StreamableHTTPServerTransport> = {};
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
logger.debug(
{
body: JSON.stringify(req.body),
},
"Received MCP request"
);
const sessionIdHeader = req.headers["mcp-session-id"] as string | undefined;
let transport: StreamableHTTPServerTransport;
if (sessionIdHeader) {
const safeSessionId = sessionIdSchema.safeParse(sessionIdHeader);
if (!safeSessionId.success) {
logger.error("Invalid session ID format");
res.status(400).json({
jsonrpc: "2.0",
error: {
code: -32000,
message: "Invalid session ID format",
},
id: null,
});
return;
}
const sessionId = safeSessionId.data;
if (transports[sessionId]) {
transport = transports[sessionId];
} else {
logger.error("Session not found");
res.status(400).json({
jsonrpc: "2.0",
error: {
code: -32000,
message: "Session not found",
},
id: null,
});
return;
}
} else if (isInitializeRequest(req.body)) {
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID(),
onsessioninitialized: (sessionId) => {
transports[sessionId] = transport;
},
});
transport.onclose = () => {
if (transport.sessionId) {
delete transports[transport.sessionId];
}
};
const outlineMcpServer = outlineMcpFactory(logger.child({ sessionId: transport.sessionId }));
await outlineMcpServer.connect(transport);
} else {
logger.error("Bad Request: No valid session ID provided");
res.status(400).json({
jsonrpc: "2.0",
error: {
code: -32000,
message: "Bad Request: No valid session ID provided",
},
id: null,
});
return;
}
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => {
logger.info("Server is running on port 3000");
});
}
main();