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.xyz/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 | The eighteen tool definitions. |
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
Seven 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,
set_refresh_schedule, and publish_dashboard on its body path.
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 eighteen 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. Three named authoring templates:
| Prompt | Arguments |
|---|---|
publish_static_dashboard | topic (required), slug (optional) |
refreshable_dashboard | connection, grain (both optional) |
audit_my_dashboards | none |
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.xyz/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.