Skip to main content
Glama
questdb

mcp-server-questdb

Official

apply_notebook_state

Apply full notebook state atomically: replace all cells, layout, variables, chart configs in one call. Use for bulk edits or from-scratch notebooks; missing cells are deleted and read-only queries run.

Instructions

Bulk-apply the entire desired state of a notebook in one atomic call. Use this for bulk edits spanning multiple cells or creating a notebook from scratch. Use update_cell or set_cell_* for small operations. Use INSTEAD OF chained add_cell + update_cell + set_cell_mode + set_cell_chart_config only when composing a multi-cell layout from scratch, changing many cells at once, or restructuring an existing notebook. The cells array is the COMPLETE desired list: cells in the current notebook whose id is missing from your request are DELETED. For new cells, omit id and one will be generated. Each cell carries exactly one of value (full verbatim SQL) or preserve_value: true (keep the existing cell's SQL, results, and run history unchanged). A changed value carries results over by content: a statement whose text is unchanged keeps its result, an edited or added one starts empty, and a rewrite that leaves nothing unchanged clears the cell's results — prefer preserve_value for every cell whose SQL you are not changing, and NEVER send a value reconstructed from a preview or a truncated get_cell read. Charts in mode='draw' render automatically — do not call run_cell afterwards. Cells with resolved mode='run' (explicit, or omitted: new defaults to 'run', existing preserves) auto-execute after the apply — EXCEPT cells whose statements include DDL/DML (INSERT/UPDATE/CREATE/DROP/...): those are NEVER auto-executed (their runs entry gets skipped: true), so applying state can never trigger a write's side effects. Take consent from the user, then call run_cell explicitly to execute them. Markdown cells (type:"markdown") are rendered prose and are likewise never auto-run. Auto-executed read-only cells run their statements in PARALLEL (one failure skips nothing; a statement rejected at validation is skipped with its validation error). Each cell also accepts auto_refresh — the same per-cell override set_cell_autorefresh writes. The response includes a runs: [{cellId, success, queryCount?, results?, error?, skipped?}] array — results is the per-statement status list ("success" / "cancelled" / "ERROR: <message>"); a top-level error is set only when the run was refused before any statement executed. Always call get_workspace_state first; the state-freshness gate applies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cellsYesComplete desired cell list, in order. Cell at index N gets position N. Missing existing-cell ids are deleted.
buffer_idYes
variablesYesOrdered notebook-scoped global variables to be referenced as @var in the query (the DECLARE block surfaced in the Variables popover). Each item is {"name": "from", "value": "dateadd('d', -7, now())"}; names have no leading '@'. Order matters: if one variable references another, place the dependency first and the dependent variable later. Values are sent as a notebook-scoped `DECLARE` block prepended to each cell statement (or merged into the cell's own `DECLARE` block when present). Globals are server-resolved at parse time, so operator precedence and lexical shadowing follow QuestDB's `DECLARE` semantics. For non-`SELECT` statement forms (`INSERT`/`CREATE`/`UPDATE`/`ALTER`/…) globals are not injected; declare locally inside the inner `SELECT` if needed. Pass null to preserve current; pass [] to clear all.
layout_modeYesNotebook layout mode after this apply. Null preserves current.
maximized_cell_idYesSpotlight one cell id, or null to clear. Pass null to clear.
auto_refresh_defaultYesNotebook-level auto-refresh default after this apply. Cells with no per-cell auto_refresh inherit it. Null preserves current.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed4 schema fields changedv0.3.1
    • addedInput schema / properties / auto_refresh_default
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": [
      +        "boolean",
      +        "null"
      +      ]
      +    },
      +    {
      +      "enum": [
      +        "1s",
      +        "5s",
      +        "10s",
      +        "30s",
      +        "1m"
      +      ],
      +      "type": "string"
      +    }
      +  ],
      +  "description": "Notebook-level auto-refresh default after this apply. Cells with no per-cell auto_refresh inherit it. Null preserves current."
      +}
    • changedInput schema / properties / cells / items / properties / auto_refresh / description
      Previous value: -"Auto-refresh for draw cells: true = adaptive poll, false = off, or a fixed interval string (\"1s\"/\"5s\"/\"10s\"/\"30s\"/\"1m\"). Null defaults to true (adaptive) when mode='draw'."New value: +"Per-cell auto-refresh value: true = adaptive poll, false = off, or a fixed interval string (\"1s\"/\"5s\"/\"10s\"/\"30s\"/\"1m\"). Omitted or null stores NO override — the cell inherits the notebook's auto_refresh_default."
    • changedInput schema / properties / cells / items / properties / grid / description
      Previous value: -"Grid position when layout_mode='grid'. x/y/w/h in 12-column units (w ≤ 12)."New value: +"Grid position when layout_mode='grid'. The 12 columns apply to width only (w ≤ 12). Rendered cell box is h*10 + (h-1)*20 px (do NOT estimate with h*30); a fixed 44px header leaves (h*30 - 64)px of content; chart plots pad a further ~40px top and ~56-86px bottom. EXAMPLES: markdown h:3 -> 70px box / 26px text (the minimum); markdown h:5 -> 130px / 86px text (a title); chart h:10 -> 280px / ~140px of plot."
    • changedInput schema / required
      Previous value: -[
      -  "buffer_id",
      -  "layout_mode",
      -  "maximized_cell_id",
      -  "variables",
      -  "cells"
      -]New value: +[
      +  "buffer_id",
      +  "layout_mode",
      +  "auto_refresh_default",
      +  "maximized_cell_id",
      +  "variables",
      +  "cells"
      +]
  2. First observedv0.3.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden and pays it off: it discloses destructive deletion of missing cell ids, id generation, preserve_value semantics, DDL/DML statements never auto-executing, markdown never auto-running, parallel execution, skipped entries, and the runs[] response shape. These go well beyond a generic mutation description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded, and nearly every sentence conveys a necessary caveat. However, it packs many critical behaviors into long flowing prose with semicolons rather than scannable structure; given the tool's complexity this is appropriate, but not maximally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers preconditions (state-freshness gate, call get_workspace_state first), safety and destructive semantics, execution behavior, output response shape, and per-cell overrides. Despite no output schema, the description tells the agent what runs[] and error will contain, making it complete for a complex bulk operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Though schema coverage is high (83%), the description adds meaning the schema can't express: the cells array is a complete PUT that deletes omitted ids, preserve_value is safest on stale reads, apply happens atomically, and auto-executed read-only cells run in parallel. This materially improves parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Bulk-apply the entire desired state of a notebook in one atomic call.' It explicitly contrasts with update_cell and set_cell_* for small operations, so an agent can distinguish it from siblings without reading their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance ('bulk edits spanning multiple cells or creating a notebook from scratch'), names the alternatives for small operations, and states when to prefer this over chained add/update/set calls. It also mandates calling get_workspace_state first, which is actionable usage direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/questdb/mcp-server-questdb'

If you have feedback or need assistance with the MCP directory API, please join our Discord server