Book a call
LESSON16mVERIFIED 2026-08-02 · CLAUDE CODE 2.1.220 · CODEX CLI 0.146.0 · GITHUB COPILOT CLI 1.0.77 · CURSOR 2026.07.23-e383d2b · KIMI CODE CLI 0.31.1

Skills vs MCP: procedural knowledge or live tool access

A skill is knowledge the agent didn't have; an MCP server is reach the harness didn't have. Three questions that settle which one your job needs.

The question everyone lands on

Usually there's a certain thing you keep doing by hand and would like the agent to do instead, and then there's two offerings on the market: either you can create a skill or run an MCP server. These are both being marketed as extending the agent's capabilities, but really, one of them does it, the other — not so much

A skill is a file, a server is a process

In terms of the differences, what's key is that they're completely different things under the hood. A skill is essentially a directory with a SKILL.md file inside (it's an industry standard established by Anthropic and then opened up). That directory can contain a couple of more things like scripts, reference docs etc but crucially, it contains a markdown file with instructions, which includes metadata like name and description, and that's what the skill is. An MCP server on the other hand is a live process, while the Model Context Protocol is generally client-server, so the host harness spins up a new client for every connected server, with its own connection to it.

There are three primitive types of things an MCP server can expose:

  • tools — which are basically functions that AI apps call in order to perform actions

  • resources — which are data sources providing context

  • prompts — which are templates for structuring conversations with LLM-s

The most important thing is that a skill is knowledge the agent didn't have, while an MCP server is reach the harness didn't have. The former tells you how to do sth, the latter allows you to contact sth. So if you reckon that a competent developer at your terminal could get the job done using what's already installed on it, and the only thing missing is that the agent doesn't know the procedure — that's a skill; if there's nothing that could touch the target — that's a server

What the model actually sees

We could now get into a long discussion about context, but let's just do some math.

When you define a skill at startup, only its name and description are being loaded into the context, which is enough for the agent to understand it's relevant. When it then faces a task it might be relevant for, the entire SKILL.md file gets pulled in; during the task's execution, any additional files included in the skill are being loaded as needed.

Codex has a codex debug prompt-input command that renders the model-visible prompt input as JSON without calling a model at all. Run in a scratch directory with eleven skills, the skills block weighs 6,356 characters — names, descriptions and file paths, no bodies — but if we now list all the SKILL.md files, they actually add up to 122,636 characters. So it's roughly 5% being paid upfront, the rest — on demand. It's also important to note that OpenAI restricts this list to 2% of the context, 8,000 characters.

But when it comes to tools, what's interesting is that it works the other way round: the client asks every connected server for its tools and merges them all into a single registry the LLM can access. So every tool comes with its name, title, description, and an inputSchema — the complete JSON Schema describing the shape of its inputs — all visible to the model before the user types anything in; which is why Anthropic writes:

In cases where agents are connected to thousands of tools, they'll need to process hundreds of thousands of tokens before reading a request.

And their own way out of it is to stop calling the tools directly — generate the code that calls them instead, so the agent only pulls in what it needs. In their worked example that's the difference between 150,000 and 2,000 tokens. But there are a few caveats here:

  • it's an extreme scenario — using thousands of tools is not something you do with three modest servers

  • it's about the client, not the protocol; the spec leaves room for the client to implement federating multiple servers to discover tools progressively, rather than pulling them all in upfront, so if yours doesn't, that's a harness problem

Another thing that we often see being omitted by advocates of MCP is that skills also rent their space. In Claude Code docs it's clearly stated that once loaded, the skill's content remains in the context turn after turn — so every line of it is a recurring token cost. A 400-lines-long skill pulled in at turn two will still be there on turn forty

The three questions that settle it

So whenever you consider an MCP server, ask yourself three questions:

  1. Does this require a connection that can't be established from the machine's shell? — like credentials the agent shouldn't have access to, or an unreachable network, or a SaaS product with no CLI client; in such case it's a server and there's no skill that could replace it

  2. Does it need to return a handle so you can revisit it later? — like long-running jobs, or a list of capabilities that change during the session; the protocol covers both scenarios, via Tasks extension (which introduces a durable handle for the LLM to return so the client can poll for the result later), and notifications (for notifying the client about changes in the tool list); whereas a markdown file doesn't do any of these

  3. Could a competent developer sitting at your terminal with what's installed on it do this job? — if yes, that's a skill; even if there were to be a server for the same thing, it'd be a skill, which costs its description until it runs, and a server, which costs its schemas in every session it's connected to, regardless of being used or not

The wrapper server

The most common misconception we come across is the "wrapper server", an MCP server whose every tool calls the CLI the agent already has. A server for git, a server for kubectl, a server for a REST API that ships with its own CLI on your machine already. It's appealing because it feels like a more serious engineering decision, so people keep doing it.

But think about it:

  • you need to set up and maintain a process

  • every tool comes with a schema in the window of every session that connects with it

  • you need to create a config entry on every developer's machine

  • you need to align another thing with what's beneath it

While a skill pointing at gh with what to run and what to verify first costs only its description until it runs. So before you consider setting up an MCP server, ask yourself if there's already an authenticated CLI client for the system in question on your machine, and if yes — write the skill

We're not saying that MCP is overhyped (that'd be a stretch), we're saying that when it comes to this particular use case of encapsulating a CLI that's already there on the machine within the protocol, it adds nothing the skill doesn't have and charges rent

