Tools Reference
Every Semaphor MCP tool, its arguments, what it returns, and which callers can use it.
Semaphor MCP has 20 tools in nine families. Each session sees only the tools its caller can use, so most sessions list fewer. Every tool name on these pages links here, and each tool's argument table is read from the server's own tool list, so it always matches the tool.
Who Sees Which Tools
Every session gets the session context, semantic discovery, governed query and dashboard tools. The rest depend on who is calling:
| Tools | Who gets them |
|---|---|
semaphor_list_projects | Interactive logins only. Token sessions are pinned to the token's project. |
Physical discovery and semaphor_query_sql_advanced | Sessions with SQL: an organization Author or higher (unless the token turns SQL off), or an end user whose token doesn't turn it off |
semaphor_propose_change | Users who can author dashboards: an organization Author or higher, or an end user with the Power User role. Proposing saves nothing, so read-only sessions get it too. |
semaphor_apply_change | The same users, in a session with the mcp:write scope |
| Caller | SQL | Write | Tools |
|---|---|---|---|
| Logged in, Author or Admin | Yes | Yes | 20 |
| Logged in, Author or Admin | Yes | No | 19 |
| Logged in, Viewer | No | No | 13 |
| Automation token, Author or Admin | Yes | Yes | 19 |
| Automation token, Author or Admin | Yes | No | 18 |
| Automation token, Author or Admin | Turned off | Yes | 14 |
| End-user token, Power User | Yes | Yes | 19 |
| End-user token, Power User | Turned off | No | 13 |
| End-user token, Viewer | Yes | No | 17 |
| End-user token, Viewer | Turned off | No | 12 |
Hiding a tool is for clarity, not the security control: the server authorizes every call. An argument that reaches physical tables or SQL inside a tool every caller sees (a physical source in semaphor_matrix, for example) returns capability_required for a session without SQL. Call semaphor_get_access_context when a tool you expected is missing.
Common Arguments
| Argument | Description |
|---|---|
projectId | The project to work in. Interactive sessions pass it on project-scoped tools; a user with exactly one project can omit it. Token sessions use the token's project, and passing another project returns an error. |
responseFormat | "json" (the default) or "markdown". JSON results also arrive as structured content when your client supports it. |
Argument names are camelCase. A tool rejects an argument it doesn't define and names it in the error, so a misspelled argument is never silently ignored:
MCP error -32602: Input validation error: Invalid arguments for tool semaphor_get_analysis_context: Unrecognized key(s) in object: 'question'Session
semaphor_list_projects
Lists the projects you can access. Available only in interactive sessions.
| Argument | Type | Required | Description |
|---|---|---|---|
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
semaphor_get_access_context
Reports who the session is and what it can do. Call it when a tool you expected is missing.
| Argument | Type | Required | Description |
|---|---|---|---|
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
Returns: actorType (organization or tenant), userId, organizationId, projectId, projectCount, accountProjectListingAvailable, scopeSummary (one sentence), mode (org_interactive, org_headless or tenant_embedded), credential, scopes and capabilities.sql. End-user sessions add tenantId and the token's semanticDomainAccess.
{
"actorType": "organization",
"projectId": "p_abc123",
"mode": "org_headless",
"credential": "mcp_project_token",
"scopes": ["mcp:read"],
"capabilities": { "sql": true },
"accountProjectListingAvailable": false
}Semantic Discovery
semaphor_get_analysis_context
The first call for any data question. It checks the semantic domains the caller can see and recommends where to go next.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
Returns: recommendedPath, recommendedNextTool, defaultAnalysisTool, fallbackAnalysisTool, guidance, semanticDomains, semanticDomainCount, fallbackConnections, projectId, projectCount, scopeSummary, actorType, mode and credential.
recommendedPath is one of:
| Value | Meaning |
|---|---|
semantic | Semantic domains are available. Next: semaphor_list_semantic_domains. |
physical | No semantic domains, but the caller can use connections. Next: semaphor_list_connections. |
restricted | Domains exist, but the token's semanticDomainAccess grants none of them. |
unavailable | Nothing the caller can query in this project. |
{
"projectId": "p_abc123",
"semanticDomainCount": 3,
"recommendedPath": "semantic",
"recommendedNextTool": "semaphor_list_semantic_domains",
"defaultAnalysisTool": "semaphor_analyze",
"fallbackAnalysisTool": "semaphor_query_sql_advanced",
"guidance": "Use semantic domains first for business questions. Then call semaphor_list_datasets for the chosen domain...",
"semanticDomains": [{ "id": "dom_abc", "name": "sales", "label": "Sales" }]
}semaphor_list_semantic_domains
Lists the semantic domains the caller can see.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | Project ID to list domains from (uses authenticated user project if not specified) |
Returns: domains, each with id, projectId, name, label, description, createdAt and createdBy.
semaphor_list_datasets
Lists the datasets in a semantic domain. Call it before semaphor_get_dataset_schema so the agent never guesses dataset names.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
domainId | string | Yes | Semantic domain ID |
Returns: datasets, each with name, label, description, analyticsRole (such as fact or dimension), type, domainId, and connection metadata (connectionId, connectionType, dialect, database, table).
semaphor_get_dataset_schema
Returns the fields of a semantic dataset, or the columns of a physical table.
- Semantic mode (preferred): pass
domainIdanddatasetName. AnyconnectionIdpassed along is ignored. - Physical mode: pass
mode: "physical"or connection coordinates (connectionIdorconnectionName, withdatabaseName,schemaNameandtableNameas the connection needs). Physical mode needs SQL access.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
mode | "semantic", "physical" | No | "semantic" (preferred) or "physical"; inferred from the coordinates you pass |
domainId | string | No | Semantic mode: the domain from semaphor_list_semantic_domains |
datasetName | string | No | Semantic mode: the exact dataset name from semaphor_list_datasets |
connectionId | string | No | Physical mode: the connection from semaphor_list_connections (ignored in semantic mode) |
connectionName | string | No | Physical mode: the connection by name, instead of connectionId |
databaseName | string | No | Physical mode: the database or catalog, when the connection has them |
schemaName | string | No | Physical mode: the schema, when the connection has them |
tableName | string | No | Physical mode: the table |
includeCalculatedFields | boolean | No (default true) | Include calculated fields (default true) |
responseDetail | "compact", "standard" | No | Use "compact" for agent-friendly fields-only schema output that omits verbose relationship previews and heavy field metadata; key fields keep their references. |
Returns: dataset (its source), fields, recommendedNextTool and toolChoiceGuidance. Each field has name, label, dataType, modelRole (fact, dimension or identifier), fieldKind, description and a grounded fieldRef. In semantic mode with the standard detail, reachableDatasets previews related datasets one join away, with example refs such as { "name": "supplier_name", "datasetName": "dim_supplier" }.
{ "domainId": "dom_abc", "datasetName": "orders", "responseDetail": "compact" }semaphor_get_domain_relationships
Returns the relationships between datasets in a semantic domain. Useful before multi-dataset questions.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
domainId | string | Yes | Semantic domain ID |
Returns: relationships, each with id, name, from, to, cardinality, defaultJoinType, isAutoJoin, joinPriority, confidence, isActive and description.
Physical Discovery
These tools need SQL access. Use them when the project has no semantic coverage for the question. Follow the capabilities semaphor_list_connections returns through the database and schema levels each connection needs.
semaphor_list_connections
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
Returns: connections, with ID, name, type, dialect and the discovery levels each one has.
semaphor_list_databases
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
connectionId | string | Yes | Connection ID to inspect |
Returns: databases (databases or catalogs).
semaphor_list_schemas
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
connectionId | string | Yes | Connection ID to inspect |
databaseName | string | Yes | Database or catalog name |
Returns: schemas.
semaphor_list_tables
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
connectionId | string | Yes | Connection ID to inspect |
databaseName | string | No | Database or catalog name |
schemaName | string | No | Schema name when the connection supports schemas |
nameCandidates | array of string | No | Candidate table/entity names to match after normalization |
limit | integer (1 to 200) | No (default 50) | Up to 200 tables (default 50) |
Returns: tables with exact coordinates. Pass nameCandidates when you have likely entity names, such as ["orders", "order_lines"].
Governed Queries
semaphor_analyze
The default query tool. It runs governed analytics over a semantic domain: metric by dimension, top-N, time series, filters, latest-available windows, period comparisons, period-change driver analysis, and joins through modeled relationships. Every call applies the caller's security policies.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
fromCard | object | No | Run a dashboard card exactly as it runs on its dashboard, for example { "dashboardId": "...", "cardId": "..." }: its fields, filters, drill steps, dashboard inputs, date range and comparisons. Pass it without the query fields; the result is the card's own rows, with executionResult.constraints naming the filters and date windows it applied and any it skipped. A Matrix card, a text card and a card in a Document section cannot be run this way. |
domainId | string | No | Semantic domain id from semaphor_list_semantic_domains. |
datasetName | string | No | Exact dataset name from semaphor_list_datasets. |
measures | array of object or null | No | Required for semantic analysis: at least one measure. To count rows, use the "__count" measure. Measure field names or source-bearing refs, for example ["sales", "profit"] or [{ "name": "profit", "datasetName": "finance" }]. Optional measure aggregate override is supported, for example { "name": "gross_margin_value", "datasetName": "fact_sales_line", "aggregate": "AVG" }. Omit aggregate to use the semantic model default. |
primaryMeasure | object | No | Measure used for ranking, headline summaries, and period-change analysis. Must refer to one of measures after normalization. May carry the same aggregate override as the selected measure. |
dateField | string or object | No | Date column for time windows and comparisons, for example "order_date", or a source-bearing ref like { "name": "order_date", "datasetName": "orders" }. In standard queries it is only grouped when timeGrain is also provided. |
timeGrain | "day", "week", "month", "quarter", "year" | No | Time grouping for dateField. |
dimensions | array of string or object | No | Dimension column names, for example ["segment", "region"], or source-bearing refs from joined semantic datasets. |
comparison | object | No | Canonical comparison object, for example { "kind": "previous_period" }, { "kind": "previous_year" }, or { "kind": "target", "targetValue": 100 }. Omit comparison when no comparison is requested. |
analysis | object | No | Canonical shared metric analysis object. Use { "kind": "period_change" } for spike, decline, volatility, or period-over-period change analysis. |
analysisOrderBy | "absolute_change", "positive_change", "negative_change", "period" | No | Ordering for period-change analysis. Use "absolute_change" for biggest movements or "period" for chronological trend output. |
orderBy | object | No | Explicit result ordering for standard metric queries, for example { "field": { "name": "net_purchase_value", "datasetName": "fact_purchase_line" }, "direction": "desc" }. The field must be one selected metric, dateField, or dimension. |
timeWindow | object | No | Canonical bounded query window. Use calendar windows for whole calendar periods, such as { "kind": "calendar", "unit": "month", "period": "this" } (this month), { "kind": "calendar", "unit": "quarter", "period": "previous" } (the previous quarter) or { "kind": "calendar", "unit": "month", "period": "this", "toDate": true } (month to date). Use rolling windows such as { "unit": "day", "value": 14, "anchor": "now" } (the last 14 days up to now) or { "unit": "month", "value": 6, "anchor": "latest_available", "completeness": "complete_periods" }. Use absolute windows such as { "kind": "absolute", "start": "2025-01-01", "end": "2025-12-31" } only for fixed dates. Calendar windows and supported rolling windows stay relative when saved to a dashboard card. Rolling windows count back from now with anchor "now", or from the latest available value of their date field with anchor "latest_available" (the default when omitted). Absolute windows, second-based windows, and complete minute or hour periods are saved as fixed dates. |
calendarContext | object | No | Optional execution calendar context for timezone-aware date windows and grouping, for example { "tz": "America/Chicago", "weekStart": 0, "anchor": "now" }. Defaults to token calendar context or UTC. |
driverMode | "absolute_delta", "largest_negative", "largest_positive", "positive_and_negative", "all" | No | Driver output mode for previous-period comparisons. Use "all" for absolute, negative, and positive drivers. |
limit | integer | No | Most rows to return, at most 1000. Default 100. |
includePopulation | boolean | No (default false) | When true, also return filtered population totals for the requested measures before dimension grouping and row limit. Use for share, concentration, and percent-of-total analysis. |
activeFilters | array of object or string | No (default []) | Optional canonical analytics filters or JSON-stringified filter arrays, for example [{ "field": "direction", "operator": "equals", "values": ["Inbound"] }]. Use "values" arrays, not singular "value". Scalar operators such as equals/contains require exactly one value; between requires exactly two; in/not_in accept multiple values. |
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
responseDetail | "compact", "standard", "debug" | No (default "standard") | Controls JSON payload verbosity. "compact" removes duplicate root arrays, full SQL text, and repeated source-heavy intent blocks; "standard" preserves today's full governed response; "debug" is currently equivalent to standard. |
Also accepted, for Semaphor's own clients only: chartTitle, chartType, connectionId, cardConfig, cardDataSource. Agents should use the arguments above.
Measures and fields. Measures are names or refs such as { "name": "revenue", "datasetName": "orders" }; a ref may add aggregate to override the modeled aggregate for this call, and "__count" counts rows. Dimensions and dateField take names or refs, including fields on related datasets.
Time windows:
| Window | Example |
|---|---|
| Calendar period | { "kind": "calendar", "unit": "month", "period": "this" } (this month) |
| Previous period | { "kind": "calendar", "unit": "quarter", "period": "previous" } |
| Period to date | { "kind": "calendar", "unit": "month", "period": "this", "toDate": true } |
| Rolling, up to now | { "unit": "day", "value": 14, "anchor": "now" } |
| Rolling, up to the latest data | { "unit": "month", "value": 6, "anchor": "latest_available" } |
| Fixed dates | { "kind": "absolute", "start": "2025-01-01", "end": "2025-12-31" } |
Rolling windows default to anchor: "latest_available", which counts back from the newest date in the data rather than from today.
Comparisons and drivers. comparison is { "kind": "previous_period" }, { "kind": "previous_year" } or { "kind": "target", "targetValue": 100000 }. analysis: { "kind": "period_change" } finds spikes, declines and period-over-period moves, ordered by analysisOrderBy. driverMode picks which drivers a comparison returns. See Metric Comparisons.
{
"domainId": "dom_abc",
"datasetName": "orders",
"measures": [{ "name": "revenue", "datasetName": "orders" }],
"dimensions": [{ "name": "region", "datasetName": "customers" }],
"dateField": { "name": "order_date", "datasetName": "orders" },
"timeWindow": { "unit": "month", "value": 6, "anchor": "latest_available" },
"limit": 10
}Returns:
| Field | What it holds |
|---|---|
answerSummary | One sentence about the result |
data.records | The rows, keyed by column label, with data.rowCount and data.rowLimitExceeded |
executionResult.status | answered, partial or failed |
executionResult.result | The rows' typed columns (name, label, role, data type, source), rowCount, limit and rowLimitExceeded |
executionResult.fieldsUsed | Each field the query ran with, its role and aggregate |
executionResult.constraints | What the query applied, and what it skipped (below) |
executionResult.coverage | answeredObligations and missingObligations: what part of the question was answered |
executionResult.validation | ok, errors, warnings and repairHints |
executionResult.relationshipDiagnostics | How the query joined datasets, and any fan-out risk |
querySpec, compiledQuery, metadata | The query as resolved and compiled, with the join plan and the generated SQL |
comparison, drivers, changes | For comparison and period-change calls |
{
"answerSummary": "Successfully executed query spec (5 rows).",
"data": {
"records": [
{ "Region": "West", "Revenue": 1758699.06 },
{ "Region": "East", "Revenue": 1670049.2 }
],
"rowCount": 5,
"rowLimitExceeded": true
},
"executionResult": {
"status": "answered",
"resultShape": "records",
"constraints": {
"applied": [
{ "kind": "filter", "field": { "name": "orders.order_date", "label": "Order Date" }, "operation": "between",
"values": ["2026-09-17", "2026-10-17"], "valueType": "date", "timezone": "America/Chicago" }
],
"skipped": []
},
"coverage": { "answeredObligations": ["governed_query_executed"], "missingObligations": [] }
}
}executionResult.constraints says what the query applied:
applied: each filter it ran with (field, operation, and values as executed; a relative date window shows the dates it resolved to), the card's own filters when you ran a card, and each measure's comparison windows. When measures ran over different periods (one for the full month, one month to date), a filter that applied to some of them names them inmeasures. A date filter names the calendar zone the query ran in astimezone: bounds that span whole days in that zone are those dates.skipped: each filter it left out, with the reason:dataset_not_reachable,field_not_resolvable,missing_metadataorunsupported_calculated_filter.
It never includes security policies or their values. "responseDetail": "compact" leaves out duplicate arrays, full field source metadata and the full SQL text, and lists what it left out in omitted.
When a field is wrong or missing, the tool returns isError: true with a validation payload: a code such as missing_measure or invalid_dimension, the valid candidates from the schema, and a recommended next step.
Run a dashboard card
Pass fromCard to answer from a dashboard card exactly as your users see it. The tool runs the card's own query with everything it runs on its dashboard: its fields, filters and drill steps, the dashboard's default inputs and date range, its parameters and its comparisons. The card runs as a new viewer opens the dashboard, under your security policies, and you need access to the dashboard.
{ "fromCard": { "dashboardId": "dash_abc", "cardId": "card_123" } }The result is the card's rows (at most 1,000) with executionResult.metadata.queryApproach set to "dashboard_card_replay", and executionResult.constraints naming the filters and date windows the card applied. To ask something the card doesn't show, build the query with the arguments above instead.
| Error code | When |
|---|---|
card_not_found | The dashboard or card doesn't exist, or you can't open the dashboard |
card_not_supported | A Matrix card, a text card or a card in a Document section; details.reason is matrix, no_query or document_section |
from_card_unavailable | The card can't run right now (its dashboard filter mapping needs fixing), or the call also passed query arguments |
See Querying Data for more examples.
semaphor_matrix
Runs a governed Matrix window: multi-level row and column hierarchies, totals and subtotals, scoped sorting, and Top or Bottom N with Others.
| Argument | Type | Required | Description |
|---|---|---|---|
intent | object | Yes | The Matrix definition: a grounded source, rows, columns, measures, filters, sorts and rankings |
matrixWindowRequest | object | Yes | Which pages and blocks of the matrix to load: each page names an axis, a parent path and a size |
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
calendarContext | object | No | Time zone and week start for date windows, as for semaphor_analyze |
Returns: executionResult, with the requested window at executionResult.result.window. A page cursor asks for the next sibling window; it doesn't mean the data was cut off. A window is never a complete export, and unloaded cells aren't zeros. This tool always returns JSON.
semaphor_plan_analytics_recovery
Plans the next governed tool calls when an agent has a typed question and schema evidence but still has unanswered parts. It returns plannedToolCalls (such as semaphor_get_dataset_schema or semaphor_analyze) and diagnostics. It plans; it doesn't run queries.
| Argument | Type | Required | Description |
|---|---|---|---|
operationIntent | object | Yes | The typed question to answer |
groundedSchemas | array of object | No | Dataset summaries already read, with measure, date and dimension candidates |
semanticTargets | array of object | No | Domains available for schema discovery |
physicalTargets | array of object | No | Grounded physical tables (needs SQL access) |
remainingToolCalls | integer | No | Planning budget, up to 20 |
responseFormat | "markdown", "json" | No | "json" (default) or "markdown" |
SQL
semaphor_query_sql_advanced
Runs SQL against a connection, under the same security policies as every other query, with optional Python post-processing. Use it when a question can't be expressed through semaphor_analyze. Needs SQL access.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | The project to work in. Interactive sessions pass it on project-scoped tools (a user with one project can omit it); token sessions use the token's project. |
connectionId | string | Yes | The connection from semaphor_list_connections |
analyzeFallbackReason | "user_explicitly_requested_sql", "no_semantic_domain_available", "field_not_exposed_in_semantic_model", "unsupported_sql_construct", "unsupported_join_or_grain", "needs_raw_rows", "debugging_or_validation_query" | Yes | Required reason this SQL escape hatch is necessary instead of governed semantic analysis. Do not use SQL merely because the analyze tool was not loaded; load it for governed BI questions. |
analyzeFallbackExplanation | string | Yes | Required concise explanation of the specific limitation or user request that makes governed semantic analysis insufficient for this SQL call. |
sql | string | Yes | The query. Include a row limit for exploration. |
pythonCode | string | No | Python that post-processes the result rows |
Returns: records, rowLimitExceeded, optional output and warnings, the echoed fallback reason, and executionResult.
{
"connectionId": "conn_123",
"analyzeFallbackReason": "unsupported_sql_construct",
"analyzeFallbackExplanation": "Needs a running total with a window function over monthly revenue.",
"sql": "SELECT month, revenue, SUM(revenue) OVER (ORDER BY month) AS running_total FROM monthly_revenue ORDER BY month LIMIT 100"
}Dashboards
semaphor_list_dashboards
Lists the dashboards the caller can open in a project, most recently updated first.
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | Project ID. Optional for project-token sessions because the token determines the active project. Interactive org-user sessions should pass projectId explicitly. |
search | string | No | Search dashboards by title or description |
tags | array of string | No | Exact dashboard tags to match. Tags must already be canonical lowercase values. |
tagMatch | "all", "any" | No (default "all") | Tag matching mode. "all" requires every tag; "any" requires at least one. Requires tags. |
origin | "org_created", "tenant_created", "unknown" | No | Who created the dashboard: "org_created" (an organization user), "tenant_created" (a tenant user) or "unknown" (no creator recorded: created before creators were recorded, or the creator was deleted). |
limit | integer (1 to 500) | No (default 100) | Maximum number of dashboards to return |
offset | integer | No | Number of results to skip, for page-numbered views. Can't be combined with cursor or updatedSince. Offset pages can skip or repeat dashboards that change while you read. |
cursor | string | No | nextCursor from the previous page of the same listing (same filters and updatedSince). With updatedSince (oldest change first) a scan sees every dashboard even while they change; newest first, a dashboard edited between pages can be missed. |
updatedSince | string | No | ISO timestamp. Returns dashboards updated at or after it, oldest change first; follow nextCursor to the end. Use 1970-01-01T00:00:00Z to scan everything. A dashboard edited during the scan appears again later, so de-duplicate by id. |
idsOnly | boolean | No | When true, returns only { ids, total, nextCursor }. A finished scan from updatedSince 1970-01-01T00:00:00Z with no search, tags or origin lists every accessible dashboard, so an id missing from it was deleted or is no longer accessible. Any other scan is partial by design. |
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
To read every dashboard while people may be editing them, scan oldest change first: pass updatedSince (1970-01-01T00:00:00Z for everything) and follow nextCursor to the end. A dashboard edited during the scan moves to the end and is read again, so de-duplicate by ID. The default newest-first order, and offset, can miss a dashboard that's edited between pages.
To find deleted dashboards, run a full scan with idsOnly: true: updatedSince: "1970-01-01T00:00:00Z" and no search, tags or origin. An ID that's missing from that finished scan was deleted, or you no longer have access to it. An incremental scan (a later updatedSince) or a filtered one leaves out dashboards on purpose, so don't treat its missing IDs as deletions.
Returns: dashboards (a page of rows), total and nextCursor (null on the last page). Each row has id, title, description, projectId, tags, origin, its creator and update times, and access: who can open the dashboard, as the dashboards console shows it, with a one-line summary in access.line. For tenant callers, and for dashboards that belong to a tenant, access lists only the rules that reach that tenant. With idsOnly, the response is ids, total and nextCursor.
semaphor_get_dashboard_details
Returns one dashboard's details, or several at once.
| Argument | Type | Required | Description |
|---|---|---|---|
dashboardId | string | No | The unique ID of the dashboard to retrieve. Use this or dashboardIds. |
dashboardIds | array of string | No | Up to 20 dashboard IDs to retrieve at once. Use this or dashboardId. |
fields | array of "summary", "cards", "bindings", "sql", "template", "outline" | No | Which parts to return. "summary" (the default) is the dashboard record with its access; "cards", "bindings" (every dashboard filter and control as an input, and card control bindings), "sql" (saved card SQL) and "template" add those parts. "outline" (one dashboardId only) describes the dashboard for semaphor_propose_change. |
sheetIds | array of string | No | Limit cards, bindings, SQL, template and the outline to these sheets. |
cardIds | array of string | No | Limit cards, bindings, SQL, template and the outline to these cards. |
responseFormat | "markdown", "json" | No (default "json") | Output format: "markdown" for human-readable or "json" for machine-readable |
Returns: for one dashboard, its record (title, description, project, tenant, tags, access, dates) plus the parts you asked for. For several, dashboards and notFound (IDs that don't exist or that you can't open).
With a live token, every part but summary describes the dashboard on the user's screen, unsaved edits included, and names one dashboardId.
outline takes one dashboardId. It describes the dashboard for making changes: every sheet, card and filter by ID and name, each sheet's layout, each card's query in the same fields semaphor_analyze uses, each filter's reach and its default as the dashboard loads it, which cards and filters can be changed (and why not), the dashboard's updatedAt, and access: canEdit, or canCopy when you can save a private copy instead. With fields: ["outline"] alone, the response is { id, title, outline }.
{
"dashboardIds": ["d_q1sales", "d_pipeline"],
"fields": ["summary", "cards"]
}semaphor_get_dashboard_analysis_context
Returns compact grounding for a dashboard the agent already knows: its cards, filters, authored measures, dimensions and date fields, source references, and optional query inputs for semaphor_analyze. Use it before broad discovery when a question starts from a dashboard. It reads the dashboard and never runs its queries. The project comes from the dashboard, so there's no projectId.
| Argument | Type | Required | Description |
|---|---|---|---|
dashboardId | string | Yes | The unique ID of the dashboard to inspect |
includeQueryInputs | boolean | No (default true) | Include bounded cardConfig/cardDataSource query inputs when available so agents can use the dashboard's authored query setup. |
maxCards | integer (1 to 50) | No (default 30) | Maximum dashboard cards to return in the compact context. |
sheetIds | array of string | No | Only cards on these sheets. |
cardIds | array of string | No | Only these cards. |
responseFormat | "markdown", "json" | No (default "json") | Output format: "json" for machine-readable or "markdown" for human-readable |
Returns: dashboard (metadata and link), summary (counts, and missingSheetIds and missingCardIds for IDs that don't exist), filters, cards (per-card analyses with their saved filterConditions and AND and OR groups), referencedSemanticDomains, referencedDatasets, referencedFieldCandidates, referencedConnections, referencedPhysicalSources, physicalSourceLimitations, analysisHints and suggestedNextSteps. A relative window such as "This month" comes back as its relative intent, and a latest-value condition as latestValue: true, because the server resolves both on every run.
Changes
semaphor_propose_change previews a change and saves nothing. semaphor_apply_change applies a stored proposal by its proposalId, exactly as previewed. See Making Changes for every change, its fields, the responses, retries and errors.
semaphor_propose_change
| Argument | Type | Required | Description |
|---|---|---|---|
projectId | string | No | For dashboard.generate and relationship.add in interactive sessions; dashboard changes use the dashboard's project |
dashboardId | string | No | The dashboard to change (dashboard changes) |
domainId | string | No | The semantic domain to change (relationship.add). Ignored with dashboard changes. |
changes | array of object | Yes | 1 to 20 changes, applied in order, all or nothing. See Making Changes for each change. |
saveAs | "original", "copy" | No | "original" (default) or "copy": save the changes as your own private copy |
preview | "sample", "rows", "none" | No | "sample" (default, up to 5 rows per changed card), "rows" (up to 50) or "none" |
include | array of "outline" | No | ["outline"] also returns the outline as it will be after the changes |
rationale | string | No | Why the change is needed, up to 500 characters; kept with the proposal |
Returns: proposalId, expiresAt, risk, target, summary, changes, warnings, preview, proposedOutline (with include: ["outline"]) and next. See Proposals. With a live token, the change is sent to the user's screen and the result also has delivery: its deliveryId and what became of it (applied, not_applied or not_confirmed).
semaphor_apply_change
| Argument | Type | Required | Description |
|---|---|---|---|
proposalId | string | Yes | The proposalId from semaphor_propose_change. |
Returns: applied, replayed, target, created, summary and warnings. Safe to retry with the same proposalId: a retry returns the recorded result with replayed: true and never applies the change twice. See Save, Copy and Apply.