[BUG] Notion MCP connector serializes JSON object parameters as strings, breaking update/move/create operations

Status Open
Maintainer reply None cached
Activity 14 comments · opened Feb 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When using the official Notion MCP connector in Cowork mode, all tool calls that require a JSON object parameter fail because the MCP framework serializes the object into a JSON string before passing it to the tool.

Three tools are affected:

| Tool | Broken Parameter | Expected Type |
|------|-----------------|---------------|
| notion-update-page | data | object |
| notion-move-pages | new_parent | object |
| notion-create-pages | parent | object |

The parameter value {"type": "page_id", "page_id": "abc123"} arrives at the Notion MCP server as the string "{\"type\": \"page_id\", \"page_id\": \"abc123\"}" — causing Zod validation to reject it.

This makes it impossible to update page content, move pages, or create pages under a parent. The only working write path is notion-create-pages without a parent parameter (which creates orphan pages at workspace root), requiring users to manually drag pages into position in Notion afterward.

Tools with string-typed parameters (notion-fetch, notion-search, notion-create-pages without parent) work fine — suggesting the framework JSON.stringify()'s all parameter values regardless of whether the tool schema expects a string or object.

What Should Happen?

Object parameters should be passed as actual JSON objects to the MCP tool, preserving their type. Tools like notion-move-pages, notion-update-page, and notion-create-pages (with parent) should work as documented.

Error Messages/Logs

**notion-move-pages:**

MCP error -32602: Invalid arguments for tool notion-move-pages: [
  {
    "code": "invalid_union",
    "unionErrors": [
      {
        "issues": [
          {
            "code": "invalid_type",
            "expected": "object",
            "received": "string",
            "path": ["new_parent"],
            "message": "Expected object, received string"
          }
        ],
        "name": "ZodError"
      }
    ],
    "path": ["new_parent"],
    "message": "Invalid input"
  }
]


**notion-update-page:**

MCP error -32602: Invalid arguments for tool notion-update-page: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": ["data"],
    "message": "Expected object, received string"
  }
]


**notion-create-pages (with parent):**

MCP error -32602: Invalid arguments for tool notion-create-pages: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": ["parent"],
    "message": "Expected object, received string"
  }
]

Steps to Reproduce

  1. Open Claude Desktop → Cowork mode
  2. Connect the official Notion MCP connector
  3. Have at least two Notion pages shared with the integration (a parent page and a child page)
  4. Ask Claude: "Move page [child-page-url] under [parent-page-url]"
  5. Claude will call notion-move-pages with:

``json
{
"page_or_database_ids": ["<child-page-id>"],
"new_parent": {"type": "page_id", "page_id": "<parent-page-id>"}
}
``

  1. Observe Expected object, received string error on new_parent
  2. Repeat with "Update the content of [page-url]" → same error on data param of notion-update-page
  3. Repeat with "Create a new page under [parent-page-url]" → same error on parent param of notion-create-pages

Environment:

  • Platform: Claude Desktop (Cowork mode)
  • OS: macOS
  • Notion MCP connector ID: mcp__2a4c8006-4047-4496-8cd4-0d762c457ab2
  • Date: February 15, 2026

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

Working as of February 13, 2026. Broke by February 15, 2026. Exact version unknown — Claude Desktop / Cowork mode auto-updates.

Claude Code Version

Claude Desktop (Cowork mode) — version unknown, auto-updated between Feb 13–15, 2026

Platform

Other

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Bug occurs in Cowork mode (not Claude Code CLI). The Notion MCP connector is the official hosted connector (ID: mcp__2a4c8006-4047-4496-8cd4-0d762c457ab2), not a self-hosted notion-mcp-server. The Terminal/Shell field is not applicable — this is entirely within the Cowork UI, no terminal involved.

View original on GitHub ↗

14 Comments

gmq68vm5kh-sketch · 6 months ago

Confirming this bug + additional findings

We independently discovered and tested this exact issue. Confirming all observations from the original report.

Additional test: notion-create-comment (flat parameters, no nested objects)

The Notion MCP server has since updated notion-create-comment to accept page_id as a top-level string parameter instead of nested inside a parent object. Despite this, the call still fails:

{
  "page_id": "e93f25e5-1fe0-4812-9602-59f218597335",
  "rich_text": [{"text": {"content": "Test comment"}}]
}

Error from Notion API:

body failed validation: body.create_comment.parent should be defined, instead was `undefined`.

What this tells us

Even when the MCP tool schema uses flat string parameters (no nested objects), the values are not correctly transmitted to the MCP server. The server receives the parameters but cannot use them to reconstruct the API payload.

This suggests the serialization issue may affect more than just object-type parameters — it could be a broader problem with how Claude Code transmits tool arguments to MCP servers.

Affected tools (confirmed)

  • notion-create-pages (parameter parent) — object param, broken
  • notion-update-page (parameter data) — object param, broken
  • notion-move-pages (parameter new_parent) — object param, broken
  • notion-create-comment (parameter page_id) — string param, also broken

