Skip to content

feat(canvas): createDataframeTools() — framework-provided dataframe_query/describe/drop surface #225

Description

@cyanheads

The api-canvas skill makes a dataframe_query tool mandatory once any tool emits a canvas_id (#185), and the linter flags its absence (#209) — but the framework ships none of that surface. Every canvas consumer hand-builds it; across ~15 consumer servers two divergent dialects have emerged:

Dialect Shape Duplicated per server
canvas-token canvas_id in tool I/O, spillover() staging query/describe/drop tool definitions + canvas accessor
shared-canvas hidden per-tenant canvas, minted df_<id> handles all of the above plus a ~400-line bridge: handle minting, provenance + TTL bookkeeping in ctx.state, catalog denial, structured missing-table errors (cyanheads/secedgar-mcp-server src/services/canvas-bridge/)

Fixes do not propagate: the structured-error work in one bridge (cyanheads/secedgar-mcp-server#47) never reached the sibling copies, and the two dialects give agents inconsistent UX across servers backed by the same primitive.

Proposal

Philosophy: the skill mandates the surface, so the framework should ship it.

A /canvas/toolkit subpath export:

const { tools, registerDataframe } = createDataframeTools({
  toolPrefix: 'secedgar',   // → secedgar_dataframe_query / _describe / _drop
  scope: 'shared-canvas',   // or 'canvas-token'
  ttlMs: 3_600_000,         // optional per-table TTL, forwarded to #140's sliding ttlMs
});

Scope

  • New src/services/canvas/toolkit/ + subpath export
  • api-canvas skill: recipe section becomes "import the toolkit"; template example updated

Out of scope

  • New engine/provider work; Workers support
  • Migrating existing consumers (per-server adoption follows separately)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions