MCP server exposition
Otoroshi can expose tool functions and MCP connectors as MCP servers using three different transport protocols: HTTP, SSE, and WebSocket. This allows external MCP clients to connect to your Otoroshi-managed tools.
Supported MCP methods
All three transport plugins (HTTP, SSE, WebSocket) implement the full MCP protocol:
| Method | Description |
|---|---|
initialize | Initialize the MCP session |
tools/list | List all available tools (from tool functions and MCP connectors) |
tools/call | Call a tool by name with arguments |
resources/list | List all available resources from connected MCP servers |
resources/read | Read a resource by its URI. Returns text or binary content. |
resources/templates/list | List all available resource templates from connected MCP servers |
prompts/list | List all available prompts with their arguments |
prompts/get | Get a prompt by name with arguments. Returns the prompt description and messages (each with role and content). |
Resources
When listing resources, each resource includes:
uri- The resource URIname- The resource namedescription- A description of the resourcemimeType- The MIME type of the resource
When reading a resource, the content is returned as either text (with uri, mimeType, text) or binary blob (with uri, mimeType, blob).
Resource Templates
When listing resource templates, each template includes:
uriTemplate- The URI template with parametersname- The template namedescription- A description of the templatemimeType- The MIME type of resources generated by this template
Prompts
When listing prompts, each prompt includes:
name- The prompt namedescription- A description of the promptarguments- An array of arguments, each withname,description, andrequired
When getting a prompt, the response includes:
description- The prompt descriptionmessages- An array of messages, each withrole(e.g.user,assistant) andcontent(text or image)
Filtering at the plugin level
All MCP server exposition plugins (HTTP, SSE, WebSocket) support filtering which tools, resources, resource templates, and prompts are exposed to clients. These filters are applied on top of any filters already configured on the MCP connectors themselves.
Available filters
| Parameter | Type | Description |
|---|---|---|
include_functions | array of strings | Only expose functions matching these regex patterns |
exclude_functions | array of strings | Hide functions matching these regex patterns |
include_resources | array of strings | Only expose resources matching these patterns |
exclude_resources | array of strings | Hide resources matching these patterns |
include_resource_templates | array of strings | Only expose resource templates matching these patterns |
exclude_resource_templates | array of strings | Hide resource templates matching these patterns |
include_resource_template_uris | array of strings | Only expose resource template URIs matching these patterns |
exclude_resource_template_uris | array of strings | Hide resource template URIs matching these patterns |
include_prompts | array of strings | Only expose prompts matching these patterns |
exclude_prompts | array of strings | Hide prompts matching these patterns |
allow_rules | object | Advanced JsonPath-based allow rules (see MCP Connectors - Advanced rules) |
disallow_rules | object | Advanced JsonPath-based disallow rules |
emit_audit_events | boolean | Emit audit events for every MCP method call (default: false) |
Example plugin configuration with filters
{
"name": "filtered-mcp-server",
"version": "1.0.0",
"refs": ["tool-function_xxxxx"],
"mcp_refs": ["mcp-connector_xxxxx"],
"include_functions": ["get_.*", "list_.*"],
"exclude_functions": ["delete_.*"],
"include_prompts": ["summarize"],
"exclude_prompts": [],
"include_resources": [],
"exclude_resources": ["admin_.*"]
}
These plugin-level filters are merged with the filters defined on each MCP connector. This means you can have broad access on the connector itself and restrict it further at the exposition level, or vice versa.
Audit events
All MCP server exposition plugins (HTTP, SSE, WebSocket) can emit audit events for every MCP method call. This is useful for monitoring, debugging, and auditing MCP usage across your infrastructure.
Enabling audit events
Set emit_audit_events to true in the plugin configuration:
{
"name": "my-mcp-server",
"version": "1.0.0",
"refs": ["tool-function_xxxxx"],
"mcp_refs": ["mcp-connector_xxxxx"],
"emit_audit_events": true
}
By default, this option is disabled (false).
Audit event payload
Each MCP method call will produce an AuditEvent with the audit type McpAudit. The event contains the following fields:
| Field | Type | Description |
|---|---|---|
mcp_method | string | The MCP JSON-RPC method called (e.g. tools/call, resources/list, initialize) |
mcp_id | number | The JSON-RPC request id |
mcp_request_payload | object | The full JSON-RPC request payload |
mcp_response | object | The JSON-RPC response (available for WebSocket transport, null for HTTP and SSE) |
transport | string | The transport protocol used: http, sse, or websocket |
duration | number | The request duration in milliseconds |
status | string | success or error |
error | string | Error message if the request failed, null otherwise |
user | object | The authenticated user information (if available) |
apikey | object | The API key used for the request (if available) |
route | object | The Otoroshi route that handled the request |
Example audit event
{
"@type": "AuditEvent",
"audit": "McpAudit",
"mcp_method": "tools/call",
"mcp_id": 3,
"mcp_request_payload": {
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "city": "Paris" }
}
},
"mcp_response": null,
"transport": "http",
"duration": 142,
"status": "success",
"error": null,
"user": null,
"apikey": { "clientId": "xxx", "clientName": "my-api-key" },
"route": { "id": "route_xxx", "name": "mcp-server" }
}
Filtering audit events in data exporters
You can use Otoroshi's data exporter filtering to collect only MCP audit events:
{
"include": [
{
"@type": "AuditEvent",
"audit": "McpAudit"
}
]
}
MCP Http Plugin


Configuration
{
"_loc": {
"tenant": "default",
"teams": [
"default"
]
},
"id": "route_2629d12c2-130b-42d5-aba5-b584b95961c9",
"name": "MCP HTTP server exposition",
"description": "MCP HTTP server exposition",
"tags": [],
"metadata": {},
"enabled": true,
"debug_flow": false,
"export_reporting": false,
"capture": false,
"groups": [
"default"
],
"bound_listeners": [],
"frontend": {
"domains": [
"mcp-http-expo.oto.tools"
],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": []
},
"backend": {
"targets": [
{
"id": "target_1",
"hostname": "request.otoroshi.io",
"port": 443,
"tls": true,
"weight": 1,
"predicate": {
"type": "AlwaysMatch"
},
"protocol": "HTTP/1.1",
"ip_address": null,
"tls_config": {
"certs": [],
"trusted_certs": [],
"enabled": false,
"loose": false,
"trust_all": false
}
}
],
"root": "/",
"rewrite": false,
"load_balancing": {
"type": "RoundRobin"
},
"client": {
"retries": 1,
"max_errors": 20,
"retry_initial_delay": 50,
"backoff_factor": 2,
"call_timeout": 30000,
"call_and_stream_timeout": 120000,
"connection_timeout": 10000,
"idle_timeout": 60000,
"global_timeout": 30000,
"sample_interval": 2000,
"proxy": {},
"custom_timeouts": [],
"cache_connection_settings": {
"enabled": false,
"queue_size": 2048
}
},
"health_check": {
"enabled": false,
"url": "",
"timeout": 5000,
"healthyStatuses": [],
"unhealthyStatuses": []
}
},
"backend_ref": null,
"plugins": [
{
"enabled": true,
"debug": false,
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"include": [],
"exclude": [],
"config": {},
"bound_listeners": [],
"plugin_index": {
"transform_request": 0
},
"nodeId": "cp:otoroshi.next.plugins.OverrideHost"
},
{
"enabled": true,
"debug": false,
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpRespEndpoint",
"include": [],
"exclude": [],
"config": {
"name": "first-mcp-http-server",
"version": "1.0.0",
"refs": [
"tool-function_0511ff44-0ce5-487d-aa1c-d1980ac9a4b8"
],
"mcp_refs": []
},
"bound_listeners": [],
"plugin_index": {},
"nodeId": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpRespEndpoint"
}
],
"kind": "proxy.otoroshi.io/Route"
}
MCP SSE Plugin


