Skip to content

Commit 92aad83

Browse files
committed
change to streamable http
1 parent 93b458b commit 92aad83

File tree

1 file changed

+77
-50
lines changed

1 file changed

+77
-50
lines changed

src/index.ts

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
33
import { z } from "zod";
44

55
import express, { Request, Response } from "express";
6-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
6+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
77
import http from "http";
88
import WebSocket, {WebSocketServer} from "ws"
99

1010
// Create mcpServer instance
1111
const mcpServer = new McpServer({
12-
name: "winccoa",
13-
version: "1.0.0",
14-
capabilities: {
15-
resources: {},
16-
tools: {},
17-
},
12+
name: "winccoa-mcp-streamable-http",
13+
version: "1.0.0"
1814
});
1915

2016

@@ -50,60 +46,79 @@ async function mainStdio() {
5046
async function mainSse()
5147
{
5248
const app = express();
53-
// Attach WebSocket server to the HTTP server
54-
const wss = new WebSocketServer({ noServer:true });
49+
app.use(express.json());
5550

56-
const PORT = process.env.PORT || 3001;
51+
const transport: StreamableHTTPServerTransport =
52+
new StreamableHTTPServerTransport({
53+
sessionIdGenerator: undefined, // set to undefined for stateless servers
54+
});
55+
56+
// Setup routes for the mcp server
57+
const setupServer = async () => {
58+
await mcpServer.connect(transport);
59+
};
60+
61+
app.post("/mcp", async (req: Request, res: Response) => {
62+
console.log("Received MCP request:", req.body);
63+
try {
64+
await transport.handleRequest(req, res, req.body);
65+
} catch (error) {
66+
console.error("Error handling MCP request:", error);
67+
if (!res.headersSent) {
68+
res.status(500).json({
69+
jsonrpc: "2.0",
70+
error: {
71+
code: -32603,
72+
message: "Internal server error",
73+
},
74+
id: null,
75+
});
76+
}
77+
}
78+
});
5779

58-
const server = app.listen(PORT, () => {
59-
//console.log(`✅ Server is running at http://localhost:${PORT}`);
80+
app.get("/mcp", async (req: Request, res: Response) => {
81+
console.log("Received GET MCP request");
82+
res.writeHead(405).end(
83+
JSON.stringify({
84+
jsonrpc: "2.0",
85+
error: {
86+
code: -32000,
87+
message: "Method not allowed.",
88+
},
89+
id: null,
90+
})
91+
);
92+
});
93+
94+
app.delete("/mcp", async (req: Request, res: Response) => {
95+
console.log("Received DELETE MCP request");
96+
res.writeHead(405).end(
97+
JSON.stringify({
98+
jsonrpc: "2.0",
99+
error: {
100+
code: -32000,
101+
message: "Method not allowed.",
102+
},
103+
id: null,
104+
})
105+
);
60106
});
61107

62-
server.on('upgrade', (request, socket, head) => {
63-
  const pathname = new URL(request.url!, `http://${request.headers.host}`).pathname;
64-
  if (pathname === '/ws') {
108+
// Create HTTP server with websocket support
109+
const serverHttp = http.createServer(app);
110+
serverHttp.on("upgrade", (request, socket, head) => {
111+
  if (request.url === "/ws") {
65112
    wss.handleUpgrade(request, socket, head, (ws) => {
66-
      wss.emit('connection', ws, request);
113+
      wss.emit("connection", ws, request);
67114
    });
68115
  } else {
69116
    socket.destroy();
70117
  }
71118
});
72119

73-
// to support multiple simultaneous connections we have a lookup object from
74-
// sessionId to transport
75-
const transports: { [sessionId: string]: SSEServerTransport } = {};
76-
77-
app.get("/sse", async (req: Request, res: Response) => {
78-
// Get the full URI from the request
79-
const host = req.get("host");
80-
81-
const fullUri = `https://${host}/jokes`;
82-
const transport = new SSEServerTransport(fullUri, res);
83-
84-
transports[transport.sessionId] = transport;
85-
res.on("close", () => {
86-
delete transports[transport.sessionId];
87-
});
88-
await mcpServer.connect(transport);
89-
});
90-
91-
app.post("/jokes", async (req: Request, res: Response) => {
92-
const sessionId = req.query.sessionId as string;
93-
const transport = transports[sessionId];
94-
if (transport) {
95-
await transport.handlePostMessage(req, res);
96-
} else {
97-
res.status(400).send("No transport found for sessionId");
98-
}
99-
});
100-
101-
app.get("/", (_req, res) => {
102-
res.send("The WinCC OA MCP server is running!");
103-
});
104-
105-
106-
120+
// WebSocket server setup
121+
const wss = new WebSocketServer({ server: serverHttp });
107122

108123
// Événement déclenché lorsque le serveur WebSocket reçoit une connexion
109124
wss.on('connection', (ws: WebSocket) => {
@@ -134,6 +149,18 @@ async function mainSse()
134149
});
135150
});
136151

152+
// Start the server
153+
const PORT = process.env.PORT || 3001;
154+
setupServer()
155+
.then(() => {
156+
serverHttp.listen(PORT, () => {
157+
console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
158+
});
159+
})
160+
.catch((error) => {
161+
console.error("Failed to set up the server:", error);
162+
process.exit(1);
163+
});
137164

138165
}
139166

0 commit comments

Comments
 (0)