Open app →
Documentation

The company-brain MCP

Connect Claude Code, Cursor, or any MCP client to operate your Elliptic workspace as first-class tools, with OAuth 2.1 consent, per-org or all-org tokens, per-domain scopes, and 144 tools across tasks, notes, meetings, calendar, comments, the org, the brain, and AI agents.

What the company-brain MCP is

The company-brain MCP is a first-party Model Context Protocol server built directly into the Elliptic API. It exposes your workspace as a set of callable tools, so an MCP client like Claude Code, Cursor, or Claude Desktop can read and write the same surfaces you use in the app: tasks and boards, projects, notes, meetings and transcripts, calendar, comments, notifications, teams, the org and its members, the activity feed, the brain, and your AI agents. This is the mechanism that makes Elliptic Jira for your agents. An agent connects as a member and operates the same surfaces you do, on the org's own model key.

The server is a stateless FastMCP app mounted in the API at /api/v1/mcp. Each tool runs through a single boundary that authenticates the caller, enforces the tool's required scope, resolves the org context, and owns the database transaction, committing on success and rolling back on error. Every call is scoped to one organization and acts as the connecting user, so a tool can do exactly what that person can do in the web app, no more. Whatever an agent does through the MCP lands in activity the same way a person's action would.

Endpoint
On the hosted instance the server lives at https://api.elliptic.sh/api/v1/mcp, a single streamable-HTTP MCP endpoint. Self-hosting follows the same path under your own API origin (for local development, http://localhost:8000/api/v1/mcp). Authentication is OAuth 2.1, so there is nothing to copy and paste. The client walks you through a browser consent the first time.

Authenticating

The MCP is protected by OAuth 2.1, so you never hand a client a raw API key. The first time a client connects it discovers the authorization server, registers itself, and opens a Elliptic consent screen in your browser. You pick a workspace and approve a set of permissions, and the client receives a token scoped to that org and those permissions. From then on the client refreshes silently.

  • Dynamic client registration (RFC 7591). Clients self-register at the registration endpoint as public PKCE clients. There is no manual app setup, and each registered client gets a generated client_id.
  • PKCE with S256. The authorization-code flow requires a code_challenge using the S256 method. Other methods and a missing challenge are rejected, which keeps the flow safe for public and native clients.
  • Canonical resource binding. A resource parameter (RFC 8707) on the authorize and token requests must equal the canonical MCP resource URI, so a code minted for this server cannot be replayed against another audience. Clients that omit resource still work: the server binds the request to the canonical URI from its own metadata.
  • Short-lived codes, rotating refresh. Authorization codes are single-use and expire after 60 seconds. Refresh tokens rotate on every use, and reusing a consumed refresh token revokes the whole token family.
  • Signed request envelope. The validated authorize parameters are signed into a request id that the consent page cannot tamper with. It is valid for 10 minutes.

When a client connects you land on the Elliptic authorization page. You choose a single workspace, or pick all your organizations, then approve the permissions the client asked for. The screen groups permissions by domain. Every domain's read scope is the baseline set: it shows as Always on and stays checked and locked, so the standard read surface is always granted. Write and elevated permissions are an explicit, deliberate opt-in. Approve to connect, or decline to cancel. Either way you are returned to the client.

Consent is the only place permissions are decided. The token the client receives carries exactly the scopes you ticked. A client that requested specific scopes caps the grant at its request; a client that requested none (most MCP clients) receives precisely your selection. Nothing the client does later can widen the grant without a fresh consent.

Root / Admin: one switch for trusted agents
At the top of the consent screen is a Root / Admin toggle. Turn it on and every permission is selected at once and locked so the individual rows cannot be unchecked, granting the agent the complete tool surface on your behalf. Use it when you want an agent to act as a full operator of your workspace. Leave it off and hand-pick scopes when you want to keep the agent narrow.

Personal access tokens (the no-OAuth path)

If you would rather not run the OAuth flow, the MCP also accepts a Elliptic personal access token directly. Send your cos_pat_ token as a Bearer header (or as an x-api-key header) and the call is authenticated as you. A PAT is treated like a logged-in session: it acts across every organization you belong to and carries the full scope set, so use it only with clients you trust. OAuth with hand-picked scopes is the safer default for third-party agents.

Single-org versus all-orgs tokens

Your token comes in one of two shapes, decided at consent time.

  • Pinned single-org token. You picked one workspace, so the token is bound to that org. Tools target it automatically, and if a call passes an org_id that does not match, it is rejected. This is the tightest setup: the agent can only ever touch the one workspace you chose.
  • Cross-org token (all organizations). You picked all your organizations, so the token carries no fixed org. Every org-scoped tool then accepts an optional org_id to choose which workspace the call lands in. If you omit it, the call falls back to your earliest-joined org, so always pass org_id when you mean a specific one.
