Troubleshooting
Fix common Semaphor MCP connection, authentication, tool and query errors.
Start Here: Check the Session
When something is missing or refused, ask the agent to call semaphor_get_access_context. It reports:
mode:org_interactive(logged in),org_headless(automation token) ortenant_embedded(end-user token)scopes:mcp:read, andmcp:writeif the session can apply changescapabilities.sql: whether SQL and physical tables are availableprojectId: the token's project, or none for a login session, which passesprojectIdon each tool
Most problems below come down to one of these values.
The Semaphor Tools Don't Appear
- Restart the client after installing the plugin (
/reload-pluginsin Claude Code). - Check the plugin is installed:
claude plugin list, orcodex plugin list --marketplace semaphor-analytics. - Check the server: run
/mcpin Claude Code and look forsemaphor, or runcodex mcp listin Codex. - If the server needs a login, complete it (
/mcpin Claude Code,codex mcp login semaphorin Codex), then ask again.
A Tool I Expected Is Missing
The tool list depends on who is calling. See Tools Reference.
| Missing | Why | Fix |
|---|---|---|
| SQL and table tools | Your role is Viewer, or the token was minted with "sql": false | Ask for an Author role, or mint a token with SQL on |
semaphor_propose_change | Your role can't author dashboards: below Author for an organization user, below Power User for an end user | Ask for a role that can author dashboards |
semaphor_apply_change | The session doesn't have mcp:write (proposing still works) | Log in again with write access, or mint a token with mcp:write |
semaphor_list_projects | You're using a token, which is pinned to one project | Expected. The token's project is used automatically. |
Authentication Errors
| Status and message | What it means | What to do |
|---|---|---|
401 "No authorization provided" | No credential was sent, or the login expired | Log in again (/mcp, or codex mcp login semaphor), or check the Authorization header |
401 "Invalid token" or "Token has expired" | The OAuth token failed verification or expired | Log in again |
401 "MCP project token is invalid or expired. Mint a new one with POST /api/v1/token and the mcp option." | The MCP project token expired, has a bad signature, or was minted for a different server | Mint a new token with the mcp option and update it in your client |
401 "This token was not minted for the MCP. Mint an MCP project token with POST /api/v1/token and the mcp option." | The token was minted without the mcp option, for example a dashboard embed token or an API token | Mint an MCP project token. See Other tokens. |
403 "Insufficient scope" | The credential doesn't include mcp:read | Log in again, or mint a new token |
400 invalid_grant when refreshing a login | The refresh failed | Log in again |
Check the header format: Authorization: Bearer <token>, with one space after Bearer.
Tool Errors
Tool errors arrive as results with isError: true. Structured errors include a code:
| Code | What it means | What to do |
|---|---|---|
capability_required | An argument needs SQL access the session doesn't have. The payload names the argument. | Use the semantic form of the tool (domain, dataset and fields) |
missing_relationship, ambiguous_relationship | Data is disconnected or has multiple possible relationship paths | Choose related data or specify the intended relationship |
unsafe_join | A join could count measure values more than once | Follow the returned guidance to group by shared fields or query the measures separately |
unsupported_capability | The requested execution strategy is not supported by this view | Change the query configuration |
execution_failed, timeout | The query failed or timed out while running | Retry or narrow the request; include the error code if the problem persists |
tool_timeout | The tool ran past the server's time limit | Ask a narrower question: fewer rows, a shorter window, fewer fields |
write_scope_required | Apply was called by a session without mcp:write; the error lists requiredScope and grantedScopes | Log in again with write access, or use a token with mcp:write |
change_not_allowed_for_credential | A token session asked for a semantic model change (its tool doesn't list relationship.add, so this usually shows as an input validation error) | Use an interactive login for semantic model changes |
invalid_change_target | The target doesn't fit the changes, or one proposal mixes kinds of change | Dashboard changes take dashboardId; relationship.add takes domainId; dashboard.generate takes neither |
invalid_change | The proposed change failed validation; nothing was stored | Fix the request and propose again |
proposal_not_found | Unknown or expired proposal, or someone else's | Propose again |
proposal_stale | The target changed after the preview | Propose again |
apply_in_progress | The first apply of this proposal is still running | Retry the same call shortly |
apply_outcome_unknown | The first apply never recorded a result | Follow howToCheck to see whether the change landed before proposing again |
See Making Changes for the change errors in context.
Project Errors
| Message | What it means | What to do |
|---|---|---|
Project token is scoped to project "..." | A token session can't switch projects | Use the token's project, or mint a token for the other project |
projectId is required: you can access N projects | You belong to several projects and didn't name one | Tell the agent which project you mean. The error lists your projects. |
Project "..." not found or you do not have access to it | The project ID is wrong, or you aren't a member | Check the ID, and your access in the Semaphor console |
Mint Errors
POST /api/v1/token with the mcp option returns 400 with { "error": "<code>", "message": "<text>" }:
error | Fix |
|---|---|
mcp_invalid_scope | mcp.scopes must be ["mcp:read"] or ["mcp:read", "mcp:write"], and mcp.sql must be true or false |
mcp_write_not_allowed | Write access needs a user to act as: an organization user (orgUserId) with an Author role or higher, or an end user (endUserId with tenantId) |
mcp_token_lifetime_invalid | tokenExpiry must be a whole number of seconds from 60 to 86400 |
mcp_identity_required | Pass orgUserId, or endUserId with tenantId; a tenantId alone isn't supported for MCP tokens |
Discovery Issues
No Semantic Domains Found
semaphor_get_analysis_context reports the reason in recommendedPath:
physical: The project has no semantic domains. Callers with SQL access can use physical discovery. To usesemaphor_analyze, ask your admin to set up a semantic domain.restricted: Domains exist, but the token'ssemanticDomainAccessdoesn't include any of them. Mint a token that includes the domains the agent needs.unavailable: There's nothing this caller can query in the project. Check connections, CLS policies and, for tokens, whether SQL is turned off.
Empty Dataset List
The semantic domain may not have datasets yet. Check the domain setup in the Semaphor console.
Query Issues
A Query Returns No Rows
- Check that the dataset or table has data for the window you asked about.
- Row-level security may be filtering every row for this caller. Two people can see different results for the same question.
- With
semaphor_query_sql_advanced, try a simple count first.
Answers Look Wrong
- Ask the agent which dataset, fields and time window it used. Governed results report the window that ran.
- Compare with the dashboard: ask the agent to read the dashboard's analysis context and re-run a card's question.
Connection Refused or Timeouts
- Check that the data connection is active in the Semaphor console.
- Check that the database is reachable from Semaphor.
Client-Specific Issues
Claude Code: Change Tools Ask Every Time
Claude Code asks before an MCP tool runs unless it's allowed. Choose "Yes, and don't ask again", or add the tool to permissions.allow. See Making Changes.
Cursor: "Tool not found"
- Restart Cursor after changing
~/.cursor/mcp.json. - Check the file is valid JSON (no trailing commas).
claude.ai: Connector Not Appearing
- Check that your Claude plan supports custom connectors.
- Remove and re-add the connector, and complete the sign-in.
Your Own HTTP Client: 406 Not Acceptable
Send Accept: application/json, text/event-stream on every request. See Connect with a Token.
Live Changes Don't Reach the Dashboard
If your agent hears screen_unavailable while your user has the dashboard open, check that:
- the token was minted with
mcp: { live: true }; - the iframe URL has
?showControls=true; - your user can edit the dashboard, so they see Edit in the toolbar;
- the tab has been in use within the last two minutes;
- your users' network passes streaming responses through (see Show the iframe with the toolbar).
If it hears multiple_screens, the dashboard is open in more than one tab with the same token. Live Changes lists every refusal and what to do.
Getting Help
If you're still stuck:
- Check your project, connection and user status in the Semaphor console.
- Review your security policies (CLS, SLS, RLS) in the project settings.
- Contact support at support@semaphor.cloud.