readDoc
Read a knowledge document
Read the content of one document. Either give the project id and a path within it (this is the form listDocs returns, whose paths are relative to the project), or give one combined path of the form "<project>/<path>", which is the form searchKnowledge returns. Large documents are paged: if truncated is true, call again with offset = nextOffset. For a document in your own home the result also carries an opaque version identifying the bytes you read: pass it to writeDoc or editDoc as expectedVersion to make the change conditional on nothing else having changed the file, and pass it back here as version to keep paging bound to the same bytes.
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
project | string | optional | Project id from listProjects; omit if path already starts with it |
path | string | required | Document path, e.g. "acme/rate-card.md", or "rate-card.md" when project is given (the latter is what listDocs returns) |
offset | integer | optional | Byte offset to start from (for paging) |
maxBytes | integer | optional | Max bytes to return (default 50000) |
version | string | optional | The version from an earlier readDoc of this document, to pin later pages to the same bytes. The read is refused as a conflict if the file has changed since. There is no history, so the earlier bytes cannot be returned. |
expectedVersion | string | optional | Not used here. Pass version instead. Supplying this is an error rather than a silent no-op. |
Scopes
knowledge:read
Annotations
- Read only: yes
- Destructive: no
When to use
Use readDoc to read the full text of a document that listDocs or searchKnowledge found. Always read the current document before you state a fact from it or change it.
The tool needs the knowledge:read scope. There are two ways to name the document:
projectandpath, wherepathis relative to the project. This is the form thatlistDocsreturns.pathalone, in the form<project>/<path>. This is the form thatsearchKnowledgereturns.
Paging:
- One call returns at most
maxBytesbytes. The default and the maximum is 50,000. - When
truncatedistrue, call again withoffsetset tonextOffset.nextOffsetis present only whentruncatedistrue. - Page edges never split a character, so
bytesReturnedcan be a little less thanmaxBytes. Join the pages in order to get the document.
The version field:
- A member's connection gets a
versionwhen this instance has document writing turned on for that kind of project. Admin and staff connections never get one. There is also noversionwhen the path is one that the write tools cannot take, for example a file type they do not support. - Pass
versiontowriteDocoreditDocasexpectedVersion, so that the change fails if someone else changed the file. - Pass it back to
readDocasversionwhen you read the next page. The read then fails if the file changed between pages. There is no history, so the earlier bytes cannot be returned. - Do not send
expectedVersiontoreadDoc. It is refused. The argument here isversion.
A member can read their own home and each ordinary project where they hold a grant. Admin and staff can read every active ordinary project, but no member home. Paths whose first segment is skills or prompts, and paths with a segment that starts with ., are never readable.
Example
The first page of a document, read by a member's connection on an instance with shared-project writing turned on:
{ "project": "northwind-advisory", "path": "pricing-policy.md", "maxBytes": 400 }
{
"path": "northwind-advisory/pricing-policy.md",
"content": "# Pricing policy\n\nOwner: Commercial lead. Last reviewed: March 2026.\n\nThis policy sets how Northwind Advisory prices client work. It applies to every proposal, statement of work and change request. A partner must approve any departure from it in writing.\n\n## Day rates\n\nWe price most work on a day rate. The standard rates are:\n\n- Partner: £1,450 per day\n- Senior consultant: £1,050 per day\n- Consu",
"totalBytes": 1730,
"offset": 0,
"bytesReturned": 400,
"truncated": true,
"nextOffset": 400,
"version": "AQ-example-opaque-version"
}
The next page, pinned to the same bytes:
{ "path": "northwind-advisory/pricing-policy.md", "offset": 400, "maxBytes": 400, "version": "AQ-example-opaque-version" }
Refusals and what to do
Error in readDoc: Not found: the project does not exist or this person cannot see it, or the path is not allowed (a first segmentskillsorprompts, a segment that starts with., an empty segment, or a segment that contains%). CalllistProjectsandlistDocsand use a project and path from their results.Error in readDoc: Document not found: the project is visible, but the document is not there. Check the path withlistDocsorsearchKnowledge.Error in readDoc: version_conflict:stale_version: you passedversion, and the file changed after that read. CallreadDocagain fromoffset0 withoutversion, and use the new text.Error in readDoc: handle_invalid:handle_unverifiable: this connection cannot check aversionfor this document, for example because it is an admin or staff connection, or writing is off for this kind of project. Read again withoutversion.Error in readDoc: handle_invalid:handle_malformedorhandle_invalid:handle_rejected: theversionis not one that this instance issued for this document. Use the exactversionfrom an earlierreadDocof the same document.Error in readDoc: invalid_input:use_version_not_expected_version: you sentexpectedVersion. Sendversioninstead.- If the connection does not hold
knowledge:read, the tool is not in your tool list, and a call to it returnsMCP error -32602: Tool readDoc not found. Read thepermissionssection ofgetDocs. A scope is never added to an existing connection: the person must reconnect, or mint a new token, withknowledge:read.
Related
searchKnowledgeandlistDocsfind the path to read.listProjectsgives the project ids.- The
member-home-writefamily (writeDocandeditDoc) takes theversionfrom this tool asexpectedVersion.