MCP Server
The Model Context Protocol (MCP) server bridges AI assistants like Claude to your indexed codebase, enabling intelligent code search, pattern recognition, and Wikit-aware development.
Overview
The MCP server provides:
- Semantic Code Search: Find code by meaning across all projects
- WordPress Pattern Recognition: Understand hook registrations, invocations, and ACF fields
- Wikit Block Discovery: Search indexed Gutenberg blocks and their schemas
- Project Management: Inspect project indexing status and manifests
- Saved Searches & History: Persist common queries and review past searches
Architecture
%%{init: {'theme':'neutral'}}%%
graph TB
subgraph "AI Layer"
Claude[Claude Desktop]
Cursor[Cursor IDE]
Other[Other AI Tools]
end
subgraph "MCP Server"
Server[MCP Server<br/>Host port 6765<br/>SSE transport]
Tools[MCP Tools]
end
subgraph "Data Layer"
Qdrant[(Vector DB<br/>Qdrant)]
Git[Git Repositories]
Projects[WordPress Projects]
end
Claude -->|MCP Protocol| Server
Cursor -->|MCP Protocol| Server
Other -->|MCP Protocol| Server
Server --> Tools
Tools --> Qdrant
Tools --> Git
Tools --> Projects
Available Tools
Code Search Tools
search_codebase
Semantic search across all indexed repositories.
# Example usage in Claude
search_codebase(
query="custom post type registration",
project="my-site",
file_types="php",
exclude_patterns=["tests/"],
include_context=True,
limit=10
)Parameters:
query(string): Search queryproject(string, optional): Project name to scope search ("platform","framework", or a project name). When omitted, searches all collections.file_types(string | list, optional): Filter by file extensions. Accepts a comma-separated string (e.g."php,js") or a list.component_type(string, optional): Filter by function, class, hook, etc.exclude_patterns(list, optional): Path substrings to exclude (e.g.["vendor/", "tests/"])include_context(bool, optional): Include surrounding code lines (default:false)context_lines(int, optional): Number of context lines before/after, 1-20 (default: 5)limit(int): Maximum results (default: 20)
Returns: A result object with status, count, collection, query, search_type, execution_time_ms, and a results array. Each result entry:
{
"file_path": "wp-content/themes/custom/functions.php",
"component_type": "function",
"name": "register_portfolio_post_type",
"line_number": 45,
"language": "php",
"content": "function register_portfolio_post_type() {...}",
"repository": "my-site",
"score": 0.89
}search_all_collections
Search across ALL indexed collections at once (framework, platform, and every project). Useful when you don't know which collection holds the code.
search_all_collections(
query="user authentication flow",
file_types="php"
)search_functions
Find specific functions by name. Supports fuzzy matching across naming conventions (e.g. getUser finds get_user).
search_functions(
function_name="get_user",
project="my-site",
language="php",
fuzzy_match=True
)search_classes
Find class definitions by name. Supports fuzzy matching across naming conventions.
search_classes(
class_name="CustomPostType",
project="my-site",
fuzzy_match=True
)Parameters: class_name, project (optional), fuzzy_match (default true). There is no language parameter.
search_code_patterns
Find code by structural relationship: class inheritance, interface implementation, or function calls.
search_code_patterns(
pattern_type="extends", # "extends" | "implements" | "calls_function"
pattern_value="WP_Widget"
)search_function_callers
Find what functions call a given function (reads the indexed calls metadata).
search_function_callers(function_name="render_block", project="my-site")search_function_calls
Find what functions a given function calls.
search_function_calls(function_name="render_block", project="my-site")WordPress-Specific Tools
search_wordpress_hooks
Find WordPress hook registrations — add_action() and add_filter() calls.
search_wordpress_hooks(
hook_name="init",
hook_type="action", # "action" | "filter"
project="my-site"
)To find where hooks are invoked (do_action() / apply_filters()), use search_hook_invocations instead.
search_hook_invocations
Find where WordPress hooks are invoked — do_action() and apply_filters() calls (not registrations).
search_hook_invocations(
hook_name="save_post",
invocation_type="action", # "action" for do_action, "filter" for apply_filters
project="my-site"
)search_acf_fields
Find Advanced Custom Fields (ACF) field and field-group definitions.
search_acf_fields(
field_name="hero_image",
field_type="image",
project="my-site"
)search_acf_field_usages
Find where ACF fields are used in code — get_field(), get_sub_field(), the_field(), have_rows() calls.
search_acf_field_usages(
field_name="hero_image",
project="my-site"
)wordpress_docs
Search WordPress core documentation.
wordpress_docs(
query="register_post_type",
type="function",
get_details=True
)Wikit-Specific Tools
search_wikit_blocks
Search indexed Wikit Gutenberg blocks. Can filter by attribute, supported feature, or category.
search_wikit_blocks(
block_name="hero", # Optional
has_attribute="backgroundType", # Optional
supports="align", # Optional
category="wdg-layout" # Optional
)Returns: A result object with status, query, filters, count, and a results array of indexed block components.
get_block_schema
Get the full parsed block.json schema for a Wikit block — attributes, supports, parent, keywords, and category.
get_block_schema(
block_name="wdg/hero", # full or partial block name
project="my-site" # Optional
)Project Management Tools
get_project_info
Get project details and indexing status.
get_project_info(
project_name="my-site"
)Returns: Indexing status from the vector database, plus the project manifest (project.yml) when present.
{
"status": "success",
"project": "my-site",
"indexed": true,
"collection": "project_my_site",
"vectors_count": 1450,
"languages": ["php", "javascript"],
"component_types": ["function", "class", "wikit_block"],
"repositories": ["my-site"],
"manifest": { "jira_project_key": "MS", "hosting": "pantheon" }
}list_collections
List all vector database collections.
list_collections()Recent Changes Tools
search_recent_changes
Get recently indexed code.
search_recent_changes(
project="my-site",
limit=10
)Batch Search
batch_search
Run multiple searches in a single call (parallel by default). Each entry is a search config dict.
batch_search(
searches=[
{"id": "hooks", "query": "add_action", "file_types": "php"},
{"id": "blocks", "query": "registerBlockType", "file_types": "js"}
],
parallel=True,
fail_fast=False
)Parameters: searches (list of dicts — each may include id, query, project, file_types, component_type, exclude_patterns, limit), parallel (default true), fail_fast (default false). Maximum 10 concurrent searches per call.
Saved Searches & History
save_search
Save a search with a label for quick recall.
save_search(label="auth-hooks", query="authenticate", filters={"file_types": "php"})get_saved_search
Retrieve a saved search by label; optionally execute it.
get_saved_search(label="auth-hooks", execute=True)list_saved_searches
List saved searches, sorted by last_used, use_count, label, or created_at.
list_saved_searches(sort_by="last_used", limit=20)delete_saved_search
Delete a saved search by label.
delete_saved_search(label="auth-hooks")get_search_history
Retrieve recent search history with result counts and timing.
get_search_history(limit=50, query_filter="payment")MCP Auth Proxy (OAuth-Protected Services)
A separate MCP Auth Proxy (mcp-server/proxy_server.py) runs on host port 6766 and brokers authenticated access to external MCP services. Proxied tools appear at runtime with the mcp__mcp-auth-proxy__<service>_* prefix.
- SSE endpoint:
http://localhost:6766/sse - Health check:
curl http://localhost:6766/health
Configured services (in mcp-server/registry.json):
| Service | Tool prefix | Transport | Description |
|---|---|---|---|
| Atlassian | atlassian_* | HTTP (proxied) | Jira issues, Confluence pages, search |
| Figma | figma_* | HTTP (proxied) | Design files, variables, screenshots |
| Read.ai | read-ai_* | HTTP (proxied) | Meeting transcripts and summaries |
| Slack | slack_* | HTTP (proxied) | Messages, channels, search, canvases |
Authenticate a service with wdg mcp auth <service> (opens a browser for OAuth) and check token validity with wdg mcp status.
Configuration
Server Configuration
The MCP server is reachable from the host at port 6765 (set by MCP_SERVER_PORT in .env.defaults) over the SSE transport. The host port maps to the container's internal port 8765 — 8765 is container-internal only and should never appear in host or client configuration.
# docker-compose.yml (illustrative)
mcp-server:
ports:
- "6765:8765" # host 6765 -> container 8765
environment:
- MCP_PORT=8765 # container-internal listen port
- QDRANT_HOST=qdrant
- QDRANT_PORT=6333Host-facing endpoint: http://localhost:6765/sse
Client Configuration
Claude Desktop
Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"wdg-local": {
"url": "http://localhost:6765/sse"
}
}
}Cursor IDE
Add to Cursor settings (.cursor/mcp.json):
{
"servers": {
"wdg-local": {
"url": "http://localhost:6765/sse",
"name": "WDG AI Dev Environment"
}
}
}Usage Examples
Example 1: Finding Similar Code
User prompt to AI:
"Find all places where we validate email addresses"
AI uses MCP:
search_codebase(
query="email validation",
file_types=["php", "js"]
)Result:
is_valid_email()in utils.phpvalidateEmailAddress()in forms.js- Email regex patterns
- WordPress sanitize_email() usage
Example 2: Understanding Wikit Blocks
User prompt:
"What Wikit blocks are available for layout?"
AI uses MCP:
search_wikit_blocks()AI responds with:
- Hero block
- Grid block
- Columns block
- Section block
- Container block
Example 3: Project Context Search
User prompt:
"In the client-website project, show me how we handle custom post types"
AI uses MCP:
search_codebase(
query="custom post type registration",
project="client-website",
component_type="function"
)Advanced Features
Contextual Awareness
The MCP server understands:
- Project context: Scopes searches to active project
- File relationships: Knows which files depend on others
- Git history: Can reference specific commits
- WordPress conventions: Understands hooks, filters, CPTs
Multi-Project Search
Search across multiple projects:
# Search in all projects
search_codebase(
query="user authentication",
project=None # Searches all projects
)
# Compare implementations across projects
search_functions(
function_name="get_user",
project=None
)Pattern Recognition
The MCP server identifies:
- Wikit patterns: Recognizes WDG's standard implementations
- WordPress best practices: Identifies secure coding patterns
- Code reusability: Finds similar implementations
Performance
Response Times
| Operation | Average Time | Notes |
|---|---|---|
search_codebase | 50-100ms | Depends on collection size |
search_functions | 20-50ms | Direct lookup |
search_wikit_blocks | 10-20ms | Small collection |
get_project_info | <10ms | Cached |
list_collections | <10ms | Direct query |
Caching
The MCP server implements caching for:
- Project metadata (15 min TTL)
- Collection lists (5 min TTL)
- Wikit block catalog (1 hour TTL)
Optimization
# Limit result count for faster responses
search_codebase(query="...", limit=5)
# Use filters to reduce search space
search_codebase(
query="...",
project="my-site",
file_types=["php"],
component_type="function"
)Security
Network Security
# Bind only to localhost (default)
MCP_HOST=127.0.0.1 # Local only
# Or bind to all interfaces (be careful!)
MCP_HOST=0.0.0.0 # Accessible on networkAuthentication
Currently, the MCP server runs locally without authentication. For production deployments:
# Add API key authentication
MCP_API_KEY=your-secret-key
# Or use JWT tokens
MCP_JWT_SECRET=your-jwt-secretData Privacy
- All queries stay local
- No external API calls for search
- Code never leaves your machine
- Project data is isolated
Troubleshooting
Server Not Responding
# Check if server is running (host-facing SSE server health endpoint)
curl http://localhost:6765/health
# View server logs
docker logs wdg-mcp-server
# Restart server
docker compose restart mcp-serverConnection Refused
# Check port is not in use
lsof -i :6765
# Verify Docker network
docker network inspect wdg-network
# Check firewall settings
sudo ufw statusSlow Responses
# Check Qdrant status
curl http://localhost:6333/collections
# Monitor server resources
docker stats wdg-mcp-server
# Reduce search limits
# Use more specific queriesEmpty Results
# Verify collections exist
curl http://localhost:6333/collections
# Check indexing status
wdg status
# Re-index if needed
wdg index my-siteAPI Reference
Health Check
The SSE app exposes a single plain-HTTP health endpoint. There are no REST /tools, /metrics, or WebSocket endpoints — tool discovery and invocation happen over the MCP/SSE protocol, not REST.
curl http://localhost:6765/healthResponse:
{
"status": "ok",
"version": "0.1.0"
}The version field is read from the platform VERSION file (falls back to "unknown" if unreadable). For the full tool list and parameters, see the MCP API Reference.
Best Practices
1. Use Specific Queries
# Good: Specific and contextual
search_codebase(
query="WordPress REST API endpoint registration",
component_type="function"
)
# Bad: Too vague
search_codebase(query="api")2. Scope to Project
# Good: Scoped search
search_codebase(
query="user authentication",
project="client-website"
)
# Bad: Unscoped (slower)
search_codebase(query="user authentication")3. Use Appropriate Tools
# Good: Use specific tool
search_functions(function_name="get_user")
# Bad: Generic search
search_codebase(query="get_user")4. Limit Results
# Good: Limited results
search_codebase(query="...", limit=5)
# Bad: Too many results
search_codebase(query="...", limit=100)Integration Examples
Claude Desktop
Create a custom slash command:
// ~/Library/Application Support/Claude/commands/search-code.json
{
"command": "/search-code",
"description": "Search WDG codebase",
"handler": {
"tool": "search_codebase",
"parameters": {
"query": "$input"
}
}
}Cursor IDE
Use in Cursor's chat:
User: "@wdg Find email validation in my-site project"
Cursor: [Uses MCP search_codebase tool]
Found 3 implementations:
1. is_valid_email() in utils.php
2. validateEmail() in forms.js
3. Email validation in checkout.phpMonitoring
View Real-Time Logs
# Follow MCP server logs
docker logs -f wdg-mcp-server
# Filter for searches
docker logs wdg-mcp-server | grep "search_codebase"Search History
The server records search activity internally. Review it through the get_search_history MCP tool rather than a REST endpoint:
get_search_history(limit=50)Next Steps:
- Learn about Code Indexing
- Review MCP API Reference
- Configure Claude Code Setup