MCP Protocol
MCPProxy implements the Model Context Protocol (MCP) specification, providing AI clients with unified access to multiple upstream MCP servers.
Endpoint
http://127.0.0.1:8080/mcp
Note: The MCP endpoint does not require API key authentication for client compatibility.
Built-in Tools
MCPProxy provides several built-in tools for managing and interacting with upstream servers.
retrieve_tools
Search for tools across all connected servers using BM25 keyword search.
Input Schema:
{
"query": "string (required) - Search keywords",
"limit": "number (optional) - Maximum results, default 15"
}
Example:
{
"query": "create github issue",
"limit": 5
}
call_tool_read
Execute a read-only tool on an upstream server. Use for operations that query data without modifying state.
Input Schema:
{
"name": "string (required) - Tool name in server:tool format",
"args_json": "string (optional) - Tool arguments as JSON string",
"intent": {
"operation_type": "read (required)",
"data_sensitivity": "string (optional) - public|internal|private|unknown",
"reason": "string (optional) - Explanation for audit trail"
}
}
Example:
{
"name": "github:list_repos",
"args_json": "{\"org\": \"myorg\"}",
"intent": {
"operation_type": "read"
}
}
Validation: Rejected if server marks tool as destructiveHint: true.
call_tool_write
Execute a state-modifying tool on an upstream server. Use for operations that create or update resources.
Input Schema:
{
"name": "string (required) - Tool name in server:tool format",
"args_json": "string (optional) - Tool arguments as JSON string",
"intent": {
"operation_type": "write (required)",
"data_sensitivity": "string (optional) - public|internal|private|unknown",
"reason": "string (optional) - Explanation for audit trail"
}
}
Example:
{
"name": "github:create_issue",
"args_json": "{\"repo\": \"owner/repo\", \"title\": \"Bug report\", \"body\": \"Description\"}",
"intent": {
"operation_type": "write",
"reason": "Creating bug report per user request"
}
}
Validation: Rejected if server marks tool as destructiveHint: true.
call_tool_destructive
Execute a destructive tool on an upstream server. Use for operations that delete or permanently modify resources.
Input Schema:
{
"name": "string (required) - Tool name in server:tool format",
"args_json": "string (optional) - Tool arguments as JSON string",
"intent": {
"operation_type": "destructive (required)",
"data_sensitivity": "string (optional) - public|internal|private|unknown",
"reason": "string (optional) - Explanation for audit trail"
}
}
Example:
{
"name": "github:delete_repo",
"args_json": "{\"repo\": \"test-repo\"}",
"intent": {
"operation_type": "destructive",
"data_sensitivity": "private",
"reason": "User confirmed deletion"
}
}
Validation: Most permissive - allowed regardless of server annotations.
Use retrieve_tools to discover tools - each result includes a call_with field recommending the appropriate variant based on server annotations.
See Intent Declaration for complete documentation on the two-key security model.
upstream_servers
Manage upstream server configurations.
Actions:
list- List all serversadd- Add a new serverremove- Remove a serverenable- Enable a serverdisable- Disable a server
Example (list):
{
"action": "list"
}
code_execution
Execute JavaScript code to orchestrate multiple tools. Disabled by default.
See Code Execution for complete documentation.
Tool Name Format
Tools from upstream servers are prefixed with the server name:
<serverName>:<originalToolName>
Examples:
github:create_issuefilesystem:read_filesqlite:query
This prevents naming conflicts when multiple servers provide similar tools.
Quarantine Behavior
When a tool is called on a quarantined server:
- The tool call is not executed
- A security analysis is returned instead
- User must approve the server via Web UI or config
This protects against Tool Poisoning Attacks (TPA).
Connection States
Upstream servers can be in these states:
| State | Description |
|---|---|
| Disconnected | Not connected to server |
| Connecting | Attempting to connect |
| Authenticating | OAuth flow in progress |
| Ready | Connected and operational |
| Error | Connection failed |
Tool Change Notifications
MCPProxy subscribes to the MCP notifications/tools/list_changed notification from upstream servers. This enables automatic tool re-indexing when servers add, remove, or modify their available tools.
How It Works
- Server Capability: Servers that support tool change notifications advertise
capabilities.tools.listChanged: trueduring initialization - Notification Handler: MCPProxy registers a notification handler after connecting to each server
- Automatic Re-indexing: When a notification is received, MCPProxy triggers
DiscoverAndIndexToolsForServer()within seconds - Fallback Behavior: Servers without notification support continue to use the 5-minute background polling cycle
Supported Connection Types
Tool change notifications are supported across all connection types:
- stdio: Local process servers
- HTTP/SSE: Remote HTTP-based servers
- Streamable HTTP: Modern HTTP transport
Resilience Features
- Deduplication: Rapid successive notifications are deduplicated to prevent redundant discovery
- Timeout Protection: Discovery operations have a 30-second timeout
- Graceful Degradation: Errors during discovery are logged but don't crash the proxy
Logs
When notifications are received, MCPProxy logs:
| Level | Message |
|---|---|
| INFO | "Received tools/list_changed notification from upstream server" |
| DEBUG | "Server supports tool change notifications - registered handler" |
| DEBUG | "Tool discovery triggered by notification" |
| WARN | "Received tools notification from server that did not advertise listChanged capability" |
Error Handling
MCP errors follow the JSON-RPC 2.0 error format:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": {}
}
}