MCP (AI Assistants)
The Model Context Protocol (MCP) is an open standard that lets AI assistants connect to external data sources. Roam's MCP server exposes the Roam API as MCP tools — giving your AI assistant direct access to your meetings, transcripts, chat, calendar, and more. You can ask questions like "What did we decide about pricing in last week's meeting?" and get answers grounded in your actual conversations, or have the assistant post a chat message or create a calendar event on your behalf.
Connections
OAuth MCP connections (Claude, ChatGPT, Codex, Grok via the connect card) are personal —
each is created by an individual user and scoped to that user's own meetings, chats, calendar, and
groups. They never receive roam-wide meeting access (admin:meetings:read is org-only).
Custom MCP clients can also send a Personal Access Token (rmp-…) or an organization API
key (rmk-…) as a Bearer token. A PAT is still Personal access. An API key is Organization
access: the bot persona, group membership, and org scopes (including admin:meetings:read when
granted). MCP is outbound only — it does not make Grok a DM-able bot in
Roam chat. For that, see Grok Bot.
Admin Controls
Roam admins control whether MCP connections are allowed in your workspace. By default, new connections require admin approval before they can access data.
Admins can change the approval policy in Administration > Developer:
| Policy | Behavior |
|---|---|
| Require Approval (default) | New connections are pending until an admin approves them |
| Auto-Approve | New connections are approved automatically |
| Disabled | MCP connections are not allowed |
When a user creates a new connection with the Require Approval policy, admins will be notified and can approve or deny the request from the Administration panel.

Scopes & Permissions
Every tool maps to a Roam API endpoint that requires a specific OAuth scope (for example,
meetings:read to read meetings, or chat:send_message to post a chat message). The
Tool Reference lists the scope each tool needs.
MCP uses the same OAuth scopes as the rest of the Roam API. The full set the MCP server supports is
published in its
protected-resource metadata under
scopes_supported, so clients can discover it programmatically.
calendar_list needs calendar:readReading connected calendars requires calendar:read. This used to fall under meetings:read,
which grants it only for clients registered before 2026-07-29T00:00Z — anything registered on
or after that date must hold calendar:read, or calendar_list returns a
missing-scope 403.
Only calendar_list is affected; the meeting_* tools still use meetings:read. See
Scopes.
How scopes are granted depends on the client:
- OAuth assistants (Claude, ChatGPT, Codex, Grok) can't present a Roam scope picker, so each
connection is granted the default MCP scope set automatically — the same set published in
scopes_supported. It's a broad set that covers every MCP tool, including write tools such aschat_post,calendar_event_create, and the OnAir tools. - Personal Access Tokens and other custom clients let you choose exactly which scopes to grant (see Custom MCP Clients) — grant only what your integration needs.
The server advertises every tool regardless of your granted scopes; calling a tool whose scope
you weren't granted returns a permission error (403). In practice this only affects Personal
Access Tokens created with a narrow scope selection — a default OAuth connection receives the full
set and can call every tool.
Per-connection scope selection for OAuth assistants is a planned future capability. Today these connections receive the full default MCP scope set; use a Personal Access Token if you need tighter, least-privilege scoping.
Claude
Claude supports MCP natively through its Connectors feature. No token or manual configuration is needed — Claude handles authentication via OAuth.
The button opens Claude's custom-connector dialog with Name Roam and URL
https://api.ro.am/mcp already filled in. Click Add, then Connect, and complete
the OAuth consent flow.
Roam is not in Claude's connector directory, so searching Suggested Connectors won't find it — use the button above, or add a custom connector by hand:
- Open Settings > Connectors.
- Click Add custom connector.
- Enter a name (e.g. "Roam") and the Remote MCP Server URL:
https://api.ro.am/mcp - Click Connect and complete the OAuth consent flow.

Once connected, Roam's tools are available in your conversations.
Using Prompts
To use a built-in prompt, click the + button in the message composer, select Add from Roam,
and choose a prompt (e.g. morning_brief or weekly_digest).

ChatGPT
ChatGPT supports MCP through its Apps feature. To connect Roam:
Using OpenAI's Codex coding agent instead of the ChatGPT app? It's a different product configured separately — see Codex.
- Open Settings > Apps > Advanced Settings.
- Turn on Developer Mode.
- Click Create app.
- Enter a name (e.g. "Roam") and the MCP URL:
https://api.ro.am/mcp - Click Create.


Once connected, you can use Roam in a conversation by clicking + > More > Roam.

Try asking about your recent meetings or chat messages.
ChatGPT does not support MCP prompts. Use the tools directly by asking questions in natural language.

Codex
OpenAI's Codex coding agent is not the ChatGPT app — it connects to MCP servers through Codex's own settings, not through ChatGPT's Apps settings, so the ChatGPT steps above don't apply. Roam is served over Streamable HTTP, which current Codex versions support natively. Connect it from the command line or the Codex app; either way the connection authenticates over OAuth and receives the default scope set, the same as Claude and ChatGPT.
Command line
Register Roam with the codex mcp CLI:
codex mcp add roam --url https://api.ro.am/mcp
Because Roam advertises OAuth, Codex detects it and opens your browser to Roam's consent flow automatically — there's no token to copy and no separate login step:
Added global MCP server 'roam'.
Detected OAuth support. Starting OAuth flow…
Successfully logged in.
Verify with /mcp inside Codex — Roam should appear as connected, with its tools listed. (To
re-authenticate later, run codex mcp login roam.)
If codex mcp add can't load the server — for example an error like
missing field `command` in `mcp_servers.roam` — your Codex version is too old to use URL-based
(Streamable HTTP) servers and only understands command-based stdio servers. Upgrade to the latest
Codex and the url entry will load.
Codex app
In the Codex app, open Settings > MCP servers and click Add server. Fill in the form:
- Name:
Roam - Select the Streamable HTTP transport.
- URL:
https://api.ro.am/mcp - Leave Bearer token env var and the header fields empty — Roam uses OAuth.
Click Save.

Back on the MCP servers list, the new server shows an Authenticate button. Click it to complete Roam's OAuth consent flow.

Codex does not support MCP prompts. Use the tools directly by asking questions in natural language.
Grok
xAI has three products that connect to MCP. Setup does not carry over between them. This section is outbound (Grok calls Roam tools). For a Grok Bot people DM inside Roam, see Grok Bot.
Short version for each product:
Grok Bot
Grok Bot has no config file. In a conversation:
Add a custom MCP server called roam at https://api.ro.am/mcp
Say custom server — there is no Roam marketplace plugin yet. Confirm, then complete the OAuth
connect card (Personal access). For an org bot, tell it to add the same URL with header
Authorization: Bearer rmk-…. Type @ and attach roam before asking about meetings or chat.
Grok chat
- Open grok.com/connectors
- New Connector → Custom
- URL:
https://api.ro.am/mcp - Complete Roam OAuth (Personal)
On Grok Business / Enterprise, a team admin must provision the custom server first.
Grok Build
grok mcp add --transport http roam https://api.ro.am/mcp
Roam advertises OAuth, so Grok Build opens a browser to the consent flow. For a PAT or org API key instead:
grok mcp add --transport http roam https://api.ro.am/mcp \
--header "Authorization: Bearer ${ROAM_TOKEN}"
grok mcp doctor roam verifies the connection.
Custom MCP Clients
You can connect any MCP-compatible client to Roam's server.
Server URL: https://api.ro.am/mcp
Transport: Streamable HTTP
Authentication: Bearer token in the Authorization header. Clients can complete the OAuth
flow (the server supports Dynamic Client Registration), send a Personal Access Token (rmp-…),
or send an organization API key (rmk-…). OAuth and PATs are Personal access; an API key is
Organization access.
OAuth details
For the general third-party OAuth install flow (non-MCP), token lifetimes, and refresh, see OAuth & Authentication. MCP-specific discovery and DCR notes continue below.
Clients that implement the MCP authorization flow can discover everything they need from Roam's standard metadata:
| Item | Value |
|---|---|
| Protected-resource metadata | https://api.ro.am/.well-known/oauth-protected-resource |
| Authorization-server metadata | https://ro.am/.well-known/oauth-authorization-server |
| Resource (audience) | https://api.ro.am/mcp |
| Authorization endpoint | https://ro.am/oauth/authorize |
| Token endpoint | https://ro.am/oauth/token |
| Registration endpoint (DCR) | https://ro.am/oauth/register |
| PKCE | Required for public clients; S256 only |
| Token endpoint auth methods | none (public client + PKCE), client_secret_post, client_secret_basic |
| Scopes | See scopes_supported in the protected-resource metadata |
Both public clients (token_endpoint_auth_method: none with PKCE) and confidential clients (with a
client secret) are supported. Public clients must use PKCE with code_challenge_method=S256 —
plain is rejected. Dynamically registered assistants that don't request specific scopes receive
the default MCP scope set.
Using mcp-remote: the most reliable setup passes a Personal Access Token as a bearer header:
npx mcp-remote https://api.ro.am/mcp --header "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN"
mcp-remote's built-in OAuth (Dynamic Client Registration) support is version-dependent, and some
releases mishandle the PKCE code verifier (No code verifier saved for session). If its OAuth flow
fails, use the bearer-token form above.
Create a Personal Access Token
A Personal Access Token (PAT) is the simplest way to authenticate a custom client, and — unlike an OAuth connection — it lets you choose exactly which scopes to grant.
- In Roam, open User Settings > Developer.
- Click Create Personal Access Token.
- Give it a descriptive name (e.g. "MCP Inspector").
- Select the scopes you need. The Tool Reference lists the scope each tool
requires — for example,
chat:historyforchat_history,calendar:writeforcalendar_event_create, oronair:readfor the OnAir read tools. Grant only what your integration uses. - Click Create Token and copy it (it starts with
rmp-…).

