Transport & endpoints
The Cortex MCP server speaks Streamable HTTP (the post-2025-03-26 standard) over a single endpoint, with optional SSE for server-initiated messages during active sessions. Push dispatch and callbacks are out-of-band HTTPS webhooks (not MCP — the spec deprecated server-initiated push). No stdio — this is a remote service.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /mcp | Send client-to-server JSON-RPC messages. The body is one JSON-RPC request (or batch). |
| GET | /mcp | Open an SSE stream for server-initiated notifications during an active session (per the 2026-07-28 MCP spec). Server-initiated requests outside an active session are not supported by the protocol — push dispatch uses out-of-band webhooks (below). |
| DELETE | /mcp | Terminate a session (matched by mcp-session-id header). |
| POST | /v1/triggers/{trigger_id}/complete | Callback endpoint — your handler reports successful execution. See Dispatch · Callbacks. |
| POST | /v1/triggers/{trigger_id}/reverse | Callback endpoint — your handler reports a reversal. Demotes trust if user intent. |
| GETPOST | /health | Unauthenticated health probe. 200 when the process is up. |
Base URLs
| Environment | URL | Status |
|---|---|---|
| Local dev | http://localhost:3002/mcp | available |
| Production | https://mcp.cortex.jakeselby.com/mcp | July 20, 2026 |
Required headers
Authorization: Bearer <YOUR_TOKEN>
Content-Type: application/json
MCP-Protocol-Version: 2025-03-26Authorization— required on every request. See Authentication.Content-Type—application/jsonfor POSTs.MCP-Protocol-Version— informational; server speaks2025-03-26.mcp-session-id— echo the value the server returned in response toinitialize. Omit on the first request; the server assigns one.
Session lifecycle
The Streamable HTTP transport is stateful by default. A normal lifecycle:
- Client
POST /mcpwith aninitializeJSON-RPC request and nomcp-session-idheader. - Server responds
200with the initialize result and a newmcp-session-idheader (exposed viaAccess-Control-Expose-Headers). - Client sends every subsequent request (
tools/list,tools/call, notifications) with themcp-session-idechoed back. - Client optionally opens a long-lived
GET /mcpSSE stream with the samemcp-session-idfor server-initiated messages. - Client
DELETE /mcpwith the session id when finished (best-effort cleanup).
Stateless mode
Clients that don't need server-initiated notifications can omit the mcp-session-id header on every call. The server creates a fresh session per request, executes, and discards. This is the right mode for short-lived agents (a CI tool making one call) or workloads behind their own retry logic.
CORS
The server is configured permissively for local development:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, mcp-session-id, MCP-Protocol-Version
Access-Control-Expose-Headers: Content-Type, mcp-session-idProduction CORS will scope Allow-Origin per (user × client) once OAuth ships. Until then, treat the public URL as bearer-token-only and store tokens server-side.
Initialize result
The server advertises a minimal capability set: tools only. No resources, no prompts, no sampling, no logging level negotiation.
{
"protocolVersion": "2025-03-26",
"serverInfo": {
"name": "cortex-mcp-server",
"version": "0.1.0"
},
"capabilities": {
"tools": {}
}
}Server-initiated messages (SSE)
Server-initiated MCP messages are restricted by the protocol. Per the MCP 2026-07-28 release candidate (SEP-2260, SEP-2322), servers may only send messages during the processing of a client-initiated request; long-lived server-pushed work is out-of-spec. Cortex stays inside the spec:
notifications/tools/list_changed— standard MCP notification fired when the tool surface re-registers (rare; typically only on server restart with a different version).notifications/decisions/created— fired during an active session when a newpending_approvaldecision lands in your queue, so a client pollingaction.pendingcan wake immediately.
Outbound webhooks (server → your handler)
When the substrate decides an action should happen, Cortex HMAC-SHA256 signs a JSON envelope and POSTs it to the customer-registered handler URL. The full transport-level contract:
| Property | Value |
|---|---|
| Method | POST |
| URL | The url you registered via handler.register (must be HTTPS, must respond ≤30s). |
| Body | JSON TriggerEnvelope — see Envelope & headers. |
| Signing | X-Cortex-Signature: sha256=hex(hmac_sha256(secret, ts + "." + body)) with the handler's webhook_secret. 5-minute replay window. See Dispatch. |
| Idempotency | X-Cortex-Idempotency-Key — dedupe on this header. Repeated dispatches share the same key. |
| Retry policy | Exponential backoff (1s, 5s, 30s, 2m, 10m, 1h, 6h, 24h). Up to 8 attempts before DLQ. |
| Success criteria | 2xx response within 30 seconds, OR an explicit trigger.complete callback (async confirmation). |
| Dead-letter | Queryable via trigger.history; replayable via trigger.replay. |
Out-of-band webhooks are the industry standard for this pattern: Stripe Radar, Twilio Engage, Anthropic Managed Agent webhooks, Armalo agent webhooks, OpenAI Standard Webhooks all use the same shape. The MCP spec deprecation of in-protocol server push (SEP-2260) forecloses any MCP-native alternative; this is fine because the webhook pattern is better-understood operationally.
Callback endpoints (your handler → server)
Two REST endpoints on the Cortex MCP host. Both authenticate via your principal bearer token (the same token you use for inbound MCP calls). Full schema in Dispatch · Callbacks.
POST https://mcp.cortex.jakeselby.com/v1/triggers/{trigger_id}/complete
POST https://mcp.cortex.jakeselby.com/v1/triggers/{trigger_id}/reverse
Authorization: Bearer <YOUR_PRINCIPAL_TOKEN>
Content-Type: application/json
Idempotency-Key: <unique-key-per-callback>