Semaphor
MCP

MCP Overview

Connect Claude, Codex, Cursor and your own agents to Semaphor analytics using the Model Context Protocol.

Semaphor runs a Model Context Protocol server that lets agents discover and query your analytics. Agents ground answers in your semantic model, run governed queries under the caller's permissions, read your dashboards, and, with write access, make changes you preview first.

Building an agent? Build an Agent is one page with everything it needs, and /llms-full.txt holds all of these pages as one Markdown document to hand to Claude or any other agent. Every page also has Copy Markdown.

How it works

One endpoint, one caller profile, one analytics spine

Every request to https://semaphor.cloud/api/mcp carries a credential. The server verifies it, builds a caller profile (who you are, which projects you can reach, your scopes, and whether you get SQL), and registers only the tools that profile may use. Tool calls then run through the same governed path as your dashboards. On a self-hosted install, use your Semaphor URL followed by /api/mcp.

MCP clientClaude, ChatGPT, Codex,Cursor, your backendVerify credentialOAuth login orMCP project tokenCaller profilemodeinteractive · headless · embeddedreachyour projects · one projectscopesmcp:read · mcp:writesqlon · offTool list for this callertool families filtered by role,scopes and SQL accessStrict argumentsan unknown name failsand says which oneGroundingdomains, datasets,fields, relationshipsGoverned querycompiled with yoursecurity policiesStructured resultJSON, or an errorwith a stable codebearertools/callpins the project, gates SQL arguments and changes
The caller profile is built once per request from the verified credential. The tool list, the project a session is pinned to, and whether SQL and changes are allowed all come from the profile, never from how the caller logged in.

From the caller's side

Who's calling decides what they see

There are three ways in. Pick one to see how it logs in, what it can do, and what a failure looks like.

Interactive

You connect your AI client and log in with your Semaphor account.

  1. Add https://semaphor.cloud/api/mcp to Claude, ChatGPT, Codex or Cursor, or install the Semaphor plugin.
  2. Your client opens the Semaphor login.
  3. Approve read access, and write access if the agent should make changes.
  4. Ask a question. With one project, the agent doesn’t need to ask which.
Reach
Every project you belong to
Tools
20 with write · 19 read only · 13 as a viewer
SQL
Author role or higher
Changes
Dashboards, generated dashboards and relationships; applying needs write

Tool families

Discovery (available)Analyze (available)Matrix (available)Dashboards (available)SQL (available)Changes (available)Project list (available)

Several agents can share one login. When it expires, your client asks you to log in again.

CallerCredentialToolsWhat's different
Org admin in an AI client, writeOAuth login20Everything, including the change tools
Org admin in an AI client, read onlyOAuth login19Can propose changes, not apply them
Org viewer in an AI clientOAuth login13No SQL, physical tables or change tools
Org admin automation, writeMCP project token19No project list; pinned to one project
Org admin automation, read onlyMCP project token18No project list; can propose, not apply
End user, SQL onMCP project token17Read, analyze, SQL and physical discovery under their policies
End user, SQL offMCP project token12Semantic model only
End user with the Power User role, writeMCP project token19Also changes the dashboards they can edit

Hiding a tool is for clarity, not the security control: the server still authorizes every call. SQL-shaped arguments inside shared tools (a physical source in semaphor_matrix, for example) return capability_required for callers without SQL. See Tools Reference.

Tools

What agents can do

Discover the datasemaphor_get_analysis_context

List projects, semantic domains, datasets, fields and relationships. Callers with SQL access can also browse connections, schemas and tables.

Ask governed questionssemaphor_analyze · semaphor_matrix

Run analytics over the semantic model, or SQL with semaphor_query_sql_advanced when a question needs it. Two people can get different numbers for the same question.

Work from your dashboardssemaphor_list_dashboards

List dashboards, see who can actually open them, and read a dashboard's cards, filters and saved queries.

Make changes, with a previewsemaphor_propose_change

Add, change and remove dashboard cards and filters, arrange a layout, generate a dashboard, or add a relationship to a semantic model. Every change is previewed first; saving it needs write access.

Reads

Every answer is grounded, then governed

An agent answering a question starts with semaphor_get_analysis_context, finds the exact domain, dataset and fields, and runs semaphor_analyze. Nothing is guessed, and every query runs under the caller's security policies. See Discover and Query.

A questionin plain wordsanalysis_contextrecommends the pathGround the fieldsdomains, datasets, schemasemaphor_analyzegoverned by your policiesThe answerrows and what appliedabout a dashboard card: fromCard runs the card as your users see itno semantic model, and SQL access:tables, then semaphor_query_sql_advanceda wrong field fails andnames the valid onesanswered, partial or failed;filters applied and skipped
The agent never guesses a name: every domain, dataset and field comes from discovery, and a wrong one fails with the valid choices. Each answer says whether it was answered in full, and which filters and date windows it applied or skipped. Two people can get different numbers for the same question, because each sees only their own data.

Writes

Every change is a preview, then an apply

semaphor_propose_change saves nothing and returns one sentence per change, with the new numbers. semaphor_apply_change applies exactly that preview by its proposalId. New capabilities arrive as new changes, never new tools.

Read the outlinesheets, cards, filterspropose_changesentences, preview, riskThe user confirmsreads the sentencesapply_changeexactly as previewedAppliednew IDs in createdFailednothing writtenretry: same resultsaves nothing; expires in 30 mincan view, not edit: saveAs: "copy"needs mcp:writesomeone saved the dashboard first: proposal_stale, read the outline again
Proposing saves nothing and needs no write access; applying needs mcp:write and the user's yes. A proposal expires after 30 minutes. If the person can view the dashboard but not edit it, the agent proposes with saveAs: "copy" and the change is saved as their private copy.

Change kinds

  • Dashboard changes: card.add, card.update, card.remove, the filter.* changes and layout.arrange, on a dashboard you can edit, or as your own private copy. Organization authors and end users with the Power User role.
  • dashboard.generate: plans a new private dashboard from a prompt over one semantic domain. Organization authors, logged in or with a token.
  • relationship.add: adds a relationship between two datasets. Needs an interactive login, because every query on the domain can use it.

Permission is not approval

The server enforces permission: write scope, an Author role, the credential rule for each kind, and project access. Approval is the client's job: the apply tool is marked destructive, so clients that honor annotations ask you before running it. For automation tokens, minting write scope is the approval.

Developer experience

What building against it looks like

Connect an agent with a token

Mint a token on your server:

POST /api/v1/token
{
  "projectId": "p_...",
  "projectSecret": "...",
  "orgUserId": "...",
  "mcp": { "scopes": ["mcp:read"], "sql": true },
  "tokenExpiry": 3600
}

Connect any client that takes a header:

.mcp.json
{
  "mcpServers": {
    "semaphor": {
      "type": "http",
      "url": "https://semaphor.cloud/api/mcp",
      "headers": { "Authorization": "Bearer ${SEMAPHOR_MCP_TOKEN}" }
    }
  }
}

What to expect

  • semaphor_get_access_context answers "why is this tool missing": mode, credential, scopes and whether SQL is on.
  • Results are JSON by default and arrive as structured content, checked against each tool's output schema.
  • Errors carry a stable code your code can branch on.
  • A misspelled argument fails with its name instead of being silently dropped.

Error codes worth knowing

write_scope_requiredLog in with write, or mint with mcp:write
capability_requiredThe argument needs SQL; use the semantic form
missing_measureAnalyze needs a measure; __count counts rows
tool_timeoutThe call ran too long; ask a narrower question
proposal_staleThe target changed; propose again
apply_outcome_unknownCheck the target before proposing again

Next

Get started