MCP (Model Context Protocol) Plugin
The MCP Plugin enables Codumentor to integrate with Model Context Protocol (MCP) servers, exposing their tools as native Codumentor tools. You can configure which agents (main agent, subagents, or both) receive these tools.
Overview
The MCP plugin:
- Connects to MCP servers over stdio (local processes) or HTTP/SSE (remote servers)
- Discovers available tools from MCP servers
- Wraps MCP tools as Codumentor tools
- Makes tools available to configured agents (main agent, subagents, or both)
- Shares MCP client connections across all agent instances to avoid redundant processes
Installation
The MCP plugin is included with Codumentor. No additional installation is required.
Testing
The MCP plugin tests are optional and skipped by default to keep the test suite fast. They spawn actual processes and take ~8-12 seconds to run.
Run all tests except MCP tests (default)
python -m unittest discover -s tests
Run only MCP tests
RUN_MCP_TESTS=1 python -m pytest tests/test_mcp_plugin.py -v
Run all tests including MCP tests
RUN_MCP_TESTS=1 python -m unittest discover -s tests
Configuration
Add the MCP plugin to your Codumentor configuration file. You can configure either a local stdio server or a remote HTTP/SSE server.
Local stdio Server Configuration
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
executable: "path/to/mcp-server" # Required: MCP server executable
args: [] # Optional: Command-line arguments
env: {} # Optional: Environment variables
enabled: true # Optional: Enable/disable the plugin (default: true)
target_agents: "all" # Optional: Which agents receive tools (default: "all")
disabled_tools: [] # Optional: Tools to disable (single string or list)
Remote HTTP/SSE Server Configuration
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
url: "https://mcp-server.example.com" # Required: Remote MCP server URL
headers: # Optional: HTTP headers for authentication
Authorization: "Bearer your-token"
X-API-Key: "your-api-key"
enabled: true # Optional: Enable/disable the plugin (default: true)
target_agents: "all" # Optional: Which agents receive tools (default: "all")
disabled_tools: [] # Optional: Tools to disable (single string or list)
Configuration Parameters
For Local stdio Servers
- executable (required): Path or name of the MCP server executable
- args (optional): List of command-line arguments to pass to the executable
- Example:
["--verbose", "--config", "config.json"] - env (optional): Dictionary of environment variables to set for the process
- Example:
{"API_KEY": "your-key", "LOG_LEVEL": "debug"} - response_truncate_length (optional): Maximum length in characters for response content before truncation (default:
30000) - Example:
50000(50KB) - If a response exceeds this limit, it will be truncated and a truncation message will be appended
- The full response is still parsed and processed, but only the truncated version is returned to the agent
For Remote HTTP/SSE Servers
- url (required): URL of the remote MCP server
- Example:
"https://mcp-server.example.com" - Example:
"https://api.example.com/mcp" - headers (optional): Dictionary of HTTP headers for authentication
- Example:
{"Authorization": "Bearer your-token"} - Example:
{"X-API-Key": "your-api-key", "Authorization": "Bearer token"}
Common Parameters (Both Types)
- enabled (optional): Whether the plugin is enabled (default:
true) - target_agents (optional): Which agents should receive the MCP tools (default:
"all") "main": Only register tools with the main agent"subagent": Only register tools with subagents"all": Register tools with both main agent and subagents (default)- disabled_tools (optional): Tools to disable. Can be a single tool name (string) or a list of tool names
- Example:
"read_file"(disable a single tool) - Example:
["read_file", "write_file"](disable multiple tools)
Per-user secrets in headers / env
Rather than hard-coding a shared token in config, you can reference a per-user secret with a ${secret:<name>} placeholder in headers (remote) or env/args (stdio). It is resolved from the calling user's secret registry at request time — so a single server config authenticates each user with their own key, and the token never appears in config or the agent transcript.
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
url: "https://api.example.com/mcp"
headers:
Authorization: "Bearer ${secret:my_service_token}" # per-user
The MCP plugin scans its configured headers/env/args for these placeholders and declares them to the User Secrets pane, which shows the user exactly which secrets to create ("Needed by plugins", set/unset). Requires the user_secrets plugin to be loaded — it is what resolves the placeholder and surfaces the requirement. This indirection is also why a Codumentor-native plugin is preferable to MCP when you need per-user identity for a local tool: a stdio MCP server's environment is fixed at spawn and shared across all sessions, so it cannot carry per-user identity the way a placeholder-in-headers remote server (or a native plugin like redmine) can.
Examples
Local stdio Server - Basic Configuration
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
executable: "mcp-filesystem"
Local stdio Server - With Arguments
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
executable: "mcp-server"
args: ["--workspace", "/path/to/workspace"]
env:
API_KEY: "your-api-key"
LOG_LEVEL: "info"
response_truncate_length: 50000 # Truncate responses longer than 50K characters
Remote HTTP/SSE Server - Basic Configuration
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
url: "https://mcp-server.example.com"
Remote HTTP/SSE Server - With Authentication
plugins:
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
url: "https://api.example.com/mcp"
headers:
Authorization: "Bearer your-oauth-token"
X-API-Key: "your-api-key"
Multiple MCP Servers (Local and Remote)
You can configure multiple MCP plugins to connect to different servers:
plugins:
# Local stdio server
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
executable: "mcp-filesystem"
# Another local stdio server
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
executable: "mcp-github"
env:
GITHUB_TOKEN: "your-github-token"
# Remote HTTP/SSE server
- module: codumentor.plugins.mcp
class: MCPPlugin
args:
url: "https://remote-mcp.example.com"
headers:
Authorization: "Bearer your-token"
How It Works
MCP Protocol
The plugin implements the Model Context Protocol, which is a JSON-RPC protocol. The protocol supports two transports:
- stdio Transport: For local MCP server processes (JSON-RPC over stdin/stdout)
- HTTP/SSE Transport: For remote MCP servers (JSON-RPC over HTTP with Server-Sent Events)
The protocol includes:
- Initialization: Handshake with the MCP server to establish protocol version and capabilities
- Tool Discovery: Listing available tools and their schemas
- Tool Execution: Calling tools with arguments and receiving results
Tool Integration
MCP tools are automatically integrated into Codumentor's tool system:
- Tool Wrapping: Each MCP tool is wrapped as a Codumentor
Toolinstance - Schema Translation: MCP's JSON schemas are translated to Codumentor's tool parameter schemas
- Result Translation: MCP tool results are converted to Codumentor's
ToolResultformat
Shared Client Architecture
The plugin uses a shared client architecture to optimize resource usage:
- Single Process per Server: Only one MCP server process is started per unique configuration
- Shared Across Agents: The same MCP client is reused by the main agent and all subagents
- Thread-Safe: Concurrent access to the MCP client is handled with async locks
Hook-Based Registration
Tools are registered dynamically via the onPromptAssemble hook:
- Called before each LLM prompt is assembled
- Adds MCP tools to the available tools list based on
target_agentsconfiguration - Registers tools with the agent's tool registry on-demand
- Respects the
target_agentssetting to control which agents receive tools
Tool Naming
MCP tools are exposed with their original names from the MCP server. They appear in logs with the [MCP] prefix for easy identification:
[MCP] read_file(path='/path/to/file')
Error Handling
The plugin handles various error scenarios:
- Server Startup Failure: Logs error and disables the plugin
- Communication Errors: Tool calls fail gracefully with error messages
- Timeout Handling: Requests timeout after 30 seconds
- Process Cleanup: MCP server processes are properly terminated on shutdown
Troubleshooting
Plugin Not Loading
Check the logs for plugin loading errors:
grep "MCPPlugin" logs/codumentor.log
Common issues:
- Executable not found: Ensure the path is correct and the executable exists
- Permission denied: Make sure the executable has execute permissions
- Missing dependencies: Some MCP servers may require additional dependencies
Tools Not Appearing
If MCP tools don't appear in the agent:
- Verify the MCP server is starting correctly
- Check that the server returns tools in the
tools/listresponse - Look for errors in the MCP server's stderr (logged by the plugin)
Communication Issues
For JSON-RPC communication problems:
- Enable debug logging in your configuration
- Check the MCP protocol version compatibility
- Verify the server implements the expected MCP protocol
Advanced Usage
Custom MCP Server
You can implement your own MCP server in any language. The server must:
- Read JSON-RPC messages from stdin (one per line)
- Write JSON-RPC responses to stdout (one per line)
- Implement the MCP protocol methods: -
initialize: Handshake and capability negotiation -tools/list: Return available tools and their schemas -tools/call: Execute tool calls
Example minimal MCP server (Python):
#!/usr/bin/env python3
import json
import sys
def handle_request(request):
method = request["method"]
if method == "initialize":
return {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "my-server", "version": "1.0.0"}
}
elif method == "tools/list":
return {
"tools": [
{
"name": "example_tool",
"description": "An example tool",
"inputSchema": {
"type": "object",
"properties": {
"message": {"type": "string"}
},
"required": ["message"]
}
}
]
}
elif method == "tools/call":
tool_name = request["params"]["name"]
args = request["params"]["arguments"]
# Implement your tool logic here
result = {"content": [{"type": "text", "text": f"Processed: {args}"}]}
return result
# Main loop
for line in sys.stdin:
request = json.loads(line)
response = {
"jsonrpc": "2.0",
"id": request.get("id")
}
try:
response["result"] = handle_request(request)
except Exception as e:
response["error"] = {"message": str(e)}
print(json.dumps(response), flush=True)
Programmatic Access
You can also use the MCP client programmatically:
from codumentor.plugins.mcp.mcp_client import MCPClient
# Create and start a client
client = MCPClient(executable="mcp-server", args=["--config", "config.json"])
await client.start()
# List tools
print(f"Available tools: {[t.name for t in client.tools]}")
# Call a tool
result = await client.call_tool("example_tool", {"message": "Hello"})
print(result)
# Stop the client
await client.stop()
Performance Considerations
- Startup Time: MCP servers are started once and kept running
- Memory Usage: Shared clients reduce memory overhead
- Latency: stdio communication adds minimal latency (typically < 10ms)
- Concurrency: Multiple tools can be called concurrently from the same client
Security Considerations
- Untrusted Executables: Only run MCP servers from trusted sources
- Environment Variables: Be careful with sensitive data in
envconfiguration. For per-user credentials prefer a${secret:<name>}placeholder (see Per-user secrets in headers / env) so the value lives in the encrypted store rather than plaintext config. - Subprocess Isolation: MCP servers run as separate processes with limited privileges
- Input Validation: MCP tool arguments are validated by the server's input schema
Remote Server Support
The MCP plugin supports connecting to remote MCP servers over HTTP/SSE. This enables:
- Centralized Services: Connect to MCP servers hosted on remote infrastructure
- Authentication: Use API keys (bearer tokens) for secure authentication
- Scalability: Remote servers can handle multiple clients and scale independently
- Network Access: Access MCP servers across networks without local installation
Remote Server Requirements
Remote MCP servers should:
- Support HTTP POST requests for JSON-RPC messages
- Optionally support Server-Sent Events (SSE) for real-time responses
- Implement the MCP protocol (initialize, tools/list, tools/call)
- Support authentication via HTTP headers
Transport Details
- HTTP POST: Used for sending JSON-RPC requests and receiving responses
- Server-Sent Events (SSE): Used for real-time response streaming (optional, falls back to HTTP polling if unavailable)
- Authentication: Via HTTP headers (Authorization, X-API-Key, etc.)
Future Enhancements
Potential improvements for the MCP plugin:
- Support for MCP resources and prompts
- WebSocket transport support
- Automatic reconnection on server failure
- Tool result caching
- Hot-reloading of MCP servers
- MCP server health monitoring