docs/api/mcp-protocol.md
MCPProxy implements the Model Context Protocol (MCP) specification, providing AI clients with unified access to multiple upstream MCP servers.
http://127.0.0.1:8080/mcp
Serves the routing mode configured in routing_mode (default: retrieve_tools).
Each routing mode has a dedicated endpoint that is always available regardless of the configured default:
| Endpoint | Mode | Description |
|---|---|---|
/mcp | (configured) | Default routing mode from config |
/mcp/call | retrieve_tools | BM25 search via retrieve_tools + call_tool variants |
/mcp/all | direct | All upstream tools as serverName__toolName |
/mcp/code | code_execution | JavaScript orchestration via code_execution tool |
See Routing Modes for details on each mode.
Note: MCP endpoints do not require API key authentication for client compatibility.
MCPProxy provides several built-in tools for managing and interacting with upstream servers.
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
}
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.
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.
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.
:::tip Choosing the Right Tool Variant
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.
Manage upstream server configurations with smart patching support.
Operations:
list - List all servers with health statusadd - Add a new server (quarantined by default)remove - Remove a serverupdate - Update server (smart merge)patch - Patch server (smart merge)tail_log - View server logsSmart Patching (update/patch):
Uses deep merge semantics - only specify fields you want to change:
| Field Type | Behavior | Example |
|---|---|---|
| Scalars | Replace | enabled: true |
| Maps (env, headers) | Merge | New keys added, existing updated |
| Arrays (args) | Replace entirely | All args replaced |
| Objects (isolation, oauth) | Deep merge | Only specified fields change |
Explicit null | Remove field | isolation_json: "null" removes isolation |
Example (patch - toggle enabled):
{
"operation": "patch",
"name": "my-server",
"enabled": true
}
Only enabled changes - all other fields (env, isolation, oauth) are preserved.
Example (add with isolation):
{
"operation": "add",
"name": "isolated-server",
"command": "npx",
"args_json": "[\"-y\", \"some-mcp-server\"]",
"isolation_json": "{\"enabled\": true, \"image\": \"node:20\"}"
}
Example (patch isolation image only):
{
"operation": "patch",
"name": "isolated-server",
"isolation_json": "{\"image\": \"node:22\"}"
}
Only isolation.image changes - isolation.enabled and other fields preserved.
:::caution Concurrent Edits MCPProxy does not support three-way merge with conflict detection. Avoid making concurrent edits to the same server configuration from multiple sources (MCP tool, Web UI, CLI) simultaneously. If concurrent edits occur, the last write wins and earlier changes may be lost.
Best practices:
list operation to verify current state before patchingExecute JavaScript code to orchestrate multiple tools. Disabled by default.
See Code Execution for complete documentation.
Tools from upstream servers are prefixed with the server name:
<serverName>:<originalToolName>
Examples:
github:create_issuefilesystem:read_filesqlite:queryThis prevents naming conflicts when multiple servers provide similar tools.
When a tool is called on a quarantined server:
This protects against Tool Poisoning Attacks (TPA).
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 |
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.
capabilities.tools.listChanged: true during initializationDiscoverAndIndexToolsForServer() within secondsTool change notifications are supported across all connection types:
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" |
MCP errors follow the JSON-RPC 2.0 error format:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": {}
}
}