Skip to content

fix: wrap top-level array params in anyOf to also accept JSON-encoded strings#261

Open
cheafon wants to merge 1 commit into
makenotion:mainfrom
cheafon:main
Open

fix: wrap top-level array params in anyOf to also accept JSON-encoded strings#261
cheafon wants to merge 1 commit into
makenotion:mainfrom
cheafon:main

Conversation

@cheafon

@cheafon cheafon commented Apr 10, 2026

Copy link
Copy Markdown

Problem

When calling notion-create-pages from Claude Code (or Cursor), the pages
array parameter arrives as a JSON-encoded string instead of an actual array,
causing validation to fail:

Invalid input: expected array, received string
Too big: expected string to have <=100 characters

This is a known MCP client behavior where top-level array parameters get
double-serialized (JSON.stringify'd) before being sent.

Root Cause

withStringFallback() in parser.ts already handles this for object
parameters by wrapping them in anyOf: [schema, { type: 'string' }]
allowing both the native type and a JSON-encoded string. However, this
treatment was missing for array parameters.

The runtime fix (deserializeParams() in proxy.ts) already correctly
converts "[...]" strings back to arrays — so only the schema validation
needed to be updated.

Fix

Apply the same anyOf: [array, string] wrapping to array-typed parameters
in withStringFallback(). This is consistent with the existing object
handling and resolves the schema validation error.

Testing

  • Added a test case in parser.test.ts covering an array request body
    parameter (mirrors the notion-create-pages / pages scenario)
  • Updated existing parser-multipart.test.ts expectations to reflect the
    new anyOf structure for array properties
  • All 75 tests pass

Fixes #176

… strings

Some MCP clients (e.g. Claude Code, Cursor) double-serialize top-level
array parameters, sending them as a JSON string (e.g. "[{...}]") instead
of an actual array. This caused `notion-create-pages` to fail with:

  Invalid input: expected array, received string

The existing `withStringFallback` already handles this for object-typed
params by wrapping them in `anyOf: [schema, { type: 'string' }]`.
This commit applies the same treatment to array-typed params.

At runtime, `deserializeParams()` in proxy.ts already correctly converts
the JSON-encoded string back to an array, so no runtime changes are needed.

Fixes: makenotion#176
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: MCP Tool Parameter Serialization Issue - Nested Objects Serialized as Strings

1 participant