MCP.

Houston exposes your agents as tools over the Model Context Protocol. Connect Claude Code, or any MCP client, to one endpoint and let it list your agents and start, check, and cancel their missions.

The endpoint

POST /mcp

A single Streamable HTTP MCP endpoint. It is stateless: each POST carries one JSON-RPC request and gets one JSON response, with no SSE stream and no session. It authenticates with your hst_... API key as a bearer token.

Stateless by design

The server answers initialize, ping, tools/list, and tools/call. initialize works as usual, but no Mcp-Session-Id is issued or needed, so every call simply carries the Authorization header. Notifications get an empty 202, and GET or DELETE get 405.

The server implements protocol version 2025-06-18. initialize also accepts 2025-03-26 and 2024-11-05 and echoes the version you asked for; any other version is answered with 2025-06-18.

Connect a client

Point any MCP client at https://gateway.gethouston.ai/mcp with your key in the Authorization header. The tools act in your personal organization. To work with a team organization's agents, also send x-houston-org: <organization id>, using the Organization ID from Settings → API keys or an AI Employee's Settings → API access (see Organizations).

Claude Code

Add it from the CLI:

claude mcp add --transport http houston https://gateway.gethouston.ai/mcp \
  --header "Authorization: Bearer hst_9f2c1a7b4e8d0364f1a2b3c4d5e6f7089f2c1a7b4e8d0364f1a2b3c4d5e6f708"

Or add it to your project's .mcp.json (the same shape works for other MCP clients that use a JSON server config):

{
  "mcpServers": {
    "houston": {
      "type": "http",
      "url": "https://gateway.gethouston.ai/mcp",
      "headers": {
        "Authorization": "Bearer hst_9f2c1a7b4e8d0364f1a2b3c4d5e6f7089f2c1a7b4e8d0364f1a2b3c4d5e6f708"
      }
    }
  }
}
Do not commit your key

.mcp.json is often checked into a repo. Keep the raw key out of version control, for example by referencing an environment variable if your client supports it, and revoke any key that leaks from Settings → API keys.

Tools

The server exposes four tools. Their input schemas are standard JSON Schema, so MCP clients render and validate them automatically. A successful result comes back twice: as a JSON text block in content and as an object in structuredContent.

list_agents

Lists the agents in the organization the request acts in. No input.

{
  "name": "list_agents",
  "description": "List the Houston agents in your workspace. Returns each agent's slug (use it as the 'agent' argument to start_mission) and display name.",
  "inputSchema": {
    "type": "object",
    "properties": {},
    "additionalProperties": false
  }
}

Each item is { "agentSlug", "name" }. The structured result wraps the list in an object:

{
  "agents": [
    { "agentSlug": "3f9a1c07b2e84d65", "name": "Revenue Manager" }
  ]
}

start_mission

Starts a mission on an agent and returns the mission, with the same fields as the REST mission JSON. mode defaults to auto when omitted.

{
  "name": "start_mission",
  "description": "Start an agent working on a task. The mission runs asynchronously: this returns immediately with a mission id you poll using get_mission until its status is completed, failed, or canceled.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "agent": {
        "type": "string",
        "description": "The slug of the agent to run (from list_agents)."
      },
      "input": {
        "type": "string",
        "description": "The task or message to send the agent."
      },
      "mode": {
        "type": "string",
        "enum": ["execute", "plan", "auto"],
        "description": "How the agent should approach the task: 'execute' acts directly, 'plan' produces a plan first, 'auto' (default) lets the agent decide."
      }
    },
    "required": ["agent", "input"],
    "additionalProperties": false
  }
}

get_mission

Returns a mission's status and, once terminal, its result.

{
  "name": "get_mission",
  "description": "Fetch a mission by id to check its status and read its result. Poll this after start_mission until the status is a terminal state (completed, failed, canceled).",
  "inputSchema": {
    "type": "object",
    "properties": {
      "missionId": {
        "type": "string",
        "description": "The id returned by start_mission."
      }
    },
    "required": ["missionId"],
    "additionalProperties": false
  }
}

cancel_mission

Cancels a running mission and returns it in the canceled state. On a mission that already ended, the tool returns an error result instead.

{
  "name": "cancel_mission",
  "description": "Cancel a running mission by id. Returns the mission in its canceled state.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "missionId": {
        "type": "string",
        "description": "The id of the mission to cancel."
      }
    },
    "required": ["missionId"],
    "additionalProperties": false
  }
}

Tool errors

When a tool call fails, for example an unknown agent, a missing mission, or a busy agent, the result has "isError": true and a text block that explains it, so the model can read it and correct course. A few cases are JSON-RPC errors instead: an unknown tool or arguments that are not valid JSON (-32602), and a reached message limit on start_mission (-32029, with resetsAt in error.data).

In practice

Once connected, ask your MCP client to "list my Houston agents, then start a mission on the revenue manager." It calls list_agents, then start_mission, then get_mission to report the result.