SwarmOps
ReferenceMcp toolsread_file
View as Markdown

read_file#

Reads one file at a revision, without a checkout, as UTF-8 text or base64, from offset or the lines a range names; pass max_bytes of 32768 or less (less for a binary file), since clients limit long tool results and this one holds the content twice, and read on from next_offset while the result is truncated.

Metadata
Since
0.1.0
Mutates
no
Identity required
no
Envelope op
read_file
Cli command
swarmops cat
Request type
ReadFileReq
Annotations
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
Max result chars
200000
CLI command
swarmops cat

Input schema#

arguments is a ReadFileReq: swarmops schema ReadFileReq prints the type. A field the type does not know is ignored.

FieldTypeRequiredDefaultDescription
linesobject or nullnoRead these lines instead, numbered from 1, both ends included: a line ends after its newline, and a last line without one is a line too. The lines of the range that exist come back, none past the file's last. Give this or offset, not both (E_INVALID_ARG).
max_bytesintegerno1048576The most content bytes to return; more comes back truncated, with the next_offset to read on from.
offsetintegerno0Where to start reading, in bytes from the file's start: a truncated read's next_offset reads on from where it stopped. An offset past the end gives empty content. Give this or lines, not both (E_INVALID_ARG).
pathstringyesThe file's repository path.
revstringyesThe revision to read at. A revision as the caller wrote it, for the store to resolve: a ref name (main, release/1.2), a full 64-hex changeset id or a unique prefix of at least 12 hex digits, optionally followed by ~N for the N-th first-parent ancestor.

JSON Schema#

As tools/list gives it: each $ref replaced by its definition, so that it stands alone.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "`read_file` (CLI `cat`): read one file at a revision, without a checkout: from an offset, or\na range of its lines.",
  "properties": {
    "lines": {
      "anyOf": [
        {
          "description": "A range of a file's lines, numbered from 1: `first` to `last`, both included.",
          "properties": {
            "first": {
              "description": "The range's first line: at least 1.",
              "format": "uint64",
              "minimum": 1,
              "type": "integer"
            },
            "last": {
              "description": "The range's last line: at least `first`.",
              "format": "uint64",
              "minimum": 1,
              "type": "integer"
            }
          },
          "required": [
            "first",
            "last"
          ],
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "description": "Read these lines instead, numbered from 1, both ends included: a line ends after its\nnewline, and a last line without one is a line too. The lines of the range that exist\ncome back, none past the file's last. Give this or `offset`, not both (`E_INVALID_ARG`)."
    },
    "max_bytes": {
      "default": 1048576,
      "description": "The most content bytes to return; more comes back truncated, with the `next_offset` to\nread on from.",
      "format": "uint64",
      "minimum": 0,
      "type": "integer"
    },
    "offset": {
      "default": 0,
      "description": "Where to start reading, in bytes from the file's start: a truncated read's `next_offset`\nreads on from where it stopped. An offset past the end gives empty content. Give this or\n`lines`, not both (`E_INVALID_ARG`).",
      "format": "uint64",
      "minimum": 0,
      "type": "integer"
    },
    "path": {
      "description": "The file's repository path.",
      "type": "string"
    },
    "rev": {
      "description": "The revision to read at. A revision as the caller wrote it, for the store to resolve: a ref name (`main`,\n`release/1.2`), a full 64-hex changeset id or a unique prefix of at least 12 hex digits,\noptionally followed by `~N` for the N-th first-parent ancestor.",
      "type": "string"
    }
  },
  "required": [
    "rev",
    "path"
  ],
  "title": "ReadFileReq",
  "type": "object"
}

Annotations#

It only reads the store.

AnnotationValueMeaning
destructiveHintfalseTrue: a tool that changes the store may overwrite or delete what is there, not only add to it.
idempotentHinttrueTrue: calling it again with the same arguments changes nothing more.
openWorldHintfalseTrue: it reaches beyond a closed set of things. Every tool here stays inside the store.
readOnlyHinttrueTrue: the tool does not change its environment, the store.

Its entry in tools/list carries _meta: {"anthropic/maxResultSizeChars": 200000}: Claude Code keeps a result of up to 200000 characters in the conversation instead of saving it to a file.

CLI command#

swarmops cat runs the same operation and prints the same envelope.

Examples#

{
  "id": 8,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "path": "README.md",
      "rev": "main"
    },
    "name": "read_file"
  }
}
{
  "id": 8,
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "text": "{\"ok\":true,\"op\":\"read_file\",\"api\":1,\"result\":{\"blob\":\"[blob]\",\"size\":7,\"kind\":\"file\",\"encoding\":\"utf8\",\"content\":\"# acme\\n\",\"truncated\":false},\"meta\":{\"repo\":\"[tmp]/store\",\"elapsed_ms\":\"[elapsed_ms]\",\"resolved\":{\"main\":\"[c1]\"},\"auth\":\"trust\"}}",
        "type": "text"
      }
    ],
    "isError": false,
    "structuredContent": {
      "api": 1,
      "meta": {
        "auth": "trust",
        "elapsed_ms": "[elapsed_ms]",
        "repo": "[tmp]/store",
        "resolved": {
          "main": "[c1]"
        }
      },
      "ok": true,
      "op": "read_file",
      "result": {
        "blob": "[blob]",
        "content": "# acme\n",
        "encoding": "utf8",
        "kind": "file",
        "size": 7,
        "truncated": false
      }
    }
  }
}

The server ran as swarmops mcp --repo [tmp]/store --as agent/worker-17, after initialize. Recorded by the MCP tests. A name in square brackets, such as [tmp] or [c1], stands for what differs from run to run: the test's temporary directory, an id, a time, the version.

Details#

Pass max_bytes of 32768 or less (less for a binary file, which comes back as base64): the operation's own default is 1 MiB, and a result holds the content twice. While the result is truncated, call again with offset set to its next_offset. lines reads a range of lines, numbered from 1, both ends included, instead of an offset; giving both is E_INVALID_ARG.

read_file is the one tool that raises Claude Code's result size limit for itself, through its _meta in tools/list: see Result size limits.

Return information#

A tool result: the envelope, whose op is read_file, as structuredContent and again as the text of its one content block. isError is true exactly when the envelope's ok is false. On success the envelope's result is what swarmops cat returns.

Errors#

A failed call is a tool result with isError: true; the envelope's error.code is one of the error codes.

  • E_INVALID_ARG: arguments that do not fit ReadFileReq, a field named twice among them included, or that break one of the server's own rules.
  • E_NOT_A_REPO: the server's store is not there; the server serves on.
  • E_INTERNAL: the operation panicked, a bug.

Then the errors of the operation, as swarmops cat lists them.

See also#

Edit on GitHub

On this page