Standalone guide

MCP or a single API call

A judgment call on two axes, not a rule that decides for you.

Behrad Mirafshar
Behrad Mirafshar
Founder, Bonanza Design
7 min read

What you end this page with

You end this page with a way to decide between an MCP server and a single API call for one specific job, not a rule that decides for you.

This is a decision, not a method, so there is no assignment here and nothing to build. It sits under Specialist 4, Automate recurring work, because skills, hooks and MCP all answer the same question (how does your method run without you) from different angles.

MCP vs API: the two axes

Two things decide this, not one. Weigh both before reaching for either.

Token cost

Every tool an MCP server offers has to describe itself: its name, what it does, what arguments it takes. That description sits in the context window on every single turn, whether the tool gets used or not. Connect five MCP servers with a dozen tools each, and that's dozens of descriptions loaded before you've typed a word. A single API call has no such description sitting in the conversation: its shape lives in a file, not in the window.

Access scope

An MCP server hands over whatever it was built to expose, often a whole platform's worth of actions, because that's what makes it useful to many different tasks and many different people. A single API call reaches exactly the one endpoint you wrote it against, nothing more and nothing less. Wider access is convenient until it's also the thing a reviewer has to reason about.

Where the line blurs

Skills optimise the MCP side. A well-scoped skill turns a dozen tool calls someone would otherwise make by hand into one instruction. The token cost of the tool descriptions buys back the time a person would have spent chaining them manually.

Code optimises the API side. A script that makes one API call costs nothing in the context window on any given turn, because its logic lives in a file that runs, not in a description that gets read. It also does the exact same thing every time, which an MCP tool call, reasoned about fresh each turn, does not guarantee.

Which is why the line blurs in practice. A lot of real setups end up as a skill that wraps a direct API call: the ease of "one instruction, done" from the MCP side, without paying MCP's per-turn tax for every other tool sitting unused in the same server.

A worked comparison

Same job, read from each side of the choice: list a repository's open issues. Both snippets are illustrative, not code from a real build.

What an MCP tool description costs

One tool, of many the server exposes
{
  "name": "list_issues",
  "description": "List issues in a repository. Supports filtering by state, labels, assignee, and milestone. Returns issue number, title, state, labels, assignee, and body.",
  "input_schema": {
    "type": "object",
    "properties": {
      "owner": { "type": "string" },
      "repo": { "type": "string" },
      "state": { "type": "string", "enum": ["open", "closed", "all"] },
      "labels": { "type": "array", "items": { "type": "string" } },
      "assignee": { "type": "string" },
      "milestone": { "type": "string" }
    },
    "required": ["owner", "repo"]
  }
}
// One of dozens of tool descriptions the server exposes.
// This one loads into every turn's context whether it's called or not.
// So do the other create_issue, update_issue, add_comment, merge_pr … tools.

What a single API call costs

list-open-issues.js
// list-open-issues.js: the one job this script does, and nothing else.
async function listOpenIssues(owner, repo) {
  const res = await fetch(
    `https://api.github.com/repos/${owner}/${repo}/issues?state=open`,
    { headers: { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } },
  );
  return res.json();
}

// This description exists here, in the file. It costs zero tokens in the
// context window on any turn. Claude runs the script, it doesn't reason
// about a schema for it first.

Laid out side by side, the trade stays consistent across every job you'd point either one at.

Same job, read from each side of the choice: list a repo's open issues.
MCP serverSingle API call
What loads every turnEvery tool the server exposes: list_issues plus create_issue, update_issue, add_comment, merge_pr and whatever else ships with itNothing. The request shape lives in a file that runs, not in the conversation
What it can reachWhatever the server was built to expose, usually most of the platform's API surfaceThe one endpoint the script calls, and only that
Who has to maintain itNobody, once it's connected. The server's author keeps it currentYou, or whoever wrote the script and its auth handling
What it costs to add a second jobNothing new. The server likely already exposes the next tool you needA second script, or a second function in the same one

When each choice is right

MCP tends to fit when…

the task changes shape from one session to the next, several people need the same connection without each writing their own client, or the platform's API is large enough that hand-rolling a wrapper for every action isn't worth it. The per-turn token cost buys flexibility you'd otherwise pay for in setup time.

A single API call tends to fit when…

it's the same job, run the same way, over and over. The kind of thing a skill or a script should just do without re-reasoning about a schema each time. You're already comfortable writing and maintaining the wrapper, and you want that job to cost nothing in context no matter how many times it runs.

Neither is the default. Check your own setup with /context: if a connected server's tool descriptions show up as a visible slice of the window, that slice is what this page means by token cost. Weigh it against how often you actually reach for that server's tools.

Skills are the thing that usually settles it in practice. See Specialist 4 for where skills live and how they get wired to a hook, and Claude Code skills for designers for a working set of skills that wrap direct calls instead of a broad connection.

How eliminating SaaS costs changed the MCP-versus-skills calculus

FAQ

Yes. Every tool description the server exposes loads into the context window on every turn once the server is connected, regardless of whether that turn calls it. Run /context to see the actual slice it takes in your own setup.

No. This page is about context budget and access scope, not raw latency. An MCP call and a direct API call can both be fast or slow depending on the service behind them. The trade-off here is what sits in the window and what the connection can reach, not which one responds quicker.

Most real setups do. MCP for the ad hoc, changes-every-session work where flexibility matters more than the per-turn cost; a script or a skill wrapping a single API call for the one job that runs constantly and should cost nothing in context.

No. A skill is how a task gets done: the written method Claude follows. An API call is what actually executes. A skill often wraps a direct API call precisely so the task gets MCP's "one instruction, done" feel without paying MCP's per-turn token cost for tools that aren't this task.

There isn't a verdict on this page, on purpose. An earlier version tried to give one and it read as good-versus-bad, which isn't true. Weigh the two axes above against your own task: how often you reach for it, how many people need it, and how much of the platform it actually has to touch.

Yes, and most do. The decision is per job, not per project: a connector three people use every day earns its place in the context window, while a one-off pull from the same service is often cheaper as a single call inside a skill. Decide each one on the two axes.

Want this run live with your team?

The same method, taught over two mornings against your own project instead of ours.

Book the masterclassLearn more