Testing with MCP Inspector
The MCP Inspector is a browser-based tool for testing MCP servers. Use it to verify your connection and explore available tools.
- Launch the inspector:
npx @modelcontextprotocol/inspector
- In the inspector UI:
- Set Transport Type to Streamable HTTP.
- Set URL to
https://api.ro.am/mcp. - Under Request Headers, add:
- Header name:
Authorization - Header value:
Bearer YOUR_PERSONAL_ACCESS_TOKEN
- Header name:
- Click Connect.

- Once connected, click the Tools tab to see all available tools. Click any tool to view its input schema and try it out.
- Click the Prompts tab to see built-in prompts like
morning_briefandweekly_digest.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
invalid_client / "Client authentication failed" at token exchange | A public client omitted PKCE, or a confidential client sent its secret in a way the endpoint didn't read | Public clients: register with token_endpoint_auth_method: none and use PKCE (S256). Confidential clients: send the secret via client_secret_post or HTTP Basic. |
| Browser says authentication completed, but the client still shows "not logged in" | The browser callback succeeded but the background token exchange failed | Check the token-endpoint auth method and that the resource parameter is https://api.ro.am/mcp. |
code_challenge is required or code_challenge_method must be S256 | A public client started the flow without S256 PKCE | Send code_challenge with code_challenge_method=S256. Public clients must use S256; plain is rejected. |
A tool is listed but returns 403 when called | Your token lacks that tool's scope | Use a token that includes the scope (see the Tool Reference). Default OAuth connections already include the full default scope set; narrow Personal Access Tokens may not. |
MCP endpoint returns 401 with no bearer token | Expected unauthenticated response | Follow the WWW-Authenticate header to the protected-resource metadata, then send a bearer token in the Authorization header. |
No code verifier saved for session (with mcp-remote) | PKCE-state bug in some mcp-remote releases | Use the bearer-token form (--header "Authorization: Bearer …") or upgrade mcp-remote. |
Tool Reference
Roam's MCP server exposes the tools below, grouped by category. Each tool requires the listed OAuth scope.
Remember that a default OAuth connection (Claude, ChatGPT, Codex, or Grok) is granted only the default scope set — tools whose scope falls outside it require a Personal Access Token until per-connection scope selection ships.
User & Token
| Tool | Description | Scope |
|---|---|---|
token_info | Get info about the current token (client, user, org, scopes, expiration) | — |
get_me | Get the authenticated user's profile (name, image, email, status) | — |
user_info | Resolve a member, guest, or automated principal by ID (or a workspace member by email) | user:read |
user_list | List active workspace members, or hydrate up to 100 principals with ids | user:read |
user_status_bubble_get | Get the live thought bubble shown over a user's assigned office seats | user:read.statusBubble |
user_status_bubble_set | Set or replace a user's thought bubble | user:write.statusBubble |
user_status_bubble_clear | Clear a user's thought bubble | user:write.statusBubble |
user_info returns required type: "user" | "bot" and is available to Personal connections.
user_list without ids remains the member directory; pass one comma-separated ids value to
hydrate message/webhook actor IDs in request order. See
Identity & Principals.
Status-bubble tools accept a user ID or workspace member email. Personal connections may target only their owner; organization connections may target any active workspace member. OAuth MCP connections created before these tools shipped must be removed and reconnected to receive the new default scopes if a call returns a missing-scope error.
Chat
| Tool | Description | Scope |
|---|---|---|
chat_list | List conversations (DMs, channels, team Roam, meeting channels) | chat:read |
chat_history | Read messages from a chat or thread, including sender userType | chat:history |
chat_post | Post a message to a chat, channel, or thread | chat:send_message |
chat_update | Update a bot-posted message | chat:send_message |
chat_delete | Delete a bot-posted message (destructive) | chat:send_message |
chat_search | Full-text search across chats, with sender/date/attachment filters and sender userType | chat:history |
search | Simplified search alias (ChatGPT compatibility — accepts only query) | chat:history |
resolve_chat_link | Resolve a Roam chat link URL to its chat/thread IDs | chat:history |
create_chat_link | Create a shareable Roam link to a chat message | chat:history |
Reactions
| Tool | Description | Scope |
|---|---|---|
reaction_add | Add an emoji reaction to a message | chat:send_message |
reaction_remove | Remove an emoji reaction from a message | chat:send_message |
reaction_list | List emoji reactions on a message | chat:history |
Groups
| Tool | Description | Scope |
|---|---|---|
group_info | Get a group/channel's info by ID or name | group:read |
group_list | List groups/channels, with search and type filters | group:read |
group_join | Join a public group as the calling identity | group:write |
Meetings
| Tool | Description | Scope |
|---|---|---|
meeting_list | List meetings, with optional summary/action-item/chapter expansion | meetings:read |
meeting_info | Get details about a specific meeting | meetings:read |
meeting_participants | List a meeting's participants | meetings:read |
meeting_transcript | Get a meeting transcript (VTT) | meetings:read |
meeting_search | Search meetings by keywords or natural language | meetings:read |
meeting_prompt | Ask an AI question about a meeting's transcript | meetings:read |
meeting_link_create | Create a meeting link | meetinglink:write |
meeting_link_info | Get details about a meeting link | meetinglink:read |
meeting_link_update | Update a meeting link | meetinglink:write |
Calendar
| Tool | Description | Scope |
|---|---|---|
calendar_list | List scheduled events from connected calendars (Google, Outlook) | calendar:read |
calendar_event_create | Create a calendar event with a Roam meeting link | calendar:write |
OnAir
| Tool | Description | Scope |
|---|---|---|
onair_event_list | List OnAir broadcast events | onair:read |
onair_event_info | Get details about an OnAir event | onair:read |
onair_event_create | Create an OnAir event | onair:write |
onair_event_update | Update an OnAir event | onair:write |
onair_event_cancel | Cancel an OnAir event | onair:write |
onair_guest_list | List an OnAir event's guests | onair:read |
onair_guest_info | Get details about an OnAir guest | onair:read |
onair_guest_add | Add guests to an OnAir event | onair:write |
onair_guest_update | Update an OnAir guest | onair:write |
onair_guest_remove | Remove a guest from an OnAir event | onair:write |
onair_attendance_list | List attendance records for an OnAir event | onair:read |
Magicast
| Tool | Description | Scope |
|---|---|---|
magicast_list | List Magicasts (metadata only) | magicast:read |
magicast_info | Get Magicast details, transcript, and video | magicast:read |
magicast_share_link | Get or create a shareable player URL | magicast:read |
Lobbies
| Tool | Description | Scope |
|---|---|---|
lobby_list | List configured lobbies | lobby:read |
lobby_booking_list | List bookings for a lobby | lobby:read |
Webhooks
| Tool | Description | Scope |
|---|---|---|
webhook_subscribe | Subscribe to webhook events at a URL | webhook:write |
webhook_unsubscribe | Unsubscribe from a webhook | webhook:write |
Prompts
Built-in prompts provide ready-made workflows. In Claude, add them from the + menu (see Using Prompts). Some prompts take an argument.
| Prompt | Description |
|---|---|
action_item_radar | Action items by urgency and ownership, highlighting carry-over and at-risk work |
meeting_prep | A concise prep brief for your next meeting |
morning_brief | Yesterday's meetings and action items, today's schedule, and recent chat activity |
chat_recap | Recent activity across your conversations, highlighting items needing a response |
group_digest | Activity summary for a specific group (argument: group) |
decision_log | Decisions from recent meetings: what, when, and by whom |
project_status | Status report for a specific project, from meetings and chat (argument: project) |
weekly_digest | Comprehensive weekly summary with key decisions and action items |
ChatGPT does not support MCP prompts. Use the tools directly by asking questions in natural language.