MCP server for Project Gutenberg — 75,000+ public-domain ebooks with full plain-text retrieval.
Search, browse, and read 75,000+ public-domain books from Project Gutenberg with full plain-text retrieval and offset/limit chunking via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://gutenberg.caseyjhand.com/mcp
Project Gutenberg's library of 78,000+ public-domain books, cataloged through the Gutendex API and served from a Gutenberg content mirror. Search by title, author, topic, or language, fetch full book metadata, and retrieve plain-text content in offset/limit chunks for long works from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
gutenberg_search_books | Search the catalog by title, author, topic, language, or author lifespan, with pagination and popularity sorting |
gutenberg_get_book | Fetch complete metadata for a book by ID — authors, translators, editors, full formats map, subjects, copyright status |
gutenberg_get_text | Retrieve a book's plain-text content stripped of license boilerplate, with offset/limit chunking |
gutenberg_browse_popular | Browse the most-downloaded books, optionally filtered by language or topic |
gutenberg_search_books toolquery matches titles and author names; topic matches subjects/bookshelves separately from querylanguages (ISO 639-1 codes), author_year_start/author_year_end lifespan range, ids for a batch lookup by known ID listsort: popular (default, by download count) or ascending/descending by Gutenberg IDtotalCount and hasMore drive further pageshas_plain_text to pre-filter before calling gutenberg_get_textno_results, page_out_of_range, catalog_unavailablegutenberg_get_book toolformats map (MIME type → download URL) — plain text, HTML, EPUB, cover imagehas_plain_text confirms a UTF-8 plain-text format exists; media_type distinguishes text books from audio ("Sound")summary is the first entry of Gutendex's summaries array — both are null/empty when Gutendex has nonenot_found, catalog_unavailablegutenberg_get_text tooloffset/limit chunking (limit 1–50,000, default 20,000) for works that routinely run 500KB–2MBsourceFormat reports which)totalChars, length, remainingChars, hasMore — use length, not limit, to compute the next offset, since paragraph-boundary trimming can return slightly less than requestedprovenance carries the Gutenberg ID, title, and license URL for attributionnot_found, audio_book (refuses media_type "Sound"), no_text_format, offset_out_of_range, text_fetch_failed, catalog_unavailablegutenberg_browse_popular toollimit, default 20) ordered by download count, most popular firstlanguages and topic filters, applied togethertotalInCatalog gives full context (e.g. "top 20 of 60,000")gutenberg_search_books to page through the restno_results, catalog_unavailableBuilt 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:
gutenberg_get_book, gutenberg_get_text) read from a local SQLite+FTS5 catalog mirror when it holds the record, falling back to the live Gutendex API otherwiseAgent-friendly output:
has_plain_text flag on every search/browse result lets agents pre-filter before attempting text retrievalgutenberg_get_text — offset, length, totalChars, remainingChars, hasMore for reliable sequential readsprovenance and discriminated sourceFormat fields on every text response, for attribution and fidelity awarenessgutenberg_browse_popular enrichment reports truncation state and the download-count ceiling of omitted resultsA 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"
}
}
}
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
git clone https://github.com/cyanheads/gutenberg-mcp-server.git
cd gutenberg-mcp-server
bun install
cp .env.example .env
# edit .env if you need to override any defaults
| Variable | Description | Default |
|---|---|---|
GUTENDEX_BASE_URL | Base URL for the Gutendex catalog API. Override for self-hosted instances. | https://gutendex.com/books/ |
GUTENBERG_TEXT_BASE_URL | Base URL for a Project Gutenberg content mirror serving the /cache/epub file tree. Override to use a different mirror. | https://gutenberg.pglaf.org |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_SESSION_MODE | HTTP session mode: auto, stateful, or stateless. Overrides the stateless posture the server declares in createApp(). | stateless |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE | Storage backend. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
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 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.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and inits services. |
src/config/server-config.ts | Server-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/. |
See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Data from Project Gutenberg is in the public domain. Catalog metadata sourced from Gutendex (MIT license).
Apache-2.0 — see LICENSE for details.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @cyanheads/gutenberg-mcp-serverMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cyanheads-gutenberg-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/gutenberg-mcp-server"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cyanheads/gutenberg-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.