Skip to content

fix(mcp): ignore malformed path-like text#4456

Merged
WillemJiang merged 1 commit into
bytedance:mainfrom
VectorPeak:codex/mcp-ignore-malformed-text-uri
Jul 25, 2026
Merged

fix(mcp): ignore malformed path-like text#4456
WillemJiang merged 1 commit into
bytedance:mainfrom
VectorPeak:codex/mcp-ignore-malformed-text-uri

Conversation

@VectorPeak

Copy link
Copy Markdown
Contributor

Why

MCP tool results can include free-text file paths that are parsed by DeerFlow so local stdio MCP outputs can be rewritten into /mnt/user-data/... virtual artifact paths. That rewrite is intentionally best-effort: text that is not a real resolvable local file should be left untouched.

A malformed path-like token such as:

Saved at //[::1/foo.png

breaks that contract today. The free-text path regex captures //[::1/foo.png, _local_path_from_uri() passes it directly to urllib.parse.urlparse(), and Python raises:

ValueError: Invalid IPv6 URL

That exception bubbles through _rewrite_local_paths_in_text() and _convert_call_tool_result(), so one malformed provider/server text result can fail the whole MCP tool result conversion instead of being ignored as an unresolvable local path candidate.

Call chain:

MCP server text result
  -> _convert_call_tool_result(...)
  -> _rewrite_local_paths_in_text(...)
  -> _local_uri_to_virtual_path(...)
  -> _local_path_from_uri(...)
  -> urlparse(uri)
  -> ValueError: Invalid IPv6 URL

What changed

  • _local_path_from_uri() now treats urlparse() ValueErrors the same way it treats remote, missing, relative-without-base, or otherwise non-local candidates: return None.
  • Free-text path rewriting keeps malformed path-like text unchanged instead of aborting result conversion.
  • Added regression coverage at the parser helper, free-text rewrite helper, and full CallToolResult conversion boundary.

This does not broaden what gets rewritten. Valid local paths, valid file:// URIs, remote URLs, missing files, and existing virtual path behavior stay unchanged.

Surface area

  • Frontend UI - page / component / setting / interaction under frontend/
  • Backend API - endpoint / SSE event / request-response shape under backend/app
  • Agents / LangGraph - MCP tool result normalization under backend/packages/harness/deerflow/mcp
  • Sandbox - docker/ or sandboxed execution
  • Skills - change under skills/
  • Dependencies - new/upgraded entry in backend/pyproject.toml or frontend/package.json (say what it buys us)
  • Default behavior change - changes existing behavior without the user opting in (default model, default setting, data shape)
  • Docs / tests / CI only - no runtime behavior change

Screenshots / Recording

N/A. This is a backend MCP result-normalization fix with command-line reproduction and unit coverage.

Bug fix verification

  • Test path that reproduces the bug:
    • backend/tests/test_mcp_file_migration.py::TestLocalPathFromUri::test_malformed_uri_is_ignored
    • backend/tests/test_mcp_file_migration.py::TestRewriteLocalPathsInText::test_malformed_path_like_text_is_left_untouched
    • backend/tests/test_mcp_file_migration.py::TestConvertCallToolResultRewrites::test_malformed_path_like_text_result_does_not_raise
  • Did it go red on main and green on this branch? Yes for the same behavior. A focused pre-fix reproduction raised ValueError: Invalid IPv6 URL; after the fix, the same payload returns a text block with the original text unchanged.

Focused reproduction:

uv run --project backend python -c "from deerflow.mcp import tools as mcp_tools; from mcp.types import CallToolResult, TextContent; result = CallToolResult(content=[TextContent(type='text', text='Saved at //[::1/foo.png')], isError=False); print(mcp_tools._convert_call_tool_result(result, thread_id='t1', user_id='u1'))"

Before the fix, this raised from urlparse():

ValueError: Invalid IPv6 URL

After the fix, it returns the text unchanged:

([{'type': 'text', 'text': 'Saved at //[::1/foo.png', 'id': '...'}], None)

Validation

  • uv run --project backend pytest backend/tests/test_mcp_file_migration.py::TestLocalPathFromUri::test_malformed_uri_is_ignored backend/tests/test_mcp_file_migration.py::TestRewriteLocalPathsInText::test_malformed_path_like_text_is_left_untouched backend/tests/test_mcp_file_migration.py::TestConvertCallToolResultRewrites::test_malformed_path_like_text_result_does_not_raise - passed, 3 tests.
  • uv run --project backend python -c "...malformed //[::1/foo.png reproduction..." - passed after the fix; returned unchanged text content.
  • uv run --project backend ruff check backend/packages/harness/deerflow/mcp/tools.py backend/tests/test_mcp_file_migration.py - passed.
  • uv run --project backend ruff format --check backend/packages/harness/deerflow/mcp/tools.py backend/tests/test_mcp_file_migration.py - passed.
  • git diff --check - passed.
  • Additional attempted check: uv run --project backend pytest backend/tests/test_mcp_file_migration.py on Windows reported existing POSIX path expectation failures unrelated to this patch (15 failed, 43 passed, 1 skipped). The three new malformed-URI regressions passed in the focused run.
  • Additional attempted check: WSL/Linux rerun was blocked while rebuilding backend/.venv on the mounted D: drive by an environment copy I/O error before tests executed.

AI assistance

Tool(s) used: Codex

How you used it: Codex inspected the MCP result conversion path, reproduced the malformed URI failure, implemented the small guard, added regression tests, and ran focused validation. I reviewed the final diff and validation output.

  • I've read and understand every line of this change and take responsibility for it - it's not unreviewed AI output.

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@github-actions github-actions Bot added area:mcp Model Context Protocol integration risk:medium Medium risk: regular code changes size/S PR changes 20-100 lines labels Jul 25, 2026
@WillemJiang WillemJiang added this to the 2.1.0 milestone Jul 25, 2026
@WillemJiang
WillemJiang merged commit 07d8b98 into bytedance:main Jul 25, 2026
12 checks passed
yangjl pushed a commit to yangjl/deer-greenagent that referenced this pull request Jul 26, 2026
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:mcp Model Context Protocol integration risk:medium Medium risk: regular code changes size/S PR changes 20-100 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants