All articles

by Bryce Cee

MCP servers vs. skills: what I learned benchmarking both in a large monorepo

The useful question is not which agent capability is more powerful. It is which boundary makes a task reliable, discoverable, and cheap to operate.

  • Agentic engineering
  • MCP
  • Evaluation

Teams adopting coding agents often reach the same architecture question: should a capability be exposed through a Model Context Protocol server, or packaged as a skill the agent can load when needed?

The easy answer is that MCP is for tools and skills are for instructions. That distinction is useful, but it is not enough. A realistic capability can contain both: a workflow needs procedural guidance, and that procedure may need structured access to repository or service data.

The more useful question is:

Which boundary gives the agent enough capability to complete the task while keeping behavior reliable, context-efficient, and operable by the team that owns it?

I reached that framing while comparing MCP servers and skills against representative work in a large JavaScript monorepo. This article explains the benchmark model, the patterns that held up, and the decision rules I now use.

Specific internal repositories, services, and measurements are intentionally omitted. The evaluation shape and conclusions are transferable.

First, define the two boundaries

An MCP server exposes capabilities through a protocol. It gives a client a structured catalog of tools and resources, typed inputs, and a clear execution boundary. The server can own authentication, data access, validation, and integration behavior.

A skill is a focused package of knowledge and procedure that an agent loads for a task. It can teach the agent how to inspect a repository, choose a workflow, use existing tools, and verify its work. Its main value is not computation. Its value is giving the model the right operational context at the right time.

This leads to an important distinction:

BoundaryPrimarily ownsBest at
MCP serverExecution and data accessStable, typed operations over a service or domain
SkillTask strategy and repository procedureContextual guidance that composes existing tools

The boundaries can work together. A skill can explain when and how to call MCP tools. The mistake is making both layers own the same policy.

Benchmark the task, not the demo

A capability demo usually proves that one happy path can work. It does not show whether an agent can discover the capability, choose it at the correct time, recover from bad inputs, or produce a verifiable result.

I used task scenarios with four parts:

  1. Starting state. The repository state, available context, and permissions visible to the agent.
  2. User intent. A prompt stated as an engineer would state it, without naming the capability under test.
  3. Observable outcome. Files, commands, queries, or explanations that can be checked independently.
  4. Failure categories. Wrong tool selection, invalid assumptions, incomplete verification, excessive context use, and unsafe actions.

That structure matters because capability selection is part of the behavior being evaluated. If the prompt tells the model to call a specific tool, the test skips one of the hardest parts.

A simplified scenario definition looked like this:

type Scenario = {
  id: string
  intent: string
  repositoryFixture: string
  expectedSignals: readonly string[]
  prohibitedActions: readonly string[]
  maximumToolCalls?: number
}

export function passesScenario(
  observedSignals: readonly string[],
  scenario: Scenario,
): boolean {
  return scenario.expectedSignals.every((signal) =>
    observedSignals.includes(signal),
  )
}

The real harness also captured traces and graded qualitative dimensions, but the core principle stayed simple: define success outside the model response.

What I measured

The benchmark used dimensions that affect production use, not only task completion.

1. Discovery

Can the agent identify that the capability applies from the user’s intent?

MCP tool descriptions are always part of the client’s capability surface, although clients differ in how they present or select them. A skill can stay out of context until a trigger matches, but its name and description must carry enough signal for correct activation.

Poor descriptions hurt both approaches. A precise schema does not rescue a tool that the agent never selects. A detailed skill body does not help when its activation description is vague.

2. Reliability

Does the same task produce the same class of result across repeated runs and varied inputs?

MCP was stronger when the important operation could be reduced to validated inputs and deterministic service behavior. A tool that accepts a repository identifier and returns a normalized build graph has less room for interpretation than a paragraph telling the agent how to reconstruct that graph.

Skills were strong when the task depended on local repository judgment: inspect these files, follow the nearest ownership rules, choose the smallest validation command, and explain a failure in terms the team uses.

3. Context cost

How much context must the model consume before it can act?

A large tool catalog has a cost even if the agent calls one tool. A long skill has a cost once loaded, especially when most of its content does not apply to the current branch of the task.

The best results came from narrow capability descriptions and progressive disclosure. Put selection-critical information in the short description. Load detailed procedure or data only after the agent has chosen the capability.

4. Operational ownership

Who deploys, versions, supports, and secures the capability?

An MCP server is a service boundary. That can be an advantage when the capability needs credentials, centralized policy, or access to data that must not be copied into a repository. It also creates service lifecycle work: deployment, compatibility, observability, authentication, and incident ownership.

A skill can often ship with the repository or agent configuration that needs it. This makes changes easy to review with the code they affect. It is a poor place for secrets or for logic that must remain consistent across many clients.

5. Composability

Can the capability participate in a larger workflow without duplicating decisions?

Typed MCP tools compose well as execution primitives. Skills compose well as procedural layers, but only when each skill has a clear scope. Two skills that both redefine how to diagnose a build can create more ambiguity than either removes.

The result was not a winner

The benchmark did not produce a global winner. It produced a clearer capability model.

Use an MCP server when the capability:

  • needs authenticated access to a remote system;
  • benefits from typed inputs and deterministic validation;
  • must enforce a policy outside the model;
  • returns structured data that several agent clients should consume;
  • has an owner prepared to operate a service boundary.

Use a skill when the capability:

  • teaches a repository-specific workflow;
  • primarily coordinates tools the agent already has;
  • changes with the codebase and should be reviewed beside it;
  • needs nuanced local judgment more than a new execution primitive;
  • can be loaded only when a focused class of tasks requires it.

Use both when a stable execution primitive needs contextual procedure. Keep the contract explicit: the MCP server owns the operation; the skill owns when and why the workflow uses it.

A practical decision sequence

I now work through the decision in this order.

Does the agent need a new authority?

If the capability needs credentials, private service data, or centrally enforced policy, prefer a tool boundary. Do not put authority in prompt text.

Does the agent need a new operation?

If the model cannot complete the task with its existing file, shell, search, and code-intelligence tools, define the missing operation. A narrow MCP tool is usually better than a skill that simulates the operation through brittle steps.

Does the agent need better judgment?

If the operation already exists but the model uses it poorly, add focused procedure. Explain triggers, decision points, constraints, and verification. That is skill territory.

Where does the knowledge change?

Repository-specific knowledge should usually version with the repository. Cross-repository service logic should usually live with the service. Put the capability where its source of truth changes.

Can success be checked without asking the model?

If not, improve the evaluation before expanding the capability. An LLM judge can help grade explanations and traces, but deterministic signals should carry the parts that can be deterministic.

Design lessons that mattered more than the format

Several lessons applied to both MCP servers and skills.

Descriptions are routing infrastructure. Write them as selection criteria, not marketing copy. State when the capability applies, what it returns, and what it does not own.

Narrow beats comprehensive. A capability with one coherent responsibility is easier for the model to select and easier for a team to evaluate.

Progressive disclosure protects context. Keep the initial surface small. Load procedures, examples, schemas, and data when the task reaches the point that needs them.

Verification belongs in the workflow. A capability is incomplete if it tells the agent how to act but not how to know the action worked.

Trace failures by category. “The answer was wrong” is not an actionable result. Distinguish discovery failures, planning failures, tool errors, invalid assumptions, incomplete execution, and judge disagreement.

The architecture principle underneath it

MCP servers and skills are not competing product categories. They are different places to put responsibility.

The best boundary is the one that reduces what the model must infer:

  • Put secure and deterministic operations behind typed tools.
  • Put contextual strategy in focused, loadable guidance.
  • Keep policy in one place.
  • Evaluate capability selection as well as execution.
  • Treat context as a finite system resource.

Once I stopped asking which option was more powerful, the tradeoff became easier. The goal is not to give an agent the largest capability surface. The goal is to give it the smallest reliable path from intent to a verifiable outcome.