forked from koshikraj/ottopus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtransport.ts
More file actions
44 lines (42 loc) · 1.84 KB
/
Copy pathtransport.ts
File metadata and controls
44 lines (42 loc) · 1.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js'
import type { Context } from 'hono'
import { buildServer, type ToolContext, type ToolDeps } from './server.js'
/**
* Streamable HTTP, stateless.
*
* The SDK's web-standard transport takes a Request and returns a Response,
* which is exactly Hono's shape — the Node transport wants IncomingMessage and
* ServerResponse, and the SDK's own OAuth router is Express-bound. Neither
* would fit here without adapting one runtime to another.
*
* `sessionIdGenerator: undefined` is what makes it stateless: no Mcp-Session-Id,
* no transport object held between requests. Every request carries its bearer
* token, and the token is what maps to a user — so there is no session to lose
* when Railway restarts the process, and no session affinity to arrange if this
* ever runs as more than one. It also keeps the architecture's rule honest:
* state belongs in Supabase, not in a process Map.
*
* What it costs is server-initiated messages. Nothing needs them yet — plans are
* polled, deliberately, because the MCP interface must never hold a request open
* waiting for a person. When something does, this becomes a real decision.
*/
export async function handleMcpRequest(
c: Context,
ctx: ToolContext,
deps: ToolDeps,
): Promise<Response> {
const server = buildServer(ctx, deps)
const transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
})
// Close on the way out rather than in a finally that fires before the
// response is read: the transport owns the body stream it just returned.
try {
await server.connect(transport)
return await transport.handleRequest(c.req.raw)
} catch (err) {
await transport.close().catch(() => {})
throw err
}
}