The MCP tool surface is self-describing.
get_schema(<kind>) returns the live,
apply-layer-enforced shape of any document or registry — call
get_schema(graph_dsl) before authoring and get_schema(node_types) for the
current node-type alphabet. This tutorial names specific tools and types, but
get_schema is always the source of truth if anything here has moved on.Prerequisites
- A Panels account (sign up free).
-
An MCP client connected to your workspace. If you haven’t done this, follow
Connect a client first —
one command in Claude Code:
-
A database connection secret in your workspace (this tutorial uses one named
postgres_prod). Any reachable Postgres works; swap the secret name and table for your own.
What you’ll build
type, a config
(how it runs), its inputs (upstream node names), and a typed payload —
source for ingest, transform for SQL.
Build it
1
Find your project
Every graph lives inside a project. List what you can reach and keep the
project_id you want to build in:2
Find or create the graph
A project’s computation graph is a scope document at
Keep the
project.dsl/graph/<graph_id>. List existing graphs; if there are none, reading
the bare path once lazy-creates the first graph, after which it has a stable id:etag — every write is optimistic-concurrency checked against it. If a
write returns ETAG_STALE, re-read and retry with the fresh etag.3
Write the pipeline
When the graph is empty you can author the whole thing in one Pass it as the
core_write_scope
call. orders_raw pulls a Postgres table; orders_clean drops cancelled rows;
revenue_by_day aggregates and materialises as a table:content of the write:4
Run it
core_run_node walks the upstream chain automatically — calling it on the leaf
materialises orders_raw and orders_clean first, then revenue_by_day:5
Verify
core_list_nodes reports each node’s schema_summary, row_count, and
last_run.status. Filter to the nodes that produced data:core_read_scope never returns table rows inline — to read the actual data, use
the artifact-presign URL on a node’s last_run.6
Iterate
For follow-up changes, prefer
core_edit_scope (a surgical text splice that
preserves the rest of the document and produces a readable diff) over rewriting
the whole graph. Say the source table was misnamed:Make it interactive: add a selection
A selection node is an interactive filter over upstream data — a status picker, a date range, a region list. Add one and wire a query to it, and that query re-filters whenever the value changes. The important part is how selections connect: you do not reference a selection in SQL. Its active clauses are composed into the downstreamWHERE by the
server at evaluation time, so wiring the input edge is the whole job.
Declare the selection node. Its payload rides definition, and data_type is
the value shape — scalar, list, or range — not a SQL type:
inputs —
and leave the SQL untouched:
status_filter re-filters server-side when the
selection changes — no SQL edit, no extra wiring. To give it a UI affordance,
add a selection element to a view (see view authoring).
Next steps
MCP server reference
Endpoints, OAuth, and the
operator scope for privileged operations.Build a dashboard
Turn a pipeline’s output into an interactive, shareable dashboard.