MCP Client Guide

Build an MCP client for diagram tools: transport, auth, and the call order that works

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

Sometimes the client is your own. An internal agent, a bot, a service that needs to turn a description into a diagram without a human in the loop. The Datadef server is an ordinary Streamable HTTP MCP endpoint, so the official SDKs connect to it in a few lines, and the design decisions that matter are about which tools you expose and in what order.

7 min readFor engineers wiring a custom agent or service to an MCP server with the official SDK

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

151/20003 credits left
Try:

No account needed · Editable canvas, not a picture

Connecting with the SDK

The TypeScript SDK gives you a Client and a StreamableHTTPClientTransport. The transport takes the endpoint URL and a requestInit object whose headers carry the bearer credential. The Python SDK has the same shape through its streamable HTTP client, which takes a headers mapping.

The server is stateless, which simplifies the client. It reports itself as datadef version 1.0.0 during the handshake, there is no session identifier to thread through subsequent requests, and a request carries everything the server needs to answer it. A tool call may run for up to five minutes, so set your client timeout above the default rather than discovering the ceiling through cancelled generations.

One caveat that has bitten people on several SDK versions: custom headers belong in the transport options, not in the client options, and older releases dropped them silently. If tool calls come back unauthorized while listings succeed, print the outgoing headers before suspecting the key.

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const transport = new StreamableHTTPClientTransport(
  new URL('https://datadef.io/mcp'),
  {
    requestInit: {
      headers: { Authorization: `Bearer ${process.env.DATADEF_API_KEY}` },
    },
  },
);

const client = new Client({ name: 'my-agent', version: '1.0.0' });
await client.connect(transport);

const { tools } = await client.listTools();   // 36 tools
const result = await client.callTool({
  name: 'create_diagram',
  arguments: { prompt: 'Kafka to Snowflake pipeline with dbt models', scope: 'overview' },
});

Discovery before credentials

You can build against this server before anyone has created a key. The handshake and the listings are anonymous: initialize, ping, tools/list, prompts/list, resources/list and the templates listing all answer without credentials. Only tools/call is gated. That is deliberate, so directories and crawlers can score the server, and it happens to be the most convenient thing about integrating with it.

The practical use is code generation and testing. Pull the tool schemas in CI, generate typed bindings from them, and assert that the tools your agent depends on still exist with the argument names it uses. A schema change then breaks a test rather than a production run.

The same anonymity gives you a clean health check that does not need a secret in the monitoring system. A tools/list that returns 36 entries means the server is up and complete.

Which tools to expose, and in what order

There are two layers. Nine outcome tools do whole-diagram work: create_diagram, create_blank_diagram, list_diagrams, get_diagram, edit_diagram, export_diagram, repo_status, repo_refresh and get_design_guide. Twenty-seven canvas tools, all prefixed canvas_, operate on individual elements: nodes, edges, columns, groups, lineage, annotations, geometry, layout and validation.

For an agent that should produce a good diagram from a description, expose create_diagram and stop there. For an agent that builds deliberately, the working order is get_design_guide first, then create_blank_diagram, then adding nodes, grouping them into zones, connecting them, laying out, and finally validating and measuring. Feeding the design guide in as a system prompt is more reliable than hoping the model calls the tool, because the guide is what keeps output at the same standard as a generated diagram.

End every build with canvas_validate_canvas and canvas_measure_canvas. Orphan nodes, overlaps and a canvas that is far too large are the failure modes a language model cannot detect in its own output, and they are exactly what these two report. An agent that treats their output as a to-fix list produces diagrams that survive review.

Credits and plans, in one line

Generation consumes a credit and is refunded when it fails. Tool calls need an active paid plan, rechecked on every request rather than at issue time, and every new account starts with a 7-day trial that needs no card.

The four limits a headless client has to handle

Time. A tool call may run for up to five minutes. create_diagram holds the connection for about 35 seconds and returns a finished diagram if generation lands inside that window; otherwise it returns a diagram_id and expects you to wait roughly 60 seconds and poll get_diagram every 30. Typical end-to-end is one to three minutes. Calling create_diagram again while one is still generating produces a duplicate and spends a second credit, so the retry path in your client has to be a poll, never a re-call.

Credits. Generation consumes one and refunds it when generation fails, so a failed run costs nothing but the wait. create_blank_diagram spends nothing at all, which is why an agent that builds deliberately with the canvas tools is cheaper than one that regenerates until it likes the result.

Refreshes. repo_refresh is bucketed at ten per ten minutes per account, so a client fanning out across linked projects has to pace itself rather than discover the ceiling in production. A refresh also regenerates from the repository and replaces manual canvas edits, so it belongs only on projects whose diagram is meant to be generated.

Attribution. Every call is recorded with the credential label, the tool name, the status, the duration and an argument excerpt capped at 140 characters; full prompts are never stored. Give an autonomous client its own key with its own label and its traffic stays separable from human traffic at a glance, which is the difference between debugging an agent and guessing about it.

FAQ

How does a custom client authenticate against this MCP server?

With an Authorization bearer header carrying a Datadef API key, or with an OAuth 2.1 access token obtained through the authorization code flow with PKCE. Both resolve to the same user and the same tools. In the TypeScript SDK the header goes in the transport requestInit options, not in the client options.

Do I need to manage a session identifier?

No. The server is stateless, so each request carries everything needed to answer it and there is no session header to persist between calls. The server identifies itself as datadef version 1.0.0 during the handshake. It also means a client can be restarted or scaled horizontally with no reconnection dance, because no server-side state is tied to a particular connection.

Can I read the tool schemas before I have an API key?

Yes. The handshake and every listing method answer anonymously, including tools/list, so you can generate typed bindings and write contract tests against the real schemas before any credential exists. Only tool calls require authentication. The same property gives monitoring a health check that needs no secret: post tools/list and assert that 36 entries come back.

How long can a single tool call take?

Up to five minutes. Diagram generation returns a finished result if it completes within about 35 seconds and otherwise returns an identifier to poll, so a client should raise its default timeout and implement the poll rather than retrying the generation.

Which tools should an autonomous agent be given?

For a single-shot result, just the generation tool. For deliberate construction, the design guide tool first, then the blank diagram tool and the element-level canvas tools, finishing with validation and measurement so the agent can catch orphan nodes, overlaps and oversized canvases before handing the result over.