Repository navigation
Say when an MCP read leaves content out #380
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
Four MCP read paths can leave content out. Three say nothing, and one gives the wrong next step. Each should say what it left out and what to do next.
Parent: #230 (moved from #328, which has no row for it). Split from #226. Build after #456 and #457. They edit the same tools, and #457 removes the structuredContent of find_documents, get_outline and list_chat_rooms.
Where
apps/hocuspocus.server/src/modules/mcp/tools/documentTools.ts:find_documents176-198,get_outline246-255,read_document284-289.apps/hocuspocus.server/src/modules/mcp/tools/chatTools.ts:list_chat_rooms78-108.apps/hocuspocus.server/src/modules/mcp/infra/documentStore.ts:31-53:listDocuments, unchanged.apps/hocuspocus.server/src/modules/mcp/types.ts:12:MAX_READ_CHARS.docs/mcp/reference.md:75and:101.
What happens
Read from code and app docs, not measured.
get_outlinereturns every heading, andlist_chat_roomsreturns every chat room, with no cap. Connected apps cap a tool result near 150,000 characters, and a document can hold 5 MiB.find_documentsreturns at mostlimitrows (default 20, max 50) and never says more exist. An owner with 60 documents who asks "list all my documents" gets 20 and treats them as all.read_documentwithsection_idthat hits the cap says "read one section at a time with section_id", which the agent already did (documentTools.ts:287-289). The agent cannot read the rest, and it never sees the[n]numbers of the cut blocks, soedit_blockscannot reach them.
Fix
Each note is docs.plus's own guidance, so it sits after the data frame, as read_document does today (documentTools.ts:286). Build every character count in a note from MAX_READ_CHARS, never from a literal.
get_outlineandlist_chat_rooms: build the lines as today. Keep lines from the first one whilesize + line.length + 1 <= MAX_READ_CHARS.- This walk goes forward. Do not copy the
read_chat_threadloop as it is (chatTools.ts:139-144): it walks from the end and keeps the newest lines. - For
get_outline, the lines arerenderOutline(outline), in tree order. - When lines are cut, add
[Truncated: showing N of M headings.]forget_outline, or[Truncated: showing N of M rooms.]forlist_chat_rooms.
- This walk goes forward. Do not copy the
find_documents: calllistDocumentswithlimit: limit + 1;infra/documentStore.tsstays a plaintake. When the extra row comes back, drop it and add[More documents exist. Narrow with query, or raise limit up to 50.]Whenlimitis already 50, the note is[More documents exist. Narrow with query.]read_documentwithsection_id, when cut:- If
max_charswas given and is belowMAX_READ_CHARS:[Truncated: showing {cap} of {total} characters. Call again with a larger max_chars, up to {MAX_READ_CHARS}.] - Otherwise:
[Truncated: showing {MAX_READ_CHARS} of {total} characters. This section alone is longer than {MAX_READ_CHARS}.] - A read without
section_idkeeps today's note.
- If
docs/mcp/reference.md: the §Limits "Read output" row (line 101) says the cap also applies toget_outlineandlist_chat_rooms. Thefind_documentsparagraph (line 75) says a note tells the agent when more documents match.
No new test: each change is a short loop or a note string, and AGENTS.md §Test Policy makes tests opt-in.
Out of scope
- A cursor or offset for
find_documents. An owner with more than 50 documents still needs a query to reach the rest. read_chat_thread: it already says when it cuts.from_blockforread_document(see Open decisions).
Acceptance criteria
-
get_outlinekeeps the first headings up toMAX_READ_CHARS, and ends with[Truncated: showing N of M headings.]after the data frame. -
list_chat_roomskeeps the first rooms the same way, and ends with[Truncated: showing N of M rooms.]after the data frame. - With 21 or more documents and the default limit,
find_documentsreturns 20 rows and the note, after the data frame. With 20 or fewer, it returns no note. - A cut section read gives the total. The
max_charsnote names a largermax_chars; the other note says the section alone is longer. Neither tells the agent to usesection_id. - A short outline and a short list are unchanged.
-
docs/mcp/reference.md:75and:101describe the notes.
Verify
cd apps/hocuspocus.server && bun run typecheck && bun test.- Read the diff: the outline and room walk keeps the first lines, and each note sits after the data frame.
Open decisions
- Add
from_blocktoread_documentso a long section can be read in parts? Recommended: no, not now. No real section near 100,000 characters has been reported.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
[-]Cap the get_outline and list_chat_rooms output[/-][+]Say when an MCP read leaves content out[/+]HMarzban commentedon Oct 7, 2026
Maintainer ruling, 2026-10-07
Open decision (
from_block): no. docs.plus does not build a way to read long sections in parts, a search gateway, or embedding search for agents. Agents bring their own search and context tools. docs.plus only tells them, and through them the person, when something is very long.What to build instead, kept small and quiet:
get_outlineadds one short marker on that heading's line, for example(very long: about 95,000 tokens), so the agent knows before it reads.read_documenttruncation note for that section adds one sentence: "This section is very long. Tell the person that only the first part was read."