Semaphor
MCP

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:

ToolsWho gets them
semaphor_list_projectsInteractive logins only. Token sessions are pinned to the token's project.
Physical discovery and semaphor_query_sql_advancedSessions 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_changeUsers 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_changeThe same users, in a session with the mcp:write scope
CallerSQLWriteTools
Logged in, Author or AdminYesYes20
Logged in, Author or AdminYesNo19
Logged in, ViewerNoNo13
Automation token, Author or AdminYesYes19
Automation token, Author or AdminYesNo18
Automation token, Author or AdminTurned offYes14
End-user token, Power UserYesYes19
End-user token, Power UserTurned offNo13
End-user token, ViewerYesNo17
End-user token, ViewerTurned offNo12

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

ArgumentDescription
projectIdThe 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:

An unknown argument
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.

ArgumentTypeRequiredDescription
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.

ArgumentTypeRequiredDescription
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.

Example response
{
  "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.

ArgumentTypeRequiredDescription
projectIdstringNoThe 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:

ValueMeaning
semanticSemantic domains are available. Next: semaphor_list_semantic_domains.
physicalNo semantic domains, but the caller can use connections. Next: semaphor_list_connections.
restrictedDomains exist, but the token's semanticDomainAccess grants none of them.
unavailableNothing the caller can query in this project.
Example response (shortened)
{
  "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.

ArgumentTypeRequiredDescription
projectIdstringNoProject 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.

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
domainIdstringYesSemantic 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 domainId and datasetName. Any connectionId passed along is ignored.
  • Physical mode: pass mode: "physical" or connection coordinates (connectionId or connectionName, with databaseName, schemaName and tableName as the connection needs). Physical mode needs SQL access.
ArgumentTypeRequiredDescription
projectIdstringNoThe 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
domainIdstringNoSemantic mode: the domain from semaphor_list_semantic_domains
datasetNamestringNoSemantic mode: the exact dataset name from semaphor_list_datasets
connectionIdstringNoPhysical mode: the connection from semaphor_list_connections (ignored in semantic mode)
connectionNamestringNoPhysical mode: the connection by name, instead of connectionId
databaseNamestringNoPhysical mode: the database or catalog, when the connection has them
schemaNamestringNoPhysical mode: the schema, when the connection has them
tableNamestringNoPhysical mode: the table
includeCalculatedFieldsbooleanNo (default true)Include calculated fields (default true)
responseDetail"compact", "standard"NoUse "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" }.

Semantic mode
{ "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.

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
domainIdstringYesSemantic 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

ArgumentTypeRequiredDescription
projectIdstringNoThe 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

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
connectionIdstringYesConnection ID to inspect

Returns: databases (databases or catalogs).

semaphor_list_schemas

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
connectionIdstringYesConnection ID to inspect
databaseNamestringYesDatabase or catalog name

Returns: schemas.

semaphor_list_tables

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
connectionIdstringYesConnection ID to inspect
databaseNamestringNoDatabase or catalog name
schemaNamestringNoSchema name when the connection supports schemas
nameCandidatesarray of stringNoCandidate table/entity names to match after normalization
limitinteger (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.

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
fromCardobjectNoRun 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.
domainIdstringNoSemantic domain id from semaphor_list_semantic_domains.
datasetNamestringNoExact dataset name from semaphor_list_datasets.
measuresarray of object or nullNoRequired 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.
primaryMeasureobjectNoMeasure 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.
dateFieldstring or objectNoDate 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"NoTime grouping for dateField.
dimensionsarray of string or objectNoDimension column names, for example ["segment", "region"], or source-bearing refs from joined semantic datasets.
comparisonobjectNoCanonical comparison object, for example { "kind": "previous_period" }, { "kind": "previous_year" }, or { "kind": "target", "targetValue": 100 }. Omit comparison when no comparison is requested.
analysisobjectNoCanonical 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"NoOrdering for period-change analysis. Use "absolute_change" for biggest movements or "period" for chronological trend output.
orderByobjectNoExplicit 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.
timeWindowobjectNoCanonical 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.
calendarContextobjectNoOptional 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"NoDriver output mode for previous-period comparisons. Use "all" for absolute, negative, and positive drivers.
limitintegerNoMost rows to return, at most 1000. Default 100.
includePopulationbooleanNo (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.
activeFiltersarray of object or stringNo (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:

WindowExample
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.

Revenue by region, last six months
{
  "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:

FieldWhat it holds
answerSummaryOne sentence about the result
data.recordsThe rows, keyed by column label, with data.rowCount and data.rowLimitExceeded
executionResult.statusanswered, partial or failed
executionResult.resultThe rows' typed columns (name, label, role, data type, source), rowCount, limit and rowLimitExceeded
executionResult.fieldsUsedEach field the query ran with, its role and aggregate
executionResult.constraintsWhat the query applied, and what it skipped (below)
executionResult.coverageansweredObligations and missingObligations: what part of the question was answered
executionResult.validationok, errors, warnings and repairHints
executionResult.relationshipDiagnosticsHow the query joined datasets, and any fan-out risk
querySpec, compiledQuery, metadataThe query as resolved and compiled, with the join plan and the generated SQL
comparison, drivers, changesFor comparison and period-change calls
Example response (shortened)
{
  "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 in measures. A date filter names the calendar zone the query ran in as timezone: 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_metadata or unsupported_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.

The card's own answer
{ "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 codeWhen
card_not_foundThe dashboard or card doesn't exist, or you can't open the dashboard
card_not_supportedA Matrix card, a text card or a card in a Document section; details.reason is matrix, no_query or document_section
from_card_unavailableThe 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.

ArgumentTypeRequiredDescription
intentobjectYesThe Matrix definition: a grounded source, rows, columns, measures, filters, sorts and rankings
matrixWindowRequestobjectYesWhich pages and blocks of the matrix to load: each page names an axis, a parent path and a size
projectIdstringNoThe 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.
calendarContextobjectNoTime 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.

ArgumentTypeRequiredDescription
operationIntentobjectYesThe typed question to answer
groundedSchemasarray of objectNoDataset summaries already read, with measure, date and dimension candidates
semanticTargetsarray of objectNoDomains available for schema discovery
physicalTargetsarray of objectNoGrounded physical tables (needs SQL access)
remainingToolCallsintegerNoPlanning 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.

ArgumentTypeRequiredDescription
projectIdstringNoThe 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.
connectionIdstringYesThe 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"YesRequired 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.
analyzeFallbackExplanationstringYesRequired concise explanation of the specific limitation or user request that makes governed semantic analysis insufficient for this SQL call.
sqlstringYesThe query. Include a row limit for exploration.
pythonCodestringNoPython that post-processes the result rows

Returns: records, rowLimitExceeded, optional output and warnings, the echoed fallback reason, and executionResult.

Example
{
  "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.

ArgumentTypeRequiredDescription
projectIdstringNoProject ID. Optional for project-token sessions because the token determines the active project. Interactive org-user sessions should pass projectId explicitly.
searchstringNoSearch dashboards by title or description
tagsarray of stringNoExact 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"NoWho 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).
limitinteger (1 to 500)No (default 100)Maximum number of dashboards to return
offsetintegerNoNumber 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.
cursorstringNonextCursor 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.
updatedSincestringNoISO 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.
idsOnlybooleanNoWhen 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.

ArgumentTypeRequiredDescription
dashboardIdstringNoThe unique ID of the dashboard to retrieve. Use this or dashboardIds.
dashboardIdsarray of stringNoUp to 20 dashboard IDs to retrieve at once. Use this or dashboardId.
fieldsarray of "summary", "cards", "bindings", "sql", "template", "outline"NoWhich 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.
sheetIdsarray of stringNoLimit cards, bindings, SQL, template and the outline to these sheets.
cardIdsarray of stringNoLimit 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 }.

Two dashboards with their cards
{
  "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.

ArgumentTypeRequiredDescription
dashboardIdstringYesThe unique ID of the dashboard to inspect
includeQueryInputsbooleanNo (default true)Include bounded cardConfig/cardDataSource query inputs when available so agents can use the dashboard's authored query setup.
maxCardsinteger (1 to 50)No (default 30)Maximum dashboard cards to return in the compact context.
sheetIdsarray of stringNoOnly cards on these sheets.
cardIdsarray of stringNoOnly 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

ArgumentTypeRequiredDescription
projectIdstringNoFor dashboard.generate and relationship.add in interactive sessions; dashboard changes use the dashboard's project
dashboardIdstringNoThe dashboard to change (dashboard changes)
domainIdstringNoThe semantic domain to change (relationship.add). Ignored with dashboard changes.
changesarray of objectYes1 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"
includearray of "outline"No["outline"] also returns the outline as it will be after the changes
rationalestringNoWhy 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

ArgumentTypeRequiredDescription
proposalIdstringYesThe 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.

On this page