Create playbooks via MCP — tool sequence

Standard admin workflow for AI agents using the anythinggraph-thin MCP server to author playbooks and bindings. Based on ag-cli/AGENTS.md and the MCP server instructions in serverCore.ts.

Use MCP tools only. Agents should call registered tools (introspect_source, query_graph, …) — not curl or scripts against port 8787 unless the user explicitly asks for a standalone script.

Before any MCP tools

These steps are manual — MCP cannot do them:

  1. Start the stack./start-all.sh in ag-cli/ (reasoning-service on :8787, MCP on :3334/mcp).
  2. Configure credentials — edit profiles/local.yaml and set env vars such as AG_SQL_DSN, AG_NOTION_TOKEN, AG_PAYROLL_CSV_PATH.
  3. Connect MCP with an admin token — set AG_ADMIN_TOKENS and pass Authorization: Bearer <admin-token> in Cursor or Claude MCP config.
Profiles are never written via MCP. Agents discover sources with list_sources but cannot save credentials.

Visual flow

End-to-end path from service health check to a governed query. The binding block repeats once per source key in your playbook sources map (e.g. postgres, csv, notion).

Optional before authoring — copy demo templates:

  • get_binding("crm-payroll-access.postgres")
  • get_binding("crm-payroll-access.csv")

Full sequence (one line)

health_check → list_sources → get_adapter_guide(source_id) # once per source → introspect_source(source_id, schema_name?) → propose_playbook → save_playbook → get_playbook_context → suggest_bindings(playbook_id, source_id) → propose_binding → test_binding(execute=true) → save_binding # repeat binding loop for each source key → query_graph

Phase 1 Discover sources & schema

StepToolPurpose
1 health_check Confirm reasoning-service is reachable
2 list_sources Real source_id values from profile — never invent ids
3 get_adapter_guide(source_id) Required before bindings — instructions_markdown, example_binding_yaml, what schema_name means
4 introspect_source(source_id, schema_name?) Live schema (Postgres tables/columns/FKs, Notion properties, CSV headers, …)

Repeat steps 3–4 for each source your playbook will use.

For Postgres, schema_name defaults to public. For Notion, schema_name is the database id (see adapter guide).

Phase 2 Create the playbook

StepToolNotes
5 propose_playbook(playbook_id, playbook_json) Validates compact JSON — no disk write
6 save_playbook(playbook_id, playbook_json) Writes playbooks/{id}.json

Save the same JSON you passed to propose_playbook — not a reformatted dump from the response.

Compact playbook shape uses maps: entities, relationships, sources, optional access. See the playbooks guide for examples.

Phase 3 Create bindings (per source key)

StepToolNotes
7 get_playbook_context(playbook_id) Confirm entities, relationships, source routing
8 suggest_bindings(playbook_id, source_id, schema_name?) Heuristic entity → table / object mapping
9 propose_binding(playbook_id, binding_yaml) Validate YAML — read save_instruction in response
10 test_binding(playbook_id, binding_yaml, execute=true, …) Compile + optional live read-only query
11 save_binding(playbook_id, adapter_suffix, binding_yaml) Writes bindings/{playbook_id}.{suffix}.yaml

adapter_suffix matches the source key in the playbook sources map (e.g. postgres, csv). The profile id (e.g. warehouse_pg) goes inside binding YAML as source_id.

Repeat steps 8–11 for every entry in sources.

Binding YAML allowed keys: source_id, entities, relationships only (unless adapter guide says otherwise). No raw SQL, lookup, or operations blocks.

Phase 4 Verify & query

StepTool / commandPurpose
12 query_graph(playbook_id, entity, by_name, …) End-to-end test with proof envelope
cargo run -p anythinggraph-ag -- validate --playbooks playbooks CLI validation (outside MCP)

If the playbook defines ReBAC access, pass subject_id on queries and use list_allowed_rows to inspect visible row ids.

Workflow variants

A. New playbook from scratch

Run the full sequence above — Phase 1 through Phase 4.

B. Map an existing demo playbook to your database

Skip propose_playbook / save_playbook. Start at:

get_playbook_context → suggest_bindings → propose_binding → test_binding → save_binding → query_graph

Example prompt:

Using anythinggraph-thin MCP: load playbook crm-payroll-access, inspect my Postgres
source, suggest how to map entities to my tables, test the binding, and save it.

Golden rules

  1. propose_* validates; save_* persists — same input both times.
  2. Never save debug_compiled_binding_yaml — debug only when AG_DEBUG_COMPILED=1.
  3. source_id always from list_sources — never invented.
  4. get_adapter_guide before propose_binding — binding shape is adapter-specific.
  5. Compact declarative format only — see ag-cli/AGENTS.md.
  6. Live data is read-only — no insert/update/delete via MCP.

Auth & roles

RoleCan create playbooks?
admin Yes — all authoring tools (propose_playbook, introspect_source, …)
user No — query only (query_graph, get_playbook_context, …)
{
  "mcpServers": {
    "anythinggraph-thin": {
      "url": "http://127.0.0.1:3334/mcp",
      "headers": {
        "Authorization": "Bearer admin-secret-change-me"
      }
    }
  }
}

Example agent prompt (full onboarding)

Connect to anythinggraph-thin MCP as admin. For my Postgres warehouse_pg source:
1) introspect the schema
2) create a new playbook "my-crm-access" with entities for users and accounts
3) map bindings, test with execute=true, and save
4) query how many accounts Alex Anderson owns

Troubleshooting

“Postgres introspection failed; pulling schema from bindings”

This message comes from the AI agent, not AnythingGraph. It means introspect_source failed and the agent fell back to get_binding / get_playbook_context.

Common fixes:

  • Set AG_SQL_DSN before ./start-all.sh
  • Confirm Postgres is running and tables exist (default schema public)
  • Use an admin bearer token — user tokens cannot introspect
  • Use source_id from list_sources (e.g. warehouse_pg)

403 insufficient role

MCP client is using a user token. Switch to an admin token from AG_ADMIN_TOKENS.

Binding save rejected

Call get_adapter_guide(source_id) first. Remove forbidden keys (lookup, operations, raw SQL). Save the same YAML you passed to propose_binding.