Description
Is your feature request related to a problem? Please describe.
Experimenting with writing MCP Servers in Cloudflare Workers/Durable Objects. Currently doing a simple pivot from stdin/stderr to HTTP, e.g.
server.setRequestHandler(ListToolsRequestSchema, async () => {
const { url } = await serverReady
const resp = await fetch(`${url}/tools/list`)
return resp.json()
})
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params
const { url } = await serverReady
const resp = await fetch(`${url}/tools/call/${name}`, {
method: 'POST',
body: JSON.stringify(args)
})
return resp.json()
})
Describe the solution you'd like
It would be a bit neater if I could do something like:
// On the local server
const serverReady = await // boot something locally or get an auth token for remote
const proxy = new TransportProxy()
const localTransport = new StdioServerTransport()
const wsTransport = new WebsocketTransport({ url: serverReady.wssUrl })
await proxy.connect(localTransport, wsTransport)
// Inside the worker
const webSocketPair = new WebSocketPair();
const client = webSocketPair[0], server = webSocketPair[1];
const transport = new WebsocketTransport({ connection: server })
this.ctx.waitUntil(server.connect(transport))
return new Response(null, {
status: 101,
webSocket: client,
});
The issue with making this completely generic is being able to establish the websocket in a secure way. I can see the advantage of stdin/stdout in that respect! But I thought I'd raise the issue to see if there'd been interest in using websockets like this?
Describe alternatives you've considered
Making Claude Desktop config allow a "websocket"
URL instead of a "command"
, and a "headers"
field instead of "args"
for auth? That sounds like the end goal, but this might be a good stopgap.
Additional context
I am also not sure if @modelcontextprotocol/sdk
works out of the box in Cloudflare Workers, but that should be a fairly easy fix.