@@ -30,7 +30,7 @@ import { mcpSessionStub } from "@executor-js/cloudflare/mcp/session-stub";
3030
3131import { wrapMcpSseResponse } from "../observability/memory-metrics" ;
3232import { WorkerTelemetryLive } from "../observability/telemetry" ;
33- import { cloudMcpAuth } from "./auth-provider" ;
33+ import { authenticateClientChannelToken , cloudMcpAuth } from "./auth-provider" ;
3434import { isMcpSessionMetaUnavailable } from "./session-meta" ;
3535import { McpSessionDOSqlite } from "./session-durable-object" ;
3636import { parseTraceparent } from "./traceparent" ;
@@ -44,7 +44,7 @@ const corsPreflightResponse = (): Response =>
4444 "access-control-allow-origin" : "*" ,
4545 "access-control-allow-methods" : "GET, POST, DELETE, OPTIONS" ,
4646 "access-control-allow-headers" :
47- "content-type, authorization, mcp-session-id, accept, mcp-protocol-version" ,
47+ "content-type, authorization, mcp-session-id, accept, mcp-protocol-version, x-executor-client-token " ,
4848 "access-control-expose-headers" : "mcp-session-id, WWW-Authenticate" ,
4949 } ,
5050 } ) ;
@@ -171,6 +171,8 @@ const resourceFromPath = (request: Request): McpResource => {
171171const propsForPrincipal = (
172172 request : Request ,
173173 principal : Extract < AuthOutcome , { readonly _tag : "Authenticated" } > [ "principal" ] ,
174+ clientIdentity : string | undefined ,
175+ clientManifestGeneration : number | undefined ,
174176 resource : McpResource ,
175177) : Effect . Effect < McpSessionProps > =>
176178 Effect . gen ( function * ( ) {
@@ -187,6 +189,8 @@ const propsForPrincipal = (
187189 ...( principal . organizationSlug ? { organizationSlug : principal . organizationSlug } : { } ) ,
188190 ...sessionOrgRoleMetadata ( principal ) ,
189191 userId : principal . accountId ,
192+ ...( clientIdentity === undefined ? { } : { clientIdentity } ) ,
193+ ...( clientManifestGeneration === undefined ? { } : { clientManifestGeneration } ) ,
190194 elicitationMode : readElicitationMode ( request ) ,
191195 artifactsEnabled : readArtifactsEnabled ( request ) ,
192196 searchToolsEnabled : readSearchToolsEnabled ( request ) ,
@@ -246,6 +250,23 @@ export const makeCloudMcpAgentHandler = () => {
246250 return renderAuthError ( auth , request , outcome ) ;
247251 }
248252
253+ // A channel token is only a session binding layered on top of the normal
254+ // cloud bearer auth above. Its opaque value selects a DO; identity is read
255+ // from durable server-side state and must match the bearer principal.
256+ const channelToken = request . headers . get ( "x-executor-client-token" ) ;
257+ let clientIdentity = outcome . clientIdentity ;
258+ let clientManifestGeneration = outcome . clientManifestGeneration ;
259+ if ( channelToken !== null ) {
260+ const channelIdentity = await authenticateClientChannelToken (
261+ env . MCP_CLIENT_CHANNEL ,
262+ channelToken ,
263+ outcome . principal ,
264+ ) ;
265+ if ( ! channelIdentity ) return jsonRpcResponse ( 401 , - 32001 , "Invalid client channel token" ) ;
266+ clientIdentity = channelIdentity . binding ;
267+ clientManifestGeneration = channelIdentity . generation ;
268+ }
269+
249270 if ( ! sessionId && request . method === "DELETE" ) {
250271 // Matches the old envelope's contract (@modelcontextprotocol/sdk's
251272 // `WebStandardStreamableHTTPServerTransport.handleDeleteRequest`): 200,
@@ -266,6 +287,8 @@ export const makeCloudMcpAgentHandler = () => {
266287 {
267288 accountId : outcome . principal . accountId ,
268289 organizationId : outcome . principal . organizationId ,
290+ ...( clientIdentity === undefined ? { } : { clientIdentity } ) ,
291+ ...( clientManifestGeneration === undefined ? { } : { clientManifestGeneration } ) ,
269292 } ,
270293 resource ,
271294 ) ;
@@ -297,7 +320,16 @@ export const makeCloudMcpAgentHandler = () => {
297320 }
298321 }
299322
300- const props = await runTraced ( request , propsForPrincipal ( request , outcome . principal , resource ) ) ;
323+ const props = await runTraced (
324+ request ,
325+ propsForPrincipal (
326+ request ,
327+ outcome . principal ,
328+ clientIdentity ,
329+ clientManifestGeneration ,
330+ resource ,
331+ ) ,
332+ ) ;
301333 ( ctx as ExecutionContext & { props ?: McpSessionProps } ) . props = props ;
302334 const forwarded = withOrgWriteAccess (
303335 withVerifiedIdentityHeaders (
0 commit comments