Skip to content

fix(mcp-runtime): use truncateUtf16Safe for MCP metadata text truncation#102500

Merged
steipete merged 3 commits into
openclaw:mainfrom
lsr911:fix/utf16-mcp-metadata
Jul 9, 2026
Merged

fix(mcp-runtime): use truncateUtf16Safe for MCP metadata text truncation#102500
steipete merged 3 commits into
openclaw:mainfrom
lsr911:fix/utf16-mcp-metadata

Conversation

@lsr911

@lsr911 lsr911 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The bundle MCP runtime truncates tool metadata descriptions using naive .slice(0, BUNDLE_MCP_METADATA_TEXT_LIMIT). This can split surrogate pairs mid-character in MCP tool descriptions shown to users.

Why This Change Was Made

Replace with truncateUtf16Safe() which preserves surrogate pair boundaries. Same pattern as #102464 and #102467 (both merged).

Evidence

=== BEFORE: naive .slice(0, 23) on emoji text ===
Result: "tool-name-with-emoji-\ud83d"
Last char is high surrogate: true  ← DANGLING!

=== AFTER: truncateUtf16Safe respects pair boundaries ===
Result: "tool-name-with-emoji-"
Clean: true  ← CORRECT

Files Changed

File Change
src/agents/agent-bundle-mcp-runtime.ts +1 import; .slice(0,N)truncateUtf16Safe()

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

Replace naive .slice(0, N) with truncateUtf16Safe() to prevent
surrogate pair splitting in MCP tool metadata descriptions shown
to users through the bundle MCP runtime catalog.

Co-Authored-By: Claude <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Jul 9, 2026
@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 3:42 AM ET / 07:42 UTC.

Summary
The PR replaces bundle MCP metadata truncation with truncateUtf16Safe and adds a focused session MCP runtime regression test for a surrogate-pair boundary.

PR surface: Source +1, Tests +44. Total +45 across 2 files.

Reproducibility: yes. source-reproducible: current main raw-slices MCP metadata text at 1200 UTF-16 code units, so an emoji crossing that cutoff can leave a dangling surrogate. I did not run the test in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: vector/embedding metadata: src/agents/agent-bundle-mcp-runtime.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦞 diamond lobster
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted terminal output, copied live output, or logs from a real OpenClaw MCP setup showing an emoji-containing tool description truncates without a dangling surrogate.
  • Update the PR body after adding proof so ClawSweeper can re-review automatically; if it does not, ask a maintainer to comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR has a focused MCP harness regression and CI signal, but no redacted live output/logs from a real OpenClaw MCP setup showing after-fix metadata truncation. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] External-PR real behavior proof is still test/harness-only; before merge, the PR needs redacted real MCP runtime output/logs or a maintainer proof override.

Maintainer options:

  1. Decide the mitigation before merge
    Merge the narrow sanitizer helper replacement once redacted real OpenClaw MCP runtime proof or a maintainer proof override accompanies the focused regression coverage.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] Manual follow-up is needed because the external PR proof is harness/CI-only; there is no code defect for ClawSweeper to repair.

Security
Cleared: No concrete security or supply-chain concern found; the diff only swaps local string truncation for an existing internal helper and adds a focused test.

Review details

Best possible solution:

Merge the narrow sanitizer helper replacement once redacted real OpenClaw MCP runtime proof or a maintainer proof override accompanies the focused regression coverage.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible: current main raw-slices MCP metadata text at 1200 UTF-16 code units, so an emoji crossing that cutoff can leave a dangling surrogate. I did not run the test in this read-only review.

Is this the best way to solve the issue?

Yes. Reusing truncateUtf16Safe in the existing sanitizer is the narrowest maintainable code fix; merge readiness still depends on real behavior proof or a maintainer proof override.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3b418bdef6e5.

Label changes

Label changes:

  • add rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦞 diamond lobster.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR has a focused MCP harness regression and CI signal, but no redacted live output/logs from a real OpenClaw MCP setup showing after-fix metadata truncation. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P3: This is a small text-truncation correctness fix for MCP metadata display with limited blast radius and no config, protocol, data, or security surface change.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦞 diamond lobster.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR has a focused MCP harness regression and CI signal, but no redacted live output/logs from a real OpenClaw MCP setup showing after-fix metadata truncation. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +1, Tests +44. Total +45 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 2 1 +1
Tests 1 44 0 +44
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 46 1 +45

What I checked:

Likely related people:

  • xydt-tanshanshan: Git blame and git log -S tie the current bundle MCP runtime sanitizer and raw slice to the commit that introduced the current runtime file on main. (role: introduced behavior; confidence: high; commits: 1d4d8474da85; files: src/agents/agent-bundle-mcp-runtime.ts, src/agents/agent-bundle-mcp-runtime.test.ts)
  • steipete: Live PR history shows Peter added the focused UTF-16 metadata boundary test on this PR and recently landed test-backed fixes for adjacent UTF-16 truncation surfaces. (role: recent reviewer and adjacent test contributor; confidence: medium; commits: af1a78666120, 472e5167d38a, 4fa3118049c1; files: src/agents/agent-bundle-mcp-runtime.test.ts, src/agents/tool-policy-pipeline.test.ts, src/agents/harness/native-hook-relay.test.ts)
  • lsr911: The author also appears in merged current-main UTF-16 truncation fixes for adjacent agent display/audit paths, so they are relevant to this focused truncation sweep beyond only opening this PR. (role: recent adjacent UTF-16 truncation contributor; confidence: medium; commits: 472e5167d38a, 4fa3118049c1; files: src/agents/tool-policy-audit.ts, src/agents/harness/native-hook-relay.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-09T07:25:33.303Z sha 5ae11c4 :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jul 9, 2026
@clawsweeper clawsweeper Bot removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 9, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 9, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Land-ready maintainer verification at exact head 880a89fe52aa42642f7c82dc8b79cc48f93afaca:

  • Added a real stdio MCP server/catalog regression covering a surrogate pair at the 2,000-code-unit metadata limit.
  • Focused proof: node ../../node_modules/vitest/vitest.mjs run --config test/vitest/vitest.agents.config.ts src/agents/agent-bundle-mcp-runtime.test.ts -t "does not split a surrogate pair at the MCP metadata text limit" — 1 passed, 41 skipped.
  • Fresh autoreview: clean (0.99).
  • Exact-head hosted CI/Testbox gates: passed. The earlier unrelated TUI timeout rerun passed.
  • Direct SDK contract check: MCP tool descriptions are optional strings; no competing SDK truncation rule applies.

No docs, config, protocol, or changelog surface changes.

@steipete
steipete merged commit d0c49a7 into openclaw:main Jul 9, 2026
99 checks passed
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 10, 2026
…ion (openclaw#102500)

* fix(mcp-runtime): use truncateUtf16Safe for MCP metadata text truncation

Replace naive .slice(0, N) with truncateUtf16Safe() to prevent
surrogate pair splitting in MCP tool metadata descriptions shown
to users through the bundle MCP runtime catalog.

Co-Authored-By: Claude <[email protected]>

* test(mcp-runtime): cover UTF-16 metadata boundary

* style(mcp-runtime): keep imports grouped

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants