Skip to main content

What this is

The other side of MCP. Instead of an external client calling Halo, Halo calls an external MCP server and treats its tools the same way it treats a native integration’s actions. In the dashboard these are called Connectors. Once connected, the discovered tools show up under AI Agents > [Agent] > Actions as enable-able toggles. Use it for:
  • An internal company API exposed as an MCP server (your billing system, your provisioning service)
  • A vendor’s MCP server (anything from the public MCP registry)
  • A small wrapper over a domain-specific data source you don’t want to ingest into Halo’s knowledge base
Connectors are available to every org by default. Your Halo admin can disable them per-workspace with the mcp_external_servers feature flag, in which case the connect endpoints return 403 and the dashboard surface is hidden.

Connecting a server from the dashboard

Go to Integrations > Connectors (also available under Settings > Integrations) and click Add connector: Halo connects and discovers the server’s tools immediately. If discovery fails (bad URL, bad credentials, unreachable server), the connector is still saved with the error shown on its card so you can fix and Refresh without re-entering everything. Each connector card shows the server’s status, its discovered tools (with destructive operations flagged), and actions to re-run discovery or disconnect. Connectors display the server’s own branding when it declares an icon, falling back to the server’s favicon, then a generic mark. The integrations:manage role is required for any mutating call (connect, disconnect, refresh). Read-only members with integrations:view can list connected servers.

Connect via API

Halo runs initialize + tools/list synchronously on connect, so the response includes the discovered tool count (or a clear error message) in the same call:
A failed discovery leaves the row with status: "error" and last_error populated, so you can fix the URL or credentials and retry without re-entering everything.

List, refresh, disconnect

Protocol compatibility

Halo speaks the MCP streamable HTTP transport and works with both stateless and stateful servers:

Server icons

Servers that declare icons in their initialize response (serverInfo.icons, SEP-973) get their own branding on the connector card and in the agent Actions tab. Because icons are input from an external server, Halo validates hard before persisting anything:
  • https icon URLs must be same-site with the MCP server’s own host and pass the same SSRF checks as the server URL itself.
  • Inline icons must be base64 raster data URIs (PNG, JPEG, WebP, or GIF). SVG is rejected since it can embed script.
  • Icons are re-derived on every discovery run, so a server that changes or drops its branding never leaves a stale icon behind.
If no declared icon passes validation, the card falls back to the server origin’s favicon, then a generic MCP mark.

Security

External MCP servers run inside Halo’s request path, so the connect flow is hardened: Discovery is also rerun on a schedule (an Inngest cron) so a tool added or removed on the upstream server eventually shows up in Halo without manual intervention. You can force a refresh from the server’s row by clicking Refresh discovery.

How discovered tools surface

Each connected server contributes a synthetic integration to the registry. The integration id is mcp_<slug> and each tool’s action id is mcp.<slug>.<tool_name>. Example. You connect a server with slug: internal_billing that exposes get_invoice and void_invoice. Halo creates: Enable them on the agent like any other action. The agent will call them during conversations whenever the tool descriptions match the user’s intent.

Tool-name rules

Halo filters discovered tools to enforce two rules: Bad names are dropped silently with a warn log; the rest of the server’s tools are kept. So a single broken tool doesn’t take down the whole integration.

Customer binding

Static actions know who the customer is via for_customer_email (passed by the AI SDK). External MCP tools don’t get that override. Instead, the customer binding flows through the MCP session’s _meta.bound_end_user_id envelope when Halo calls the upstream server, so:
  • An external MCP server that wants to scope its tools to “the user this conversation is about” should read _meta.bound_end_user_id from each tools/call.
  • An external MCP server that doesn’t care (e.g. a generic search API) can ignore _meta.

Disconnecting

DELETE /api/integrations/mcp/servers/{id} soft-deletes the row, wipes the encrypted credentials, and removes every discovered tool from the registry. The row itself is kept for audit-log integrity so historical action_executions rows still resolve to a real server entity. Reconnecting always re-takes credentials from you, so a wiped row can’t be revived without re-entering them.

Limits

Per-org per-action rate limits apply to MCP tools the same way they apply to native integration actions, so a runaway agent can’t spam an upstream server.