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
| Fact | Value |
|---|---|
| Endpoint | https://mcp.dashies.ai/mcp |
| Transport | JSON-RPC 2.0 over HTTP, streamable, stateless |
| Accepted paths | /mcp and /mcp/ only |
| Accepted method | POST only |
| Server identity | { "name": "dashies", "version": "0.6.0" } |
Anything else on the API route is refused before any tool runs:
| Condition | Response |
|---|---|
| Any other path | 404 Not Found |
| Any method other than POST | 405 Method Not Allowed, with an allow: POST header |
| A body that is not JSON | HTTP 400, with the JSON-RPC parse error below |
| No or invalid bearer token | 401, 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:
| Method | Purpose |
|---|---|
initialize | Negotiate the protocol revision and read capabilities. |
notifications/initialized | Client handshake completion. No reply. |
notifications/cancelled | Client cancelled a request. No reply. |
ping | Liveness. |
tools/list | Every tool definition. |
tools/call | Invoke one tool. |
prompts/list | The named dashboard-authoring prompt templates. |
prompts/get | One prompt template, filled in. |
resources/list | Your dashboards as MCP resources. |
resources/templates/list | The single dashies://{handle}/{slug} URI template. |
resources/read | One 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 added | Name shown |
|---|---|
| The Dashies plugin (recommended) | mcp__plugin_dashies_dashies__<tool> |
A bare MCP server named dashies | mcp__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:
| Prompt | Arguments |
|---|---|
refreshable_dashboard | connection, grain (both optional) |
audit_my_dashboards | none |
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.