[BUG] MCP array parameters still double-stringified in Notion tool calls (regression from #3023)

Status Fixed / completed
Maintainer reply None cached
Activity 5 comments · opened Feb 13, 2026 · closed Feb 27, 2026

Description

Issue #3023 (closed July 2025, fixed in v1.0.53) addressed double-stringification of parent object parameters in Notion-MCP tool calls. However, the same serialization bug persists for array parameters, specifically the children parameter in API-patch-block-children.

Steps to Reproduce

  1. Configure @notionhq/notion-mcp-server v2.1.0 in Claude Code (local stdio)
  2. Create a Notion page (via curl or any method)
  3. Use Claude Code to call mcp__notion__API-patch-block-children with:
{
  "block_id": "<page_id>",
  "children": [
    {"type": "paragraph", "paragraph": {"rich_text": [{"type": "text", "text": {"content": "Hello"}}]}}
  ]
}

Expected Behavior

Notion API receives children as a JSON array and creates the blocks.

Actual Behavior

Notion API receives children as a string (JSON-stringified array):

body.children should be an array, instead was "[{\"type\":\"paragraph\",...".

Environment

  • Claude Code: v2.1.34
  • OS: Windows 11 Pro (10.0.26200)
  • @notionhq/notion-mcp-server: v2.1.0
  • Notion API version: 2025-09-03
  • Transport: stdio (local, not remote/web connector)

Analysis

The fix from #3023 appears to have addressed object-type parameters (like parent) but not array-type parameters (like children). The MCP transport layer still stringifies arrays before passing them to the server.

Pattern observed:

  • Simple objects (filter: {property: "object", value: "data_source"}) → WORKS
  • Flat nested objects (properties: {Status: {status: {name: "Done"}}}) → WORKS
  • Deep nested objects (parent: {database_id: "..."}) → Previously BROKEN, supposedly fixed
  • Arrays of objects (children: [{type: "paragraph", ...}]) → STILL BROKEN

Workaround

Bypass MCP and call the Notion API directly via HTTP (Python urllib.request, curl, etc.).

Related Issues

  • makenotion/notion-mcp-server#82 (open, 16 upvotes — same serialization pattern)
  • makenotion/notion-mcp-server#79 (closed as "Claude's issue")
  • #3023 (closed, but regression persists for array params)

View original on GitHub ↗

5 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/22394
  2. https://github.com/anthropics/claude-code/issues/24599
  3. https://github.com/anthropics/claude-code/issues/22708

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

RMANOV · 6 months ago

Root Cause Update (Feb 2026)

The root cause has been identified by @gogakoreli in #18260:

The MCP TypeScript SDK's schemaToJson() does not resolve $ref pointers.

When a tool's parameter schema uses $ref (which Notion's API schema does extensively), the type information is lost at the client layer, and the value is serialized as a string instead of being passed as the correct type.

Fix submitted upstream:

  • SDK Issue: modelcontextprotocol/typescript-sdk#1562
  • SDK PR: modelcontextprotocol/typescript-sdk#1563 (adds dereferenceLocalRefs())

This is not a duplicate of the server-side issues — it's the client-side root cause that affects ALL MCP servers using $ref in their schemas (Notion, Webflow, GitHub, custom servers).

Request to Anthropic: Please either adopt the SDK fix or add client-side $ref resolution in Claude Code. This affects multiple MCP integrations across Windows, macOS, and Claude Desktop (Cowork).

Related: #18260 (master issue), #22394 (Webflow), #24599 (all non-string types), #26094 (Claude Desktop Cowork)

RMANOV · 6 months ago

Update: Notion Deployed Partial Fix (2026-02-24)

Notion Support (ticket #5172415) notified us that a fix was deployed. Verification reveals it's partial:

What's Fixed

  • API-patch-block-children now works correctly via MCP — the children parameter schema is properly typed with $ref resolution to blockObjectRequest
  • Multi-block calls with Unicode/Cyrillic content work perfectly
  • Tested: single paragraph, multi-block (paragraph + bulleted_list_items), retrieve verification — all pass

What's Still Broken

  • API-post-page with children parameter — still fails with body.children should be an array or undefined, instead was string
  • Schema comparison: post-page.children uses items: {"type": "string"} instead of items: {"$ref": "#/$defs/blockObjectRequest"}
  • This is the exact $ref resolution issue described in this ticket — unresolved refs fall back to string type

Implication

This confirms the bug is real and affects multiple endpoints independently. The Notion team fixed patch-block-children but missed post-page — likely because each endpoint's schema needs separate $ref resolution.

The upstream SDK fix (modelcontextprotocol/typescript-sdk#1563) remains the correct systemic solution, as it would resolve $ref pointers client-side for ALL endpoints at once, rather than requiring server-by-server, endpoint-by-endpoint fixes.

Please do not auto-close this issue as duplicate. The evidence above demonstrates this is an active, partially-unresolved bug affecting the MCP client's JSON Schema handling.

RMANOV · 6 months ago

Final Status: All Core Functionality Restored (2026-02-27)

Automated Verification Results

| Endpoint + Param | Schema | Runtime | Status |
|------------------|:------:|:-------:|--------|
| API-post-pageparent | ✅ | ✅ | Fixed (double-serialization resolved) |
| API-post-pageproperties | ✅ | ✅ | Fixed |
| API-post-pagechildren (block objects) | ❌ string | ✅ Works | Functional fix (schema cosmetic) |
| API-patch-block-children | ✅ $ref | ✅ | Fully fixed |
| API-patch-page | ✅ | ✅ | Working |

Key Finding

\API-post-page\ with \children\ as actual block objects (not JSON strings) works correctly despite the schema declaring \items: {\"type\": \"string\"}\. The fix was applied at the server's serialization layer — objects pass through without schema validation.

Result: Single-call page + content creation is now possible. The \curl\/\urllib\ workaround from the original report is no longer needed.

Remaining: Cosmetic Schema Issue

\children\ in \API-post-page\ schema still uses \items: {\"type\": \"string\"}\ instead of \\$ref: blockObjectRequest\. This doesn't block functionality but causes misleading documentation for tool consumers and potential validation failures in strict MCP clients.

Upstream fix: modelcontextprotocol/typescript-sdk#1563 — adds \dereferenceLocalRefs()\ to \schemaToJson()\. Still an open PR, not yet merged.

Cross-References

Closing — primary functionality fully restored.

github-actions[bot] · 5 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.