Semaphor
MCP

Authentication and Security

How Semaphor MCP identifies each caller, and how your security policies, SQL access and write permissions apply to every call.

Every MCP query passes through the same security enforcement as your dashboards. Semaphor builds a caller profile from the credential on each request, then applies your existing policies, with no MCP-specific configuration.

Caller profileorganization, projectand tenant reachCLSwhich connectionsthe caller can useSLSwhich schemas, tablesand columnsRLSwhich rows comeback

Credentials

Semaphor MCP accepts two credentials, sent on every request as Authorization: Bearer <token>. Which one you use depends on who is calling.

CallerCredentialReach
You, in Claude Code, Codex, claude.ai, ChatGPT or CursorOAuth login with your Semaphor accountEvery project you belong to
Automation (CI, schedulers, scripts)MCP project token for an organization userOne project, fixed by the token
An agent in your product, acting for an end userMCP project token for a tenant userOne project and that user's tenant

Hiding a tool from a caller is for clarity, not the security control. The server still authorizes every call against the caller's role, scopes and permissions.

OAuth Login

People in an MCP client sign in with their Semaphor account in the browser, and the client stores and refreshes the login. OAuth login is for organization users. See Connect an AI Client for each client's steps.

Scopes

ScopeGrants
mcp:readEvery read tool: discovery, queries and dashboards. Required for every request.
mcp:writeThe change tools that create dashboards and add relationships.

A client that doesn't ask for a scope gets mcp:read only. To use the change tools, the client must request mcp:read mcp:write at login. Write scope is never enough on its own: the change tools also need an Author role or higher, and your permissions still decide what you can change.

OAuth Endpoints

Most clients discover these from the server's metadata. They're listed for client developers; on a self-hosted install, replace https://semaphor.cloud with your Semaphor URL.

ParameterValue
MCP endpointhttps://semaphor.cloud/api/mcp
Protected resource metadatahttps://semaphor.cloud/.well-known/oauth-protected-resource
Authorization server metadatahttps://semaphor.cloud/.well-known/oauth-authorization-server
Authorization endpointhttps://semaphor.cloud/api/mcp/oauth/authorize
Token endpointhttps://semaphor.cloud/api/mcp/oauth/token
Client registrationhttps://semaphor.cloud/api/mcp/oauth/register (dynamic client registration)
Grant typesauthorization_code, refresh_token
PKCES256
Scopesmcp:read, mcp:write

MCP Project Tokens

Automation and agents in your product use a short-lived token your backend mints with the project secret. Minting, request fields and mint errors are on Connect with a Token.

Isolation

Organization

  • Every caller is scoped to its organization. Cross-organization access isn't possible.
  • Interactive callers reach only projects they belong to, checked on each call that passes a projectId.
  • Token callers are pinned to the token's project. Another projectId returns an error.

Tenant

  • An end-user token acts for one end user in one tenant, with the token's security settings applied.
  • Tenant callers never get change tools, and an end-user token can't be minted with write scope.
  • Dashboard access summaries list only the rules that reach the caller's tenant.

Security Policies

Semaphor enforces three layers of policy on every query, from every query tool, including semaphor_query_sql_advanced:

PolicyWhat it controls
CLS (connection-level)Which connections a caller can use
SLS (schema-level)Which schemas, tables and columns are visible
RLS (row-level)Which rows are returned, through filters injected into the SQL

Two callers can get different numbers for the same question. That's expected: each sees only their own data.

SQL Access

SQL and physical table discovery reach your database more directly than the semantic model, so they're limited:

  • Organization users need an Author role or higher. Viewers stay on the semantic model.
  • Tenant users have SQL unless the token turns it off.
  • Any token minted with "mcp": { "sql": false } has no SQL or physical discovery.

Some tools every caller sees also accept arguments that reach physical tables, such as physical mode on semaphor_get_dataset_schema. Without SQL access, those arguments return capability_required, and the semantic form of the tool keeps working.

Semantic Domain Access

When you mint a token, semanticDomainAccess controls which semantic domains the agent can see:

Limit an end user's agent to two domains
{
  "projectId": "p_...",
  "projectSecret": "<project-secret>",
  "tenantId": "tenant_123",
  "endUserEmail": "maria@acme.com",
  "mcp": { "scopes": ["mcp:read"] },
  "semanticDomainAccess": { "mode": "include", "domains": ["sales", "marketing"] }
}
ModeBehavior
allEvery semantic domain (default)
noneNo semantic domains
includeOnly the listed domains
excludeEvery domain except the listed ones

A token whose domain access excludes every domain doesn't fall back to physical tables: semaphor_get_analysis_context reports recommendedPath: "restricted".

Permission and Approval

Writes raise two separate questions: may this caller write, and has someone approved this particular change?

Permission: enforced by Semaphor

A change needs the mcp:write scope, an Author role or higher, the per-kind credential rule (semantic model changes need an interactive login), and the caller's project permissions. Every change is previewed, then applied exactly as previewed.

Approval: a client behavior

semaphor_apply_change is marked destructive and semaphor_propose_change read only. These hints don't force a confirmation, and Semaphor can't prove a person saw the preview. Whether you're asked depends on your client: see Making Changes.

Headless write tokens are delegated authority. Minting a token with mcp:write approves that automation's writes in advance, with no per-change human approval. Grant write scope only to jobs that need it, with the shortest practical tokenExpiry.

Session Security

  • Logins are tied to the user's Semaphor account. The transport is stateless, and project access is checked on every call.
  • Tokens are signed, carry their project, identity, scopes and SQL setting, and expire within 24 hours. A token that fails verification gets 401 with "MCP project token is invalid or expired."
  • Proposals live 30 minutes and can only be applied by the user who proposed them, in the same project.

Best Practices

  • Grant read unless you need writes. Add mcp:write only for automation that creates dashboards.
  • Turn off SQL for end users who don't need it. Set "sql": false so the agent stays on the semantic model.
  • Limit domains. Use semanticDomainAccess to show the agent only the domains it needs.
  • Keep tokens short-lived. Mint per job or per user session, with the shortest tokenExpiry that works.
  • Prefer semaphor_analyze. It uses governed semantic domains, relationship diagnostics, and all three policy layers.
  • Store secrets safely. Use environment variables or a secret manager, never commit tokens or project secrets, and keep MCP traffic on HTTPS.

On this page