MCP Server Configuration

MDDB has a built-in MCP (Model Context Protocol) server implementing the 2025-11-25 specification. This document covers all MCP configuration options.

โ†’ LLM client setup (Claude, Cursor, ChatGPT, Ollama) | โ†’ Custom YAML tools

Transports

Transport Endpoint Spec Version Status
Stdio stdin/stdout 2025-11-25 Default for Claude Desktop
Streamable HTTP POST/GET/DELETE /mcp 2025-11-25 Recommended for remote
SSE (legacy) GET /sse + POST /message 2024-11-05 Backward compatible

All transports run on the MCP port (default: 9000, configurable via MDDB_MCP_ADDR).

Streamable HTTP (Recommended)

curl -X POST http://localhost:9000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

Client Configuration

{
  "mcpServers": {
    "mddb": {
      "transport": "streamable-http",
      "url": "http://localhost:9000/mcp"
    }
  }
}

Environment Variables

Core

Env Var Default Description
MDDB_MCP_ENABLED true Enable MCP HTTP server
MDDB_MCP_ADDR :9000 MCP HTTP listen address
MDDB_MCP_PORT 9000 MCP HTTP port (alternative to ADDR)
MDDB_MCP_STDIO false Run in MCP stdio mode (replaces HTTP/gRPC)
MDDB_MCP_DOMAIN โ€” Server hostname for Panel config generation
MDDB_MCP_MODE โ€” Access mode override: read, write, or wr (inherits MDDB_MODE)

Server Info

Env Var Default Description
MDDB_MCP_SERVER_NAME mddbd Server name in MCP initialize response
MDDB_MCP_SERVER_DESCRIPTION โ€” Server description
MDDB_MCP_SERVER_VENDOR โ€” Vendor name
MDDB_MCP_SERVER_HOMEPAGE โ€” Homepage URL
MDDB_MCP_INSTRUCTIONS โ€” System prompt for LLM โ€” guidance on how to use this server

Tools

Env Var Default Description
MDDB_MCP_CONFIG โ€” Path to YAML file with custom tool definitions
MDDB_MCP_BUILTIN_TOOLS true Set to false to hide all 79 built-in tools (only custom tools exposed)

API Key Authentication

Env Var Default Description
MDDB_MCP_API_KEY_ENABLED false Require API key for MCP HTTP access
MDDB_MCP_API_KEYS โ€” Static keys: key1:name1,key2:name2 (defined at startup)
MDDB_MCP_API_KEY_CACHE_TTL 60s Cache TTL for dynamic key lookups

โš ๏ธ MCP exposure vs. main auth (SEC-002). The MCP listener (default :9000) is a separate port that grants full read/write access to the database. Its own MCPAPIKeyMiddleware is inactive unless MDDB_MCP_API_KEY_ENABLED=true. To prevent MCP from becoming an unauthenticated bypass of the main API, the server reconciles MCP exposure with MDDB_AUTH_ENABLED at startup:

MDDB_AUTH_ENABLED MDDB_MCP_API_KEY_ENABLED MCP listener behaviour
true false Gated by the main AuthManager โ€” MCP requires the same Authorization: Bearer / X-API-Key credentials as the HTTP API. Anonymous tools/call โ†’ 401.
true true Gated by MCP API keys (as configured below).
false true Gated by MCP API keys.
false false No authentication. If MCP is bound beyond loopback (e.g. the default :9000), the server logs a prominent startup warning. Use only on a trusted/loopback bind, or set one of the flags above.

Two sources of keys:

  • Static โ€” MDDB_MCP_API_KEYS env var (defined at startup, no restart needed to validate)
  • Dynamic โ€” REST API (/v1/mcp/keys) stored in BoltDB, persists across restarts, managed without downtime

Clients authenticate via:

  • X-API-Key: <key> header
  • Authorization: Bearer <key> header
  • ?api_key=<key> query parameter (for SSE connections)
docker run -d \
  -e MDDB_MCP_API_KEY_ENABLED=true \
  -e "MDDB_MCP_API_KEYS=sk-prod:claude-prod,sk-dev:cursor-dev" \
  -p 9000:9000 \
  tradik/mddb:latest

Dynamic Key Management API

Keys stored in internal BoltDB bucket (_mcp_api_keys). Requires admin auth when MDDB_AUTH_ENABLED=true.

