diff --git a/.changeset/fuzzy-dragons-elicit.md b/.changeset/fuzzy-dragons-elicit.md new file mode 100644 index 000000000..87d93e0bf --- /dev/null +++ b/.changeset/fuzzy-dragons-elicit.md @@ -0,0 +1,5 @@ +--- +"executor": patch +--- + +Preserve `elicitation_mode=native` when creating self-hosted MCP sessions. diff --git a/packages/hosts/mcp/src/in-memory-session-store.test.ts b/packages/hosts/mcp/src/in-memory-session-store.test.ts new file mode 100644 index 000000000..8d87f5697 --- /dev/null +++ b/packages/hosts/mcp/src/in-memory-session-store.test.ts @@ -0,0 +1,54 @@ +import { expect, it } from "@effect/vitest"; +import { Effect } from "effect"; + +import { + makeInMemoryMcpSessionStore, + McpEngineBuildError, + type McpBuildServerOptions, +} from "./in-memory-session-store"; +import { defaultMcpResource, type Principal } from "./seams"; + +const TEST_PRINCIPAL: Principal = { + accountId: "acct_test", + organizationId: "org_test", + organizationName: "Test Org", + email: "test@example.com", + name: "Test", + avatarUrl: null, + roles: ["user"], +}; + +it("preserves native elicitation mode when creating an in-memory MCP session", async () => { + let buildOptions: McpBuildServerOptions | undefined; + const sessions = makeInMemoryMcpSessionStore((_principal, options) => { + buildOptions = options; + return Effect.fail(new McpEngineBuildError({ cause: "stop after capturing options" })); + }); + + const result = await Effect.runPromise( + sessions.store.dispatch({ + request: new Request("https://executor.test/mcp?elicitation_mode=native", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "initialize", + params: { + protocolVersion: "2025-06-18", + capabilities: { elicitation: { form: {} } }, + clientInfo: { name: "test-client", version: "1.0.0" }, + }, + }), + }), + principal: TEST_PRINCIPAL, + resource: defaultMcpResource, + sessionId: null, + method: "POST", + }), + ); + + expect(result).toBeInstanceOf(Response); + expect((result as Response).status).toBe(500); + expect(buildOptions?.elicitationMode).toEqual({ mode: "native" }); +}); diff --git a/packages/hosts/mcp/src/in-memory-session-store.ts b/packages/hosts/mcp/src/in-memory-session-store.ts index e2d233e8c..4e5e53522 100644 --- a/packages/hosts/mcp/src/in-memory-session-store.ts +++ b/packages/hosts/mcp/src/in-memory-session-store.ts @@ -218,7 +218,8 @@ export const makeInMemoryMcpSessionStore = ( request: Request, sessionId: () => string | null, ): McpBuildServerOptions => { - if (readElicitationMode(request) !== "browser") return { elicitationMode: { mode: "model" } }; + const mode = readElicitationMode(request); + if (mode !== "browser") return { elicitationMode: { mode } }; return { elicitationMode: { mode: "browser",