Where a skill genuinely cannot go

There are four things a skill can't do that the protocol can:

  • credentials — project skills are git files; if you were to instruct the agent to call an API with a token in a skill, you'd end up with the token in git, but if you were to use a server for it instead, it'd stay on the server side and the client would just authenticate against the HTTP transport using a bearer token, API key, or OAuth (which the spec recommends)

  • nothing installed locally — if there's an API with an authentication flow and no CLI client anywhere near your machine, you can't create a skill because the skill is just a file telling the agent what to run

  • statefulness — the protocol is stateless as of 2026-07-28 (each request comes with its own version and capabilities), but an MCP server can have its state and return a handle for you to revisit a job later; skills are just files

  • machine-readable contract — tools come with inputSchema, the JSON Schema describing the shape of their inputs, a type that travels with them; skill instructions are prose the LLM might or might not follow

They compose, and that is the normal case

It's not a "versus" thing, that's composition — this is the normal configuration; the "versus" narrative is mostly a misconception. In every setup we run there's both, splitting one thing — the server for reach, the skill for reasoning

Here's an example:

  • we have an MCP server exposing a tool to create an issue

  • but it doesn't tell the agent anything about our team's conventions

That we:

  • should include the reproduction steps in the body, not the title

  • use a specific label for anything connected with billing

  • check if there's no duplicate before creating the issue

This is skills territory. We'd write a skill referring to the server's tool, so both the connection and the procedure end up in the context at once. Which also means that:

  • our rules are cheaper as skills — a line in a tool description sits in the window of every session that connects with the server, while the same line in a skill body costs nothing in every session that doesn't trigger it

IN YOUR HARNESS

In Claude Code

The location of the skill files is ~/.claude/skills/<name>/SKILL.md (per-user) and .claude/skills/<name>/SKILL.md (per-project). Claude Code also finds skills in .claude/skills directories nested under the working directory, but only after Claude reads or modifies a file in this subdirectory. That's so packages in monorepos can ship their own skills. Now both slash commands and skills are unified in terms of the implementation to the extent that .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md will both define a /deploy command with exactly the same behaviour.

If you were wondering how to set up MCP, here's an example:

BASH
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp list
  • claude mcp add --transport http sentry https://mcp.sentry.dev/mcp — adding a Sentry server (via HTTP transport)

  • claude mcp list — listing the servers, verifying they work

  • Generally, servers defined in a committed .mcp.json are not connected until approved, so listing them will display a "pending" status instead of displaying them as active

The last thing — the Claude CLI is the only one of the six whose docs never mention .agents/skills/, so just keep in mind that if you put your skill there, it might not be loaded here; check before you rely on it. Also, it's good to know a few limitations before writing an essay:

  • The description and when_to_use fields are truncated after 1,536 characters in the listing

  • After compaction, only the first 5,000 tokens of every invoked skill are being re-attached

  • There's a general limit of 25,000 tokens for all the skills that are being re-attached

