slack_read_file returns malformed content block for PDF attachments >= ~5 MB
Component: Slack MCP connector — slack_read_file tool
Summary: Reading a binary (PDF) attachment via slack_read_file fails with an MCP schema validation error when the file is roughly 5 MB or larger, even though the tool's documented cap is 10 MB. The same files read successfully when uploaded directly into Claude (not via Slack), which rules out the files themselves being malformed or unparseable.
Steps to reproduce:
- In a Slack channel/thread, attach a PDF ≥ ~5 MB.
- Call
slack_read_filewith that file's ID.
Observed:
MCP error -32602: Invalid tools/call result: [...]
The error shows the second content block in the response (path: ["content", 1]) failing validation against all five MCP content-type schemas (text, image, audio, resource_link, resource) simultaneously — each variant's required payload field (text, data, blob, etc.) is undefined. The block carries a type tag but no actual payload, i.e. the response is malformed rather than a clean error.
Reproduced with (both from the same Slack thread):
901_Wicker_St_Residential_Solar_Array_PlanSet_Mon_Aug_3_2026_13-05-52.pdf— 5.5 MB — failed twice901_WICKER_ST_WOODSTOCK_IL_US_60098.pdf— 5.2 MB — failed twice, including a fresh call with no other change
Expected: Either the file content returns successfully (both files are under the documented 10 MB cap), or the tool returns a clean, schema-valid error (e.g. a text block stating the file is too large) instead of a payload-less block that fails client-side schema validation.
Impact: Any workflow depending on reading Slack-attached PDFs over a few MB (e.g. permit packages, plan sets, contracts) breaks with an opaque schema error rather than an actionable one.
Notes:
- Retrying the same file, waiting and retrying fresh, and trying the smaller of two files all produced the identical failure — this is deterministic at this size range, not transient.
- Likely mechanism: the connector's Slack-side file fetch (auth + download + base64-encode) hits an internal size/timeout limit and returns a partially-built content block instead of surfacing a clean error.