AI Engineering, Agent Frameworks17 min read

Skills vs MCP: Which to Build for AI Agents

Compare Agent Skills and MCP — measured context cost, the 2026-07-28 stateless spec, and a decision rule for which one to build.

Skills vs MCP: Which to Build for AI Agents

Skills vs MCP: Which Should You Build for Your AI Agent?

TL;DR: Skills and MCP are not competitors, and choosing between them is not a preference question. MCP is a wire protocol that gives an agent reach into systems it cannot otherwise touch — a database behind a credential, a SaaS API, another team's service. A Skill is a markdown file that teaches an agent a procedure using tools it already has. The decision rule is a boundary test: if the capability requires a credential, a network hop, or a process the agent does not control, you need MCP. If it is knowledge about how to sequence existing tools, you need a Skill. The cost profiles differ sharply — MCP tool definitions load on every request and scale linearly with tool count, while a Skill's body loads only when invoked. In four production skills measured for this article, the always-on cost was 6.2% of the full content.

Key Takeaways

  • The two technologies answer different questions. MCP answers "what can this agent reach?" — it is a JSON-RPC protocol with a schema, a transport, and a security model. Skills answer "what does this agent know how to do?" — the format is a markdown file with YAML frontmatter and no runtime at all.
  • The cost asymmetry is the strongest practical differentiator. MCP tool definitions sit in context on every request and grow linearly: 100 realistically-sized tool definitions run roughly 24,700 tokens, about 12% of a 200k window, spent before the agent does anything. Skills use progressive disclosure — only the description is always-on.
  • MCP revision 2026-07-28 removed protocol-level sessions and the `initialize` handshake entirely. A `tools/call` is now a single self-describing HTTP POST. That erases the sticky-routing requirement that made MCP servers awkward to scale, and it removes one of the strongest historical arguments for avoiding MCP.
  • Skills have no security boundary, and this is the most misunderstood distinction. A Skill is instructions the model may follow or ignore; MCP is a client-server call an application can audit, rate limit, and gate on human approval. `allowed-tools` in a Skill pre-approves permissions — it does not restrict what the model attempts.
  • The `isError: true` distinction in MCP is a design feature, not error plumbing. Tool execution errors are returned as results so the model can read them and self-correct; protocol errors are JSON-RPC failures the model usually cannot fix. Collapsing the two removes the agent's ability to retry intelligently.
  • The mature architecture uses both: MCP for the capability surface, a Skill for the procedure that drives it. A Skill that says "query the warehouse with `execute_sql`, then reconcile against yesterday's snapshot" is doing work no tool schema can express.

Why does this comparison confuse experienced engineers?

Because both technologies get described with the same verb: they "give the agent tools." That phrasing is accurate for MCP and misleading for Skills, and the ambiguity has produced a genuinely unhelpful genre of "Skills killed MCP" commentary.

The confusion has a specific origin. Through 2025, developers noticed that an agent harness with terminal access and curl could reproduce most of what a simple MCP server did — with less ceremony. If your MCP server is a thin wrapper over a REST API, and your agent can already make HTTP requests, the server is pure overhead. That observation is correct, and it is the reason a lot of MCP servers should never have been written.

But it generalizes badly. Simon Willison, who made a version of that critique, later argued the opposite direction: handing an agent a shell plus unrestricted network access is harder to secure than a defined tool surface, and it demands a strong model to drive it safely. A defined set of MCP tools is easier to audit, easier to reason about, and workable with smaller local models. Both claims are true. They are about different failure modes.

Here is the framing that actually resolves it. These technologies live on different axes:

An agent with no MCP servers and fifty Skills can reach nothing new; it just has opinions about how to use its built-in tools. An agent with fifty MCP servers and no Skills can reach a great deal and has no idea which capability to use when. Most production failures I have debugged are the second kind.

What is MCP actually specifying?

MCP is a protocol, and reading it as one clarifies what it does and does not give you. A server declares a tools capability, and clients discover tools with tools/list and invoke them with tools/call.

A tool definition carries name, optional title, description, inputSchema, and optionally outputSchema, icons, annotations, and an execution block. The inputSchema must be a valid JSON Schema object — never null — and defaults to draft 2020-12 when no $schema is present. For a tool with no parameters, the spec recommends {"type": "object", "additionalProperties": false} to explicitly accept only empty objects:

Two details in that snippet are worth dwelling on, because they are where MCP earns its complexity.

Error handling is bifurcated on purpose. MCP separates protocol errors (standard JSON-RPC failures — unknown tool, malformed request) from tool execution errors, returned as a normal result with isError: true. The spec is explicit about why: execution errors carry actionable feedback the model can use to self-correct and retry with adjusted parameters, and clients should pass them to the model. Protocol errors indicate a broken request the model is unlikely to fix. A server that raises a JSON-RPC error for "date must be in the future" has converted a recoverable situation into a dead end.

Annotations are untrusted input. The spec states clients must treat tool annotations as untrusted unless they come from a trusted server. An annotation claiming a tool is read-only is a claim by the server, not a guarantee. Any authorization decision made on the strength of a readOnlyHint is an authorization decision made by whoever operates that server.

How did the 2026-07-28 revision change the calculus?

Substantially, and in the direction that removes MCP's biggest operational objection.

Before this revision, a tools/call over HTTP required two round trips. The client POSTed an initialize request with its protocolVersion, capabilities, and clientInfo, received a session identifier, and then sent the actual call with an Mcp-Session-Id header. The session ID was the statefulness: the server had to remember it between requests, which meant a load balancer had to route a given session back to the same backend instance.

Revision 2026-07-28 removed protocol-level sessions and the GET stream endpoint. Every request is now self-describing. Protocol metadata travels in the body under _meta.io.modelcontextprotocol/*, and the Streamable HTTP transport mirrors selected fields into headers so intermediaries can route without parsing the body:

MCP-Protocol-Version, Mcp-Method, and Mcp-Name are required. The Mcp-Param-Region header comes from the x-mcp-header annotation in the schema above — servers may designate primitive parameters to be mirrored into Mcp-Param-{Name} headers, and clients must support it.

The critical rule is that the body remains the source of truth, and servers must reject any mismatch with HTTP 400 and JSON-RPC error -32020 (HeaderMismatch). This is a security requirement, not tidiness: if a load balancer routes on the header while the server executes on the body, an attacker who can desynchronize the two can route a request to one tenant's infrastructure while executing another tenant's query. The spec closes that gap by mandating validation.

What this buys you architecturally: no session state, no sticky routing, any request can hit any instance. Three mechanisms from the older revisions are gone — Mcp-Session-Id, GET-initiated standalone SSE streams, and Last-Event-ID stream resumability. A server supporting only this revision should return 405 Method Not Allowed to GET or DELETE on the MCP endpoint, and silently ignore Mcp-Session-Id and Last-Event-ID headers rather than honoring them.

Server-to-client interaction changed shape too. Servers no longer send their own JSON-RPC requests for sampling, elicitation, or roots. Instead a server returns an InputRequiredResult containing inputRequests, and the client re-sends the original request with matching inputResponses — the Multi Round-Trip Requests pattern. Long-lived change notifications now arrive on the response stream of a subscriptions/listen request rather than a standalone stream.

If you evaluated MCP in 2025 and rejected it because operating stateful session-affine servers was not worth the payoff, that evaluation is now out of date.

What does a Skill actually cost in context?

This is where I think the public discussion is weakest, so I measured it against real files rather than reasoning about it.

A Skill is a SKILL.md file with YAML frontmatter. Every field is optional; description is recommended because that is what the model reads when deciding whether the Skill is relevant. Skills live at ~/.claude/skills//SKILL.md (personal, all projects), .claude/skills//SKILL.md (project), or inside a plugin. The mechanism that matters is progressive disclosure: descriptions are loaded into context so the model knows what exists, and the full body loads only on invocation.

I measured the four production skills in this repository — the automation that publishes articles, sends the newsletter, runs the SEO optimizer, and handles post-deploy indexing:

The always-on cost is 6.2% of the full content. Four multi-step operational procedures — each with git commands, file paths, and failure handling — are advertised to the model for under 200 tokens.

Now the same exercise for MCP. Tool definitions are not progressively disclosed; the client sends them with the request. Using the spec's minimal get_weather example (263 chars) and a realistically-detailed execute_sql definition with descriptions and an output schema (889 chars), at roughly 3.6 characters per token:

Percentages are against a 200k window. Treat these as engineering estimates, not vendor figures — the tokenizer ratio is approximate and real tool definitions vary widely. The shape is the point: linear growth, paid on every request, before the agent has done any work. Connect eight mid-sized MCP servers and you can spend a tenth of your window on a menu.

Skills are not free either, and the ceilings are worth knowing:

  • The combined `description` and `when_to_use` text is truncated at 1,536 characters in the skill listing. Front-load the key use case.
  • The listing budget scales at 1% of the model's context window. On overflow, descriptions are dropped starting with the skills you invoke least — so a rarely-used skill can silently lose the keywords the model needed to match your request. Raise it with `skillListingBudgetFraction`.
  • Once invoked, a Skill's body stays in context across turns. Every line is a recurring cost, which is why terse imperative instructions beat narration.
  • Under auto-compaction, the most recent invocation of each Skill is re-attached after the summary, keeping the first 5,000 tokens of each within a combined 25,000-token budget, filled from most-recently-invoked. Invoke many skills in one session and the early ones are dropped entirely.

That last point has a practical consequence: if a Skill seems to stop influencing behavior late in a long session, it may have been evicted. Re-invoke it.

Which one should you build?

Apply the boundary test, in this order.

1. Does the capability require crossing a trust boundary? A credential, a network hop, a database, another team's service, a process the agent does not control. If yes, you need MCP — or an equivalent authenticated API surface. A markdown file cannot hold a secret or terminate a connection.

2. Can the agent already do it with the tools it has? If the agent has a shell, a file system, and network access, and the task is sequencing those correctly, that is a Skill. Writing an MCP server to wrap git log adds a process, a schema, and a deploy pipeline in exchange for nothing.

3. Does anything need to be enforceable? This is the question most often skipped. A Skill is advisory: the model reads it and may follow it. If a rule must hold every time — a blocked path, a mandatory review gate, a lint check — it belongs in a hook, a CI check, or an MCP server's own authorization logic. Not a bullet point in markdown.

4. How often will it change? A Skill is a git commit. An MCP tool schema change is a coordinated deploy plus client rediscovery. Procedural knowledge that changes weekly wants to be a Skill.

Worked examples:

And the combination that most teams should end up with. The Skill supplies judgment the schema cannot express:

execute_sql is the MCP tool: it crosses the boundary and holds the credential. The Skill is the four things a competent analyst knows that no inputSchema can carry — which table to compare against, what threshold matters, what to do next, and what not to touch. Note that step 4 is a convention, not a control. If read-only access must be guaranteed, it is enforced by the warehouse credential the MCP server holds, not by that sentence.

One caveat on allowed-tools: it pre-approves tools so the model is not stopped for permission during the invoking turn. It does not sandbox the Skill. To remove tools from the model's reach while a Skill is active, use disallowed-tools; to block them everywhere, use deny rules in permission settings.

FAQ

Are Skills replacing MCP?

No, and the framing mistakes a knowledge format for a protocol. Skills cannot open a database connection, hold a credential, or expose a capability an agent lacks — they are instructions loaded into context. MCP cannot tell an agent which of its forty tools to reach for in a given situation. The 2025 argument that Skills eclipsed MCP applied narrowly to MCP servers that were thin wrappers over APIs the agent could already call, and that critique is worth honoring by not writing those servers.

When is writing an MCP server the wrong choice?

When it crosses no boundary the agent cannot already cross. If the agent has network access and the target is a public REST API with no credential, a server adds a process to run, a schema to version, and per-request token cost, in exchange for a slightly tidier call. Also reconsider if you are about to expose dozens of fine-grained tools — 100 realistically-sized definitions cost roughly 12% of a 200k context window on every request. Fewer, broader tools usually beat many narrow ones.

What actually changed in MCP revision 2026-07-28?

Protocol-level sessions and the GET stream endpoint were removed. There is no initialize handshake: each request carries its own protocol version, client info, and capabilities in _meta, mirrored into the required MCP-Protocol-Version, Mcp-Method, and Mcp-Name headers. Servers must reject header/body mismatches with -32020 HeaderMismatch. Server-initiated requests are gone, replaced by the Multi Round-Trip Requests pattern where a server returns InputRequiredResult and the client retries with inputResponses. Operationally, the payoff is that no request needs to be routed back to a specific instance.

Do Skills work outside Claude Code?

The SKILL.md format follows the Agent Skills open standard, which is designed to work across multiple AI tools; Claude Code layers on extras like invocation control, forked-subagent execution, and glob-scoped activation via paths. Portability of the file is good. Portability of the extended frontmatter is not guaranteed, so treat vendor-specific fields as extensions and keep the instructions themselves tool-agnostic where you can.

How do I tell if a capability should be enforceable rather than instructed?

Ask what happens on the run where the model ignores it. If the answer is "we get a slightly worse commit message," a Skill is fine. If the answer is "we deployed unreviewed code" or "we wrote to production," the rule must live somewhere the model cannot decline — a hook, a CI gate, or the credential scope of the MCP server itself. Instructions shape behavior; they do not constrain it.

📬 Get this weekly →

Subscribe to the newsletter

By subscribing, you agree to our Terms of Service and Privacy Policy.

About the Author

Aaron is an engineering leader, software architect, and founder with 18 years building distributed systems and cloud infrastructure. Now focused on LLM-powered platforms, agent orchestration, and production AI. He shares hands-on technical guides and framework comparisons at fp8.co.

Cite this Article

Aaron. "Skills vs MCP: Which to Build for AI Agents." fp8.co, August 5, 2026. https://fp8.co/articles/Skills-vs-MCP-Agent-Capability-Architecture

Related Articles

How to Build Claude Code Skills: 5 Examples (2026)

Build custom Claude Code Skills with 5 ready-to-use examples. Covers SKILL.md spec, security controls, plugin distribution, and team sharing workflows.

AI Development Tools, Developer Productivity, Claude Code

MCP Explained: Complete Protocol Guide 2026

Master Model Context Protocol from architecture to implementation. Build MCP servers, understand the spec, and integrate with Claude Code and Cursor.

AI Development Tools, Model Context Protocol

Context Engineering for AI Agents: Cut LLM Costs 10x in 2026

Context engineering cuts AI agent costs 10x via KV cache optimization, tool masking and 5 more patterns, production-tested on million-token workflows.

AI Engineering, Agent Frameworks