Configuration
{
"_loc": {
"tenant": "default",
"teams": [
"default"
]
},
"id": "route_73e79129a-1cc6-4473-970a-b80905e80c7b",
"name": "mcp-sse-exposition",
"description": "mcp-sse-exposition",
"tags": [],
"metadata": {},
"enabled": true,
"debug_flow": false,
"export_reporting": false,
"capture": false,
"groups": [
"default"
],
"bound_listeners": [],
"frontend": {
"domains": [
"mcp-sse-exposition.oto.tools"
],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": []
},
"backend": {
"targets": [
{
"id": "target_1",
"hostname": "request.otoroshi.io",
"port": 443,
"tls": true,
"weight": 1,
"predicate": {
"type": "AlwaysMatch"
},
"protocol": "HTTP/1.1",
"ip_address": null,
"tls_config": {
"certs": [],
"trusted_certs": [],
"enabled": false,
"loose": false,
"trust_all": false
}
}
],
"root": "/",
"rewrite": false,
"load_balancing": {
"type": "RoundRobin"
},
"client": {
"retries": 1,
"max_errors": 20,
"retry_initial_delay": 50,
"backoff_factor": 2,
"call_timeout": 30000,
"call_and_stream_timeout": 120000,
"connection_timeout": 10000,
"idle_timeout": 60000,
"global_timeout": 30000,
"sample_interval": 2000,
"proxy": {},
"custom_timeouts": [],
"cache_connection_settings": {
"enabled": false,
"queue_size": 2048
}
},
"health_check": {
"enabled": false,
"url": "",
"timeout": 5000,
"healthyStatuses": [],
"unhealthyStatuses": []
}
},
"backend_ref": null,
"plugins": [
{
"enabled": true,
"debug": false,
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"include": [],
"exclude": [],
"config": {},
"bound_listeners": [],
"nodeId": "cp:otoroshi.next.plugins.OverrideHost",
"plugin_index": {
"transform_request": 0
}
},
{
"plugin_index": {},
"nodeId": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpSseEndpoint-0",
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpSseEndpoint",
"enabled": true,
"debug": false,
"include": [],
"exclude": [],
"bound_listeners": [],
"config": {
"name": "mcp-sse",
"version": "1.0.0",
"refs": [
"tool-function_0511ff44-0ce5-487d-aa1c-d1980ac9a4b8"
],
"mcp_refs": []
}
}
],
"kind": "proxy.otoroshi.io/Route"
}
MCP WebSocket Plugin


Configuration
{
"_loc": {
"tenant": "default",
"teams": [
"default"
]
},
"id": "route_62c427cac-43c9-4d86-bab4-56cb0b61040b",
"name": "mcp-websocket-exposition",
"description": "mcp-websocket-exposition",
"tags": [],
"metadata": {},
"enabled": true,
"debug_flow": false,
"export_reporting": false,
"capture": false,
"groups": [
"default"
],
"bound_listeners": [],
"frontend": {
"domains": [
"mcp-websocket-exposition.oto.tools"
],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": []
},
"backend": {
"targets": [
{
"id": "target_1",
"hostname": "request.otoroshi.io",
"port": 443,
"tls": true,
"weight": 1,
"predicate": {
"type": "AlwaysMatch"
},
"protocol": "HTTP/1.1",
"ip_address": null,
"tls_config": {
"certs": [],
"trusted_certs": [],
"enabled": false,
"loose": false,
"trust_all": false
}
}
],
"root": "/",
"rewrite": false,
"load_balancing": {
"type": "RoundRobin"
},
"client": {
"retries": 1,
"max_errors": 20,
"retry_initial_delay": 50,
"backoff_factor": 2,
"call_timeout": 30000,
"call_and_stream_timeout": 120000,
"connection_timeout": 10000,
"idle_timeout": 60000,
"global_timeout": 30000,
"sample_interval": 2000,
"proxy": {},
"custom_timeouts": [],
"cache_connection_settings": {
"enabled": false,
"queue_size": 2048
}
},
"health_check": {
"enabled": false,
"url": "",
"timeout": 5000,
"healthyStatuses": [],
"unhealthyStatuses": []
}
},
"backend_ref": null,
"plugins": [
{
"enabled": true,
"debug": false,
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"include": [],
"exclude": [],
"config": {},
"bound_listeners": [],
"nodeId": "cp:otoroshi.next.plugins.OverrideHost",
"plugin_index": {
"transform_request": 0
}
},
{
"plugin_index": {},
"nodeId": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpWebsocketEndpoint-0",
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.McpWebsocketEndpoint",
"enabled": true,
"debug": false,
"include": [],
"exclude": [],
"bound_listeners": [],
"config": {
"name": "mcp-server",
"version": "1.0.0",
"refs": [
"tool-function_0511ff44-0ce5-487d-aa1c-d1980ac9a4b8"
],
"mcp_refs": []
}
}
],
"kind": "proxy.otoroshi.io/Route"
}