The endpoint
Every Exponential instance exposes a streamable-HTTP MCP server at:
https://app.exponential.at/api/mcpSelf-hosting? It's the same path on your instance: https://your-instance/api/mcp. There is no separate /sse variant; modern clients speak streamable HTTP directly.
Authentication
OAuth for interactive clients
Point a client at the endpoint with no credentials and it registers itself (dynamic client registration) and sends you to your browser to approve. The consent screen is a scope picker: grant the client everything, specific teams, or specific boards. The token it receives is confined to exactly that grant. A client with no grant gets nothing. Re-running consent updates the grant, so you can widen or narrow access later.
API keys for headless use
Scripts and CI use a personal API key instead. Generate one under Settings → Security in the web app and send it as a bearer token:
Authorization: Bearer expu_...API keys act as you, with your full membership. Guard them accordingly.
Client setup
Claude (Desktop & claude.ai)
Settings → Connectors → Add custom connector, paste the endpoint URL, and hit Connect. Your browser opens for OAuth and the scope picker. Works the same in the Claude desktop app and on claude.ai.
mcp-remote (see "Other clients" below).ChatGPT
On chatgpt.com, enable Settings → Apps & Connectors → Advanced settings → Developer mode (Plus/Pro/Business; the menu naming varies while the feature is in beta). Then Create connector, paste the MCP URL, and choose OAuth as the authentication. Write-capable tools ask for confirmation per call.
Claude Code
claude mcp add --transport http --scope user exponential https://app.exponential.at/api/mcpThen run /mcp in a session to sign in via OAuth. For headless use, attach an API key instead:
claude mcp add --transport http --scope user exponential https://app.exponential.at/api/mcp \
--header "Authorization: Bearer expu_..."A configured header disables the OAuth fallback. In .mcp.json form, the server entry needs "type": "http".
Codex CLI
codex mcp add exponential --url https://app.exponential.at/api/mcp
codex mcp login exponentialOr configure it in config.toml, with an API key via an environment variable:
[mcp_servers.exponential]
url = "https://app.exponential.at/api/mcp"
bearer_token_env_var = "EXPONENTIAL_API_KEY"Cursor
Add the server to ~/.cursor/mcp.json (or a project's .cursor/mcp.json):
{
"mcpServers": {
"exponential": {
"url": "https://app.exponential.at/api/mcp"
}
}
}Click Connect next to the server in Cursor's MCP list to run the OAuth flow. For API keys, add a headers object with the Authorization header instead.
OpenClaw
Install the Exponential plugin from ClawHub (the MCP server plus a skill) and give the gateway an API key, or add the server by hand and sign in with OAuth:
openclaw plugins install clawhub:@exponential/openclaw-plugin
export EXPONENTIAL_API_KEY=expu_...
# or, with OAuth
openclaw mcp add exponential --url https://app.exponential.at/api/mcp --transport streamable-http --auth oauth
openclaw mcp login exponentialTurn on OpenClaw's MCP Apps bridge (openclaw config set mcp.apps.enabled true --strict-json) and the issue list and a run's report render as Exponential's own views in the dashboard; the issue list also opens straight from the app catalog.
Interactive views (MCP Apps)
Clients that render MCP Apps show five tools as Exponential views instead of JSON: exponential_issues_show (the issue list, grouped by status; a row opens the issue), exponential_sessions_list (your runs), exponential_sessions_get (a coding run's report), exponential_notifications_list (your inbox) and exponential_devices_list (your machines and their agent logins). Self-hosted instances serve the same views; nothing to configure on the server.
Other clients
Most MCP clients accept the generic mcpServers JSON shown above. VS Code (Copilot) uses a top-level servers key with "type": "http" per server. Clients that only speak stdio can bridge:
npx mcp-remote https://app.exponential.at/api/mcpTool reference
What a connected client can do, grouped by area. Every call is confined to the OAuth grant's scope (or the API key's membership). Every list tool paginates (50 by default, 200 at most, 1000 for issues_list), and issue parameters take an identifier ("EXP-42") wherever they take a UUID.
exponential_sessions_end, exponential_sessions_ask_parent, exponential_sessions_results and exponential_sessions_show only inside an agent run the launcher started; and exponential_report_bug only on the cloud. Ask the server's own tools/list for the exact set your client sees.Teams
exponential_teams_list: List the teams you belong to.exponential_teams_get: Get a single team by id.exponential_teams_create: Create a new team you own.exponential_teams_update: Rename a team or change its icon (owner only).
Boards
exponential_boards_list: List boards in one team or across all your teams.exponential_boards_get: Get a single board.exponential_boards_create: Create a board (optionally repo-backed).exponential_boards_update: Update name, color, icon, or the board's default branch.exponential_boards_delete: Move a board to the 48-hour trash (owner only).exponential_boards_set_repository: Point a board at a different registered repository.
Issues
exponential_issues_list: List issues, open work only unless includeClosed (or a status filter) says otherwise: boards, statusId / statusCategory, priority, assignee, labels (any, all, or unlabeled), source (user or widget), comment activity, created/updated ranges, title search, each with an exclude twin, plus sort (a "-" prefix descends). Up to 1000 per page.exponential_issues_get: Get one issue with labels, relations and recent comments, by UUID or identifier ("EXP-42").exponential_issues_show: The issue list as an interactive view in clients that render MCP Apps (OpenClaw, Claude, ChatGPT): status groups, priorities and PR numbers; a row opens the issue. Other clients get the same rows as exponential_issues_list.exponential_issues_create: Create an issue. Pass statusId for a custom status.exponential_issues_update: Update an issue's fields. Pass only what changes.exponential_issues_delete: Permanently delete an issue and everything attached to it.exponential_issues_update_status: Set status during a coding run (PR events move it to the team's configured statuses).exponential_pr_open: Open + link the pull request server-side: issueId for one, issueIds + head for a batch, or repositoryId + head for a chore PR that links nothing. A follow-up run builds on its parent run's branch with base; such a tree merges root first, and the root's merge retargets its children.exponential_pr_merge: Squash-merge through the GitHub App (no gh, no token): issueId, issueIds, or repositoryId + prNumber. endSessions overrides the team's end-sessions-on-merge setting for this call.exponential_pr_retarget: Repoint an open PR's base branch, the fix for a PR whose base branch is gone.exponential_issues_pr_files: List the linked PR's changed files with patches and add/delete counts.
Relations
exponential_issue_relations_add: Link two issues: blocks, parent, duplicate or related, stored one way (issueId blocks / is the parent of / duplicates relatedIssueId; related is symmetric). Pass inverse for blocked by, sub-issue of or duplicated by.exponential_issue_relations_remove: Unlink two issues, named in the direction the link is stored; exponential_issues_get lists them.
Statuses
exponential_statuses_list: List a team's issue statuses with id, name, category and color — the ids you pass as statusId.exponential_statuses_create: Create a custom status in a category (never duplicate; started allows at most four).exponential_statuses_update: Rename or recolor a custom status. Builtins are locked.exponential_statuses_delete: Delete a custom status; issues still on it need a reassignToId replacement.
Labels & issue labels
exponential_labels_list: List a team's labels.exponential_labels_get: Get a label by id.exponential_labels_create: Create a label.exponential_labels_update: Rename or recolor a label.exponential_labels_delete: Delete a label.exponential_issue_labels_add: Attach a label to an issue.exponential_issue_labels_remove: Detach a label from an issue.
Comments
exponential_comments_list: List an issue's comments, oldest first, each with its parentId when it is a reply.exponential_comments_create: Post a comment as the connected user; it shows as "via MCP". Pass parentId to reply under a comment (threads are one level deep), or audience: "reporter" on a widget-filed issue whose reporter left an email to send it to them as well (top-level only); the result says whether that mail went out.exponential_comments_update: Edit your own comment.exponential_comments_delete: Delete a comment.
Subscriptions & notifications
exponential_issues_subscribe: Subscribe to an issue's notifications.exponential_issues_unsubscribe: Unsubscribe (and suppress auto-resubscribe).exponential_notifications_list: List your notifications, newest first.exponential_notifications_mark_read: Mark one notification read, or all of them.exponential_notifications_send: Send a notification (inbox row + push) to members of a team, or to yourself; recipients are member user ids or emails. A member who turned off messages from teammates' agents is reported as declined; your own user always receives.
Members & invites
exponential_members_list: List a team's members (useful to resolve an assigneeId).exponential_invites_create: Create an invite link (owner only).exponential_invites_list: List pending invites.exponential_invites_revoke: Revoke a pending invite (owner only).
Repositories & branch diff
exponential_repositories_list: List a team's registered repositories and the boards they back.exponential_repositories_add: Register a GitHub repository ("owner/name") with a team.exponential_repositories_branch_diff: Diff an issue's branch against the repo's default branch.
Actions
exponential_actions_list: List a team's actions, the reusable AI prompts members run on their own desktop, each with its triggers.exponential_actions_create: Create an action with markdown instructions and an optional repository (owner only).exponential_actions_update: Update an action (owner only). The triggers field replaces the whole array: send every trigger you keep with its id, a new one without an id.exponential_actions_delete: Delete an action (owner only).
Coding sessions & devices
exponential_devices_list: List your machines (desktop app or CLI daemon) plus servers shared with the team, with their online state and the agents each can run.exponential_devices_account_login: Sign an agent account in on one of your own machines. The machine runs the agent's own login; only the sign-in link and the code you type travel, the credential never leaves it.exponential_sessions_start: Start a run on an ONLINE device: an issue, a batch of issues, an action, or a resume. Offline devices are refused — starts are live, never queued.exponential_sessions_list: List coding sessions newest first, with status, subject, branch, device, any usage wall, and who ended an ended run.exponential_sessions_get: Get one session; poll it after a start to follow running → in review → ended, with any question the run parked for you. waitForIdle holds the call until the run's turn ends (120s at most).exponential_sessions_messages: Read what a session you own or host said: its transcript (your messages, its replies, tool calls and questions), its newest messages with a cursor for what comes next.exponential_sessions_message: Send text into a live session you own or host — it arrives as user input to that agent.exponential_sessions_results: Publish a screenshot of this run's work: it hands back a short-lived upload link and a curl line, filed under a topic with one label per picture, and shows up on the run's Results face everywhere.exponential_sessions_show: Show a screenshot while the run works: it appears in the run's transcript at the call, on every client, and is filed under the Results face (topic Progress by default). A local file gets a curl line; small images upload inline as base64.exponential_sessions_kill: Abort a live session you own or host. Never your own run.exponential_sessions_end: End this run with a close-out summary for whoever started it (not stored on the run). Unattended (trigger- or agent-started) runs call it last; a person-started run only when asked.exponential_sessions_ask_parent: Inside a run: ask whoever started it, or the person who owns it, a question and end your turn; its answer arrives as a user message. A starter that is not a run reads the parked question with sessions_get and answers with sessions_message.
Bug reports
exponential_report_bug: File a bug about Exponential itself with its developers. Never for the caller's own project. Cloud only.
Attachments
exponential_attachments_get: Fetch any attachment: metadata plus a short-lived signed download URL (images also come back inline).exponential_attachments_upload: Upload an image and get its embeddable markdown form back.exponential_attachments_delete: Delete an attachment; embeds in descriptions and comments are rewritten in the same transaction.
Recipes
File a bug with labels, from chat
"File a bug on the app board: it drops drag events on narrow viewports. Priority high, label it bug." The client chains exponential_boards_list → exponential_issues_create → exponential_labels_list → exponential_issue_labels_add, and answers with the new identifier.
Check a PR's files from chat
"What does EXP-42's PR actually change?" The client calls exponential_issues_pr_files, which returns the changed files with patches, so the model can summarize the diff, flag a risky change, or compare it against the issue's acceptance criteria.
One combined PR for several issues
An agent that fixed several issues on one pushed branch opens a single PR for all of them: exponential_pr_open with issueIds (the batch) and head (the pushed branch). Every listed issue links to the PR and moves to In Review; merging completes them all. This is exactly what a batch coding run does.
A pull request with no issue behind it
Some work never gets filed: a dependency bump, a typo sweep. Pass repositoryId + head to exponential_pr_open (and repositoryId + prNumber to exponential_pr_merge) and you get an ordinary pull request with nothing linked, moved, or notified.
Start a run on one of your machines, from chat
"Have my build box take EXP-42." The client calls exponential_devices_list to find an online machine that runs the agent you want, then exponential_sessions_start, and follows the run with exponential_sessions_get. Steer it mid-run with exponential_sessions_message and read its replies with exponential_sessions_messages. Details in CLI & daemon.
Your own MCP servers
Everything above is Exponential as an MCP server. This is the other direction: the MCP servers your coding runs connect to besides Exponential — your error tracker, your docs, your internal API.
They are a team registry under Settings → MCP servers. Every member sees the list; owners add and edit. A row is non-secret configuration only: a name, the transport (a remote URL or a local command), the auth kind, and the names of the headers or environment variables a machine has to supply.
exponential mcp set-secret <server> <NAME> on a daemon — and never travels through a command line.Each row carries a readiness chip per machine, so you can see at a glance which of your machines can actually reach the server. For an OAuth server, the chip on one of your own machines offers Sign in: that machine builds the authorize URL, you consent in the browser you are already in, and the machine finishes the sign-in itself. On a headless box, exponential mcp login <server> does the same locally, or --paste prints a URL you open anywhere and paste the redirect back.
Pick the servers a run gets in the Agent page composer and on the session page. Runs are strict about it: an agent started by Exponential connects to the servers Exponential wired in and nothing else, whatever the CLI has configured globally.