curl -X POST http://localhost:11023/v1/mcp/keys \
  -H "Authorization: Bearer <admin-token>" \
  -d '{"name": "claude-prod", "expiresAt": 0}'

curl http://localhost:11023/v1/mcp/keys \
  -H "Authorization: Bearer <admin-token>"

curl -X DELETE http://localhost:11023/v1/mcp/keys \
  -H "Authorization: Bearer <admin-token>" \
  -d '{"key": "mcp_a1b2c3d4e5f6..."}'

curl -X POST http://localhost:11023/v1/mcp/keys/disable \
  -H "Authorization: Bearer <admin-token>" \
  -d '{"key": "mcp_a1b2c3d4e5f6..."}'

Key features:

  • TTL support โ€” expiresAt Unix timestamp (0 = never expires)
  • Disable without delete โ€” revoke instantly, keep for audit
  • Cache โ€” lookups cached for MDDB_MCP_API_KEY_CACHE_TTL (default 60s), auto-invalidated on create/delete/disable
  • Panel UI โ€” manage keys from the web panel (LLM Connections โ†’ API Keys tab)

Rate Limiting

Env Var Default Description
MDDB_MCP_RATE_LIMIT_ENABLED false Enable per-client rate limiting
MDDB_MCP_RATE_LIMIT_REQUESTS 100 Max requests per window
MDDB_MCP_RATE_LIMIT_WINDOW 60 Window duration in seconds
MDDB_MCP_RATE_LIMIT_BURST 20 Burst allowance above limit
MDDB_MCP_RATE_LIMIT_BY ip Rate limit key: ip, api_key, or session

Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Returns 429 Too Many Requests with Retry-After header when exceeded.

Request Logging

Env Var Default Description
MDDB_MCP_LOGGING_ENABLED false Enable structured JSON audit logs
MDDB_MCP_LOGGING_LEVEL info Log level: debug, info, warn, error

Logs are written to stderr in JSON format:

{"timestamp":"2026-03-26T10:30:00Z","method":"POST","path":"/mcp","status":200,"duration_ms":45,"client_ip":"1.2.3.4","key_name":"claude-prod","session_id":"abc123","user_agent":"claude-code/1.0"}

Access Modes

Each protocol can have its own read/write mode:

Env Var Protocol Default
MDDB_MODE Global wr
MDDB_API_MODE HTTP/REST + GraphQL inherits global
MDDB_GRPC_MODE gRPC inherits global
MDDB_MCP_MODE MCP (all transports) inherits global
MDDB_HTTP3_MODE HTTP/3 (QUIC) inherits global

In read-only mode:

  • Built-in tools with readOnlyHint=true (search, stats, list, export) โ†’ allowed
  • Built-in tools with writes/deletes โ†’ blocked with error
  • Custom tools with read-only actions (semantic_search, search_documents, full_text_search) โ†’ allowed
  • Custom tools with write actions โ†’ blocked
docker run -d \
  -e MDDB_MCP_MODE=read \
  -e MDDB_MCP_BUILTIN_TOOLS=false \
  -e MDDB_MCP_API_KEY_ENABLED=true \
  -e "MDDB_MCP_API_KEYS=sk-public:external" \
  -e MDDB_MCP_RATE_LIMIT_ENABLED=true \
  -e MDDB_MCP_RATE_LIMIT_REQUESTS=60 \
  -e MDDB_MCP_LOGGING_ENABLED=true \
  -e MDDB_MCP_CONFIG=/app/tools.yml \
  tradik/mddb:latest

Protocol Features (2025-11-25)

Feature Description
Tool Annotations readOnlyHint, destructiveHint, idempotentHint, openWorldHint on all tools
Structured Output outputSchema on 9 key tools for client-side validation
5 Prompts analyze-collection, search-help, summarize-collection, import-guide, rag-pipeline
Completion Autocomplete for collection names and prompt arguments
Logging logging/setLevel with RFC 5424 levels (debug โ†’ emergency)
Progress Tokens notifications/progress for long-running operations
Cursor Pagination tools/list and resources/list
Notifications notifications/initialized, notifications/cancelled
Memory RAG Tools 6 tools for conversational memory: start session, add message, recall, summarize, list sessions, history
Async Bulk Ingest Tools (v2.9.12+) 4 tools for long-running ingest jobs: submit, status, list, cancel
Autocomplete Tool (v2.9.12+) Prefix autocomplete over the FTS index โ€” top-N suggestions ranked by document frequency
Per-Query Boost (v2.9.12+) full_text_search and hybrid_search tools accept a boost map keyed by "metaKey:metaValue" to boost/demote matching documents at query time

