MCP Server Protocol
The MCP (Model Context Protocol) wire format used by Octopus is a simple HTTP/JSON contract. This page documents every request and response shape your server must implement.
Protocol Overview
Octopus communicates with an external MCP server over HTTPS using two endpoints. The server must respond with Content-Type: application/json on all routes. HTTP 200 indicates success; 4xx/5xx responses cause the agent to receive a structured error result.
| Endpoint | Called When | Purpose |
|---|---|---|
GET /tools | Agent startup / config refresh | Discover all available tools and their schemas |
POST /tool/{name}/call | Agent decides to use a tool | Execute the named tool with the supplied arguments |
GET /health | Startup probe / monitoring | Confirm the server is running (recommended) |
GET /tools — Tool Discovery
Octopus calls GET /tools once when the agent is initialized and again on each configuration refresh. The response is a JSON array of tool descriptor objects.
Request
GET /tools HTTP/1.1
Host: my-mcp-server.internal
Authorization: Bearer eyJhbGci...
Accept: application/json
Response — 200 OK
[
{
"name": "zendesk_create_ticket",
"description": "Create a new Zendesk support ticket. Returns the ticket ID and URL.",
"inputSchema": {
"type": "object",
"properties": {
"subject": {
"type": "string",
"description": "The ticket subject line"
},
"description": {
"type": "string",
"description": "Full description of the issue"
},
"priority": {
"type": "string",
"enum": ["low", "normal", "high", "urgent"],
"description": "Ticket priority level"
}
},
"required": ["subject", "description"]
},
"outputSchema": {
"type": "object",
"properties": {
"ticket_id": { "type": "integer" },
"ticket_url": { "type": "string", "format": "uri" },
"status": { "type": "string" }
}
}
},
{
"name": "zendesk_search_tickets",
"description": "Search Zendesk tickets using full-text or field-based query.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string",
"description": "Zendesk search query string" },
"status": { "type": "string",
"enum": ["open","pending","solved","closed"],
"description": "Optional status filter" }
},
"required": ["query"]
}
}
]
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Snake-case tool identifier, unique within the server |
description | string | Yes | LLM-readable description of what the tool does and returns |
inputSchema | JSON Schema object | Yes | JSON Schema (draft-07) describing the tool's input parameters |
outputSchema | JSON Schema object | No | Optional JSON Schema describing the tool's output shape |
POST /tool/{name}/call — Tool Execution
When the LLM decides to call a tool, Octopus sends a POST to /tool/{name}/call with the argument object the LLM produced. The argument object must conform to the tool's inputSchema.
Request
POST /tool/zendesk_create_ticket/call HTTP/1.1
Host: my-mcp-server.internal
Authorization: Bearer eyJhbGci...
Content-Type: application/json
X-Octopus-Tenant-Id: tenant-abc123
X-Octopus-Correlation-Id: episode-xyz789
{
"subject": "Cannot access the billing portal",
"description": "Since the last update, users report a 403 error on /billing.",
"priority": "high"
}
Request Headers
| Header | Description |
|---|---|
Authorization: Bearer {token} | Token resolved via ICredentialResolver at agent startup |
X-Octopus-Tenant-Id | The calling tenant's ID — use for per-tenant scoping in your server |
X-Octopus-Correlation-Id | Episode ID for end-to-end tracing across logs |
Content-Type: application/json | Always JSON; your server must accept this |
Success Response — 200 OK
{
"ticket_id": 12345,
"ticket_url": "https://mycompany.zendesk.com/tickets/12345",
"status": "open"
}
Error Response — 4xx / 5xx
Return a structured error body. Octopus relays the message field to the agent as the tool result so the LLM can explain the failure to the user.
// HTTP 422
{
"error": "validation_error",
"message": "The 'priority' field must be one of: low, normal, high, urgent.",
"field": "priority"
}
// HTTP 503
{
"error": "upstream_unavailable",
"message": "Zendesk API is temporarily unavailable. Retry in 30 seconds.",
"retry_after": 30
}
GET /health — Health Check
Implement a GET /health endpoint for Kubernetes liveness probes and Octopus startup health checks. Return HTTP 200 with a simple body.
GET /health HTTP/1.1
Host: my-mcp-server.internal
HTTP/1.1 200 OK
Content-Type: application/json
{ "status": "ok", "version": "1.2.0" }
Protocol Constraints
| Constraint | Value | Notes |
|---|---|---|
| Transport | HTTPS only (TLS 1.2+) | HTTP is rejected in production mode |
| Response Content-Type | application/json | Required on all routes |
| Tool call timeout | 30 seconds (default) | Configurable per server registration |
| Max response body | 4 MB | Larger responses are truncated by Octopus |
| Max tools per server | 100 | Register multiple servers if you need more |
| Tool name characters | Lowercase a-z, digits, underscores | No hyphens, spaces, or dots |