Working tools (confirmed)

  • notion-search
  • notion-fetch
  • notion-get-users
  • notion-get-comments
  • notion-get-teams

Environment

  • Claude Code (Cowork) on macOS
  • Date: 2026-02-15
guillemfrancisco · 6 months ago

Confirming same behavior on claude.ai web chat, not just Cowork. All tools with object-typed params get JSON.stringify()'d before reaching the Notion MCP server. String params work fine. The serialization bug is upstream of Notion, somewhere in Anthropic's MCP client/proxy layer.
Re: invalid label — the hosted connector is Anthropic's infra, not Notion's. Zod is just doing its job rejecting a string where it expects an object.
If not here, where should this be reported? The git blame is out there somewhere 👀

Bumangues · 6 months ago

Confirming this behavior with the claude-agent-sdk on Version: 0.1.37

benny-yamagata · 6 months ago

Confirming this behavior as well. Still an issue.

themitchevans · 6 months ago

Confirming in Cowork mode. This is impacting production workflows, not just one-off operations.

I have ~15 custom skills in Cowork that depend on Notion as the central data store. Multiple skills rely on notion-update-page to maintain key pages through replace_content_range and insert_content_after.

Affected tools in my setup:

  • notion-update-page (data param) — used by 6+ skills
  • - notion-move-pages (new_parent param)
  • - - notion-create-pages (parent param)

Workarounds are limited. I can fetch and create-pages without a parent, but that only produces orphan pages at workspace root. There's no viable workaround for in-place content updates on existing pages.

Also noting: the invalid label on this issue seems incorrect — this is a confirmed regression (worked Feb 13, broke by Feb 15) with multiple independent confirmations across Cowork, claude.ai, and the Agent SDK.

younesdev1 · 6 months ago

Confirming this behavior as well.

tommeier · 6 months ago

Also found this today after an auto-update 👍 (Claude code 2.1.51)

lubaibv · 6 months ago

This issue was labeled "invalid" but the bug is still present as of Feb 23. The MCP framework serializes object params as strings, breaking all Notion write operations. Can a maintainer please re-triage?

QuellaCo · 6 months ago

Confirming this behavior.

I'm using the Notion MCP connector in Cowork mode to manage a database with 500+ entries. The serialization bug makes notion-update-page, notion-create-pages (with parent), and notion-move-pages completely unusable, forcing me to fall back to browser automation, clicking through each page one by one.

Given that browser clicking is the only path for write operations, what would take ~30 seconds via API (one call per record, ~1-2s each) instead takes ~60 minutes via browser automation (~9 clicks per record at 3-4 min each). That's roughly a 100x slowdown.

Environment:

  • Claude Code: 2.1.51
  • Platform: Cowork mode (Claude Desktop)
  • OS: macOS 26.3
  • Still reproducing as of Feb 27, 2026
caemkei · 5 months ago

Confirming this bug in Cowork mode — impacting Notion-based documentation workflows.
Using the Notion MCP connector in Cowork (Claude Desktop), notion-update-page consistently fails with:

MCP error -32602: page_id: Required (received: undefined)
command: Required (received: undefined)

All commands are affected (replace_content, replace_content_range, insert_content_after, update_properties). The data wrapper is correctly structured per the schema, but page_id and command are always reported as undefined by the validator.
Environment:

Platform: Cowork mode (Claude Desktop)
Still reproducing as of March 5, 2026

Impact: Unable to update any existing Notion pages. Forced to create new pages as a workaround for every content update, leading to orphaned duplicate pages across the workspace.

begelundmuller · 5 months ago

I can confirm the exact same issue happening in rare cases when using Claude over MCP with https://github.com/rilldata/rill (so this is not a Notion-specific issue).

santiagoaqmen · 5 months ago

I can confirm this same issue still happening on March 27, 2026.

krishnakrish24 · 4 months ago

Confirming that this issue is still happening

Rexmaxusss · 19 days ago

Still present on Claude Desktop (macOS) 1.26832.0, local agent mode, 2026-08-11. Fuller measurements in #26094 (comment from today): three independent remote connectors, same pattern - object/array parameters arrive as JSON-encoded strings, scalar parameters bind fine.

Two practical workarounds we verified today, since none are posted in this thread yet:

  1. Server-side tolerant decode works. If you control the MCP server, accept the stringified payload and json-decode it when the value arrives as a string. A WordPress MCP plugin that does exactly that let us perform real production writes against our site https://studiekompasset.dk today, while every strict server failed. The payload arrives as a decodable JSON string, so a small fallback (is_string -> json_decode) restores full functionality until the client is fixed.
  2. Scalar-variant tools still bind. Where a tool family offers a flat/scalar alternative to an object parameter, that path keeps working.

One triage datapoint: our app binary was unchanged (installed Aug 6) across the Aug 8 -> Aug 11 regression window - identical calls worked Aug 8 and failed Aug 11 - so the moving part looks like the bundled agent runtime or the hosted connector proxy, which matches @guillemfrancisco's read that the bug sits upstream of the individual servers.