Frequent CJK character substitution errors during Japanese text generation in MCP tool calls (Notion content_updates etc.)
Summary
When using Claude (Opus 4.7 / Sonnet 4.6) to generate or edit Japanese text via MCP tools — particularly mcp__notion__notion-update-page with single-character old_str/new_str replacements — the model frequently substitutes incorrect Unicode code points. The wrong characters are typically Simplified Chinese or rare/archaic Japanese characters that look semantically related but are wrong, indicating an issue with how the model generates CJK code points one character at a time.
Frequency observed
In a single ~3-hour session editing one Notion page in Japanese, I observed 8+ such errors:
| Intended | Actually generated | Comment |
|---|---|---|
| 嬉しい (U+5B09) | 嫌しい (U+5ACC) | Self-correction attempt failed, character substituted with semantically opposite kanji |
| 春 2026 (U+6625) | 多 2026 (U+591A) | Generated unrelated kanji |
| 複数 | 列読 | Two-char span, both wrong, semantically meaningless |
| 揃え (U+63C3) | 諿え (U+8AFF) | Rare/archaic kanji substituted |
| 処分 (U+5206) | 処勭 (U+52ED) | Very rare kanji substituted |
| 億 (U+5104) | 亿 (U+4EBF) | Simplified Chinese substituted for Japanese |
| 付いてくる (U+4ED8) | 跟いてくる (U+8DDF) | Chinese-only kanji substituted |
| 側 (U+5074) | 侧 (U+4FA7) | Simplified Chinese substituted |
| 締切った | 締切りた | Conjugation error (less severe but related) |
Reproduction pattern
Error rate is highest in three scenarios:
- Single-character replacements in
mcp__notion__notion-update-pagecontent_updatesarrays whereold_strandnew_strdiffer by one kanji - Generation of new Japanese paragraphs with mixed kanji content (especially when generating long markdown via
notion-create-pagescontent arg) - Self-correction attempts — correcting one typo frequently introduces another (compounding errors)
Hypothesized cause
The model appears to mishandle Unicode escape sequences \uXXXX when generating CJK characters one at a time. The errors are NOT transcription errors from input — input Japanese is preserved correctly when read back via notion-fetch. The errors happen during generation of new content / replacements.
This suggests a tokenizer or JSON-encoding-pipeline issue specific to single-CJK-character spans, rather than a general Japanese understanding limitation.
Impact
- Documents intended for external sharing (clients, business partners) require manual character-by-character review before publication
- Self-correction workflows are unreliable — fixing one error introduces new ones
- Trust in MCP-based document workflows degrades quickly with this error rate
- For Japanese-language users, the workaround load is significant
Current workaround
After every MCP write, immediately notion-fetch the document, grep for known-bad characters (Simplified Chinese, rare CJK), and correct manually. This is brittle and high-toil.
Suggested investigation areas
- Tokenizer behavior for CJK single-character spans (possibly subword splits introducing wrong neighbors)
- JSON encoding pipeline between Claude → MCP client → MCP server (any Unicode normalization happening?)
- Whether the same error rate occurs in non-MCP
Edittool calls on local files (initial impression: somewhat, but less frequent than MCP tool calls) - Whether including context in
old_str/new_str(e.g., 5+ chars instead of 1) reduces error rate (anecdotally yes)
Environment
- Claude Code on macOS Darwin 25.2.0
- Model: Claude Opus 4.7 (1M context)
- MCP server: Anthropic-managed Notion connector (
mcp__notion__*) - Use case: Japanese business documents (TERIYAKI Inc.)
Related
This appears to be a recurring issue. Documenting it here so the pattern is centrally visible for the team's CJK quality work.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