# MCP Server Overview
The **Model Context Protocol (MCP) Server** component provides AI assistants with structured access to your MkDocs documentation. This enables seamless integration between documentation and AI-powered tools.
## What is MCP?
The Model Context Protocol (MCP) is an open standard for connecting AI assistants with external data sources and tools. It allows AI models to:
- **Access Resources**: Read documentation, files, and structured data
- **Use Tools**: Execute functions and perform operations
- **Maintain Context**: Keep track of conversation state and preferences
## Architecture
```mermaid
graph TB
A[AI Assistant] --> B[MCP Client]
B --> C[MCP Server]
C --> D[Documentation Resources]
C --> E[Search Tools]
C --> F[Analysis Tools]
D --> G[Markdown Files]
D --> H[Frontmatter Metadata]
D --> I[Code Blocks]
E --> J[Full-text Search]
E --> K[Title Search]
E --> L[Code Search]
F --> M[Page Outlines]
F --> N[Link Analysis]
F --> O[Content Statistics]
```
## Core Components
### 1. Server (`server.py`)
The main MCP server handles:
- **Protocol Implementation**: MCP message handling and routing
- **Resource Management**: Serving documentation as MCP resources
- **Tool Execution**: Processing tool calls and returning results
- **Lifecycle Management**: Startup, shutdown, and error handling
```python
from mkdocs_mcp.server import MkDocsMCPServer
from pathlib import Path
# Initialize server
server = MkDocsMCPServer(docs_path=Path("./docs"))
# Start server
await server.run()
```
### 2. Resources (`resources.py`)
Manages documentation as MCP resources:
- **File Discovery**: Automatically finds and indexes Markdown files
- **Metadata Extraction**: Parses frontmatter and content structure
- **Content Serving**: Provides full document content on demand
- **URI Management**: Maps file paths to resource identifiers
**Resource URI Format**: `docs://path/to/file.md`
### 3. Tools (`tools.py`)
Provides AI-accessible tools for documentation interaction:
- **`search_docs`**: Full-text search across all documentation
- **`find_by_title`**: Locate pages by title or heading
- **`list_pages`**: Enumerate all available documentation pages
- **`get_page_outline`**: Extract document structure and headings
- **`search_code_blocks`**: Find and analyze code examples
## Resource Types
### Documentation Resources
Each Markdown file becomes an MCP resource with:
```json
{
"uri": "docs://getting-started/installation.md",
"name": "Installation Guide",
"description": "How to install the software",
"mimeType": "text/markdown"
}
```
### Metadata Extraction
The server automatically extracts metadata from:
**Frontmatter**:
```yaml
---
title: Installation Guide
description: How to install the software
tags: [setup, installation]
---
```
**Content Structure**:
- First heading becomes title (if no frontmatter title)
- First paragraph becomes description (if no frontmatter description)
- Code blocks are indexed for search
## Tool Capabilities
### Search Tools
#### Full-Text Search
```python
# Example tool call
result = await session.call_tool("search_docs", {
"query": "installation",
"case_sensitive": False,
"max_results": 10
})
```
**Features**:
- Case-sensitive/insensitive search
- Context highlighting around matches
- Result ranking and limiting
- Multi-file search capability
#### Title Search
```python
result = await session.call_tool("find_by_title", {
"title": "Installation",
"exact_match": False
})
```
**Features**:
- Exact or fuzzy title matching
- Search in frontmatter titles
- Search in document headings
- Hierarchical title support
### Content Analysis Tools
#### Page Listing
```python
result = await session.call_tool("list_pages", {
"include_content": False,
"pattern": "*.md"
})
```
**Features**:
- Complete page enumeration
- Metadata display
- Content previews (optional)
- Pattern-based filtering
#### Page Structure Analysis
```python
result = await session.call_tool("get_page_outline", {
"page_path": "getting-started/installation.md"
})
```
**Features**:
- Hierarchical heading extraction
- Document structure visualization
- Navigation aid generation
#### Code Block Search
```python
result = await session.call_tool("search_code_blocks", {
"language": "python",
"query": "import"
})
```
**Features**:
- Language-specific filtering
- Content-based search within code
- Syntax highlighting preservation
- Context information
## Usage Patterns
### Basic Resource Access
```python
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
server_params = StdioServerParameters(
command="python",
args=["-m", "mkdocs_mcp.server"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# List all documentation
resources = await session.list_resources()
# Read specific page
content = await session.read_resource("docs://index.md")
print(content.contents[0].text)
```
### Tool-Based Interaction
```python
# Search for specific content
search_result = await session.call_tool("search_docs", {
"query": "configuration",
"max_results": 5
})
# Get document structure
outline = await session.call_tool("get_page_outline", {
"page_path": "getting-started/configuration.md"
})
# Find code examples
code_examples = await session.call_tool("search_code_blocks", {
"language": "python"
})
```
## Configuration
### Server Configuration
```python
# Custom docs path
server = MkDocsMCPServer(docs_path=Path("/custom/docs"))
# Environment variables
import os
docs_path = os.getenv("MKDOCS_MCP_DOCS_PATH", "../docs")
server = MkDocsMCPServer(docs_path=Path(docs_path))
```
### Logging Configuration
```python
import logging
# Configure logging (important: use stderr, not stdout)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
stream=sys.stderr # Critical for STDIO transport
)
```
### Resource Caching
The server includes built-in caching for performance:
- **Resource metadata** cached during listing
- **File content** read on-demand (not cached)
- **Search results** computed fresh each time
## Transport Protocol
The server uses **STDIO transport** by default:
**Advantages**:
- Simple setup and debugging
- Direct integration with AI tools
- No network configuration required
**Limitations**:
- Single client connection only
- No authentication mechanism
- Not suitable for production web services
For production deployments, consider HTTP-based transports (future enhancement).
## Error Handling
### Common Errors
**FileNotFoundError**: Documentation directory doesn't exist
```python
# Check before starting
if not docs_path.exists():
raise FileNotFoundError(f"Docs directory not found: {docs_path}")
```
**Invalid URI**: Malformed resource URI
```python
# URI validation
if not uri.startswith("docs://"):
raise ValueError(f"Invalid URI scheme: {uri}")
```
**Tool Argument Errors**: Invalid tool parameters
```python
# Parameter validation
if not isinstance(query, str) or len(query) == 0:
raise ValueError("Query must be non-empty string")
```
### Best Practices
1. **Always log to stderr** in STDIO transport mode
2. **Validate input parameters** before processing
3. **Handle file system errors** gracefully
4. **Use async/await** properly for I/O operations
5. **Cache expensive operations** when appropriate
## Performance Considerations
### File System Access
- Documentation directories are scanned once at startup
- Individual files are read on-demand
- Large documentation sets may need indexing optimization
### Memory Usage
- Resource metadata is kept in memory
- File contents are not cached (read fresh each time)
- Search operates on file contents directly
### Scalability
- Current implementation is single-threaded
- Suitable for small to medium documentation sets
- Large deployments may benefit from database indexing
## Security
### Input Validation
- All tool parameters are validated
- File paths are restricted to documentation directory
- URI schemes are strictly checked
### File System Access
- Server cannot access files outside docs directory
- No write operations are performed
- Only reads `.md` files (configurable)
### Process Isolation
- Runs as separate process via STDIO
- No network ports opened
- Limited system resource access
## Extending the Server
### Adding New Tools
1. **Define tool schema**:
```python
Tool(
name="my_custom_tool",
description="Description of what the tool does",
inputSchema={
"type": "object",
"properties": {
"param": {"type": "string", "description": "Parameter description"}
},
"required": ["param"]
}
)
```
2. **Implement tool handler**:
```python
async def _my_custom_tool(self, param: str) -> CallToolResult:
# Tool implementation
result_text = f"Processed: {param}"
return CallToolResult(
content=[TextContent(type="text", text=result_text)],
isError=False
)
```
3. **Register tool**:
```python
elif name == "my_custom_tool":
return await self._my_custom_tool(**arguments)
```
### Custom Resource Types
```python
class CustomResourceManager(DocumentationResourceManager):
async def list_resources(self) -> List[Resource]:
resources = await super().list_resources()
# Add custom resources
return resources + custom_resources
```
## Next Steps
- **[Usage Guide](usage.md)**: Learn how to use the MCP server
- **[API Reference](../api/)**: Detailed API documentation
- **[Examples](../examples/basic-usage.md)**: Common usage patterns