LoreKeeper MCP
Provides access to comprehensive D&D 5e game data including spells, monsters, classes, races, equipment, and rules through the Open5e and D&D 5e APIs with intelligent caching.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@LoreKeeper MCPwhat spells can a level 3 wizard cast?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
LoreKeeper MCP
A Model Context Protocol (MCP) server for D&D 5e information lookup with AI assistants. LoreKeeper provides fast, cached access to comprehensive Dungeons & Dragons 5th Edition data through the Open5e API.
Features
Comprehensive D&D 5e Data: Access spells, monsters, classes, races, equipment, and rules
Semantic Search: Milvus Lite vector database with natural language search capabilities
Open5e API Integration: Access to comprehensive D&D 5e content via Open5e API
Type-Safe Configuration: Pydantic-based configuration management
Modern Python Stack: Built with Python 3.11+, async/await patterns, and FastMCP
Production Ready: Comprehensive test suite, code quality tools, and pre-commit hooks
Related MCP server: D&D 5E MCP Server
Quick Start
Prerequisites
Python 3.11 or higher
uv for package management
Installation
# Clone the repository
git clone https://github.com/your-org/lorekeeper-mcp.git
cd lorekeeper-mcp
# Install dependencies
uv sync
# Set up pre-commit hooks
uv run pre-commit install
# Copy environment configuration
cp .env.example .envRunning the Server
# Start the MCP server (recommended)
lorekeeper serve
# Or with custom configuration
lorekeeper -v serve
lorekeeper --db-path /custom/path.db serve
# Backward compatible: start server without CLI
uv run python -m lorekeeper_mcpAvailable Tools
LoreKeeper provides 6 MCP tools for querying D&D 5e game data:
search_spell- Search spells by name, level, school, class, and propertiessearch_creature- Find monsters by name, CR, type, and sizesearch_character_option- Get classes, races, backgrounds, and featssearch_equipment- Search weapons, armor, and magic itemssearch_rule- Look up game rules, conditions, and reference informationsearch_all- Unified search across all content types with semantic search
See docs/tools.md for detailed usage and examples.
Document Filtering
All lookup tools and the search tool support filtering by source document:
# List available documents first
documents = await list_documents()
# Filter spells to SRD only
srd_spells = await search_spell(
level=3,
documents=["srd-5e"]
)
# Filter creatures from multiple sources
creatures = await search_creature(
type="dragon",
documents=["srd-5e", "tce", "phb"]
)
# Search with document filter
results = await search_all(
query="fireball",
documents=["srd-5e"]
)This allows you to:
Limit searches to SRD (free) content only
Filter by specific published books or supplements
Separate homebrew from official content
Control which sources you're using for licensing reasons
See docs/document-filtering.md for comprehensive guide and cross-source filtering examples.
CLI Usage
LoreKeeper includes a command-line interface for importing D&D content:
# Import content from OrcBrew file
lorekeeper import MegaPak_-_WotC_Books.orcbrew
# Show help
lorekeeper --help
lorekeeper import --helpSee docs/cli-usage.md for detailed CLI documentation.
Configuration
LoreKeeper uses environment variables for configuration. All settings use the LOREKEEPER_ prefix. Create a .env file:
# Cache backend settings
LOREKEEPER_CACHE_BACKEND=milvus # "milvus" (default) or "sqlite"
LOREKEEPER_MILVUS_DB_PATH=~/.local/share/lorekeeper/milvus.db # or $XDG_DATA_HOME/lorekeeper/milvus.db
LOREKEEPER_EMBEDDING_MODEL=all-MiniLM-L6-v2
# SQLite settings (if using sqlite backend)
LOREKEEPER_DB_PATH=./data/cache.db
# Cache TTL settings
LOREKEEPER_CACHE_TTL_DAYS=7
LOREKEEPER_ERROR_CACHE_TTL_SECONDS=300
# Logging
LOREKEEPER_LOG_LEVEL=INFO
LOREKEEPER_DEBUG=false
# API endpoints
LOREKEEPER_OPEN5E_BASE_URL=https://api.open5e.comSemantic Search
LoreKeeper uses Milvus Lite as the default cache backend, providing semantic search capabilities powered by vector embeddings.
Features
Semantic Search: Find content by meaning, not just exact text matches
Vector Embeddings: Uses sentence-transformers for high-quality text embeddings
Hybrid Search: Combine semantic queries with structured filters
Zero Configuration: Works out of the box with sensible defaults
Lightweight: Embedded database, no external services required
Usage Examples
# Find spells by concept (not just keywords)
healing = await search_spell(search="restore health and cure wounds")
# Returns: Cure Wounds, Healing Word, Mass Cure Wounds, etc.
# Find creatures by behavior
flyers = await search_creature(search="flying creatures with ranged attacks")
# Returns: Dragon, Wyvern, Harpy, etc.
# Hybrid search: semantic + structured filters
fire_evocation = await search_spell(
search="area fire damage",
level=3,
school="evocation"
)
# Returns: Fireball (exact match for both semantic and filter)
# Search across all content types
results = await search_all(query="dragon breath weapon")First-Run Setup
On first run, LoreKeeper downloads the embedding model (~80MB). This is a one-time download:
# First run will show:
# Downloading model 'all-MiniLM-L6-v2'...
lorekeeper serveConfiguration
Configure Milvus via environment variables:
# Use Milvus backend (default)
LOREKEEPER_CACHE_BACKEND=milvus
# Custom database path (defaults to $XDG_DATA_HOME/lorekeeper/milvus.db)
LOREKEEPER_MILVUS_DB_PATH=/path/to/milvus.db
# Alternative embedding model
LOREKEEPER_EMBEDDING_MODEL=all-MiniLM-L6-v2Migrating from SQLite
If you were using an older version with SQLite caching:
Set the backend to Milvus (default):
LOREKEEPER_CACHE_BACKEND=milvusRe-import your data (Milvus cache starts empty):
lorekeeper import /path/to/content.orcbrewOr populate the cache from Open5e by running
lorekeeper sync(see Populating the cache below).
Rollback: To keep using SQLite (no semantic search):
LOREKEEPER_CACHE_BACKEND=sqlite
LOREKEEPER_DB_PATH=./data/cache.dbNote: SQLite cache does not support semantic search—only exact and pattern matching.
Populating the cache
# Import homebrew/OrcBrew content
lorekeeper import MegaPak_-_WotC_Books.orcbrew
# Fetch all Open5e content (SRD spells, creatures, equipment, rules, ...)
lorekeeper syncNote: stop the MCP server first — the Milvus Lite database only allows one process at a time.
Development
Project Structure
lorekeeper-mcp/
├── src/lorekeeper_mcp/ # Main package
│ ├── cache/ # Vector database caching layer
│ │ ├── milvus.py # Milvus Lite cache implementation
│ │ ├── embedding.py # Embedding service for semantic search
│ │ ├── protocol.py # Cache protocol definition
│ │ └── factory.py # Cache factory
│ ├── api_clients/ # External API clients
│ ├── repositories/ # Repository pattern for data access
│ ├── tools/ # MCP tool implementations
│ ├── config.py # Configuration management
│ ├── server.py # FastMCP server setup
│ └── __main__.py # Package entry point
├── tests/ # Test suite
│ ├── test_cache/ # Cache layer tests
│ ├── test_config.py # Configuration tests
│ ├── test_server.py # Server tests
│ └── conftest.py # Pytest fixtures
├── docs/ # Documentation
├── pyproject.toml # Project configuration
├── .pre-commit-config.yaml # Code quality hooks
└── README.md # This fileRunning Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=lorekeeper_mcp
# Run specific test file
uv run pytest tests/test_cache/test_db.pyCode Quality
The project uses several code quality tools:
Black: Code formatting (100 character line length)
Ruff: Linting and import sorting
MyPy: Static type checking
Pre-commit: Git hooks for automated checks
# Run all quality checks
uv run ruff check src/
uv run ruff format src/
uv run mypy src/
# Run pre-commit hooks manually
uv run pre-commit run --all-filesVector Database Cache
LoreKeeper uses Milvus Lite for semantic search and efficient caching:
Vector Storage: 384-dimensional embeddings for semantic search
Entity Collections: Separate collections for spells, creatures, equipment, etc.
Hybrid Search: Combine vector similarity with scalar filters
Source Tracking: Records which API provided cached data
Zero Configuration: Embedded database with no external dependencies
API Strategy
The project follows a strategic API assignment:
Use Open5e API for all content lookups
Prefer Open5e v2 over v1 when available
Unified source: Single API ensures consistent behavior and simplified maintenance
See docs/tools.md for detailed API mapping and implementation notes.
📋 OpenSpec Integration
This project uses OpenSpec as its core development tooling for specification management and change tracking. OpenSpec provides:
Structured Specifications: All features, APIs, and architectural changes are documented in detailed specs
Change Management: Comprehensive change tracking with proposals, designs, and implementation tasks
Living Documentation: Specifications evolve alongside the codebase, ensuring documentation stays current
Development Workflow: Integration between specs, implementation, and testing
The openspec/ directory contains:
Current specifications for all project components
Historical change records with full context
Design documents and implementation plans
Task breakdowns for development work
When contributing, please review relevant specifications in openspec/ and follow the established change management process.
Contributing
We welcome contributions! Please see our Contributing Guidelines for details.
Development Workflow
Fork the repository
Create a feature branch:
git checkout -b feature-nameMake your changes and ensure tests pass
Run code quality checks:
uv run pre-commit run --all-filesCommit your changes
Push to your fork and create a pull request
Testing
All contributions must include tests:
New features should have corresponding unit tests
Maintain test coverage above 90%
Use pytest fixtures for consistent test setup
Follow async/await patterns for async code
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
Available Tools
7 toolslist_documentsA
List all available D&D content documents in the cache.
This tool queries the cache to discover which source documents are available across all data sources (Open5e API, D&D 5e API, OrcBrew imports). Use this to see which books, supplements, and homebrew content you have access to, then use the documents parameter in other tools to filter content.
IMPORTANT: This shows only documents currently in your cache. Run the build command to populate your cache with content from configured sources.
Examples: # List all available documents docs = await list_documents()
# List only Open5e documents
docs = await list_documents(source="open5e_v2")
# List only OrcBrew homebrew
docs = await list_documents(source="orcbrew")Args: source: Optional source filter. Valid values: - "open5e_v2": Open5e API documents (SRD, Kobold Press, etc.) - "orcbrew": Imported OrcBrew homebrew files - None (default): Show documents from all sources
Returns: List of document dictionaries, each containing: - document: Document name/identifier (use this in documents) - source_api: Which API/source this came from - entity_count: Total number of entities from this document - entity_types: Breakdown of entities by type (spells, creatures, etc.) - publisher: Publisher name (if available, Open5e only) - license: License type (if available, Open5e only)
Documents are sorted by entity count (highest first).Note:
This queries only the cache and does not make API calls. You must
populate your cache first. Run lorekeeper sync to populate your
cache from Open5e, and lorekeeper import <file> for OrcBrew content.
| Name | Required | Description | Default |
|---|---|---|---|
| source | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It explicitly discloses that this tool queries the cache only, makes no API calls, requires a populated cache, returns a list with specific fields, and sorts by entity count. It does not mention behavior on empty cache or invalid source values, which would add further transparency, but it covers the main behavioral traits well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a one-sentence purpose, usage explanation, examples, Args section, Returns section, and a Note. It is front-loaded with the primary purpose and uses concise headings; no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional parameter and no annotations or output schema provided, the description thoroughly covers purpose, prerequisites, parameter values, return format, and sorting behavior. It leaves no major gaps for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only defines 'source' as a nullable string with no description. The description compensates by listing valid values ('open5e_v2', 'orcbrew', None), explaining what each source refers to, and providing examples. However, the intro mentions a third data source (D&D 5e API) that is not reflected in the source values, leaving slight ambiguity about how to filter those documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List all available D&D content documents in the cache.' It clearly distinguishes this tool from sibling search tools by explaining it is for discovering available source documents, not searching content. It also states the scope (cache) and purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: 'Use this to see which books, supplements, and homebrew content you have access to, then use the documents parameter in other tools to filter content.' It also explains the prerequisite (populate cache) and that it makes no API calls. However, it does not explicitly name alternate tools or exclusion cases, so it lacks the explicit when-not guidance seen in top-tier examples.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_allA
Search across all D&D content with semantic matching.
This tool uses Open5e's unified search endpoint to find content across multiple types (spells, creatures, items, etc.) with fuzzy typo tolerance and semantic conceptual matching. Perfect for exploratory searches like "find anything related to fire" or when you're not sure of exact spelling.
Semantic search is always enabled to provide the best conceptual matching.
Examples: # Cross-entity search search_all(query="dragon") # Finds dragons, dragon spells, etc.
# Typo-tolerant search
search_all(query="firbal") # Finds "Fireball" despite typo
# Concept-based search
search_all(query="healing magic") # Finds healing spells
# Type-filtered search
search_all(query="fire", content_types=["Spell"]) # Only spells
# Document-filtered search
search_all(query="fireball", documents=["srd-5e"])
search_all(query="spell", documents=["srd-5e", "tce"])Args: query: Search term (handles typos and concepts automatically) content_types: Limit to specific types: ["Spell", "Creature", "Item", "Background", "Feat"]. Default None searches all content types. documents: Filter results to specific documents. Provide list of document names from list_documents() tool. Post-filters search results by document field. Examples: ["srd-5e"], ["srd-5e", "tce"]. limit: Maximum number of results to return (default 20)
Returns: List of content dictionaries with varied structure based on content type. Each result includes a 'type' or 'model' field indicating content type.
Raises: ApiError: If the API request fails due to network issues or errors
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| documents | No | ||
| content_types | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavioral traits: semantic matching is always enabled, typo tolerance, post-filtering by document, return structure ('type' or 'model' field), and raising of ApiError. This is comprehensive and provides context beyond what annotations would offer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a description, examples, args, returns, and raises sections. It is longer than average but every sentence and example contributes value—there is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (4 params, 1 required, varied output types, no annotations), the description covers all essential aspects: use cases, parameter semantics, return structure, and error handling. It even includes examples for different filtering scenarios, making it fully complete for an agent to use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, but the description's Args section explains every parameter in detail: query handles typos and concepts, content_types lists allowed values and default, documents explains post-filtering and gives examples, limit states default. This significantly adds meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool 'Search across all D&D content with semantic matching,' using a specific verb and resource. It distinguishes itself from sibling tools (search_spell, search_creature, etc.) by covering multiple content types simultaneously, which is explicitly mentioned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear when-to-use guidance: 'Perfect for exploratory searches' and 'when you're not sure of exact spelling.' While it doesn't explicitly say 'use search_spell for exact spell searches,' the contrast with sibling tool names and the emphasis on cross-entity search imply the alternative. No explicit exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_character_optionA
Retrieve D&D 5e character creation and advancement options.
This tool provides access to classes, races, backgrounds, and feats for character creation and level-up decisions. Each option type provides different information relevant to character building. Results are cached for faster repeated lookups through the repository pattern.
The repository pattern handles caching transparently:
First call: Fetches from API and caches in database
Subsequent calls: Returns cached results if available
Supports test context-based repository injection via _repository_context
Examples: Default usage (automatic repository creation): classes = await search_character_option(type="class") elves = await search_character_option(type="race", search="elf") backgrounds = await search_character_option(type="background", search="soldier") feats = await search_character_option(type="feat", search="great")
With test context injection (testing):
from lorekeeper_mcp.tools.search_character_option import _repository_context
custom_repo = CharacterOptionRepository(cache=my_cache)
_repository_context["repository"] = custom_repo
classes = await search_character_option(type="class")
Semantic search (natural language queries):
warriors = await search_character_option(
type="class", search="martial combat warrior"
)
sneaky_classes = await search_character_option(
type="class", search="stealthy shadow assassin"
)
magical_races = await search_character_option(
type="race", search="innate magical abilities"
)
Hybrid search (search + filters):
srd_fighters = await search_character_option(
type="class", search="melee fighter", documents=["srd-5e"]
)Args: type: REQUIRED. Character option type. Must be one of: - "class": Player classes (Barbarian, Bard, Cleric, Druid, Fighter, Monk, Paladin, Ranger, Rogue, Sorcerer, Warlock, Wizard) - "race": Playable races (Human, Elf, Dwarf, Halfling, Dragonborn, Gnome, Half-Orc, Half-Elf, Tiefling, etc.) - "background": Character backgrounds (Acolyte, Criminal, Entertainer, Soldier, Folk Hero, Sage, etc.) - "feat": Character feats (Ability Score Improvement, Great Weapon Master, Magic Initiate, etc.) - typically chosen at levels 4, 8, 12, 16, 19 documents: Filter to specific source documents. Provide a list of document names/identifiers from list_documents() tool. Examples: ["srd-5e"] for SRD only, ["srd-5e", "tce"] for SRD and Tasha's. Use list_documents() to see available documents. search: Natural language search query for semantic/vector search. When provided, uses vector similarity to find character options matching the conceptual meaning rather than exact text matches. Can be combined with other filters for hybrid search. Examples: "martial combat warrior", "stealthy rogue", "divine magic healer" limit: Maximum number of results to return. Default 20, useful for limiting output or pagination. Examples: 1, 5, 50
Returns: List of option dictionaries. Structure varies by type:
For type="class":
- name: Class name
- hit_dice: Hit die value (1d8, 1d10, 1d12)
- class_levels: Progression table
- spellcasting: Spell slots if applicable
- features: Class features by level
For type="race":
- name: Race name
- ability_score_increase: Ability score bonuses
- age: Aging information
- alignment: Typical alignments
- size: Size category
- speed: Movement speed
- languages: Known languages
- traits: Racial traits and special abilities
For type="background":
- name: Background name
- skill_proficiencies: Skill choices
- tool_proficiencies: Tools (if any)
- feature: Special background feature
- personality_traits: Suggested personality options
- ideals: Suggested ideals
- bonds: Suggested character bonds
- flaws: Suggested character flaws
For type="feat":
- name: Feat name
- description: Feat benefits and requirements
- ability_score_increase: Ability bonuses (if any)
- prerequisites: Requirements to take featRaises: ValueError: If type parameter is not one of the valid options ApiError: If the API request fails due to network issues or server errors
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| limit | No | ||
| search | No | ||
| documents | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It thoroughly discloses caching behavior ('Results are cached... repository pattern'), explains the first-call vs. subsequent-call semantics, and details the _repository_context injection for testing. It also lists error conditions (ValueError, ApiError), making the tool's behavior highly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is quite long, but it is well-structured with clear sections: opening summary, caching note, examples, Args, Returns, and Raises. Each section adds value, though some parts (e.g., exhaustive list of class names) could be shortened without losing essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is complex with 4 parameters and variable return structures by type. The description provides comprehensive coverage: per-type return structures, error handling, examples for all parameter combinations, and a pointer to list_documents(). Despite having an output schema, the description still adds crucial context and makes the tool fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the Args section is essential and excellently detailed: type explains each enum value with examples and class lists, documents references list_documents() and gives examples, search explains semantic/vector search, and limit explains its default and use. This fully compensates for the lack of schema-level descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Retrieve D&D 5e character creation and advancement options' and explicitly lists classes, races, backgrounds, and feats. This clearly distinguishes it from sibling search tools like search_spell or search_creature by focusing specifically on character options.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains typical use cases ('character creation and level-up decisions') and provides detailed examples for default, semantic, and hybrid search. It references list_documents() for filtering, but does not explicitly state when not to use this tool or mention alternative tools like search_spell, so while clear, it lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_creatureA
Search and retrieve D&D 5e creatures using the repository pattern.
This tool provides comprehensive creature lookup including full stat blocks, combat statistics, abilities, and special features. Results include complete creature data and are cached through the repository for improved performance.
Examples: Basic creature lookup: creatures = await search_creature(search="dragon") creatures = await search_creature(cr=5) medium_creatures = await search_creature(size="Medium")
Using challenge rating ranges:
low_cr_creatures = await search_creature(cr_max=2)
mid_level_threats = await search_creature(cr_min=3, cr_max=5)
deadly_bosses = await search_creature(cr_min=10)
Filtering by type and size:
undead_creatures = await search_creature(type="undead")
humanoids = await search_creature(type="humanoid", cr_max=2)
large_creatures = await search_creature(size="Large", limit=10)
Using armor class and hit points filters:
well_armored_creatures = await search_creature(armor_class_min=15)
heavily_armored = await search_creature(armor_class_min=18)
tanky_creatures = await search_creature(hit_points_min=100)
deadly_tanky = await search_creature(
armor_class_min=16, hit_points_min=75, cr_min=5
)
With document filtering:
srd_only = await search_creature(documents=["srd-5e"])
tasha_creatures = await search_creature(
documents=["srd-5e", "tce"]
)
phb_and_dmg = await search_creature(
documents=["phb", "dmg"], cr_min=5
)
Semantic search (natural language queries):
fire_creatures = await search_creature(
search="fire breathing flying beast"
)
undead_minions = await search_creature(
search="shambling corpse horde"
)
intelligent_foes = await search_creature(
search="cunning spellcaster manipulator"
)
Hybrid search (search + filters):
fire_dragons = await search_creature(
search="fire breathing", type="dragon", cr_min=10
)
weak_undead = await search_creature(
search="shambling minion", type="undead", cr_max=2
)
With test context injection (testing):
from lorekeeper_mcp.tools.search_creature import _repository_context
custom_repo = CreatureRepository(cache=my_cache)
_repository_context["repository"] = custom_repo
creatures = await search_creature(size="Tiny")Args: cr: Exact Challenge Rating to search for. Supports fractional values including 0.125, 0.25, 0.5 for weak creatures. Range: 0.125 to 30 Examples: 0.125 (weak minion), 5 (party challenge), 20 (deadly boss) cr_min: Minimum Challenge Rating for range-based searches. Use with cr_max to find creatures in a difficulty band. Examples: 1, 5, 10 cr_max: Maximum Challenge Rating for range-based searches. Together with cr_min, defines the encounter difficulty band. Examples: 3, 10, 15 type: Creature type filter. Valid values include: aberration, beast, celestial, construct, dragon, elemental, fey, fiend, giant, goblinoid, humanoid, monstrosity, ooze, reptile, undead, plant. Examples: "dragon", "undead", "humanoid" size: Size category filter. Valid values: Tiny, Small, Medium, Large, Huge, Gargantuan Examples: "Large" for major encounters, "Tiny" for swarms armor_class_min: Minimum Armor Class filter. Returns creatures with AC at or above this value. Useful for finding well-armored threats. Examples: 15, 18, 20 hit_points_min: Minimum Hit Points filter. Returns creatures with HP at or above this value. Useful for finding creatures with significant endurance. Examples: 50, 100, 200 documents: Filter to specific source documents. Provide a list of document names/identifiers from list_documents() tool. Examples: ["srd-5e"] for SRD only, ["srd-5e", "tce"] for SRD and Tasha's. Use list_documents() to see available documents. search: Natural language search query for semantic/vector search. When provided, uses vector similarity to find creatures matching the conceptual meaning rather than exact text matches. Can be combined with other filters for hybrid search. Examples: "fire breathing dragon", "undead horde minion", "intelligent spellcaster" limit: Maximum number of results to return. Default 20, useful for pagination or limiting large result sets. Example: 5
Returns: List of creature stat block dictionaries, each containing: - name: Creature name - size: Size category - type: Creature type - alignment: Alignment (e.g., "chaotic evil") - armor_class: AC (Armor Class) - hit_points: Hit points - hit_dice: Hit dice expression (e.g., "10d10+20") - speed: Movement speeds (walk, fly, swim, burrow, climb) - strength/dexterity/constitution/intelligence/wisdom/charisma: Ability scores - challenge_rating: CR value for encounter building - actions: Possible actions in combat - legendary_actions: Legendary action options (if applicable) - special_abilities: Special abilities and traits - document_url: Source document reference
Raises: ApiError: If the API request fails due to network issues or server errors
| Name | Required | Description | Default |
|---|---|---|---|
| cr | No | ||
| size | No | ||
| type | No | ||
| limit | No | ||
| cr_max | No | ||
| cr_min | No | ||
| search | No | ||
| documents | No | ||
| hit_points_min | No | ||
| armor_class_min | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description bears full responsibility for behavioral disclosure, and it delivers: it mentions caching through the repository, semantic/vector search behavior, result content, an ApiError raise condition, and even a test context injection mechanism. This goes well beyond a basic search tool description and gives the agent a strong mental model of side effects and guarantees.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but highly organized into clear sections: overview, examples, Args, Returns, and Raises. Every line adds practical value—examples illustrate parameter combinations, and the Args section is exhaustive. The structure makes the length easy to parse, and no redundant filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters, zero schema-level descriptions, no annotations, and a high-complexity search API, this description is exceptionally complete. It covers all parameter semantics, return value structure, error behavior, caching, and provides both basic and advanced usage scenarios, leaving no significant gap for an agent to make a wrong invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates with detailed Args for all 10 parameters, including valid values (e.g., creature types, size categories), example ranges, defaults, and guidance for combining filters. It even explains fractional CR values and how to use documents with list_documents(), adding meaning far beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Search and retrieve D&D 5e creatures using the repository pattern,' clearly identifying the verb, resource, and implementation context. It distinguishes itself from siblings like search_spell and search_equipment by focusing specifically on creature lookup with stat blocks and combat statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive, concrete usage examples for all parameter combinations, including semantic search, hybrid search, and document filtering. It does not explicitly name sibling tools as alternatives or state when not to use this tool, so it misses the 'when-not/alternatives' bar for a 5, but the context is very clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_equipmentA
Search and retrieve D&D 5e weapons, armor, and magic items using the repository pattern.
This tool provides comprehensive equipment lookup across weapons, armor, and magical
items. Filter by rarity, damage potential, complexity, or attunement requirements.
Automatically uses the database cache through the repository for improved performance.
Examples:
Basic equipment lookup:
rare_items = await search_equipment(type="magic-item", rarity="rare")
light_armor = await search_equipment(type="armor", is_simple=True)
Using cost ranges (NEW in Phase 3):
affordable_weapons = await search_equipment(
type="weapon", cost_max=25
)
expensive_items = await search_equipment(
type="weapon", cost_min=50, cost_max=100
)
Using weight and properties (NEW in Phase 3):
lightweight_weapons = await search_equipment(
type="weapon", weight_max=3
)
finesse_weapons = await search_equipment(
type="weapon", is_finesse=True
)
light_dual_wield_weapons = await search_equipment(
type="weapon", is_light=True
)
magical_weapons = await search_equipment(
type="weapon", is_magic=True
)
Complex equipment queries:
affordable_simple_weapons = await search_equipment(
type="weapon", is_simple=True, cost_max=10
)
light_finesse_weapons = await search_equipment(
type="weapon", is_light=True, is_finesse=True, limit=10
)
expensive_magical_weapons = await search_equipment(
type="weapon", is_magic=True, cost_min=100
)
Searching all types:
all_chain_items = await search_equipment(
type="all", search="chain"
)
Semantic search (natural language queries):
melee_weapons = await search_equipment(
type="weapon", search="slashing blade for close combat"
)
protective_gear = await search_equipment(
type="armor", search="heavy protective plate"
)
magical_storage = await search_equipment(
type="magic-item", search="bag that holds items"
)
Hybrid search (search + filters):
finesse_slashing = await search_equipment(
type="weapon", search="elegant blade", is_finesse=True
)
rare_magical = await search_equipment(
type="magic-item", search="fire wand", rarity="rare"
)
Args:
type: Equipment type to search. Default "all" searches all types. Options:
- "weapon": Melee weapons (longsword, dagger, etc.) and ranged weapons (bow, crossbow)
- "armor": Protective gear (leather armor, chain mail, plate, etc.)
- "magic-item": Magical items (Bag of Holding, Wand of Fireballs, etc.)
- "all": Search all equipment types simultaneously (may return many results)
rarity: Magic item rarity filter (weapon/armor types don't use this).
Valid values: common, uncommon, rare, very rare, legendary, artifact
Example: "rare" for high-value magical items
damage_dice: Weapon damage dice filter to find weapons dealing specific damage.
Examples: "1d4" (dagger), "1d8" (longsword), "2d6" (greataxe), "1d12" (greatsword)
is_simple: Filter for simple weapons (True) or martial weapons (False).
Simple weapons: club, dagger, greatclub, handaxe, javelin, light hammer, mace,
quarterstaff, sickle, spear
Martial weapons: all other melee and ranged weapons
Example: True for low-complexity options
requires_attunement: Magic item attunement filter. Some powerful items require
attunement to a character. Examples: "yes", "no", or specific requirements
cost_min: Minimum cost in gold pieces (weapons and armor). Filters items costing
at least this amount. Example: 10 for items costing 10+ gp
cost_max: Maximum cost in gold pieces (weapons and armor). Filters items costing
at most this amount. Example: 25 for items costing 25 gp or less
weight_max: Maximum weight in pounds (weapons). Filters weapons weighing at most
this amount. Example: 3 for lightweight weapons
is_finesse: Finesse property filter (weapons). When True, returns only weapons
with the finesse property (can use STR or DEX modifier). Example: True
is_light: Light property filter (weapons). When True, returns only light weapons
suitable for dual-wielding. Example: True
is_magic: Magic property filter (weapons). When True, returns only magical weapons. Example: True documents: Filter to specific source documents. Provide a list of document names/identifiers from list_documents() tool. Examples: ["srd-5e"] for SRD only, ["srd-5e", "tce"] for SRD and Tasha's. Use list_documents() to see available documents. search: Natural language search query for semantic/vector search. When provided, uses vector similarity to find equipment matching the conceptual meaning rather than exact text matches. Can be combined with other filters for hybrid search. Examples: "slashing weapon for melee combat", "protective heavy armor", "magical wand for spells" limit: Maximum number of results to return. Default 20. For type="all" with many matches, limit applies to total results. Examples: 5, 20, 100
Returns:
List of equipment dictionaries. Structure varies by type:
For type="weapon":
- name: Weapon name
- damage_dice: Damage expression (e.g., "1d8")
- damage_type: Type of damage (slashing, piercing, bludgeoning)
- weight: Weight in pounds
- is_simple: Whether this is a simple weapon
- range: Range for ranged weapons (e.g., "20/60 feet")
- properties: Weapon properties (finesse, heavy, reach, two-handed, etc.)
- rarity: Equipment rarity
For type="armor":
- name: Armor name
- armor_class: AC provided by this armor
- armor_class_dex: Whether DEX bonus applies (light/medium)
- armor_class_strength: Whether STR requirement applies (heavy)
- weight: Weight in pounds
- armor_category: Light/Medium/Heavy classification
- rarity: Equipment rarity
For type="magic-item":
- name: Item name
- description: What the item does and its powers
- rarity: Rarity level (common through artifact)
- requires_attunement: Attunement requirements
- wondrous: Whether item is wondrous (non-weapon/armor)
- weight: Weight if applicable
- armor_class: AC bonus if armor
- damage: Damage if weapon
Raises:
ApiError: If the API request fails due to network issues or server errors| Name | Required | Description | Default |
|---|---|---|---|
| type | No | all | |
| limit | No | ||
| rarity | No | ||
| search | No | ||
| cost_max | No | ||
| cost_min | No | ||
| is_light | No | ||
| is_magic | No | ||
| documents | No | ||
| is_simple | No | ||
| is_finesse | No | ||
| weight_max | No | ||
| damage_dice | No | ||
| requires_attunement | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It transparently specifies that search uses 'vector similarity' for semantic queries, automatically caches via the repository, can 'return many results' for type='all', and that limit applies to total results. It also details return structures per equipment type and lists the ApiError exception. This exceeds typical disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with Examples, Args, Returns, and Raises sections. It front-loads the purpose and uses code examples effectively. While some examples are repetitive, the overall structure makes it easy to scan, and the length is justified by the tool's 14-parameter complexity. A slightly more condensed version would be ideal, but it remains appropriately sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (14 parameters, no annotations, no output schema in structured form), the description is remarkably complete. It covers purpose, usage patterns, parameter semantics, return value structures for each type, default behavior, and error handling. The Returns section compensates for the lack of an output schema, and the Raises section clarifies failure modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does thoroughly. Every parameter is explained with concrete meanings, examples, and caveats. For instance, is_simple lists which weapons are simple, cost_min/max are defined as gold pieces, and search explains semantic vs. exact matching. This adds substantial value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Search and retrieve D&D 5e weapons, armor, and magic items using the repository pattern,' providing a specific verb, resource, and scope. It clearly distinguishes itself from sibling tools like search_spell and search_creature by focusing on equipment categories. The detailed filters and example queries reinforce the tool's purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive usage context through examples showing various filter combinations, semantic search, and hybrid search. It explains defaults like type='all' and limit=20, and indicates when to use different parameters. However, it does not explicitly contrast with sibling tools or state when NOT to use this tool, making it clear but not fully prescriptive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_ruleA
Look up D&D 5e game rules, conditions, and reference information.
This comprehensive reference tool provides access to core rules, special conditions, damage types, skills, and game mechanics. Essential for resolving rules questions during play or character building. All data is sourced from official D&D 5e materials. Uses the repository pattern with database caching for improved performance.
Examples: - search_rule(rule_type="condition", search="grappled") - Find grappled condition rules - search_rule(rule_type="skill", search="stealth") - Find stealth skill details - search_rule(rule_type="damage-type", search="fire") - Find fire damage rules - search_rule(rule_type="rule", section="combat") - Find all combat rules - search_rule(rule_type="ability-score") - Get all ability score info - search_rule(rule_type="alignment") - Find alignment descriptions - search_rule(rule_type="magic-school", search="evocation") - Find evocation school info - search_rule(rule_type="rule", documents=["srd-5e"]) - Find rules from SRD only - search_rule(rule_type="condition", search="grappled", documents=["srd-5e", "tce"]) - Filter conditions by documents
Semantic search (natural language queries):
- search_rule(rule_type="condition", search="movement restricted") - Find conditions affecting movement
- search_rule(rule_type="damage-type", search="burning heat") - Find fire-related damage
- search_rule(rule_type="skill", search="sneaking hiding") - Find stealth-related skills
Hybrid search (search + filters):
- search_rule(rule_type="condition", search="cannot see", documents=["srd-5e"]) - Find blindness/vision conditionsArgs: rule_type: REQUIRED. Type of game reference to lookup. Must be one of: - "rule": Core game rules and mechanics (combat, spellcasting, movement, etc.) - "condition": Status effects (grappled, stunned, poisoned, unconscious, etc.) - "damage-type": Damage categories (acid, bludgeoning, cold, fire, force, lightning, necrotic, piercing, poison, psychic, radiant, slashing, thunder) - "weapon-property": Weapon special properties (finesse, heavy, light, reach, two-handed, versatile, ammunition, loading, thrown, etc.) - "skill": Ability-based skills (Acrobatics, Animal Handling, Arcana, Athletics, Deception, History, Insight, Intimidation, Investigation, Medicine, Nature, Perception, Performance, Persuasion, Religion, Sleight of Hand, Stealth, Survival) - "ability-score": Core abilities (Strength, Dexterity, Constitution, Intelligence, Wisdom, Charisma) and their uses - "magic-school": Schools of magic (Abjuration, Conjuration, Divination, Enchantment, Evocation, Illusion, Necromancy, Transmutation) - "language": Languages available in D&D (Common, Dwarvish, Elvish, Giant, Gnomish, Goblin, Orc, Primordial, Sylvan, Undercommon, Celestial, Draconic, Deep Speech, Infernal) - "proficiency": Character proficiency types (armor, weapon, tool, saving throw, skill) - "alignment": Character alignment axes (Lawful/Chaotic, Good/Evil, Neutral options) section: For rule_type="rule" only. Filter rules by section/chapter. Examples: "combat", "spellcasting", "movement", "actions-in-combat" Ignored for other rule types. documents: Filter to specific source documents. Provide a list of document names/identifiers from list_documents() tool. Examples: ["srd-5e"] for SRD only, ["srd-5e", "tce"] for SRD and Tasha's. Use list_documents() to see available documents. search: Natural language search query for semantic/vector search. When provided, uses vector similarity to find rules matching the conceptual meaning rather than exact text matches. Can be combined with other filters for hybrid search. Examples: "movement restricted", "fire burning damage", "stealth hiding sneaking" limit: Maximum number of results to return. Default 20 for performance. Examples: 1, 10, 50
Returns: List of rule/reference dictionaries. Structure varies by rule_type:
For rule_type="rule":
- name: Rule name/title
- desc: Full rule description and examples
- section: Section/chapter this rule belongs to
For rule_type="condition":
- name: Condition name
- desc: Effects and duration of this condition
For rule_type="damage-type":
- name: Damage type name
- desc: Description of damage type and uses
For rule_type="weapon-property":
- name: Property name
- desc: How the property affects weapon use
For rule_type="skill":
- name: Skill name
- ability_score: Associated ability (STR, DEX, CON, INT, WIS, CHA)
- desc: How skill is used and common checks
For rule_type="ability-score":
- name: Ability name
- desc: What ability represents and how it's used
- skills: Related skills
For rule_type="magic-school":
- name: School name
- desc: Philosophy and types of spells in this school
For rule_type="language":
- name: Language name
- type: Language type (common, exotic, etc.)
- script: Writing system if any
For rule_type="proficiency":
- name: Proficiency type
- class: What type of proficiency (class, background, race)
- desc: Details about this proficiency type
For rule_type="alignment":
- name: Alignment
- desc: Alignment description and common character typesRaises: ValueError: If rule_type is not one of the valid options APIError: If the API request fails due to network issues or server errors
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| search | No | ||
| section | No | ||
| documents | No | ||
| rule_type | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses semantic vector search behavior, hybrid search combining filter and semantic queries, a default limit of 20 for performance, and raises ValueError/APIError. It also mentions internal repository/caching patterns, which adds some non-behavioral context but still demonstrates transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections for purpose, examples, args, returns, and raises. It front-loads the core purpose and uses bullet-style examples. The repeated semantic search examples are somewhat redundant, but the length is largely justified by the 5-parameter complexity and 10 rule_type variants.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even with an output schema present, the description provides per-rule_type return structures, error conditions, filtering capabilities, and multiple search modes. It covers all practical invocation scenarios an agent might encounter, making the tool independently understandable without further documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for all five parameters. It does so meticulously: rule_type is fully enumerated with plain-English meanings, section is scoped to 'rule' only, documents are tied to list_documents(), search is explained as semantic, and limit includes a default and performance rationale. The extensive examples reinforce parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Look up D&D 5e game rules, conditions, and reference information,' naming the specific verb, resource, and scope. The rule_type enum and detailed categories clearly differentiate it from sibling tools like search_spell or search_creature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Extensive examples show when to use each rule_type, filtering by section/documents, and semantic/hybrid search modes. It states this is 'Essential for resolving rules questions during play or character building.' However, it never explicitly mentions when to prefer this over search_all or other sibling search tools, though the categories imply it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_spellA
Search and retrieve D&D 5e spells using the repository pattern.
This tool provides comprehensive spell lookup functionality with support for filtering by multiple criteria. Results include complete spell descriptions, components, damage, effects, and availability information. Automatically uses the database cache through the repository for improved performance.
The repository pattern handles caching transparently:
First call: Fetches from API and caches in database
Subsequent calls: Returns cached results if available
Supports test context-based repository injection via _repository_context
Examples: Search for spells: spells = await search_spell(search="fireball") spells = await search_spell(search="healing restoration")
Filtering by level:
cantrips = await search_spell(level=0)
high_level_spells = await search_spell(level=5)
Using level ranges:
mid_level_spells = await search_spell(level_min=3, level_max=5)
powerful_spells = await search_spell(level_min=5)
beginner_spells = await search_spell(level_max=2)
Filtering by school and other properties:
evocation_spells = await search_spell(school="evocation")
wizard_spells = await search_spell(class_key="wizard")
ritual_spells = await search_spell(ritual=True)
concentration_spells = await search_spell(concentration=True)
Filtering by damage type:
fire_spells = await search_spell(damage_type="fire")
cold_spells = await search_spell(damage_type="cold")
necrotic_spells = await search_spell(damage_type="necrotic")
Filtering by document:
srd_only = await search_spell(documents=["srd-5e"])
srd_and_tasha = await search_spell(documents=["srd-5e", "tce"])
Complex queries combining multiple filters:
evocation_fire_spells = await search_spell(
school="evocation", damage_type="fire"
)
cleric_rituals = await search_spell(
class_key="cleric", ritual=True, level_min=1
)
mid_level_wizard_spells = await search_spell(
class_key="wizard", level_min=3, level_max=5, limit=10
)
Semantic search (natural language queries):
fire_spells = await search_spell(search="fire damage explosion")
healing_spells = await search_spell(search="restore health allies")
protection = await search_spell(search="defensive barrier ward")
Hybrid search (search + filters):
fire_evocation = await search_spell(
search="fire explosion", school="evocation"
)
low_level_healing = await search_spell(
search="heal wounds", level_max=3
)
With test context injection (testing):
from lorekeeper_mcp.tools.search_spell import _repository_context
custom_repo = SpellRepository(cache=my_cache)
_repository_context["repository"] = custom_repo
spells = await search_spell(level=0)Args: level: Exact spell level ranging from 0-9. 0 represents cantrips/0-level spells, 9 represents 9th level spells. Example: 3 for exactly 3rd level spells level_min: Minimum spell level (inclusive) for range-based searches. Use with level_max to find spells in a range. Returns spells at this level or higher. Examples: 1 for 1st level and above, 5 for 5th level and above level_max: Maximum spell level (inclusive) for range-based searches. Use with level_min to find spells in a range. Returns spells at this level or lower. Examples: 3 for up to 3rd level spells, 5 for up to 5th level spells school: Magic school filter for spell type. Valid values: abjuration, conjuration, divination, enchantment, evocation, illusion, necromancy, transmutation. Each school has distinct characteristics. Example: "evocation" for damage-dealing spells, "abjuration" for protective spells class_key: Filter spells available to a specific class. Valid values: wizard, cleric, druid, bard, paladin, ranger, sorcerer, warlock, artificer. Each class has access to different spell lists. Example: "wizard" for spells in wizard spell list concentration: Filter for spells requiring concentration. True returns only concentration spells, False returns only non-concentration spells. Concentration is a key resource in combat. Example: True ritual: Filter for ritual spells. Returns only spells that can be cast as rituals, allowing casting without expending spell slots. Example: True casting_time: Casting time filter to find spells with specific casting times. Examples: "1 action" (most common), "1 bonus action" (quick casts), "1 reaction" (reaction spells), "1 minute" (extended preparation) damage_type: Filter spells by damage type dealt. Examples: "fire" (fire damage), "cold" (cold damage), "necrotic" (necrotic damage), "poison" (poison damage), "psychic" (psychic damage). NEW in Phase 3. documents: Filter to specific source documents. Provide a list of document names/identifiers from list_documents() tool. Examples: ["srd-5e"] for SRD only, ["srd-5e", "tce"] for SRD and Tasha's. Use list_documents() to see available documents. search: Natural language search query for semantic/vector search. When provided, uses vector similarity to find spells matching the conceptual meaning rather than exact text matches. Can be combined with other filters for hybrid search. Examples: "fire damage explosion", "healing allies", "protection from evil creatures" limit: Maximum number of results to return. Default 20. Useful for pagination or limiting large result sets. Examples: 5 for small sets, 20 for standard, 100 for comprehensive results
Returns: List of spell dictionaries, each containing: - name: Spell name - level: Spell level (0-9) - school: Magic school - casting_time: How long the spell takes to cast - range: Spell range/area of effect - components: Required components (V/S/M) - material: Material component description (if applicable) - duration: How long the spell lasts - concentration: Whether spell requires concentration - ritual: Whether spell can be cast as a ritual - desc: Full spell description and effects - higher_level: Effect when cast at higher levels - classes: List of classes that can learn this spell - document__slug: Source document reference - damage_type: Damage types dealt by the spell (if applicable)
Raises: ApiError: If the API request fails due to network issues or server errors
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | ||
| limit | No | ||
| ritual | No | ||
| school | No | ||
| search | No | ||
| class_key | No | ||
| documents | No | ||
| level_max | No | ||
| level_min | No | ||
| damage_type | No | ||
| casting_time | No | ||
| concentration | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for behavioral disclosure. It goes beyond basics by explaining the caching mechanism ('First call: Fetches from API and caches in database; Subsequent calls: Returns cached results'), test context injection via _repository_context, and the potential ApiError on network failures. It also documents semantic search behavior and return fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (summary, caching, examples, args, returns, raises) and is front-loaded with a summary. However, it is quite verbose, with multiple repetitive examples for similar filter types (e.g., five damage_type examples). While the detail is helpful for a complex tool, it could be trimmed slightly without losing value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (12 parameters, no annotations, and an output schema that is not detailed in the context), the description is fully complete. It covers all parameters with semantics and examples, explains the return structure field-by-field, documents error behavior, and discloses caching and test injection. Nothing critical is missing for an agent to correctly invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate. It does so with detailed explanations for all 12 parameters, including valid values (e.g., level 0-9, school list), inclusive bounds for level_min/level_max, examples for casting_time, and clarification that 'damage_type' is new in Phase 3. The documents parameter even points to list_documents(). This far exceeds what the bare schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Search and retrieve D&D 5e spells using the repository pattern.' It uses a specific verb+resource combination and mentions comprehensive filtering, distinguishing it from sibling tools that search other D&D data types (creatures, equipment, rules, etc.). The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive usage guidance through examples and parameter explanations, covering searching by level, school, class, damage type, and combining filters. It also references list_documents() for the documents parameter. However, it does not explicitly state when NOT to use this tool or contrast it with alternatives like search_all, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
7 tool updates
v0.1.0- First observed
list_documents - First observed
search_all - First observed
search_character_option - First observed
search_creature - First observed
search_equipment - First observed
search_rule - First observed
search_spell
TDQS
Each specific search tool targets a distinct content type (spells, creatures, character options, equipment, rules), and list_documents is clearly separate. The only overlap is search_all, which is explicitly positioned as an exploratory cross-type search, so agents can distinguish intended use.
All tool names follow a consistent verb_noun pattern: list_documents and six search_* tools for each content area. Naming is predictable and clean, with no mixed conventions.
Seven tools is well-scoped for a read-only reference server that covers the major D&D 5e content categories. Each tool serves a clear purpose without redundancy or bloat.
The server covers the core D&D reference surface: spells, creatures, character options, equipment, rules, and a unified search. A minor gap is the lack of cache-management tools (sync/import) referenced in list_documents, but that may be outside the intended MCP scope.
Maintenance
Related MCP Connectors
D&D 5e MCP — wraps the D&D 5th Edition API (free, no auth)
Look up Pokémon, moves, abilities, items, natures, and type matchups from PokéAPI v2.
Provide detailed Pokémon data and information through a standardized MCP interface. Enable LLMs an…
API Ninjas MCP — wraps the multi-endpoint API Ninjas data API (api-ninjas.com)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides D\&D 5e spell information through search and filtering tools. Access detailed spell data, class-specific spell lists, and spell school references powered by the D\&D 5e API.182MIT
- FlicenseBqualityDmaintenanceProvides comprehensive access to Dungeons & Dragons 5th Edition content through the Open5e API. It enables users to search for game mechanics, generate character builds, and create balanced encounters via natural language.3722-
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to Dungeons & Dragons 5e game information via the Model Context Protocol, enabling queries for spells, monsters, equipment, and more.48MIT
- FlicenseNot gradedqualityAmaintenanceEnables D&D 5e game masters and players to access complete game reference data, search spells, monsters, items, and calculate encounter difficulty, all through natural language.6-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/frap129/lorekeeper-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server