Custom YAML Tools for MCP
Define website-specific MCP tools in YAML that simplify AI interactions with your MDDB data.
Overview
By default, mddbd exposes 54+ built-in MCP tools (add_document, search_documents, semantic_search, hybrid_search, list_automation, etc.) with tool annotations per MCP 2025-11-25. Custom tools let you create domain-specific wrappers with preconfigured defaults โ so the AI sees search_faq(query) instead of semantic_search(collection, query, topK, threshold, ...).
Custom tools are defined in a YAML file under the custom_tools: key. Point mddbd to the file via MDDB_MCP_CONFIG=/path/to/config.yaml. They are registered alongside built-in tools and work on all transports (stdio, Streamable HTTP, and legacy SSE).
Tip: Set
MDDB_MCP_BUILTIN_TOOLS=falseto hide all built-in tools and expose only your custom tools. Combined withMDDB_MCP_MODE=read, this gives AI agents a locked-down, domain-specific read-only interface.
Quick Example
custom_tools:
- name: search_faq
description: "Search frequently asked questions"
action: semantic_search
defaults:
collection: faq
topK: 3
threshold: 0.6
parameters:
- name: query
type: string
required: true
description: "User question"
- name: latest_news
description: "Get latest news articles"
action: search_documents
defaults:
collection: news
sort: updatedAt
asc: false
limit: 5
- name: search_products
description: "Search product catalog by keyword"
action: full_text_search
defaults:
collection: products
limit: 10
parameters:
- name: query
type: string
required: true
Configuration Reference
CustomTool fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Tool name exposed to LLM (must not conflict with built-in names) |
description |
string | yes | Human-readable description shown in tools/list |
action |
string | yes | Underlying MDDB operation (see Supported Actions) |
defaults |
object | no | Default values merged with user arguments |
parameters |
array | no | Parameters exposed to the LLM (omit for zero-arg tools) |
Supported Actions
| Action | Maps to | Use case |
|---|---|---|
semantic_search |
toolSemanticSearch โ /v1/vector-search |
Find documents by meaning |
search_documents |
toolSearchDocuments โ /v1/search |
Filter/sort by metadata |
full_text_search |
toolFTSSearch โ /v1/fts |
Keyword search with TF scoring |
Defaults
All defaults are optional. Declared user parameters override most defaults โ except the scope keys collection, filterMeta, includeContent and fields, which are operator-locked once set (v2.11.0+, SEC-010): a custom tool exists to narrow the surface, so client arguments cannot widen it back.
| Default | Type | Actions | Description |
|---|---|---|---|
collection |
string | all | Target collection |
topK |
int | semantic_search | Max results |
threshold |
float | semantic_search | Minimum similarity score (0-1) |
includeContent |
bool | all | Include the document body (contentMd) in each hit. Default true; set false to drop the body on metadata-only lookups (v2.10.2+) |
fields |
list of string | all | Restrict returned meta to the listed keys; each hit keeps id, key and the requested meta.<field> keys. The body follows includeContent (pair with includeContent: false to drop it too). Empty = all meta (v2.10.2+) |
sort |
string | search_documents | Sort field (addedAt, updatedAt) |
asc |
bool | search_documents | Sort ascending (default false) |
limit |
int | search_documents, full_text_search | Max results |
offset |
int | search_documents | Pagination offset |
filterMeta |
object | semantic_search, search_documents | Metadata filter |
query |
string | semantic_search, full_text_search | Default query (usually overridden) |
Cutting client token usage (includeContent + fields)
For narrow, high-frequency lookups the default response is expensive: every hit
ships all meta keys and the full contentMd body, and each result is
re-sent on subsequent conversation turns. includeContent: false drops the body
and fields: [...] projects the meta down to just the keys you need โ together
they cut client token usage by roughly 5โ30ร on lookup-style tools. Both are
strictly opt-in and backward compatible: unset includeContent defaults to
true and empty fields returns everything, so existing tools are unchanged.
- name: version_check
description: "Check the current version of a package"
action: full_text_search # read-only, so allowed in MDDB_MCP_MODE=read
defaults:
collection: versions
limit: 1
includeContent: false # drop the changelog body
fields: [name, currentVersion, versionChangedAt, dockerImage]
parameters:
- name: query
type: string
required: true
With this config each hit is reduced to id, key and the four requested meta
keys โ e.g. version_check drops from ~266 to ~40 response tokens, and a 8-hit
batch lookup from ~4.5k to ~600. Both options also work as per-call arguments
(include_content, fields) on the built-in search_documents,
full_text_search and semantic_search tools.
Parameters
Each parameter defines an argument that the LLM can provide.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Argument name |
type |
string | yes | JSON Schema type: string, integer, number, boolean, object |
required |
bool | no | Whether the LLM must provide this argument |
description |
string | no | Description shown to the LLM |
How It Works
AI calls: search_faq(query: "reset password")
โ mddbd finds "search_faq" in custom tools
โ Merges defaults: {collection:"faq", topK:3, threshold:0.6}
โ Merges user args: + {query:"reset password"}
โ Calls: semantic_search({collection:"faq", query:"reset password", topK:3, threshold:0.6})
โ Returns: vector search results
Argument merging follows three rules (v2.11.0+, SEC-010):
- Only declared parameters pass through. A client argument whose name is not listed under
parametersis silently dropped. - Pinned scope keys are locked. When
collection,filterMeta,includeContentorfieldsis set indefaults, a client argument of the same name is ignored โ a tool pinned tocollection: public+includeContent: falsecannot be called withcollection: secrets+include_content: true. - Everything else: user wins. For example, if a custom tool has
defaults.limit: 5, declareslimitas a parameter, and the user passeslimit: 20, the value20is used.
Validation
At startup, mddbd validates all custom tools:
- Name conflicts: Custom tool names cannot match any of the 44 built-in names
- Duplicate names: No two custom tools can share the same name
- Valid action: Must be one of
semantic_search,search_documents,full_text_search - Valid parameter types: Must be valid JSON Schema types
- Required fields:
name,description, andactionare required
Invalid configuration causes a startup error with a descriptive message.
Docker Deployment
docker run -i --rm --network host \
-v ./mcp-config.yaml:/app/mcp-config.yaml \
-e MDDB_MCP_STDIO=true \
-e MDDB_MCP_CONFIG=/app/mcp-config.yaml \
tradik/mddb:latest
Docker Compose:
services:
mddb:
image: tradik/mddb:latest
volumes:
- ./mcp-config.yaml:/app/mcp-config.yaml
environment:
- MDDB_MCP_STDIO=true
- MDDB_MCP_CONFIG=/app/mcp-config.yaml
Windsurf / Claude Desktop
{
"mcpServers": {
"mddb": {
"command": "docker",
"args": [
"run", "-i", "--rm", "--network", "host",
"-v", "./mcp-config.yaml:/app/mcp-config.yaml",
"-e", "MDDB_MCP_STDIO=true",
"-e", "MDDB_MCP_CONFIG=/app/mcp-config.yaml",
"tradik/mddb:latest"
]
}
}
}
Use Cases
E-commerce Site
custom_tools:
- name: search_products
description: "Find products by description"
action: semantic_search
defaults: { collection: products, topK: 5, threshold: 0.5 }
parameters:
- { name: query, type: string, required: true, description: "Product search query" }
- name: bestsellers
description: "Show bestselling products"
action: search_documents
defaults: { collection: products, sort: updatedAt, asc: false, limit: 10, filterMeta: { tag: ["bestseller"] } }
Knowledge Base
custom_tools:
- name: ask_kb
description: "Search the knowledge base"
action: semantic_search
defaults: { collection: kb, topK: 5, threshold: 0.6 }
parameters:
- { name: query, type: string, required: true, description: "Your question" }
- name: search_articles
description: "Full-text search in articles"
action: full_text_search
defaults: { collection: articles, limit: 10 }
parameters:
- { name: query, type: string, required: true }
Multi-language Blog
custom_tools:
- name: latest_posts
description: "Get the latest blog posts"
action: search_documents
defaults: { collection: blog, sort: updatedAt, asc: false, limit: 5 }
- name: search_blog
description: "Search blog posts"
action: full_text_search
defaults: { collection: blog, limit: 10 }
parameters:
- { name: query, type: string, required: true, description: "Search keywords" }
Backward Compatibility
- If
MDDB_MCP_CONFIGis not set or the file has nocustom_toolskey,mddbdworks with built-in tools only - Built-in tools are always available regardless of custom tools configuration
- Custom tools are additive โ they never replace built-in tools