In Codex CLI

There are skills under .agents/skills/ (or any parent dir, or the root of the repo), or under ~/.agents/skills/ if it's a user-level skill. You can call them with $skill, or they get automatically picked by Codex from the description field. MCP servers are added with the codex mcp subcommand.

BASH
codex mcp add my-tool -- my-command --flag
codex mcp list

Among the six tools, Codex is the best one for observing this trade-off.

BASH
codex debug prompt-input

For example, if you type codex debug prompt-input, it prints the prompt as it's seen by LLM as JSON. So you can see it has skills, but only their names and descriptions, and file paths — their bodies aren't there until they get activated. That's the measurement in this lesson; you can even try it yourself on your repo in a second.

Gotcha: Just keep in mind that Codex looks at .agents/skills, not .claude/skills, so that's why nothing appears if you've come over from Claude Code. The same codex debug prompt-input command also shows whether a skill got picked up, so you don't need to guess based on behaviour.

In GitHub Copilot CLI

The most open of the six tools when it comes to skills location, it accepts skills defined in these paths:

  • .github/skills/, .agents/skills/, .claude/skills/ on a project level

  • ~/.copilot/skills/, ~/.agents/skills/ on user level

If you define a skill in two of the aforementioned paths, it will appear only once in the list.

Listing skills and adding one from file, URL or a directory:

BASH
copilot skill list
copilot skill add <file-or-url-or-directory>

The tool automatically reads MCP configuration from these sources:

  • ~/.copilot/mcp-config.json (personal)

  • .mcp.json or .github/mcp.json (workspace)

  • any plugin that ships with its own server

You can list them using this command copilot mcp list and it will list all of them. It's worth noticing that the CLI comes with github-mcp-server built in, so there's a server without you doing anything about it. It comes with only a part of the toolset enabled by default — which is reasonable; we wouldn't change it. If you want the whole thing, --add-github-mcp-toolset all is the flag, and it's the fastest way to find out what a crowded tool list feels like. --disable-builtin-mcps goes the other way and turns the built-ins off entirely.

In Cursor

Locations in which you can define skills:

  • per project — .agents/skills/ and .cursor/skills/

  • per user — ~/.agents/skills/ and ~/.cursor/skills/

Cursor also reads the older .claude/skills/ and .codex/skills/ paths, so it works with most of the projects created using other agent tools.

Skills are defined via frontmatter with name and description properties required, optional paths globs and disable-model-invocation (so it will work only when you use it).

You can define MCP servers in .cursor/mcp.json file per project or ~/.cursor/mcp.json globally, and if there's none the CLI will tell you about these locations. Then you can run the following commands:

BASH
agent mcp list
agent mcp list-tools <identifier>
  • agent mcp list — lists all the configured servers

  • agent mcp list-tools <identifier> — lists tools of a specific server

If you were to ask us which one is more valuable, we'd say the latter one — for a particular server it shows what tools are exposed and what arguments they have. It's the closest thing these CLIs can offer in terms of showing what a server costs.

But there's a catch — these paths belong to the editor, so if you run agent mcp list command with no servers configured it points to .cursor/mcp.json or ~/.cursor/mcp.json which are also used by the editor so you might end up having a project with tools that somebody else created for some other purpose.

In Gemini CLI

There are four levels where you can place skills:

  • Installed with the CLI

  • From an extension

  • Per-user: ~/.gemini/skills/ (or ~/.agents/skills/)

  • Per-workspace: .gemini/skills/ (or .agents/skills/)

For a single level, if you have both .gemini and .agents folders, .agents is prioritised.

To list all the skills and to install one from a git URL or local path:

BASH
gemini skills list --all
gemini skills install <git-url-or-path>

Once the session starts, you'll see a list of available skills and their descriptions, and when the LLM finds a match it calls the activate_skill tool which prompts the user to proceed with the SKILL.md contents. So basically, it's a staged disclosure process, with the user being asked for permission halfway through.

