mcpField
G
gutenberg-mcp-server

gutenberg-mcp-server

Remote
github.com/cyanheadsGames & Entertainment4Updated 2w ago
Repository

About gutenberg-mcp-server

gutenberg-mcp-server lets readers and research workflows search and read Project Gutenberg's public-domain catalog. It provides book metadata and retrieves supported text in chunks, with catalog search backed by a local mirror and Gutendex fallback.

Key features

  1. 01Search books by title, author, or topic
  2. 02Filter by language and other fields
  3. 03Retrieve book metadata and formats
  4. 04Read text in offset-based chunks
  5. 05Browse popular books

Use cases

  1. 01Find books by author, topic, or language
  2. 02Retrieve metadata for a selected edition
  3. 03Read long books in sequential chunks
  4. 04Browse popular titles by topic

MCP support

Exposes Project Gutenberg catalog search, metadata, text retrieval, and popular-book browsing to MCP clients through four tools. Available over STDIO or Streamable HTTP.

Configuration

Remote servers need no local install. Pick your client, then copy the config or install in one click.

Endpointhttps://gutenberg.caseyjhand.com/mcp
Copy install command
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.

Packages
npm@cyanheads/gutenberg-mcp-server0.2.0

Tools

4
ParameterTypeRequiredDescription
idsarrayNoNarrow results to specific Gutenberg ID numbers. Other filters still apply. Useful for batch pre-fetching known IDs; use gutenberg_get_book for single-ID lookups.
pageintegerNoPage number for paginated results (1-indexed). Each page returns up to 32 books. Use totalCount to determine total pages.
sortenumNoResult ordering. "popular" (default) sorts by downloads in the last 30 days at the source snapshot, descending. "ascending" and "descending" sort by Gutenberg ID number.popular | ascending | descending
querystringNoWords to match against book titles and author names (case-insensitive, space-separated). Example: "dickens expectations" matches Great Expectations by Charles Dickens.
topicstringNoCase-insensitive phrase to match against subjects and bookshelves. Example: "detective" returns books on the "Detective and Mystery Stories" bookshelf. Separate from query — topic searches categorization metadata, not title/author.
languagesarrayNoFilter to books in any of these two-character ISO 639-1 language codes. Example: ["en"] for English, ["fr", "de"] for French or German.
author_year_endintegerNoInclude only books with at least one author alive on or before this year. Example: author_year_start=1800 with author_year_end=1899 returns books with 19th-century authors.
author_year_startintegerNoInclude only books with at least one author alive on or after this year (positive = CE, negative = BCE). Combine with author_year_end for a range.

Details

From the project README

@cyanheads/gutenberg-mcp-server

Search, browse, and read 78,000+ public-domain books from Project Gutenberg with full plain-text retrieval and offset/limit chunking via MCP. STDIO or Streamable HTTP.

4 Tools

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://gutenberg.caseyjhand.com/mcp


Overview

Project Gutenberg's library of 78,000+ public-domain books. Search by title, author, topic, or language, fetch full book metadata, and read supported UTF-8 plain-text and HTML editions in manageable chunks.

Tools
ToolDescription
gutenberg_search_booksSearch the catalog by title, author, topic, language, or author lifespan, with pagination and popularity sorting
gutenberg_get_bookFetch complete metadata for a book by ID — authors, translators, editors, full formats map, subjects, copyright status
gutenberg_get_textRetrieve a book's plain-text content stripped of license boilerplate, with offset/limit chunking
gutenberg_browse_popularBrowse the most-downloaded books, optionally filtered by language or topic

Capability reference

gutenberg_search_books tool
  • Filters: query (title/author words), topic, languages (ISO 639-1), author_year_start/author_year_end, ids, mime_type, and copyright ("true", "false", "null"; false means public domain in the USA). Live fallback rejects queries over four words
  • sort is popular (default) or ascending/descending by Gutenberg ID. Up to 32 books per page; use totalCount and hasMore to page
  • Each result carries is_readable (readable by gutenberg_get_text) and has_plain_text. Fails with query_requires_mirror, page_out_of_range, or catalog_unavailable

gutenberg_get_book tool
  • Returns the full formats map (MIME type → download URL) and authors, translators, and editors with birth/death years
  • Also carries is_readable, has_plain_text, summary, source_notes, and download_count (downloads in the last 30 days, not lifetime)
  • Fails with not_found or catalog_unavailable

