The endpoint
Point any MCP-aware client at:The MCP server is enabled by default for every org. If you get a 403 from the URL it means MCP has been explicitly disabled on your workspace. Ask your Halo admin to set the
mcp_server feature flag back to true for your team.What happens on first connect
The first time a client points at/api/mcp, this is the flow it walks (you only see steps 3 and 4 as a user):
1
Discovery
The client POSTs to
/api/mcp, gets a 401 with WWW-Authenticate: Bearer resource_metadata="...", and follows the link to discover Halo’s authorization server.2
Dynamic registration
The client registers itself via RFC 7591 at
/api/mcp/oauth/register and receives a fresh client_id. No manual app setup is required on Halo’s side.3
Sign in to Halo
The client opens
/api/mcp/oauth/authorize in your browser. If you’re not already signed in, you bounce through /signin and back.4
Approve the request
Halo shows the consent page (
/mcp/authorize) listing the client’s name, the org you’re authorising, and the scopes it requested. You can deselect any scope before approving.5
Token exchange
The client receives an authorization code, swaps it at
/api/mcp/oauth/token (PKCE-verified), and stores the access_token + refresh_token pair. Subsequent JSON-RPC calls carry Authorization: Bearer halo_at_....Installation by client
Claude (web, desktop, mobile)
In Claude open Customize > Connectors, choose Add custom connector and pastehttps://app.haloagents.ai/api/mcp; Claude opens the Halo consent screen. Once Halo is published in the Claude Connectors Directory you can also search for Halo there and choose Connect. Full walkthrough: Use Halo in Claude.
Claude Code
/mcp inside Claude Code to sign in and check the connection. Claude Code identifies itself with a Client ID Metadata Document and a loopback redirect, both of which Halo accepts without any registration step.
ChatGPT
Halo works as a plugin for ChatGPT and Codex. In Developer mode create a connector with the URLhttps://app.haloagents.ai/api/mcp/chatgpt; once Halo is published in ChatGPT’s directory you can also search for Halo there. Full walkthrough: Use Halo in ChatGPT.
Claude Desktop (config file)
Open~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on your platform and add Halo under mcpServers:
Cursor
Open Cursor Settings > MCP > Add new MCP server. Configure:
Save. Cursor will prompt for OAuth on first use.
VS Code (Continue / GitHub Copilot Chat)
Add Halo under the MCP servers section of your AI extension’s settings (the exact key varies by extension):Custom clients
Any client that implements the MCP HTTP transport and OAuth 2.1 with PKCE can connect to Halo. Point at/api/mcp and discovery + dynamic client registration handle the rest. See Protocol Reference for the full endpoint list.
What the client sees
After the OAuth dance, the client callstools/list to enumerate available tools. The set you see depends on three things:
- Your org’s connected integrations (HubSpot, Slack, Stripe, etc. in Integrations)
- The scopes you approved at consent time
- Whether the token is bound to a specific agent (defaults to your org’s Ask AI agent)
docs:read there is no search_docs / read_doc; without inbox:write there are no ticket-reply or outreach tools; without automations:write there are no campaign tools; without cs:read / workflows:read there are no CS Suite or Workflow tools. The protection is enforced at both tools/list (the tool is hidden) and tools/call (the call is rejected with an audited refusal), so dropping a scope is safe.
On the consent page, permissions are grouped with all Read ones first and all Write ones (inbox:write, automations:write, data:write, cs:write, workflows:write, actions:destructive) below, and each row carries a Read / Write badge. Read permissions are checked by default; write permissions (including actions:* and actions:destructive) start unchecked, so tick only the ones the client needs. The page also shows where the client will send you back after you authorize, and flags any client that registered itself (rather than being provisioned by Halo) as not verified by Halo: its name and logo are self-declared, so check the redirect address before approving. Even when a write scope is granted, each write re-checks that you (the person who authorized the token) hold the matching dashboard permission, so the client can never do more than you can. See Scopes & Permissions for the full breakdown.
Upgrading an existing connection to write access
Scopes are frozen into the token at consent time, and token refresh can only narrow them, never widen them. So a connection made before write access shipped will keep working read-only but will not gain the write tools on its own. To add them:- Sign out of (or disconnect) the Halo MCP in your client, then reconnect it. This re-runs the OAuth flow.
- On the Halo consent page, tick the write permissions you want to grant (
inbox:write,automations:write,data:write, and/oractions:destructive). They start unchecked. - Approve. The new token carries the write scopes and the write tools appear in
tools/list.
Pinning a customer to a session
When an operator uses an MCP client to research or act on behalf of a specific customer, they can pin the customer for the conversation. Halo reads the binding off the JSON-RPC_meta envelope:
_meta.bound_email. Halo re-resolves the binding on every call against your org’s customer table, so a stale or forged id can never bind to a foreign tenant.
How the pin reaches the wire depends on the client. Most clients let the user select a customer in the UI and forward the selection automatically; custom clients should set _meta.bound_end_user_id themselves.
Revoking access
Today there’s no dashboard view of connected MCP clients. Revoke by token instead:token=, idempotent, always returns 200. Confidential clients also pass client_secret (or use HTTP Basic auth); public clients only need client_id.
Revoking a refresh token revokes the entire derived chain (every access and refresh token issued from the same authorization code), which is the right move if you suspect a compromise. Revoking a single access token just kills that token; the next refresh issues a new one.
Most MCP clients have a “Sign out” or “Disconnect” action that calls this endpoint for you. If you’re an admin and don’t have the token in hand, contact support and we’ll revoke the chain server-side.
Rate limits
Per-token caps sit on top of the IP-based dashboard limit:
Hitting a cap returns 429 with
Retry-After. Per-action and per-org caps still apply on top (a tool whose underlying integration has a 60/min limit will still hit that limit even if the MCP cap allows more).