Async Bulk Ingest Tools (v2.9.12+)

Queue long-running bulk ingest jobs from LLMs without blocking on the tool call. The worker drains jobs FIFO in 500-document chunks; status records persist across restarts.

Tool Description Write?
bulk_ingest_submit Queue a new job with documents + optional callback_url; returns job ID Yes
bulk_ingest_status Return current status record (counters, timestamps, errors) No
bulk_ingest_list List all jobs newest-first, optionally filtered by collection No
bulk_ingest_cancel Cancel a pending job (in-flight jobs run to completion) Yes

Autocomplete Tool (v2.9.12+)

Tool Description Write?
autocomplete Top-N prefix suggestions over the FTS inverted index, ranked by doc frequency; supports field scoping No

WordPress Publishing Tools (v2.11.0+)

Publish straight from MCP into WordPress sites running the mddb-sync plugin with Remote publishing enabled. Posts and pages, tags/categories/custom taxonomies, post meta ("metafields") and Polylang/WPML language assignment + translation linking are all supported.

Tool Description Write?
wordpress_publish Create or update a post/page (upsert by post_id, else post_type+slug) with content (Markdown or HTML), status, tags, categories, taxonomies, meta and language Yes
wordpress_set_status Change publishing status: publish, draft, pending, private, future (with date) or trash Yes

The target site comes from the collection's config โ€” one collection per WordPress site, matching how the sync plugin pushes content in:

// 1. Pin the WordPress target to the collection (once)
{"name": "set_collection_config", "arguments": {
  "collection": "example_com",
  "wordpress": {"url": "https://example.com", "api_key": "<publish key from Settings โ†’ MDDB Sync>"}
}}

// 2. Publish a post with tags, meta and a language
{"name": "wordpress_publish", "arguments": {
  "collection": "example_com",
  "post_type": "post",
  "title": "Hello from MDDB",
  "content_markdown": "# Hello\n\nPublished via MCP.",
  "status": "publish",
  "tags": ["mddb", "mcp"],
  "categories": ["News"],
  "meta": {"seoTitle": "Hello from MDDB"},
  "lang": "en_US"
}}

// 3. Later: unpublish it
{"name": "wordpress_set_status", "arguments": {"collection": "example_com", "post_id": 123, "status": "draft"}}

The site URL must be https:// (plain http:// only for localhost). Both tools also accept explicit site_url + api_key arguments to skip the collection config. Translations: pass lang plus translation_of: <post id> to link a new post as a translation via Polylang or WPML.

Projection note (v2.11.0, GO-019): for search_documents / full_text_search / semantic_search / hybrid_search, passing fields now also drops the document body by default โ€” pass include_content: true explicitly to keep it.

Memory RAG Tools

Built-in MCP tools for conversational memory and RAG:

Tool Description Write?
memory_start_session Start a new conversation session Yes
memory_add_message Add a message (auto-embedded) Yes
memory_recall Semantic/hybrid/keyword recall across sessions No
memory_summarize Generate and store session summary Yes
memory_list_sessions List sessions with filters No
memory_session_history Get chronological message history No

Example: Agent with Memory

// 1. Start session
{"name": "memory_start_session", "arguments": {"user_id": "user-1", "scenario": "support"}}

// 2. Store messages as conversation progresses
{"name": "memory_add_message", "arguments": {"session_id": "abc...", "role": "user", "content": "How do I use vector search?"}}
{"name": "memory_add_message", "arguments": {"session_id": "abc...", "role": "assistant", "content": "Use POST /v1/vector-search..."}}

// 3. In a future session, recall relevant context
{"name": "memory_recall", "arguments": {"query": "vector search usage", "user_id": "user-1", "top_k": 5, "include_content": true}}

// 4. Summarize when done
{"name": "memory_summarize", "arguments": {"session_id": "abc..."}}

Built-in Prompts

Prompt Arguments Description
analyze-collection collection (required) Document count, metadata keys, content patterns, suggestions
search-help use_case (required) Which search method to use for your use case
summarize-collection collection (required), limit Topic overview, themes, distribution
import-guide source (required) Step-by-step import from wordpress/url/file/api/scraping
rag-pipeline collection (required), model RAG pipeline design with embedding and search strategy

โ† Back to README | โ†’ LLM Connections | โ†’ Custom Tools