gutenberg_get_text tool
  • Reads a book in offset/limit chunks (default limit 20,000, capped at 50,000), with the Gutenberg license header and footer stripped. requestedLimit and appliedLimit report both
  • Prefers UTF-8 plain text and falls back to HTML converted to text; sourceFormat says which. Returns totalChars, length, remainingChars, hasMore, and provenance (ID, title, license URL). Use length, not limit, to compute the next offset
  • Fails with not_found, audio_book (media_type "Sound"), no_text_format, offset_out_of_range, text_file_not_found, text_fetch_rejected, invalid_text_response, text_fetch_failed, or catalog_unavailable

gutenberg_browse_popular tool
  • Returns up to 32 titles (limit, default 20), most downloaded in the last 30 days first. requestedLimit and appliedLimit report the cap
  • Optional languages, topic, mime_type, and copyright filters work as in search. totalInCatalog gives the full count
  • Output reports truncation and carries a continuation pointing at gutenberg_search_books. Empty results succeed with a notice; fails with catalog_unavailable

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

Gutenberg-specific:

  • Searches and lookups read a local SQLite+FTS5 catalog mirror, falling back to Gutendex when the mirror is cold or missing a record
  • Full plain-text retrieval from a Project Gutenberg content mirror, with UTF-8/HTML fallback
  • Book text is cached per tenant, so later chunk reads skip the fetch
  • No API key required

Agent-friendly output:

  • is_readable on every search and browse result flags editions gutenberg_get_text can read
  • offset, length, totalChars, remainingChars, and hasMore support reliable sequential reads
  • provenance and sourceFormat on every text response cover attribution and fidelity

Getting started

Public Hosted Instance

A public instance is available at https://gutenberg.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "gutenberg-mcp-server": {
      "type": "streamable-http",
      "url": "https://gutenberg.caseyjhand.com/mcp"
    }
  }
}
Self-Hosted / Local

No API key required. Add the following to your MCP client configuration file:

{
  "mcpServers": {
    "gutenberg-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/gutenberg-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "gutenberg-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/gutenberg-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "gutenberg-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "ghcr.io/cyanheads/gutenberg-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
  • Bun v1.4.0 or higher (or Node.js v24+).
  • No API key required — Project Gutenberg data is freely available.
Installation
  1. Clone the repository:
git clone https://github.com/cyanheads/gutenberg-mcp-server.git
  1. Navigate into the directory:
cd gutenberg-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# edit .env if you need to override any defaults

Configuration

VariableDescriptionDefault
GUTENDEX_BASE_URLGutendex catalog API base URL.https://gutendex.com/books/
GUTENBERG_TEXT_BASE_URLContent mirror serving the /cache/epub file tree.https://gutenberg.pglaf.org
GUTENBERG_MIRROR_PATHSQLite catalog path; use a persistent volume in containers../.mirror/gutenberg-catalog.sqlite
GUTENBERG_MIRROR_REFRESH_CRONCron schedule for in-process catalog refresh.Unset
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_SESSION_MODEHTTP session mode: auto, stateful, or stateless. Overrides the stateless posture the server declares in createApp().stateless
MCP_HTTP_PORTPort for HTTP server.3010
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
STORAGE_PROVIDER_TYPEStorage backend.in-memory
OTEL_ENABLEDEnable OpenTelemetry instrumentation.false

Build the local catalog with bun run mirror:init and check it with bun run mirror:verify. The server never harvests on startup, and uses Gutendex until the first harvest completes. Keep the catalog up to date with bun run mirror:refresh on a host scheduler, or set GUTENBERG_MIRROR_REFRESH_CRON.


Running the server

Local development
  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
    
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec
    
Docker
docker build -t gutenberg-mcp-server .
docker run --rm -p 3010:3010 gutenberg-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/gutenberg-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.


Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools and inits services.
src/config/server-config.tsServer-specific environment variable parsing (Gutendex and file-server URL overrides).
src/mcp-server/tools/definitions/Tool definitions (*.tool.ts).
src/services/gutendex/Gutendex catalog API client — search and book metadata.
src/services/catalog-mirror/Local SQLite+FTS5 catalog mirror — RDF ingestion and read helpers.
src/services/gutenberg-text/Full plain-text retrieval, boilerplate stripping, tenant-scoped caching, and chunking.
tests/Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools via the entry arrays in src/index.ts
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

Data attribution

Data from Project Gutenberg is in the public domain. Catalog metadata sourced from Gutendex (MIT license).


License

Apache-2.0 — see LICENSE for details.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.