MCP server
The Focal MCP server connects AI assistants to your Focal workspace over the Model Context Protocol. Search and browse your media library, read transcripts and on-screen text, work with boards, collections, comments and workflows, and query ad performance — directly from Claude, ChatGPT, Cursor or any MCP-compatible client.
Quick start
- MCP endpoint:
https://api.focal.inc/mcp - Authentication: OAuth 2.1 — you sign in to Focal and approve access in the browser. No API key needed.
- Who can connect: any member of a Focal organization (guests can’t). Your organization admin can turn the connector off for the whole organization.
- What the assistant can see: exactly what you can see in Focal, optionally narrowed further to specific spaces when you approve the connection.
Server details
| Endpoint | https://api.focal.inc/mcp |
| Transport | Streamable HTTP (JSON-RPC over POST), stateless |
| Server name | focal |
| Authorization server | https://api.focal.inc (same origin) |
| Protected resource metadata | https://api.focal.inc/.well-known/oauth-protected-resource |
| Authorization server metadata | https://api.focal.inc/.well-known/oauth-authorization-server |
| MCP Apps | Supported — interactive media player (ui://focal/media-player.html) |
The assistant acts as you: every call runs with your own Focal permissions, so it can never read or change anything you couldn’t in the Focal app.
Authentication
Focal uses OAuth 2.1 with PKCE. Most clients handle this for you — you add the server, a browser window opens, you sign in to Focal and approve.
The approval screen
When you connect, Focal shows:
- The app asking for access — its name and logo. Apps connecting from Claude are marked as such.
- The permissions it gets — a summary of what the connection can do. There is nothing to untick: what the assistant is actually allowed to do comes from your own Focal permissions (see below).
- Which spaces it can use — the whole organization, or only the spaces you pick.
The connection belongs to the organization you have selected in Focal when you approve. To connect a different organization, switch organizations in Focal first and connect again.
Permissions (scopes)
Every connection is granted all of the scopes below. They don’t decide what the assistant may do — your own Focal permissions do. The assistant acts as you, so it can only read and change what your role lets you read and change in the Focal app. For example:
- If you can only view a board, the assistant can read it but not edit it.
- Workflow tools work only if you are an org admin or space owner.
- Space settings, such as media library custom fields, can only be changed by org admins and space owners.
To limit a connection, restrict it to specific spaces when you approve it. To stop it entirely, revoke it (see Managing connections).
For reference, these are the scopes a connection carries:
| Scope | Allows the assistant to… |
|---|---|
spaces:read |
Read spaces, members and your account details |
spaces:write |
Change space settings, such as media library custom fields |
media:read |
Read media, folders, library views, transcripts and on-screen text |
media:write |
Update media, folders and library views; upload media |
media:delete |
Archive media, folders and library views |
boards:read |
Read boards, columns, rows and views |
boards:write |
Create and update boards, columns, rows and views |
boards:delete |
Archive boards, columns, rows and views |
collections:read |
Read collections |
collections:write |
Create and update collections |
collections:delete |
Archive collections |
comments:read |
Read comments on media and board rows |
comments:write |
Post, edit and react to comments as you |
comments:delete |
Remove your own comments |
workflows:read |
Read workflows, their runs and the step catalog |
workflows:write |
Create, edit and publish workflows |
workflows:run |
Start runs of published workflows, which can send Slack messages and email, upload to ad platforms and call external URLs |
workflows:delete |
Archive workflows |
metrics:read |
Read ad accounts and ad performance (spend, results, metrics) |
Sessions and tokens
- Access tokens last 1 hour and are refreshed automatically.
- A connection stays signed in as long as it’s used at least once every 30 days.
Managing connections
- Your connections: User settings → MCP lists every app you’ve connected, with a button to revoke each one. Revoking takes effect immediately.
- Organization admins: Organization settings → Connector has the switch that enables or disables the connector for everyone in the organization. Admins can’t see or revoke other people’s individual connections — each connection is personal.
Compatible clients
Any client that supports remote MCP servers with OAuth works. Point it at
https://api.focal.inc/mcp.
Claude (claude.ai, Claude Desktop, Claude mobile)
- Open Settings → Connectors and add Focal (or choose Add custom connector and paste
https://api.focal.inc/mcp). - Click Connect, sign in to Focal and approve.
On Claude Team and Enterprise plans an owner may need to add the connector for the organization first.
Claude Code
claude mcp add --transport http focal https://api.focal.inc/mcpThen run /mcp inside Claude Code and choose Authenticate for focal.
ChatGPT and Codex
-
Codex CLI:
Terminal window codex mcp add focal --url https://api.focal.inc/mcpcodex mcp login focal -
ChatGPT: add a custom connector with the URL
https://api.focal.inc/mcp(requires a plan and workspace settings that allow custom connectors).
Cursor, VS Code and other clients
Add Focal as a remote (HTTP) server in the client’s MCP config, for example:
{ "mcpServers": { "focal": { "url": "https://api.focal.inc/mcp" } }}Clients that only support local (stdio) servers can use the mcp-remote bridge:
{ "mcpServers": { "focal": { "command": "npx", "args": ["-y", "mcp-remote", "https://api.focal.inc/mcp"] } }}Add Focal only once per app. Two entries for the same server in one client (for example two
mcp-remoteconfigs) share one sign-in and can keep logging each other out. Different apps — Claude and Codex, say — can be connected at the same time without any problem.
Core workflow
- Find your spaces —
get_accountshows what the connection can access;list_spacesreturns thespace_ids that most other tools need. - Find content —
search_mediafor natural-language search across your library (including sorting and filtering by ad performance),list_media/list_foldersto browse, orlist_boards→list_board_columns→list_board_tasksfor boards. - Go deeper —
get_mediafor details,get_media_transcriptandget_media_ocrfor what’s said and shown,query_metricsfor performance,open_media_playerto view results. - Act — update metadata, set custom field values, fill board rows, organize collections, or leave comments.
Every resource includes an html_url — a link straight to that item in the Focal web app.
Available tools
Read-only tools are marked as such to the client, so assistants can run them without asking for confirmation; write tools are annotated as writes, and archive tools as destructive.
Account, spaces and users
| Tool | Description |
|---|---|
get_account |
The current connection: organization, granted scopes and allowed spaces |
list_spaces / get_spaces |
Spaces this connection can access |
list_users / get_users |
Members of a space |
Media
| Tool | Description |
|---|---|
search_media |
Natural-language and filtered search across media, including ad-metric sorting |
list_media / get_media |
Browse media or fetch specific items |
get_media_transcript |
Spoken-word transcript of a video or audio file |
get_media_ocr |
Text detected on screen |
get_media_download |
Download links for original files |
update_media |
Update media fields such as name and description |
archive_media |
Archive media |
create_media_from_url |
Import media from a public URL |
create_media_upload → complete_media_upload |
Upload a file directly: get an upload URL, upload the bytes, then complete |
get_media_upload |
Check an upload’s status |
open_media_player |
Open an interactive gallery and player for a set of media (in clients that support MCP Apps) |
Media custom fields
| Tool | Description |
|---|---|
list_media_attributes / get_media_attribute |
Custom fields defined on a media library |
set_media_attribute_value |
Set a custom field’s value on media |
add_media_attribute_options |
Add options to a tags field |
create_media_attribute / update_media_attribute |
Create or change a custom field (org admin or space owner) |
delete_media_attribute_option |
Permanently delete a tag option (org admin or space owner) |
Folders and library views
| Tool | Description |
|---|---|
list_folders / get_folders |
Browse folders |
create_folder / update_folder / archive_folder |
Manage folders |
list_library_views / get_library_views |
Saved library views |
create_library_view / update_library_view / archive_library_view |
Manage library views |
Boards
| Tool | Description |
|---|---|
list_boards / get_boards |
Browse boards |
list_board_columns / get_board_column |
A board’s columns and their settings |
list_board_tasks / search_board_tasks |
Read or search rows |
list_board_views |
A board’s views |
create_board / update_board / archive_board |
Manage boards |
create_board_column / update_board_column / archive_board_column |
Manage columns |
create_board_task / update_board_task / archive_board_task |
Manage rows and their cell values |
create_board_view / update_board_view / archive_board_view |
Manage views |
Collections
| Tool | Description |
|---|---|
list_collections / get_collection |
Browse collections |
create_collection / update_collection / archive_collection |
Manage collections |
Comments
| Tool | Description |
|---|---|
list_comments / get_comments |
Comments on media and board rows |
create_comment / update_comment / archive_comment |
Post, edit or remove your comments |
react_to_comment |
Add or remove a reaction |
Workflows
| Tool | Description |
|---|---|
list_workflow_node_types |
The step types a workflow can use, with their config and outputs |
list_workflows / get_workflow |
Browse workflows, their draft graph and validation issues |
create_workflow / update_workflow / archive_workflow |
Manage workflows and declare their steps |
publish_workflow |
Make a workflow’s draft the live version |
start_workflow_run |
Start a manual run of the published version |
list_workflow_runs / get_workflow_run |
Run history, status and per-step results |
Ad performance
| Tool | Description |
|---|---|
list_ad_accounts / get_ad_accounts |
Connected ad accounts |
list_ad_campaigns / list_ad_sets |
Campaigns and ad sets, for filtering performance queries |
list_ads / get_ads |
Ads, with their campaign, ad set, creatives and linked media |
list_creatives / get_creatives |
Creatives (one piece of ad content, across every ad running it) |
list_metrics |
Available metrics |
query_metrics |
Query performance data such as spend and results |
Feedback
| Tool | Description |
|---|---|
report_feedback |
Tell the Focal team about a missing capability or confusing behavior |
Fewer tools up front (optional)
For clients with a small tool budget, use https://api.focal.inc/mcp?tools=search. The server then
lists only a few core tools (list_spaces, get_account, search_media, open_media_player,
report_feedback) plus a search_tools tool the assistant uses to find the rest on demand.
Common use cases
- “Find our top-spending TikTok videos from last month that feature a product close-up.”
- “Summarize what’s said in these five ads and tag each with its hook type.”
- “Fill in the Status and Concept columns on the Q4 creative board for every row that’s empty.”
- “Make a collection of all approved UGC videos and share the link.”
- “What did the team comment on this video, and what changed since?”
- “Compare CTR for our static vs. video creatives across all Meta ad accounts.”
Rules for AI agents
These conventions apply across all tools and are also sent to the assistant when it connects.
- Start with
get_accountorlist_spacesto discover thespace_ids other tools require. - Tools take lists. Anything acting on resources by id takes
ids(oritems, when each entry carries its own values). Send everything in one call rather than looping. - Batch results aren’t transactions. A batch returns
{ items, succeeded, failed }withitemsin request order. A failed entry carries itsindexand afailurein place of the resource; the successful ones stay applied. Retry only the failed entries, with a freshidempotency_key. - Say what you want back. Where a tool takes
fields, it’s required — there’s no “everything” default.idalways comes back. - Board rows need
columnstoo. Every tool returning board rows requires acolumnslist (ids or names fromlist_board_columns). Pass[]for no cell values. - “Not found” means “not available to you”. An id that doesn’t exist and one you can’t access return the same error.
- Use
html_urlto link the user straight to what you found. - Report gaps with
report_feedback— not for transient errors.
Limits
| Limit | Value |
|---|---|
| Requests per connection | 600 per minute |
| Requests per organization | 1,200 per minute (all connections combined) |
| Page size | 1–100 items (default 25), cursor-based pagination |
| Items per read batch | 100 (25 for transcript, OCR, download and similar per-item reads) |
| Items per write batch | 25 |
| Upload size | Images 1 GB, video 4 GB |
| Upload completion window | 12 hours |
Errors and troubleshooting
How errors come back
Problems with a tool call (not found, missing permission, invalid arguments, conflict) come back as
a normal tool result marked isError: true, so the assistant can read the message and adjust:
{ "error": { "kind": "insufficient_scope", "message": "…", "status": 403, "required_scope": "boards:write" } }kind |
Meaning |
|---|---|
not_found |
The item doesn’t exist or isn’t available to you |
insufficient_scope |
The connection lacks a permission, or your Focal role doesn’t allow it |
invalid_arguments |
The request was malformed |
conflict |
Retry later — for example, completing an upload before the file finished uploading |
internal |
Unexpected error; includes a request_id to share with support |
Common problems
- The client keeps asking me to sign in. Check that Focal is added only once in that client
(see Compatible clients). Remove duplicates, restart the client and connect once. For
mcp-remote, clearing its cached credentials (~/.mcp-auth) and reconnecting also helps. - “The MCP Connector is disabled for this organization.” An organization admin has turned the connector off in Organization settings → Connector.
- I can’t approve the connection. Guests can’t connect — ask an admin for member access.
- The assistant can’t find something I can see in Focal. The connection may be limited to certain spaces. Revoke it in User settings → MCP and reconnect with access to the space you need.
- A write tool says
insufficient_scope. Your Focal role doesn’t allow the change — for example, editing custom fields needs an org admin or space owner. Ask someone with the right role to change your access in Focal. (A connection made before all scopes were granted by default may also be missing one: revoke it in User settings → MCP and reconnect.)
Links
- Focal help center: https://help.focal.inc
- Model Context Protocol: https://modelcontextprotocol.io
- Raw markdown (for AI agents): https://help.focal.inc/developers/mcp.md
- REST API reference: https://help.focal.inc/developers/api
- Support: use
report_feedbackfrom your assistant, or contact us through the help center.