A Bible MCP server with search capabilities, powered by a custom Bible API on Cloudflare Workers + D1
Bible MCP demonstrates solid tool design with clear naming conventions, well-structured schemas using Zod, and comprehensive descriptions. All 7 tools follow verb_noun naming patterns (get_verse, search_bible, list_books, etc.). Descriptions are detailed and provide context for LLM selection. Input schemas are properly typed with Zod validators. However, output schemas are not explicitly documented in the visible code, responses are constructed ad-hoc as text concatenation rather than returning structured objects. Error handling exists but lacks actionable guidance for LLM recovery. The read_bible tool stands out as an outlier, returning HTML rather than structured content, which may confuse LLM parsing. Security considerations are adequate (read-only operations, no secrets exposed), but parameter descriptions could be more concise to avoid token waste.
Get full chapter text with verse numbers and prev/next navigation hints. Examples: ("Genesis", 1), ("PSA", 23), ("ROM", 8)
Get a random verse from the Bible. Can filter by book or testament.
Retrieve verse text by reference. Returns formatted text with reference and translation. Examples: "John 3:16", "Romans 8:28-39", "Psalm 23" Supports comma-separated references with context inheritance: - "Romans 14:14, 22-23" (inherits book and chapter) - "Psalm 23, 24" (inherits book) - "Genesis 1:1, 2:3" (inherits book, new chapter) - "John 3:16, Romans 8:28" (independent references)
List all books of the Bible with chapter counts. Can filter by testament.
List all available Bible translations with IDs, names, languages, and licenses.
Read Bible passages with a structured, interactive HTML viewer. Supports verse lookup, chapter navigation, translation switching, and book browsing.
Output schemas not documented. Tools return text-formatted responses (constructed via string concatenation in src/mcp-server.ts) rather than structured JSON objects with documented fields. LLMs cannot predict output structure for downstream tool chaining.
read_bible returns HTML (BIBLE_READER_HTML) instead of structured content. This tool violates the response-shaper pattern, HTML is opaque to LLMs and prevents downstream reasoning. Should return structured verse data with metadata.
Error handling lacks actionable recovery guidance. formatToolError() in api-client.ts returns error objects without suggesting next steps (e.g., 'Try list_books() to see available references'). LLMs receive errors but no direction on how to proceed.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 70 | 2025-06-18+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Search for verses containing words or phrases. Returns matching verses with full text. Examples: "love", "faith" in Romans, "peace" in New Testament
Parameter descriptions include verbose enums inline (e.g., TRANSLATION_DESCRIPTION repeated 6 times). This wastes tokens and violates DRY. Should use enum constraints in schema rather than repeating in description.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) present in any tool definition. While all tools are read-only, explicit annotations would clarify this to downstream systems and improve safety contracts.
list_translations() has no parameters documented (Input: {}), but the description lists available translations, unclear if the tool accepts filters (e.g., language, license type). Either add optional filter parameters or clarify that it returns all translations unfiltered.
search_bible supports optional book and testament filters, but no guidance on how they interact (AND vs OR). If searching 'love' with book='ROM' and testament='NT', are results limited to Romans in the New Testament (redundant) or to the New Testament excluding Romans? Ambiguity forces LLM guessing.