Skip to main content
Glama

gutenberg-mcp-server

Get Gutenberg Book Text

gutenberg_get_text
Read-onlyIdempotent

Retrieve the plain-text content of a Project Gutenberg book, stripped of the standard license header and footer so the response contains only the literary work. For long works — novels routinely run 500KB–2MB — use offset and limit to read in chunks rather than fetching the whole book at once. The response reports totalChars and remainingChars for reliable pagination. Prefers UTF-8 plain text; falls back to an HTML edition converted to text; refuses audio books (media_type "Sound") with a clear error.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesProject Gutenberg book ID. Use gutenberg_search_books or gutenberg_get_book to find IDs. Example: 1342 for Pride and Prejudice, 2600 for War and Peace, 84 for Frankenstein.
limitNoMaximum number of characters to return in this chunk. Default 20,000 (~4–5 pages of prose). Increase toward 50,000 for large context windows. The actual returned length may be slightly less than limit when a natural paragraph boundary is found within 500 characters of the limit — check the length field in the response for the actual character count returned.
offsetNoCharacter offset into the stripped literary text at which to start reading. 0 returns the beginning of the work. To read subsequent chunks, use offset = prior_offset + prior_length (the length field from the previous response — NOT offset + limit, because the actual returned length may be slightly less than limit due to paragraph-boundary trimming).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
idNoGutenberg book ID.
textNoThe requested chunk of literary text, stripped of Gutenberg license boilerplate. Encoding: UTF-8. Line endings: normalized to LF.
errorNoPresent when the call failed. Absent on success.
titleNoBook title, from the catalog record.
lengthNoNumber of characters in this chunk.
offsetNoCharacter offset where this chunk begins.
hasMoreNoTrue if there is more text after this chunk. When true, call again with offset = offset + length.
provenanceNoOne-line source note with Project Gutenberg ID, title, and license URL.
totalCharsNoTotal characters in the stripped literary text. Use with offset and length to determine progress and plan subsequent calls.
sourceFormatNoThe format that was fetched. "text/html" indicates HTML-to-text conversion was applied because no plain-text format was available.
remainingCharsNoCharacters remaining after this chunk (totalChars - offset - length). 0 means this chunk includes the end of the book.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: No book exists with the given ID. `audio_book`: The book is an audio recording (media_type \"Sound\"), not a text book — no literary plain text is available. `no_text_format`: The book has no UTF-8 plain-text or HTML edition available to read (for example an older ASCII-only entry). `offset_out_of_range`: The offset is greater than or equal to totalChars (past the end of the book). `text_fetch_failed`: The Gutenberg file server returned an error or did not respond within the timeout. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `not_found`: No book exists with the given ID. `audio_book`: The book is an audio recording (media_type \"Sound\"), not a text book — no literary plain text is available. `no_text_format`: The book has no UTF-8 plain-text or HTML edition available to read (for example an older ASCII-only entry). `offset_out_of_range`: The offset is greater than or equal to totalChars (past the end of the book). `text_fetch_failed`: The Gutenberg file server returned an error or did not respond within the timeout. `catalog_unavailable`: The catalog lookup that precedes reading a book did not answer within the time this server allows. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "not_found",
      -  "audio_book",
      -  "no_text_format",
      -  "offset_out_of_range",
      -  "text_fetch_failed"
      -]New value: +[
      +  "not_found",
      +  "audio_book",
      +  "no_text_format",
      +  "offset_out_of_range",
      +  "text_fetch_failed",
      +  "catalog_unavailable"
      +]
  2. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "id",
      +      "title",
      +      "text",
      +      "offset",
      +      "length",
      +      "totalChars",
      +      "remainingChars",
      +      "hasMore",
      +      "provenance",
      +      "sourceFormat"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `not_found`: No book exists with the given ID. `audio_book`: The book is an audio recording (media_type \"Sound\"), not a text book — no literary plain text is available. `no_text_format`: The book has no UTF-8 plain-text or HTML edition available to read (for example an older ASCII-only entry). `offset_out_of_range`: The offset is greater than or equal to totalChars (past the end of the book). `text_fetch_failed`: The Gutenberg file server returned an error or did not respond within the timeout. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "not_found",
      +            "audio_book",
      +            "no_text_format",
      +            "offset_out_of_range",
      +            "text_fetch_failed"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "id",
      -  "title",
      -  "text",
      -  "offset",
      -  "length",
      -  "totalChars",
      -  "remainingChars",
      -  "hasMore",
      -  "provenance",
      -  "sourceFormat"
      -]
  3. First observed

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnly, openWorld, and idempotent hints, and the description adds substantial behavioral detail beyond that: stripping headers/footers, preferring UTF-8 plain text and falling back to HTML conversion, refusing audio books, and reporting totalChars/remainingChars for pagination. This is consistent with annotations and enriches the agent's understanding.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise relative to the complexity, with each sentence carrying key information. It front-loads the core purpose, then provides practical usage details for chunking and pagination, and ends with fallback behaviors. There is no wasted wording; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (only one required parameter) and the rich annotations and output schema, the description covers all necessary context: purpose, pagination mechanics, response fields, fallback behavior, and error cases. It is complete enough for an agent to call the tool correctly without further clarification.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers 100% of parameters, and the description adds significant semantics, especially for offset: it explicitly states to use prior_offset + prior_length rather than offset + limit due to paragraph-boundary trimming, and explains the limit default and actual return length behavior. This goes well beyond the schema's descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Retrieve' and the resource 'plain-text content of a Project Gutenberg book', and specifies the key distinguishing detail of stripping license headers/footers. It also differentiates from siblings by naming that book IDs come from gutenberg_search_books or gutenberg_get_book, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit guidance on when to use offset/limit for long works, explains pagination using totalChars/remainingChars, and notes it refuses audio books. It implies that for searching or getting book metadata, other tools should be used, effectively distinguishing this tool's usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.