For MCP-s: gemini mcp add, gemini mcp list, and enable / disable per server. The enable/disable are useful if you want to have a server configured but don't need it during a session.

Also, there's a thing called "workspace trust" that might be confusing. If the directory is not trusted, listing skills it says "Skipping project agents due to untrusted folder" and only shows the personal and built-in ones. It's just the project skill being skipped in this case. This message is displayed at the very beginning of the list so might be easily missed — make sure you don't miss it before assuming there's a problem with a file.

In Kimi Code CLI

The skills are resolved from four sources (with the highest precedence first):

  • Project directories, .kimi-code/skills/ and .agents/skills/, being located in the current directory and all its parent dirs up to the git root

  • Per-user directories, ~/.kimi-code/skills/ and ~/.agents/skills/

  • Extra skill directories, if configured under extra_skill_dirs in config.toml

  • The shipped defaults

You can use them like this: /skill:<name> [arguments]… if the skill has been defined with any.

For example: running it with a flag pointing to some temporary directory with skills so they can be used during that run without being resolved automatically. This way you can test a skill before incorporating it in some of the permanent scopes.

BASH
kimi --skills-dir ./scratch-skills

What's more, there are more frontmatter properties than just name and description in the skills.

  • whenToUse - to define the trigger

  • disableModelInvocation - set it to true if you don't want the model picking this skill up on its own

  • type - prompt or flow (for the latter only manual calls are possible)

The MCP setup is configured in mcp.json files, per-user ones at ~/.kimi-code/mcp.json and project-specific ones at .kimi-code/mcp.json. If there's a collision between the server names defined in both of these files, the project one has higher priority. There's no mcp subcommand in the Kimi Code CLI so to add or edit servers you can run /mcp-config during a session and to see their status you can use /mcp.

Once found, skills are being put into the system prompt, grouped by their scope (so the model can understand that some of them come from the project and some from your personal setup), which is good but means that it's better to keep their descriptions concise as they'll appear there in every turn after incorporating them to some of the scopes. And kimi doctor validates the config files, so run it first when some scope isn't being picked up.

What to check before you install anything

Before you add an MCP server, spend a minute to inventory what's already installed and authenticated on your machine; for most of the clients we work with, it turns out most so-called "integration problems" are git, gh, psql or kubectl. Which means that once somebody gives the agent the procedure, it can operate them via the existing shell tool

After you set up a server, spend another minute to explore what it actually did; every harness here can list the configured servers from the CLI or within the session, some of them even list the tools they expose. Because this number is not trivia — it's the per-session rent you're paying now and the basis to decide if the server was worth its place

THE FILE.agents/skills/gh-issues/SKILL.md
MARKDOWN
---
name: gh-issues
description: Read, triage and comment on GitHub issues and pull requests with the gh CLI. Use when asked about an issue or PR by number or URL, to triage the issue backlog, to find who last touched something, or to leave a comment on GitHub.
---

# GitHub through `gh`

`gh` is already authenticated on this machine. Use it instead of guessing from the repo,
and instead of asking for a GitHub token.

## Read before you write

- One issue: `gh issue view <number> --comments`
- Open issues, newest first: `gh issue list --state open --limit 30`
- Anything matching a phrase: `gh search issues "<phrase>" --repo <owner>/<name>`
- A pull request and its review state: `gh pr view <number> --comments`
- Arbitrary reads the subcommands don't cover: `gh api repos/<owner>/<name>/issues/<n>/events`

## Triage

Read the issue and the linked code before proposing a label. State which file the report
lands in and quote the line. If the report is not reproducible from what is in the repo,
say that instead of guessing a cause.

## Writing

Ask first. Every write is public and attributed to the account `gh` is logged in as.

- Comment: `gh issue comment <number> --body-file <path>`
- Label: `gh issue edit <number> --add-label <label>`
- Close: `gh issue close <number> --comment "<why>"`

Write the body to a file and show it before running the command. Never open, close or
comment on an issue in a repository the current task did not name.
j / k to move between lessons