Membership is re-checked on every call
A cross-org token does not bake in your memberships. On each call Elliptic resolves your live membership of the target org with the same join the single-org path uses. If you have been removed from an org, the token loses access to it immediately, even though it still works for the orgs you remain in. Single-org tokens are re-verified the same way.

Discovery

Clients configure themselves from the endpoint alone, with no hand-entered URLs beyond the MCP address. Two mechanisms make that work.

First, an unauthenticated request to the MCP endpoint returns a 401 with an RFC 9728 Bearer challenge. The WWW-Authenticate header points at the protected-resource metadata, so a client that hits the endpoint cold immediately learns where to begin the OAuth flow:

bash
WWW-Authenticate: Bearer resource_metadata="https://api.elliptic.sh/.well-known/oauth-protected-resource/api/v1/mcp"

Second, the well-known documents let the client finish self-configuring:

DocumentPathWhat it provides
Protected-resource metadata (RFC 9728)/.well-known/oauth-protected-resource/api/v1/mcpThe canonical resource URI, the authorization server to use, the supported scopes, and that bearer tokens go in the header.
Authorization-server metadata (RFC 8414)/.well-known/oauth-authorization-serverThe issuer plus the authorize, token, registration, revocation, and JWKS endpoints, the supported grant and response types, and that S256 PKCE is required.
JWKS/api/v1/oauth/jwks.jsonThe public keys used to verify MCP access tokens.

Installing

Claude Code

Add the server, then run /mcp and complete the browser consent:

bash
claude mcp add --transport http elliptic https://api.elliptic.sh/api/v1/mcp

# then, inside Claude Code:
/mcp        # opens the Elliptic consent screen in your browser

Cursor

Cursor speaks MCP natively. Add Elliptic to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project), then open Cursor Settings, MCP, and complete the browser consent on first use:

json
{
  "mcpServers": {
    "elliptic": {
      "url": "https://api.elliptic.sh/api/v1/mcp"
    }
  }
}

The first tool call opens the same Elliptic OAuth consent in your browser. No API key is stored in the file.

Claude Desktop and other clients

Point any MCP client at the endpoint. Clients that do not yet speak OAuth-protected HTTP natively can bridge through mcp-remote:

json
{
  "mcpServers": {
    "elliptic": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.elliptic.sh/api/v1/mcp"]
    }
  }
}
First connection
The first call triggers the OAuth flow and opens the consent screen in your browser. After you approve, the client stores the token and reconnects automatically. If you self-host, swap the URL for your own API origin.

The scope catalog

Permissions are expressed as scopes, grouped by domain. Most domains have a read scope and a write scope: approving the read scope lets the agent see that data, and the write scope lets it create, edit, and delete. The read scope of every domain is the baseline set, so it is always on at consent and cannot be unchecked, which means the standard read surface is granted by default. A handful of scopes are flagged Elevated and stay unchecked until you opt in deliberately. The Root / Admin toggle selects everything at once.

The scope catalog is broader than the MCP tool surface
The consent catalog lists every grantable scope Elliptic knows about, but not every scope has an MCP tool behind it yet. The Connected sources domain (sources:read, sources:write, sources:manage) appears in the catalog and on the consent screen, yet no MCP tool currently requires it, so approving it grants nothing callable over the MCP today. Everything else in the table below is backed by real tools.
DomainScopesMCP tools?
Taskstasks:read, tasks:writeYes. Also covers projects, boards, sub-tasks, relations, labels, and triage.
Notesnotes:read, notes:writeYes.
Meetingsmeetings:read, meetings:writeYes. Transcripts, summaries, chapters, share links, templates, and recipes.
Calendarevents:read, events:writeYes. Events and briefs.
Commentscomments:read, comments:writeYes. Comments and attachments across tasks, notes, and meetings.
Notificationsnotifications:read, notifications:writeYes.
Activityactivity:readYes. The feed and per-entity history.
Brainbrain:readYes. Catch-me-up, open threads, and resume points.
Agentsagents:read, agents:write (Elevated), agents:keys (Elevated)Yes. AI users, runs, budgets, and provider keys.
Teamsteams:read, teams:writeYes.
Viewsviews:read, views:writeYes. Saved board views.
Vocabularyvocabulary:read, vocabulary:writeYes. The org glossary.
Workflowworkflow:read, workflow:writeYes. Custom workflow statuses.
Automationautomation:read, automation:writeYes. Automation rules, including running them.
Integrationsintegrations:read, integrations:manage (Elevated)Yes. Slack connection, channels, and posting.
Profileprofile:read, profile:writeYes. Your own user profile.
Organizationorg:read, org:manage (Elevated), org:create (Elevated)Yes. Org details, members, roles, invites, creating orgs (org:create), and updating or deleting them (org:manage).
All organizationsorgs:all (Elevated)Not a per-tool scope. Granted by the all-organizations consent option and enforced as the token's cross-org reach.
Connected sourcessources:read, sources:write, sources:manage (Elevated)No. In the catalog but with no MCP tool behind it yet.

