Skip to content

fix(mcp): surface structured data in text-only tool responses - #449

Merged
pcfreak30 merged 2 commits into
developfrom
fix/mcp-upload-capabilities-stub
Aug 22, 2026
Merged

fix(mcp): surface structured data in text-only tool responses#449
pcfreak30 merged 2 commits into
developfrom
fix/mcp-upload-capabilities-stub

Conversation

@pcfreak30

@pcfreak30 pcfreak30 commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

Fixes MCP audit findings where several tools returned only stub prose in the Text channel while placing real data in StructuredContent. Plain-text MCP clients (which read only Text) received no actionable data.

Affected tools:

  • capabilities — now returns transport + source_modes + download_sink_modes JSON in Text
  • upload_list / upload_status / upload_cancel / upload_file_async — handles & status now in Text
  • upload_file (mint mode) — actual presigned url + curl_command now in Text (the upload_handle itself is only produced by the presigned PUT's 202 response, so it can't appear at mint time; the tool now says where to get it and which tool to poll)
  • vault_put_file (mint mode) and the ipfs_upload_submit app helper — same treatment

Approach

Route results through the existing toolargs.ResultJSONText convention so Text carries the same canonical JSON as StructuredContent, matching the established mcp-result-envelope contract.

Tests

  • go build ./... clean
  • All touched packages pass: internal/mcp, upload, vault, core/transfer
  • Added assertions that text-only clients receive the data (capabilities, upload tools, upload_file mint)

This pull request improves how MCP tool responses handle text-only clients by ensuring that structured data is also included in the text channel of tool results.

Problem: Several MCP tools (capabilities, upload-file, vault-put-file, IPFS upload, and async upload tools) returned their actionable data only in the StructuredContent field, while the Text field contained either a brief stub message (e.g., "Pinner capabilities." or "Upload status.") or prose instructions without the actual data. Text-only MCP clients that don't render structured content widgets would miss crucial information like presigned URLs, curl commands, and upload handles.

Changes:

  • Capabilities tool: The text response now includes the full JSON report (transport modes, source/sink modes, file support flags) instead of the stub "Pinner capabilities."
  • Upload file tool (mint presigned URL): Text now includes the actual presigned URL and curl command as JSON, plus instructions explaining that the upload handle comes from the curl response body.
  • Vault put file tool: Similar to upload-file, text now includes the presigned URL, vault path, and curl command as JSON.
  • IPFS upload submit/status tools: Submit tool text now includes the presigned URL plus poll instructions; status tool text now carries the task data JSON instead of "Upload status."
  • Async upload tools (upload_file_async, upload_status, upload_cancel, upload_list): All now embed the relevant data (handle, task status, cancellation confirmation, tracked uploads list) as JSON in the text channel instead of bare stubs.
  • Added tests verifying that text-only tool responses contain the actual data (e.g., URLs, handles, JSON keys) for capabilities, curl upload, and async upload flows.

This ensures that clients relying solely on text output receive complete, actionable information for performing uploads and checking their status.

capabilities, upload_list/status/cancel, upload_file mint mode (and
vault_put_file mint mode) emitted only stub prose in the Text channel
while putting real data in StructuredContent. Plain-text MCP clients
read only Text, so they received no actionable data (transport/source
modes, upload handles, presigned URLs, curl commands).

Route these results through toolargs.ResultJSONText so Text carries the
same canonical JSON as StructuredContent, matching the existing
mcp-result-envelope convention. Add tests asserting text-only clients
receive the data.
@kody-ai

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown

Code Coverage Report

Total Coverage: 51.7%

Generated from commit: da527ff
Repository: LumeWeb/pinner-cli

The capabilities tool no longer returns the 'Pinner capabilities.' stub
in the text channel; text now carries the same report JSON as the
structured payload. Update the e2e assertion to match.
@kody-ai

kody-ai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@pcfreak30
pcfreak30 merged commit a9c314a into develop Aug 22, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant