# How Bonnard Builds Agent-Friendly MCPs

> Source: <https://dev.to/maxbonnard/how-bonnard-builds-agent-friendly-mcps-n4i>
> Published: 2026-07-16 15:25:44+00:00

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](https://bonnard.dev/blog/mcp-charts) and the

`visualize`

tool.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.

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
```

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:

`partial`

or `complete`

, so the agent knows whether it is looking at everything.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.

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.

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.

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.

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.

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](https://bonnard.dev/blog/mcp-charts).
