Recipes

MCP-executor recipe (V1.1 preview)

ADR-0019's Tier 2 architecture: when you already host an MCP server, Cortex acts as an MCP client and invokes one of your server's tools instead of POSTing a webhook. Same envelope; different transport.

Why MCP-executor

  • You already expose internal capabilities as an MCP server — Cortex just adds itself as another client.
  • No additional HTTP endpoint to operate, harden, or expose to the public internet.
  • Symmetric protocol: Cortex pulls from your MCP server when its substrate needs state, and pushes via the same protocol when it decides.

Architecture

Instead of POSTing a JSON envelope to an HTTPS URL, Cortex acts as an MCP client and invokes a tool you advertise on your own MCP server — conventionally cortex.dispatch. The tool's arguments are the same TriggerEnvelope shape documented at Envelope & headers. The tool's return value is the equivalent of trigger.complete:

typescriptserver.ts — your MCP server exposes cortex.dispatch
import { McpServer } from "@modelcontextprotocol/sdk/server/index.js";
import { z } from "zod";

const server = new McpServer({ name: "your-mcp-server", version: "1.0.0" });

// The shape Cortex will dispatch into your server.
const triggerEnvelopeSchema = z.object({
  trigger_id:   z.string(),
  decision_id:  z.string(),
  action_class: z.string(),
  mode:         z.enum(["act", "notify_after", "ask", "test"]),
  counterparty: z.object({ id: z.string(), display_name: z.string() }).optional(),
  payload:      z.record(z.unknown()),
  reasoning:    z.string(),
  reversal:     z.object({ path: z.string(), window_sec: z.number().optional(), callback_url: z.string() }),
  expires_at:   z.string(),
  schema_version: z.string(),
});

server.tool(
  "cortex.dispatch",
  "Receive a dispatched trigger from the Cortex cognitive substrate.",
  triggerEnvelopeSchema,
  async (input) => {
    // 1. Execute through your channel
    const externalRef = await runYourChannel(input);

    // 2. Return the equivalent of trigger.complete inline.
    //    Cortex records the outcome from the tool result; no separate HTTP callback needed.
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify({
            outcome:      input.mode === "ask" ? "approved" : "executed",
            external_ref: externalRef,
            executed_at:  new Date().toISOString(),
          }),
        },
      ],
    };
  },
);

Registering with Cortex

Once V1.1 lights up, register your MCP server URL instead of an HTTPS handler URL:

json
{
  "name": "handler.register",
  "arguments": {
    "url": "https://your-mcp-server.example.com/mcp",
    "action_classes": ["communicate", "schedule"],
    "tier": "mcp-executor"
  }
}

Trade-offs vs Tier 1 webhook

DimensionTier 1 (webhook)Tier 2 (MCP-executor)
TransportHTTPS POST + HMACMCP tools/call
Auth modelPer-handler webhook_secret (HMAC)Bearer token / OAuth (whatever your MCP server uses)
Callback shapeSeparate POST /v1/triggers/{id}/complete after async executionInline — the tool's return value is the callback
Retry on failureCortex retries with exponential backoffCortex retries the MCP call
IdempotencyX-Cortex-Idempotency-Key headertrigger_id in tool arguments
AvailableJuly 20, 2026V1.1