Skip to main content

The endpoint

Point any MCP-aware client at:
That URL is all you need. Authentication, discovery, and consent are handled by the standard OAuth 2.1 flow that every modern MCP client implements out of the box, so the first time a client hits the endpoint Halo walks it through registration and consent automatically.
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_....
Access tokens last 1 hour. Refresh tokens are long-lived but rotate on every use, so a stolen refresh token only works until the legitimate client refreshes next (the rotation revokes the entire derived chain).

Installation by client

Claude (web, desktop, mobile)

In Claude open Customize > Connectors, choose Add custom connector and paste https://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

Run /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 URL https://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:
Restart Claude Desktop. The first time you reference a Halo tool in a chat, Claude will pop a browser window for the OAuth flow.

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):
Reload the window. The OAuth flow runs in your default browser.

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 calls tools/list to enumerate available tools. The set you see depends on three things:
  1. Your org’s connected integrations (HubSpot, Slack, Stripe, etc. in Integrations)
  2. The scopes you approved at consent time
  3. Whether the token is bound to a specific agent (defaults to your org’s Ask AI agent)
A token only sees what its scopes unlock: without 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:
  1. Sign out of (or disconnect) the Halo MCP in your client, then reconnect it. This re-runs the OAuth flow.
  2. On the Halo consent page, tick the write permissions you want to grant (inbox:write, automations:write, data:write, and/or actions:destructive). They start unchecked.
  3. Approve. The new token carries the write scopes and the write tools appear in tools/list.
The consent page always offers the full current scope menu, even for clients that registered before a scope existed, so a plain re-auth is enough — no need to delete and re-add the server entry.

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:
You can also pin by email with _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:
The endpoint follows RFC 7009: pass either an access or a refresh token under 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).