Skip to content

bino mcp

bino mcp runs a Model Context Protocol server over stdio, exposing bino’s introspection, validation, authoring, and build surface to AI agent clients such as Claude Code, Claude Desktop, and Cursor.

Because a bino report is plain-text YAML + SQL, an agent can author it directly - and bino’s schema and validation become the guardrails that tell the agent precisely whether what it wrote is correct.

bino mcp [--work-dir DIR]

Most agent clients are configured with a command, so bino mcp is the entrypoint you register once. Under the hood:

  • Proxy mode - if a bino daemon is already running for the project (for example because VS Code is open), bino mcp connects to that daemon’s /mcp endpoint and forwards to it, so the agent reuses the daemon’s already-loaded DuckDB session and file watcher instead of starting a second one.
  • Standalone mode - with no daemon running, bino mcp loads the project itself and serves the MCP directly.

Flags:

  • --work-dir, -w - report bundle directory (default: .).
  • --no-proxy - always run standalone, even if a daemon is running.
  • --allow-publish - also expose the registry_publish tool (see Security). When bino mcp proxies to a running daemon, the daemon’s --mcp-allow-publish flag decides instead.

Clients that speak MCP over HTTP can instead point straight at a running daemon’s endpoint (http://127.0.0.1:<port>/mcp; the port is recorded in .bino/daemon.json). The daemon mounts /mcp by default on loopback - pass bino daemon --mcp=false to disable it.

claude mcp add bino -- bino mcp --work-dir /path/to/report

Add an entry to the client’s MCP config (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json):

{
  "mcpServers": {
    "bino": {
      "command": "bino",
      "args": ["mcp", "--work-dir", "/path/to/report"]
    }
  }
}

Read-only context an agent can pull in:

URI Contents
bino://schema The full merged JSON Schema for all manifest kinds (built-in + plugin).
bino://schema/{kind} The self-contained spec schema for one kind (e.g. bino://schema/Table).
bino://kinds Every manifest kind and its capability category (data / layout / embeddable / artefact / config).
bino://documents The project index: every document → {kind, name, file, position}.
bino://packages The project’s registry packages: bino.lock merged with bino.toml [dependencies], with installed state.
bino://templates The built-in and curated templates init_bundle can scaffold from.
bino://skills Index of the knowledge skills below: name and description of each, as JSON.
bino://skills/{name} One skill as markdown (e.g. bino://skills/bino-ibcs), the same text the prompt of that name carries.

The server also serves bino’s authoring and IBCS knowledge as MCP prompts. They are the same skills the Claude Code plugin ships, embedded in the binary, so any client that can run bino mcp gets them without a copy of the plugin. Each prompt takes no arguments and returns one user message with the skill text; the same text is readable as bino://skills/{name}.

Prompt What it teaches
bino-concepts bino’s mental model: the manifest envelope, the DataSource → DataSet → LayoutPage → artefact pipeline, dependencies, standard columns, params, constraints, bino.toml. Read first.
bino-authoring The authoring loop through this server: outline, scaffold, learn columns, draft, validate_draft, write, validate_project, build.
bino-ibcs The IBCS rubric: SUCCESS rules, scenarios (ac/pp/fc/pl), variances, notations, choosing a component, data-aware commentary. Includes the full IBCS standard reference and the engine data model.
bino-data-modeling Mapping raw source columns onto scenario slots, deriving variances, choosing the grain, writing typed DataSet SQL.
bino-validation-loop The four-layer check (schema, IBCS, build-readiness, acceptance) and the bounded fix loop.

The plugin’s bino-orchestration and bino-requirements skills are not served: they drive Claude Code specific machinery (subagents, questions to the human) and mean nothing to other clients.

Tool What it does
list_kinds Every manifest kind with its capability category.
outline_kind(kind) A compact outline of one kind’s spec: every field with its path, type, required flag, enum, default and description. Layout kinds report the allowed child kinds as childKinds. Start here.
scaffold_kind(kind) A minimal YAML document for one kind with every required spec field pre-filled.
describe_kind(kind) The full spec JSON Schema for one kind. Large (up to ~20k tokens for layout kinds); prefer outline_kind.
describe_project() All documents in the project.
describe_document(file) The documents declared in one file.
get_columns(name) Column names of a DataSet or DataSource (prefix $ to force a DataSource).
get_rows(name, limit?) A sample of rows from a DataSet or DataSource.
graph_deps(kind, name, direction?, max_depth?) Dependencies (out), dependents (in), or both. Component nodes carry a columns list (dataset, column, role, field) of the dataset columns they read.
Tool What it does
validate_project(execute_queries?) Validate the project on disk; optionally execute datasets for data-validation warnings.
validate_draft(yaml) Validate manifest YAML in memory (no disk write) - the pre-write guardrail.
introspect_source(spec, sheet?, limit?) Probe a not-yet-registered CSV/Excel/DB source: columns, sample rows, sheets, detected CSV options.
Tool What it does
create_manifest(kind, name, spec, ...) Create any manifest from a spec object; validated and written atomically, auto-placed by project convention.
write_manifest(file, yaml, append?) Persist a full manifest document, validated before writing.
edit_manifest(file, position, patch) Edit one document in place via dotted-path edits, preserving comments and key order.
remove_manifest_fields(file, position, paths, dryRun?) Delete dotted paths from one document in place; a trailing [index] removes a sequence element. Validated before the atomic write; dryRun returns the rewritten file instead.
reorder_manifest_sequence(file, position, path, from, to, dryRun?) Move an element within a sequence (e.g. spec.columns) from one 0-based index to another, in place and validated.
scaffold_source(dataSource, dataSet?) Scaffold a DataSource and an optional typed DataSet in one step.
init_bundle(...) Bootstrap a new starter report bundle.

Every write validates against the merged JSON Schema before persisting, so an agent cannot write a structurally invalid manifest. Writes are atomic (temp file + rename).

Tool What it does
build(artefacts?, out_dir?) Render artefacts by running bino build - streams progress and returns the exit code, output, and produced artefacts. Subject to the usual engine-compatibility check.
get_layout_state(artefact?, component?) Build with a layout capture and report what actually rendered: per component the box, row/bar counts, resolved scaling and diagnostics, plus findings (empty components, overflow, auto-fitted fonts, diverging scales). Slow (headless Chrome). Requires template engine v1.0.0-next.24 or newer.
Tool What it does
registry_packages() The project’s dependencies, offline: bino.lock merged with bino.toml [dependencies], whether each is installed under .bino/registry/, and the params each package declares.
registry_search(query, kinds?, scopes?, tags?, page?, per_page?) Search the registry for published packages (network). Use it before authoring a component from scratch.
registry_info(spec) Resolve one package spec (@scope/name, optionally @version or @tag): version, kinds, files, dependencies, and the installed version when the project already locks it.
registry_auth_status() The resolved registry URL, whether a credential is available, and where credentials are stored. Never returns the token.
registry_add(specs) Add packages as dependencies: resolves the transitive closure, verifies every download, then writes bino.toml, bino.lock and .bino/registry/. Reports name collisions with local documents.
registry_update(packages?) Re-resolve tag-following dependencies to their newest versions and rewrite bino.lock; exact pins are held.
registry_remove(packages) Remove dependencies from bino.toml and delete every locked package no longer reachable (offline).
registry_install() Re-materialize .bino/registry/ exactly as pinned in bino.lock, without re-resolving.
registry_publish(bump?, dry_run?, visibility?) Run bino publish --json for the project’s [package]. Only registered when the server was started with the opt-in flag - see Security.
1. outline_kind({kind:"Table"})       → the Table spec fields, types, enums, defaults
2. scaffold_kind({kind:"Table"})      → a minimal Table document to fill in
3. get_columns({name:"sales"})        → {columns:["region","ac1","pl1",...]}
4. draft the Table manifest using those columns
5. validate_draft({yaml:"..."})       → {valid:false, diagnostics:[{message:"...", ...}]}
6. fix and re-validate                → {valid:true}
7. create_manifest({kind:"Table", name:"q3", spec:{...}})
8. build({artefacts:["q3"]})          → q3.pdf

The server runs SQL, reads the filesystem, and (via build) launches headless Chrome. This is intended for local use over stdio and a loopback HTTP endpoint. Exposing the daemon on a non-loopback address (bino daemon --listen-addr) is out of scope for this surface and would require additional hardening.

registry_publish is off by default. It is only registered when a human starts the server with bino mcp --allow-publish, or bino daemon --mcp-allow-publish when bino mcp proxies to a running daemon. Publishing is irreversible - it mints an immutable version that cannot be deleted - and a first publish with visibility: public makes the package public, so an agent must not be able to trigger it by accident. The other registry tools only change the local project and never return a credential; when registry_auth_status reports none, the human runs bino registry login.