The elevated scopes, the ones that stay unchecked until you opt in, are agents:write, agents:keys, org:manage, org:create, integrations:manage, sources:manage, and orgs:all. Note that there is no separate delete scope: deleting an event uses events:write, deleting a note uses notes:write, and so on. Write is enough to remove what write can create.

The tool catalog

The MCP exposes 144 tools, grouped below by domain. This is most of the member surface, but it is not literal parity with every screen. There are no MCP tools for connected sources or GitHub linking, and there are no cycle, milestone, or PQL-style query tools. Read tools list and fetch, write tools create, edit, move, and delete. Two cross-cutting conventions apply throughout: many creates accept an optional idempotency_key so a retried call never duplicates work, and the most destructive deletes take a confirm flag (call once with confirm=false to preview, again with confirm=true to apply).

Targeting an organization
Org-scoped tools accept an optional org_id. With a pinned single-org token you omit it and the call uses the token's workspace. With an all-organizations token, pass org_id to choose which workspace a call acts on. A couple of user-level tools (create_org, list_my_orgs) act on you across orgs and need no org context.

Tasks, boards, labels, and triage

ToolWhat it does
list_project_tasks, get_taskList a project's tasks with board-style filters, or fetch one task with its identifier, counts, and blocked state.
create_task, create_tasks_batchCreate a task (sub-tasks, bug kind, severity, mentions, relations), or several at once from a list.
update_task, transition_task_statusEdit fields, or move a task to a new workflow status.
delete_taskDelete a task (confirm-gated).
get_task_board, list_my_tasks, list_subtasksRead the board grouped into status columns, your assigned / created / subscribed / recent tasks, and a task's sub-tasks.
subscribe_task, unsubscribe_taskFollow or unfollow a task.
list_task_relations, add_task_relation, remove_task_relationList, link, or unlink blocking / blocked-by / related tasks.
list_labels, create_label, attach_task_labels, detach_task_labels, delete_labelManage org labels and apply them to tasks (create_label is get-or-create; delete_label is confirm-gated).
list_triage, accept_triage_task, decline_triage_taskRead incoming triage items and route them.

Projects

ToolWhat it does
list_projects, get_project, create_project, update_projectBrowse, read, create, and edit projects.
delete_project, restore_project, list_deleted_projectsSoft-delete, restore, and review deleted projects (delete confirm-gated).
subscribe_project, unsubscribe_project, get_project_subscriptionFollow a project and check your subscription.
list_project_members, add_project_member, remove_project_memberManage who is on a project.
list_project_artifacts, add_project_artifact, remove_project_artifactAttach and remove linked artifacts.

Meetings

ToolWhat it does
list_meetings, get_meeting, create_meeting, import_folio_meetingBrowse and create meetings, or import one from Folio.
update_meeting, delete_meetingEdit or delete a meeting (delete confirm-gated).
list_meeting_segments, list_meeting_chapters, list_meeting_summariesRead transcript segments, chapters, and summaries.
summarize_meeting, suggest_meeting_projectGenerate a summary, or suggest the project a meeting belongs to.
ask_meeting, meetings_chatQ&A on one meeting, or across all meetings.
run_meeting_recipeRun a saved meeting recipe.
get_meeting_share, create_meeting_share, update_meeting_shareManage public share links.
list_meeting_templates, create_meeting_template, update_meeting_template, delete_meeting_templateManage meeting templates (delete confirm-gated).
list_meeting_recipes, create_meeting_recipeBrowse and create recipes.

Notes, calendar, comments, and notifications

ToolWhat it does
list_notes, get_note, create_note, update_note, delete_noteBrowse, read, write, edit, and delete notes (delete confirm-gated).
list_calendar_events, get_calendar_event, create_calendar_event, update_calendar_event, delete_calendar_eventBrowse, read, and manage calendar events.
get_event_briefGet the AI brief for an event.
list_comments, get_comment, create_comment, update_comment, delete_commentRead and write comments on tasks, notes, and meetings (delete confirm-gated).
get_attachment, view_image_attachmentRead a comment attachment, or view an image attachment inline.
list_notifications, unread_count, mark_notification_read, mark_all_notifications_readRead your notifications and unread total, and mark them read.
archive_notification, snooze_notificationArchive or snooze a notification.

Organization, teams, members, and invites

ToolWhat it does
list_my_orgsList every organization you belong to (works with an all-organizations token).
get_org, update_orgRead and edit the workspace (update_org needs org:manage).
create_org, delete_orgCreate a new organization with org:create (you become its owner), or delete one with org:manage (confirm-gated).
list_org_members, update_member_role, remove_org_memberManage members and roles (remove confirm-gated).
list_invites, create_invite, revoke_inviteInvite people and revoke invitations.
list_teams, get_team, create_team, update_team, delete_teamManage teams (delete confirm-gated).
list_team_members, add_team_member, remove_team_memberManage team membership.

Activity and the brain

ToolWhat it does
list_activity, get_entity_activityThe org-wide activity feed, and the change history of one task, note, or meeting.
brain_open_threadsOpen loops that still need attention.
brain_changes_sinceWhat changed since a point in time (catch-me-up).
brain_resumeWhere you left off in a project, to resume work.

The brain tools are the agent-facing side of the company brain: they exist so an agent can orient itself before it acts, catching up on what changed, finding open threads, and resuming a project without you spelling out the state each time. They are read-only and run under brain:read.

AI agents and keys

ToolWhat it does
list_ai_users, get_ai_user, create_ai_user, update_ai_userManage the org's AI agents (write under elevated agents:write).
pause_ai_user, set_ai_user_budget, delete_ai_userPause, budget, and remove agents (delete confirm-gated).
list_agent_runsRecent agent runs.
list_ai_keys, create_ai_key, update_ai_key, revoke_ai_keyManage provider API keys (elevated agents:keys; revoke confirm-gated).

Views, vocabulary, workflow, and automation

ToolWhat it does
list_views, create_view, update_view, delete_viewSaved board views (delete confirm-gated).
list_vocabulary, create_term, update_term, delete_termThe org glossary (delete confirm-gated).
list_workflow_statuses, create_workflow_status, update_workflow_status, delete_workflow_statusCustom workflow statuses (delete confirm-gated).
list_automations, create_automation, update_automation, delete_automation, run_automationManage and run automation rules (delete confirm-gated).

Integrations and profile

ToolWhat it does
get_slack_integration, list_slack_channelsRead the Slack connection and its channels.
post_meeting_to_slackPost a meeting to a Slack channel (elevated integrations:manage).
get_my_profile, update_my_profileRead and update your own profile.
Linking to tasks and notes
Embed a clickable reference to a task or note in any description or comment using a Markdown link of the form [label](/__mention/kind/id). See the References & Mentions page for the full format and examples.

Managing access

Every consent you give creates a connected-app grant tied to your account, the client, and the org (or, for a cross-org token, no specific org). You can see and revoke these at any time.

  • Connected apps (grants). Each connected client shows up as a grant with its name, the org it covers (or all your organizations), its scopes, its status, and when it was granted. Re-approving the same client updates the existing grant rather than stacking duplicates.
  • Revoking a grant. Revoking a grant kills the whole token family behind it, every access and refresh token, so the client loses access immediately and must re-consent to reconnect.
  • Token revocation (RFC 7009). A client can also revoke its own token at the revocation endpoint. Revoking any token in a family tears down the family, and unknown tokens are a safe no-op.

Confidential bot apps (client_credentials)

For an unattended bot that has no browser to consent through, register a confidential OAuth app. You get a client_id and a one-time client_secret (shown once at creation, stored only as a hash). The app then exchanges those credentials at the token endpoint with grant_type=client_credentials and receives a bot token that acts as you, the owner, across your organizations. Revoking the app deactivates it and stops it from minting new tokens.

A bot app acts as its owner
A client_credentials token is minted as a personal token of the app's owner, so it inherits the owner's full reach. Treat the client secret like a password, store it in a secret manager, and revoke the app the moment it is no longer needed.

Conventions

A few rules hold across every tool, so agents behave predictably and safely.

  • Org-scoped, acting as you. Every tool resolves to one organization and runs with your membership and role. It can do exactly what you can do in the app, and the result appears in activity the same way.
  • Per-call scope checks. A tool runs only if your token carries its required scope. If not, it returns insufficient_scope and does nothing. Scopes are checked on every single call, not just at connect time.
  • Idempotent creates. Pass an idempotency_key on a supported create and a retried call returns the original result instead of duplicating work, which makes agent retries safe.
  • Confirm-gated deletes. The most destructive tools take a confirm flag. Call once with confirm=false to preview what would be removed, then again with confirm=true to apply it.
  • Live membership re-checks. With a cross-org token, your membership of the target org is verified on every call, so losing access to an org takes effect instantly.
New permissions need a fresh consent
A token only carries the scopes you approved when you connected. If a new tool domain ships after you connected, or you simply did not tick a scope you now need, the existing token will not have it. Re-run the client's connect flow (/mcp in Claude Code) and approve again. Ticking Root / Admin grants the entire current surface in one step.