Reference
The wire contract for the Graphistry visualization MCP endpoint. See Graphistry MCP for connecting and authenticating.
Methods
| Method | Auth | Notes |
POST /mcp — initialize | None | Returns protocolVersion, capabilities, and server instructions. Sets the mcp-session-id response header. |
POST /mcp — tools/list | None | Returns all nine tool definitions. Requires mcp-session-id. |
POST /mcp — tools/call | Required | Executes a tool. Requires mcp-session-id and an Authorization header. |
POST /mcp — notifications | None | Acknowledged with 202. |
GET /mcp | None | Opens the SSE stream the transport expects; requires mcp-session-id. The server holds it open but does not push notifications. |
DELETE /mcp | None | Closes the MCP transport session. |
Only tools/call requires a credential.
Tools
Every tool except list_sessions takes session_id, the id of a live Graphistry
visualization. Tools marked owner may only be called by the person
who has that visualization open; tools marked read are also available
to anyone entitled to view the underlying dataset.
list_sessionsread
Lists your own active visualization sessions — the ones opened by the account whose credential you sent. It never enumerates other people's sessions. Takes no arguments.
Treat the result as a best-effort list rather than a complete one: a session you know is open can be absent. The
more reliable source is the viewer's own address bar — the session= parameter of their
visualization URL is the same id. Every other tool takes the session_id directly and is unaffected.
get_session_inforead
Returns a plain-text schema summary for one session — not JSON. The result is a newline-separated block giving the session id, node and edge counts, the node id column, and the node and edge column names with their dtypes, plus the workbook title and description when they are set. Call this before your first query and choose column names only from the schema it returns.
Every column of the session is listed. Number, text and boolean columns also carry a short summary of what they hold: a
numeric range such as [number, 0 to 0.14], all <value> when every row shares one
number, 1 distinct when they share a value the summary will not state exactly, a distinct-value
count such as [string, 12 distinct] for text, or empty when the column holds no values.
A count shown as 40000+ distinct means the column reaches the counting limit. Range bounds are
rounded outward, so a filter built from them never excludes a row the column holds. Columns of other types, such
as dates, are listed with their dtype and no summary. Summaries are computed per axis and are skipped when the
column count multiplied by the row count is large — roughly 2 million, so a 250-column graph keeps them to
about 8,000 rows. A distinct count costs more than a range, so text and boolean columns stop being counted about
twice as soon, near 1 million; the reply then says distinct counts skipped while ranges continue.
The reply says per-column summaries skipped when all of them stop, and
summaries unavailable for N column(s) when a column's values could not be read. A range bound is the
column's own smallest or largest value, rounded outward when four significant digits cannot state it exactly;
summaries describe the whole dataset and do not narrow to a filtered view. Row data itself comes from
query_graph.
Arguments: session_id (required).
query_graphread
Runs a read-only query to filter, traverse, or summarize the graph.
| Argument | Type | Notes |
session_id | string | Required. |
gfql_operations | string | Required. One whole read-only Cypher query. |
output_type | enum | shape (default, counts only), nodes, edges, or all. |
format | enum | Leave unset. Only json is returned; csv is advertised in the schema but is
not supported, and asking for it either has no effect or fails the call. |
A query that matches nothing returns success with zero rows. Some malformed shapes do the same, so treat an empty result as unverified until you have confirmed the columns and values exist. One case is handled for you: when a string filter matches nothing exactly, the query is retried once matching that value ignoring case and punctuation, and if that matches, the reply names the filters that were loosened. The retry applies only to the legacy JSON GFQL form, never to a Cypher query.
create_collectionowner
Colors the nodes or edges matching a query, and the viewer sees the change immediately. See Collections for how collections stack and the palette list.
| Argument | Type | Notes |
session_id | string | Required. |
name | string | Required. Shown in the collections panel. |
gfql_operations | string | Required. One read-only Cypher query in a supported shape: a node filter
(MATCH (n) WHERE ... RETURN n), the endpoint of one directed relationship
(MATCH (a)-[e]->(b) WHERE ... RETURN DISTINCT b), an id list
(MATCH (n) WHERE n.<id> IN [...] RETURN n), or the connections of one directed
relationship (MATCH (a)-[e]->(b) WHERE ... RETURN e), which colors edges. Cypher with
CALL, UNION, an aggregate, a projection, or an undirected, multi-hop, or
variable-length pattern cannot be a collection, and neither can ORDER BY or LIMIT
on connections. |
node_color | string | Hex, #RRGGBB or #RRGGBBAA. |
palette | string | Palette name, for example Blues. If both are given, node_color wins. |
description | string | One-line summary. |
Validate the expression with query_graph first, then pass the identical string here. The response
carries collection.matchCount — the number of elements colored, or null when the
count is unknown. Do not read null as zero.
A collection whose name already exists is replaced, not added alongside. Vary the
name to keep both.
list_collectionsread
Lists the collections on the graph, each with its id, name, position
(0 = rendered on top), and color. Call this before any tool that takes a collection_id.
Arguments: session_id (required).
update_collectionowner
Renames or recolors an existing collection. Does not change which elements match.
Arguments: session_id, collection_id (both required);
name, node_color, palette (all optional, omit rather than passing null).
delete_collectionowner
Deletes one collection, leaving the rest intact. The built-in global background layer cannot be deleted.
Arguments: session_id, collection_id (both required).
reorder_collectionsowner
Sets render order. Where collections overlap, an earlier one is painted on top of a later one. Ids left out of the array keep their relative order after the listed ones.
Arguments: session_id, order (array of collection ids, first = on top).
reset_collectionsowner
Clears every collection at once, returning the graph to its default view.
Arguments: session_id (required).
Results and errors
A tools/call returns the tool's payload as JSON serialized into a text content block, so
the caller decodes twice: once for the JSON-RPC envelope, then again for
result.content[0].text.
Check for failure by looking for an error key in that decoded payload, not by checking
isError. When a tool fails for a reason of its own — an invalid query, a column that
does not exist — it reports that failure inside its payload and the response is still an ordinary
HTTP 200 success with no isError flag:
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text",
"text":"{\"error\":\"[column-not-found] Column \\\"degree\\\" does not exist in dataframe\"}"}]}}
isError: true appears only when a tool crashes unexpectedly. A client that branches on
isError alone will read ordinary tool failures as successes. Transport and authorization failures are
different again — those use HTTP status codes and JSON-RPC error codes, listed below.
| HTTP | Code | Meaning |
| 400 | -32700 | Parse error — body is not JSON-RPC. |
| 400 | -32000 | Missing mcp-session-id header. |
| 400 | -32602 | Invalid params. |
| 401 | -32001 | Missing or invalid credential. Carries a WWW-Authenticate header. |
| 403 | -32003 | Talk2Graph is not enabled for the account. |
| 403 | -32002 | Caller may not modify, or may not access, this session. |
| 404 | -32000 | Unknown or expired mcp-session-id. Re-initialize. |
| 410 | -32004 | Session owner unavailable — the visualization closed. |
| 500 | -32603 | Internal error. |
| 503 | -32006 | Authorization check could not be completed. Retry. |
| 504 | -32005 | Tool call timed out. |
| — | -32601 | Unknown method or unknown tool name. |
Limits
| Limit | Value |
| Collections per session | 10 (oldest dropped past the cap) |
| Query rows returned | 50 (20 when no columns are projected) |
| Tool call timeout | 60 seconds |
| Credential revocation latency | Up to 60 seconds — a revoked key can still work briefly |
Registry metadata
For clients that read a
server.json manifest, the
descriptor for this endpoint is below. It is not served from your Graphistry host and is not
published to the MCP registry — copy it into your own tooling. A client that understands manifest
variables will prompt you for host; anything else needs {host} replaced
with your Graphistry hostname by hand.
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "com.graphistry/viz",
"title": "Graphistry Visualization",
"description": "Query and recolor a live Graphistry graph visualization session",
"version": "1.0.0",
"websiteUrl": "https://hub.graphistry.com/docs/mcp/intro/",
"remotes": [
{
"type": "streamable-http",
"url": "https://{host}/mcp",
"variables": {
"host": {
"description": "Your Graphistry server host, for example hub.graphistry.com",
"isRequired": true
}
},
"headers": [
{
"name": "Authorization",
"description": "Bearer <key_id>:<key> using a Graphistry personal key, or Bearer <jwt> using a viewer token. Required on tools/call.",
"isRequired": true,
"isSecret": true
}
]
}
]
}