Skills are not tools
I connected eleven MCP servers to a coding agent in February. GitHub, Linear, Postgres, Sentry, Datadog, Slack, a browser, a filesystem, two internal ones and Notion. It felt like superpowers for about a week.
Then I looked at the token count on an empty session. Before I had typed a word, the tool list alone was 34,000 tokens. Every tool has a name, a description and a JSON schema, and every one of them is sent on every turn. Datadog alone contributed over two hundred tools. The agent got slower, it started picking search_datadog_logs when I meant search_datadog_spans, and one afternoon it tried to answer a question about a database table by opening Notion, because the Notion server had a tool called search and the word "table" was in my question.
More capability made the agent worse. That is the wall, and most teams I talk to hit it by April.
Two different problems
The reason it happens is that MCP solves one problem and gets used for two.
The problem MCP solves is access. The model cannot query your database, read your issue tracker or post to Slack on its own. A server exposes those operations as tools with typed inputs, the client lists them, the model calls them. It is a plug standard. Before it, every agent had its own way of wiring in a function, and the servers were not portable. Now they are. That is a real win and it is why MCP took over in about a year.
The problem MCP does not solve is knowledge. Knowing that this team deploys with pnpm release, that the staging database is the one with -stg in the hostname, that a Linear ticket is not done until the PR is merged and the label is set, that this repository's commit message convention has a scope in brackets. None of that is a tool. It is procedure. It is the stuff a new engineer learns in the first two weeks by asking people, and it is the stuff an agent does not have unless you put it somewhere.
Teams tried to put it in tool descriptions. The Datadog server's tool descriptions turned into small essays. Then they tried system prompts, which grew to thousands of lines that had to be loaded on every session whether or not the task was about deployment or databases. Both are the wrong container, and skills are the right one.
What a skill is
A skill is a folder with a markdown file in it. That is nearly the whole spec. The file has a short front matter block with a name and a one line description, and then instructions in plain prose: when to use this, how to do the thing, what the pitfalls are, which commands to run. The folder can also hold scripts, templates and reference documents that the instructions point at.
---
name: release
description: Cut a release of a package in this monorepo. Use when asked to release, publish, or tag a version.
---
# Releasing a package
1. Run `pnpm changeset status` and confirm there is a pending changeset
for the package. If there is none, stop and ask, do not create one.
2. Run `pnpm release:dry` and paste the version bump it proposes.
3. On confirmation, `pnpm release`. This tags, publishes through the
OIDC workflow, and opens the changelog PR.
4. Never publish with a local npm token. If `pnpm release` asks for
one, the OIDC setup is broken, stop and report.
See ./references/changesets.md for how we write changeset entries.The important part is how it is loaded. The agent does not read every skill on every turn. At startup it sees only the names and the one line descriptions, which for forty skills is a few hundred tokens. When a task matches a description, it reads that one skill's full instructions into the context, uses them, and the rest stay on disk. This is the pattern the coding agents converged on this year, Claude Code first and then the others, and the reason it spread is that it is the first mechanism that scales knowledge the way MCP scaled access.
Progressive disclosure is the whole trick
The design principle has a name, progressive disclosure, and it is why the two mechanisms are not in competition.
MCP tool lists are flat. Every tool is fully described up front because the model has to be able to call any of them at any time. That is correct for tools, and it is the source of the 34,000 tokens.
Skills are layered. The index is small. The body is loaded on demand. The references inside the body are loaded only if the body tells the agent to read them. A skill for a database migration workflow can be three lines in the index, two pages of instructions when it triggers, and a 40 page schema reference that only gets opened if the migration touches a particular table.
Once you see that, the fix for the eleven server problem is obvious. You do not need the Datadog server's two hundred tools in the context. You need a skill called investigate-incident that says "for latency questions use search_datadog_spans, for error rates use the RUM aggregate, here is how to read our service map, here are the three dashboards that matter", and you need the Datadog server to be connected. The skill carries the knowledge of which tool to use and how. The server carries the ability to use it.
The token cost of a tool is paid on every turn. The token cost of a skill is paid once, when it triggers. That single difference decides which container a piece of information belongs in.
How I split it now
After the February mess I rebuilt the setup with a rule: a server gets connected only if a skill references it. If no procedure needs a tool, the tool does not need to be in the context.
The result was four servers instead of eleven. GitHub, Linear, Postgres and Datadog. The Slack, Notion and browser servers were removed, because the things I used them for turned out to be one off requests that a skill could not improve and a tool call was not worth 3,000 tokens a turn for. The filesystem server was redundant with the agent's own file tools. The two internal servers became one, and the one gained a skill.
Then I wrote skills for the procedures I kept explaining. Releasing. Investigating an alert. Writing a migration. Reviewing a pull request the way this team reviews them, which includes checking that the Linear ticket is linked and that nothing in packages/site-config changed without a changeset. Onboarding a new MCP server, because that is a procedure too.
The empty session is now 6,000 tokens of tool schemas plus about 400 tokens of skill index. The agent picks the right tool nearly every time, because the skill that triggered told it which one. And when someone new joins and asks how we deploy, I point them at the same markdown file the agent reads, which turned out to be the best documentation the team has ever had, for the boring reason that it is the only documentation that gets exercised daily.
What goes wrong
Skills have their own failure modes and I have hit most of them.
The description is the trigger, and vague descriptions trigger on everything or nothing. "Helps with databases" triggers on any question containing the word. "Write and apply a Postgres migration in this repository. Use when asked to add, alter or drop a table, column or index" triggers when it should. Write descriptions the way you would write a function name: specific enough that the wrong caller would not reach for it.
Skills that duplicate what the model already knows are dead weight. A skill explaining what a pull request is wastes the tokens it costs. A skill explaining that in this repository PRs are squash merged and the title becomes the changelog entry is worth every token. The test is whether a strong senior engineer from outside the company would need to be told this.
Skills go stale in exactly the way READMEs go stale, except that a stale skill produces confident wrong actions rather than a confused human. When the release process changed in March, the agent kept running the old command for a week, because the skill said so and the skill was the only thing it had read. The fix was cultural: the skill lives in the repository, and a change to the process is not merged until the skill is updated in the same PR. That is the rule for tests, and it should be the rule here.
And there is a security shape to be aware of. A skill is instructions the agent will follow, so a skill from an untrusted source is a prompt injection you installed on purpose. Treat a shared skills directory the way you would treat a shared shell profile. Review it, pin it, and do not pull skills from a marketplace into an agent that has write access to anything.
A quick way to audit your own setup
Open an empty session and read the token count before you type anything. If it is over 10,000, most of it is tool schemas, and the question for each connected server is whether any procedure you actually run uses it. Disconnect the ones with no answer.
Then look at your system prompt or your project instructions file. Every paragraph that starts with "when doing X" is a skill waiting to be extracted: move it to a folder with a one line description, and the paragraph leaves the context until X comes up. On my setup that turned a 3,000 token instructions file into a 400 token one plus eleven skills, and the agent got noticeably better at following the instructions that remained, because there were fewer of them competing for its attention.
The shape of it
MCP is the socket. Skills are the manual that sits next to the machine. A workshop with fifty sockets and no manuals is a room where things get plugged in wrong. A manual with no sockets is a nice read.
If your agent has become slower and more confused as you gave it more servers, the fix is not a bigger context window and it is not a better model. Disconnect the servers no procedure needs, write down the procedures you keep repeating, and let the agent load the knowledge when the task calls for it instead of carrying all of it, all the time, for everything.