Skip to content

Reference

Server and protocol

The Dashies MCP endpoint, its JSON-RPC transport, version negotiation, the methods it handles, and the shape every result arrives in.

Everything on this page is server-level: true for every tool call, and mostly handled by your MCP client rather than by you. Read it when you are scripting against the server, debugging a client, or working out why a call did not arrive.

Endpoint and transport

FactValue
Endpointhttps://mcp.dashies.ai/mcp
TransportJSON-RPC 2.0 over HTTP, streamable, stateless
Accepted paths/mcp and /mcp/ only
Accepted methodPOST only
Server identity{ "name": "dashies", "version": "0.6.0" }

Anything else on the API route is refused before any tool runs:

ConditionResponse
Any other path404 Not Found
Any method other than POST405 Method Not Allowed, with an allow: POST header
A body that is not JSONHTTP 400, with the JSON-RPC parse error below
No or invalid bearer token401, with a WWW-Authenticate header pointing at the OAuth metadata
{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}

The 401 is not a failure state. It is the first step of the sign-in handshake: a client that sees it discovers the OAuth metadata, registers itself, and opens your browser. See Shared rules.

Protocol version negotiation

The server supports two revisions, newest first:

["2025-06-18", "2024-11-05"]

initialize echoes the client's requested revision when it is one of those two, and otherwise advertises 2025-06-18. A client pinned to 2024-11-05 keeps working; you do not have to configure anything.

initialize advertises three capabilities, each with listChanged: false: tools, prompts, resources. It also returns the server's instructions string, which is the standing guidance Dashies gives every connected AI tool.

Methods

handleRpc accepts exactly these:

MethodPurpose
initializeNegotiate the protocol revision and read capabilities.
notifications/initializedClient handshake completion. No reply.
notifications/cancelledClient cancelled a request. No reply.
pingLiveness.
tools/listEvery tool definition.
tools/callInvoke one tool.
prompts/listThe named dashboard-authoring prompt templates.
prompts/getOne prompt template, filled in.
resources/listYour dashboards as MCP resources.
resources/templates/listThe single dashies://{handle}/{slug} URI template.
resources/readOne dashboard body by URI.

Anything else returns -32601 Method not found: <method>. Any exception inside a handler becomes -32000 Internal error: <message>.

Batches

An array body is still serviced, even though JSON-RPC batching was dropped from MCP 2025-06-18. The members run concurrently, notifications are filtered out of the reply, and a batch containing only notifications returns HTTP 204 with a null body rather than an empty string.

The shape of a tool result

Every tool result is a text envelope:

{"content":[{"type":"text","text":"..."}]}

A failure is the same envelope plus "isError": true. There is no separate error channel for tools: a refusal arrives as text your AI tool reads and acts on, which is why the per-tool Errors sections quote the exact sentences.

Most tools put a machine-readable copy of their answer inside that text, fenced between two marker lines:

BEGIN_JSON
{"count":2,"connections":[...]}
END_JSON

Some tools additionally ride a proper structuredContent payload alongside the text, for clients that read it: list_dashboards, list_dashboard_versions, introspect_schema, validate_cube_sql, list_connections, explore_data, check_readiness, set_refresh_schedule, and publish_dashboard on its body path.

No count is given, because one stood here and went stale the moment a tool was added. The list above is the answer; the TOOLS array in mcp.ts is where it comes from.

No rule is given either, and that is deliberate rather than an omission. Two attempts at one both turned out false against exceptions already written on either side of this paragraph: publish_dashboard declares no outputSchema and returns structuredContent anyway on its body path, and list_dashboard_versions declares one and returns none on its empty state, which the note below says in as many words. A set with two documented exceptions flanking it is a set to enumerate, not to legislate over.

An empty result may carry no JSON block

list_dashboard_versions deliberately emits text only when a dashboard has no snapshots: no BEGIN_JSON, no structuredContent. A parser that assumes the block is always present will throw on the empty state rather than read it.

Tool names as your client shows them

tools/list returns the bare names used throughout this site. What you see in a client depends on how the server was added:

How it was addedName shown
The Dashies plugin (recommended)mcp__plugin_dashies_dashies__<tool>
A bare MCP server named dashiesmcp__dashies__<tool>

Resources and prompts

Beyond tools, the server exposes two smaller surfaces.

Resources. URI scheme dashies://, template dashies://{handle}/{slug}, default mime type text/html. resources/list enumerates the dashboards the current authorization can see, using the same cursor as list_dashboards; a workspace-authorized connection lists that workspace's dashboards. resources/read returns a body by URI, mapping its failures onto JSON-RPC codes: an invalid URI or cursor is -32602, a missing resource is -32002, and an infrastructure failure is -32000.

Prompts. Named authoring templates, each expanding into one user message:

PromptArguments
refreshable_dashboardconnection, grain (both optional)
audit_my_dashboardsnone

refreshable_dashboard walks the spec publish flow from check_readiness through validate_cube_sql to publish_dashboard with a spec, and on until the first refresh lands. A publish_static_dashboard template is retired: publishing raw HTML bytes is not available, and every spec names a connection and declares at least one dataset, so a dashboard carrying author-supplied data has no spec that can express it.

Other endpoints

GET /healthz returns ok as text/plain. Anything else on the default handler is 404 Not Found.

Check it worked

curl the endpoint without a token. A healthy server refuses with a 401 that tells your client where to authorize:

curl -sS -i -X POST https://mcp.dashies.ai/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | head -n 20

Expect HTTP/2 401 and a www-authenticate header. A 404 there means the URL is wrong, and a 405 means the request was not a POST.