MCP Charts

How Bonnard Builds Agent-Friendly MCPs

Exposing your data over MCP is the easy part. Designing a tool an agent uses well is the hard part. An agent can only use a tool it can read, so the work is shaping the tool for how the model calls it, not just for the human looking at the result. These are the techniques behind @bonnard/mcp-charts and the visualize tool.

Discovery-first, so the agent stops guessing

An agent that guesses your schema writes wrong queries. So the first tool the agent meets is a discovery tool. It calls visualize_read_me to load the chart options, the tool schema, and worked examples before it ever calls visualize, and an explore_schema tool to learn your tables and columns before it writes SQL. The agent reads, then acts.

A small set of purpose-built tools

The temptation is one tool per metric, or a single tool that takes arbitrary SQL and hopes. Both fail: too many tools blow the agent’s attention budget; one firehose tool gives it no guardrails. Bonnard ships a small set, discover, query, visualize, each with a narrow, obvious job. The agent picks the right one because there are few of them and each does one thing.

// a small, purpose-built set, not one tool per metric
server.registerTool("explore_schema", { /* list tables + columns */ }, listSchema);
addCharts(server, { runSql }); // registers visualize_read_me + visualize

Compact, honest responses

A tool that returns 10,000 raw rows poisons the context window and the agent’s next decision. Bonnard’s responses are sized for a model to read:

  • Row caps with a completeness flag. Results are capped and tagged partial or complete, so the agent knows whether it is looking at everything.
  • Partial-result warnings. When results are capped, the response says so and tells the agent not to sum or average the visible rows, use a measure instead.
  • Summaries over dumps. The chart comes back with a compact text summary the model can reason over, not just an image it cannot read.

Errors that guide the next action

A bare “error: invalid column” stalls an agent. Bonnard’s errors carry a fix. A bad field name returns a hint to check names with explore_schema; a SQL error returns targeted guidance; successful calls include a next_step pointing at the right follow-up tool. The agent self-corrects instead of looping.

Determinism over improvisation

The most important move is pushing deterministic work out of the model and into the code. The agent picks what to show (a chart type, a query). Bonnard decides how: it infers axes from the typed result, auto-detects currency and percentage formatting, fills missing time buckets, and labels null dimensions. The smaller the agent’s decision surface, the less there is to hallucinate.

Tool descriptions that double as instructions

To an agent, the tool description is the documentation. Bonnard’s tools use a typed schema with a description on every field, plus a read-me tool that returns usage examples on demand. The agent knows how and when to call visualize because the schema tells it, not because you wrote a prompt.

Frequently asked questions

What makes an MCP tool “agent-friendly”?

It is shaped for how a model calls tools: discovery-first so the agent learns before it acts, a small set of narrow tools, compact responses with completeness flags, errors that suggest the fix, and a typed, self-describing schema. The agent uses it correctly without hand-holding.

Why not just let the agent write SQL and draw the chart?

Text-to-SQL against raw tables is wrong often enough that you cannot put it in front of a customer, and an agent drawing its own chart HTML is non-deterministic. A governed query path plus a dedicated chart tool returns consistent, trustworthy visuals.

Does Bonnard support raw SQL at all?

Yes, as a narrow, audited path, not a bypass around governance. You control what runs via your runSql callback.

See the product this is built on: MCP Charts.