You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
openApiMcpServer does not forward jsonSchemaValidator to the underlying McpServer; AJV-by-default breaks elicit accept-action under Workers runtime #1491
@cloudflare/codemode's openApiMcpServer constructs new McpServer({ name, version }) with no options pass-through. The underlying @modelcontextprotocol/sdkServer then defaults to AjvJsonSchemaValidator, which calls new Function(...) to compile validators at runtime. The Cloudflare Workers runtime forbids new Function and eval ("Code generation from strings disallowed"). Any MCP server-initiated request that needs response validation against a requestedSchema — for example Server.elicitInput validating a user's accept-action payload — therefore throws the above error under Workers.
The MCP SDK already ships CfWorkerJsonSchemaValidator (using @cfworker/json-schema, an interpretive validator with no code generation) and accepts a jsonSchemaValidator option on the Server constructor. But openApiMcpServer consumers cannot opt in, because the option isn't part of the openApiMcpServer parameter surface.
As a result, using openApiMcpServer plus elicitation hits a runtime error the moment a user clicks "accept" on an elicit prompt. Decline works as it doesn't invoke any schema validation.
Affected versions
@cloudflare/codemode@0.3.4 — confirmed in production.
@modelcontextprotocol/sdk@1.29.0 — AjvJsonSchemaValidator is the default; CfWorkerJsonSchemaValidator is exported at @modelcontextprotocol/sdk/validation/cfworker but is not opt-in by default.
Workers runtime: any version that enforces the standard Code generation from strings disallowed security policy.
modelcontextprotocol/typescript-sdk PR #1012 introduced CfWorkerJsonSchemaValidator and the jsonSchemaValidator constructor option as explicitly opt-in only ("AJV remains the default; users can opt in by declaring a jsonSchemaValidator").
Dependency-resolution-style workarounds suggested in some threads (overrides, resolutions) did not work for me as they introduced various dependency version mismatches I won't go into - in any case pinning dependency versions is not a durable solution.
Reproduction
Any openApiMcpServer({ spec, executor, request }) setup where the request callback can elicit user consent, deployed to Workers, with a client that clicks accept on the resulting elicit prompt. Workers logs include the AJV-generated validator source in the failure:
(error) Error compiling schema, function code: const schema0 = scope.schema[0];return function validate0(data, …){…}
McpError: MCP error -32603: Error validating elicitation response: Code generation from strings disallowed for this context
at Server2.elicitInput (...sdk/server/index.js:...)
The "function code" preamble is the AJV-generated validator source the runtime refused to compile.
elicit-als-context-codemode-pattern.tar.gz is attached. It reproduces both this validator-default bug and the companion ALS-context bug (opened as #1490) from the same harness via independent env toggles. Steps:
tar xzf elicit-als-context-codemode-pattern.tar.gz
cd elicit-als-context/codemode-pattern
pnpm install --ignore-workspace
# Trigger this validator bug:
WRAP=1 TRIGGER_VALIDATION=1 node verify.mjs
# Apply the workaround and observe the full happy path:
WRAP=1 TRIGGER_VALIDATION=1 VALIDATOR=cfworker node verify.mjs
Toggle reference (full matrix in the tarball's README):
WRAP
TRIGGER_VALIDATION
VALIDATOR
Outcome
1
1
unset
AJV codegen error (this bug)
1
1
cfworker
tool-success — full accept happy path
TRIGGER_VALIDATION=1 makes the harness's mock client return {action:"accept", content:{confirm:"yes"}} rather than {action:"decline"} — i.e., it gives the SDK something to validate. The SDK currently requires result.action === 'accept' && result.content to enter validation, so decline skips the codepath entirely.
VALIDATOR=cfworker flips the harness host code to swap _jsonSchemaValidator post-construction, mirroring the workaround documented below.
Each invocation exits 0 if the observed behavior matches expectation. The tarball also ships per-scenario expected-output-*.txt captures for diffing.
(Trivia: unsetting WRAP will trigger "Agent was not found in send" from #1490)
Root cause
@cloudflare/codemode/dist/mcp.js (in published 0.3.4):
functionopenApiMcpServer(options){const{ executor,request: requestFn, name ="openapi", version ="1.0.0",/* ... */}=options;constspec=options.spec;constserver=newMcpServer({
name,
version
// ← no `jsonSchemaValidator` is passed through; no surface for the caller// to provide one either.});// ...}
This works but couples to a _-prefixed internal field of Server; any SDK change that renames the field will break this workaround.
Suggested fix
Forward jsonSchemaValidator (and any other ServerOptions we want to expose) through openApiMcpServer's parameter surface so callers can opt in to the SDK's already-shipped option:
functionopenApiMcpServer(options){const{ executor,request: requestFn, name ="openapi", version ="1.0.0",
jsonSchemaValidator,/* ... */}=options;constspec=options.spec;constserver=newMcpServer({ name, version, jsonSchemaValidator });// ...}
Doesn't change defaults for any existing user so fully backwards-compatible, and gives Workers consumers a clean opt-in path. However, it is just a suggestion, I am very much new to this codebase and most of this investigation was done by Claude on my behalf.
Summary
@cloudflare/codemode'sopenApiMcpServerconstructsnew McpServer({ name, version })with no options pass-through. The underlying@modelcontextprotocol/sdkServerthen defaults toAjvJsonSchemaValidator, which callsnew Function(...)to compile validators at runtime. The Cloudflare Workers runtime forbidsnew Functionandeval("Code generation from strings disallowed"). Any MCP server-initiated request that needs response validation against arequestedSchema— for exampleServer.elicitInputvalidating a user's accept-action payload — therefore throws the above error under Workers.The MCP SDK already ships
CfWorkerJsonSchemaValidator(using@cfworker/json-schema, an interpretive validator with no code generation) and accepts ajsonSchemaValidatoroption on theServerconstructor. ButopenApiMcpServerconsumers cannot opt in, because the option isn't part of theopenApiMcpServerparameter surface.As a result, using
openApiMcpServerplus elicitation hits a runtime error the moment a user clicks "accept" on an elicit prompt. Decline works as it doesn't invoke any schema validation.Affected versions
@cloudflare/codemode@0.3.4— confirmed in production.@modelcontextprotocol/sdk@1.29.0—AjvJsonSchemaValidatoris the default;CfWorkerJsonSchemaValidatoris exported at@modelcontextprotocol/sdk/validation/cfworkerbut is not opt-in by default.Code generation from strings disallowedsecurity policy.Prior relevant issues / PRs
cloudflare/agentsissue Elicitation feature fails on Cloudflare Workers due to AJV code generation (EvalError: Code generation from strings disallowed) #424 ("Elicitation feature fails on Cloudflare Workers due to AJV code generation") — closed in tandem with the MCP SDK shippingCfWorkerJsonSchemaValidatoras a callable opt-in. The closure resolves the SDK side; this issue is the follow-up for the codemode-specific surface gap (the option isn't reachable fromopenApiMcpServercallers).modelcontextprotocol/typescript-sdkPR #1012 introducedCfWorkerJsonSchemaValidatorand thejsonSchemaValidatorconstructor option as explicitly opt-in only ("AJV remains the default; users can opt in by declaring ajsonSchemaValidator").overrides,resolutions) did not work for me as they introduced various dependency version mismatches I won't go into - in any case pinning dependency versions is not a durable solution.Reproduction
Any
openApiMcpServer({ spec, executor, request })setup where therequestcallback can elicit user consent, deployed to Workers, with a client that clicks accept on the resulting elicit prompt. Workers logs include the AJV-generated validator source in the failure:The "function code" preamble is the AJV-generated validator source the runtime refused to compile.
Runnable harness (attached)
elicit-als-context-codemode-pattern.tar.gz
elicit-als-context-codemode-pattern.tar.gzis attached. It reproduces both this validator-default bug and the companion ALS-context bug (opened as #1490) from the same harness via independent env toggles. Steps:Toggle reference (full matrix in the tarball's README):
WRAPTRIGGER_VALIDATIONVALIDATOR1111cfworkerTRIGGER_VALIDATION=1makes the harness's mock client return{action:"accept", content:{confirm:"yes"}}rather than{action:"decline"}— i.e., it gives the SDK something to validate. The SDK currently requiresresult.action === 'accept' && result.contentto enter validation, sodeclineskips the codepath entirely.VALIDATOR=cfworkerflips the harness host code to swap_jsonSchemaValidatorpost-construction, mirroring the workaround documented below.Each invocation exits 0 if the observed behavior matches expectation. The tarball also ships per-scenario
expected-output-*.txtcaptures for diffing.(Trivia: unsetting WRAP will trigger "Agent was not found in send" from #1490)
Root cause
@cloudflare/codemode/dist/mcp.js(in published0.3.4):@modelcontextprotocol/sdk/dist/esm/server/index.js:Default is AJV; AJV uses
new Functioninternally; Workers forbidsnew Function→ error at validate time.Workaround
After
openApiMcpServerreturns, replace the inner Server's_jsonSchemaValidatorfield directly:This works but couples to a
_-prefixed internal field ofServer; any SDK change that renames the field will break this workaround.Suggested fix
Forward
jsonSchemaValidator(and any otherServerOptionswe want to expose) throughopenApiMcpServer's parameter surface so callers can opt in to the SDK's already-shipped option:Doesn't change defaults for any existing user so fully backwards-compatible, and gives Workers consumers a clean opt-in path. However, it is just a suggestion, I am very much new to this codebase and most of this investigation was done by Claude on my behalf.