fix: wrap tool handler results in MCP content blocks (#4) - #5
Merged
Conversation
All handlers in src/tools/*.ts returned raw Paperless API responses
directly. The MCP spec requires CallToolResult shape
`{ content: [{ type, text }, ...] }`; bare objects pass the SDK at
runtime but are silently dropped by compliant clients (Claude Code
renders an empty tool result).
Adds a shared `toTextResult(data)` helper that JSON-stringifies any
value into a single text content block, and threads it through every
handler in documents, tags, correspondents, and documentTypes.
download_document is wrapped the same way — base64 blob + filename
get stringified into the text block. A `resource`-typed content block
would be a more proper fit for binary but is not blocking.
Verified against a live Paperless-NGX instance: `tools/call list_tags`
now returns `result.content[0].type === "text"` with the full payload
in `text`.
Fixes #4.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #4. Every tool handler in
src/tools/*.tsreturned the raw Paperless API response directly. MCP requiresCallToolResultshape{ content: [{ type, text }, ...] }— bare objects pass the SDK at runtime but compliant clients (Claude Code) silently render an empty result.Adds a shared
toTextResult(data)helper insrc/tools/result.tsand threads it through every handler indocuments,tags,correspondents, anddocumentTypes.Notes
download_documentreturns{ blob, filename }stringified into the text block. Aresource-typed content block would be more correct for binary data but is out of scope here.searchDocumentstoken-efficiency stripping (PR Improve search context efficiency to prevent token overflow nloui/paperless-mcp#13) lives inPaperlessAPI.tsand is unaffected.Test
Smoke-tested against the live Paperless-NGX instance via the reproducer from #4:
Result:
result.content[0].type === "text",content[0].textcontains the JSON-stringified Paperless payload (83 tags). ✅Test plan for reviewer
npm run build, restart MCP clientlist_tags/list_correspondents/list_document_types/search_documents— results should now render in the client instead of appearing emptyupdate_document,create_*,bulk_edit_*— confirm they still take effect and return their (now-visible) response🤖 Generated with Claude Code