SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

Agent skills vs MCP servers vs rules files: which one?

Skills, MCP servers, and rules files fit all guide coding agents, but dem cost context tokens differently. Learn which one to pick and reduce repeat upkeep.

Agent skills vs MCP servers vs rules files: short answer

Agent skills, MCP servers, and rules files all dey put knowledge in front of coding agent. Choose based on wetin the knowledge dey do. MCP (model context protocol) na for data wey fit change the next time you check am. Skill na for procedure wey you fit write down today and e still go correct six weeks from now. Rules file na for the few facts wey must apply for every session.

That choice get cost, and the cost na context. Every token wey you spend for instruction wey agent no need na token wey no dey available for the code wey e dey read. You still dey pay that token again for every turn, because the full context window dey resend with each request. So the useful question no be which mechanism fit do the work. Most days, all three fit. The question na which one go cost the least while e dey idle.

Wetin each one go cost before you use am

The three dey load for different times, and na this timing make the whole difference.

A rules file dey load complete when e launch, for every session, whether e relevant or not. Claude Code dey read CLAUDE.md when every conversation start and dey load am complete, no matter the length. The documented target na under 200 lines for each file, because longer file dey use more context and model dey follow am less reliably. Both effects dey push for the same direction, na why 900-line rules file worse than useless.

A skill dey load for two stages. For startup, na only the description line from each SKILL.md frontmatter dey enter context, so model know say the skill dey exist and roughly when e apply. The body dey load when skill invoke. So, 400-line reference document almost no cost you until the time wey you need am.

MCP server used to be the expensive one, and na here most comparison wey you go read don become outdated. Tool search dey on by default for current Claude Code. Na only tool names and the server's instructions field dey load when session start, while the full JSON (JavaScript object notation) schemas dey wait until Claude search for dem. Adding server no longer dey cost thousands of tokens upfront. E still dey cost something, and e still dey cost everything upfront for configurations wey tool search dey off.

ChartStartup and post-use context cost, estimated tokens
The data behind this chart
[
  {
    "label": "Rules file, 200 lines",
    "at_startup": "2,500",
    "after_use": "2,500"
  },
  {
    "label": "Skill, 12 KB body",
    "at_startup": 40,
    "after_use": "3,000"
  },
  {
    "label": "MCP server, tool search on",
    "at_startup": 500,
    "after_use": "3,200"
  },
  {
    "label": "MCP server, tool search off",
    "at_startup": "4,500",
    "after_use": "4,500"
  }
]

Those ones na estimates, no be measurements from your machine. Dem come from the size of the text wey each mechanism dey load, at roughly four characters per token: a 200-line rules file na about 10 KB of markdown, a skill description na about 160 characters, and server wey expose twelve tools carry about 18 KB of schema plus 2 KB instructions block. Claude Code dey truncate each tool description and each server instructions field at 2 KB, so that part get limit. Next section go show you how to read your own real numbers instead.

Read the first two rows together. The rules file costs 2,500 tokens for session wey nobody need am. The skill costs 40 tokens for that same session, and 3,000 for the one session out of ten wey e run. The last two rows na the same server twice, with tool search on and off: 500 tokens against 4,500. Na this gap make old advice about MCP context bloat still dey circulate.

Tool search need model wey support tool_reference blocks, wey as of August 2026 mean Claude Sonnet 4.5, Haiku 4.5, Opus 4.5 and later. Claude Code dey turn am off when ANTHROPIC_BASE_URL point to host wey no be first party, because most proxies no dey forward those blocks. Set ENABLE_TOOL_SEARCH to control am: false dey load every schema upfront, true dey defer all of dem, and auto dey load dem upfront only when dem fit inside 10% of the context window.

# Load schemas up front only if they fit in 5% of the window
ENABLE_TOOL_SEARCH=auto:5 claude

Di deciding question be: data dey change between invocations?

Ask this one first, because e go remove one option completely. If agent need read or write something wey fit different the next time e check am, you need a server. Issue tracker, database, monitoring dashboard, or your own internal API (application programming interface). Writing am down no go help, because wetin you write don stale immediately somebody else edit the record.

If the answer go still correct six weeks from now without anybody maintaining am, you want a skill. Release checklist. Migration procedure. The format of your error responses. How this repository want make dem write tests. Skill na file for git. E no get port, process, or failure mode apart from being wrong, and code review fit catch that.

If na one fact wey must apply to work wey you never think about yet, put am for rules file. Run make lint before committing. Never push to main. Handlers live in src/api/handlers/. One line for each. Once entry don grow reach steps, e don stop being fact and become procedure, so e suppose move go skill.

When rules file dey enough

Rules files fit load from different places, starting from the broadest go the most specific: managed policy file, your personal ~/.claude/CLAUDE.md, the project own ./CLAUDE.md or ./.claude/CLAUDE.md, and one gitignored ./CLAUDE.local.md. All the files wey system discover go join together; dem no dey override each other. Files wey dey closer to your working directory go read last.

Claude Code dey read CLAUDE.md, no be AGENTS.md. If your repository already get AGENTS.md for other tools, no maintain two copies wey fit drift apart.

ln -s AGENTS.md CLAUDE.md

The symlink no print anything when e succeed. Start session, run /context, and confirm say CLAUDE.md dey show under Memory files. If e no dey listed there, the agent never see am, and changing the wording no go help. If you also want Claude-specific lines, use the import form instead and put dem below the import.

@AGENTS.md

## Claude Code

Use plan mode for changes under `src/billing/`.

One trap dey here. @path imports no save context. The imported file go expand and load when launch happen, together with the file wey reference am, up to four hops deep. If you split one 600-line rules file into six imports, e go organise am for humans, but the token cost no go change at all. The conventions behind AGENTS.md and its human-facing twin dey worth reading before you choose layout.

Wetin reduce the cost na .claude/rules/ with one paths field. Rules file wey get paths frontmatter go load only when the agent touch file wey match one of the patterns.

---
paths:
  - "src/api/**/*.ts"
---

# API rules

- Every endpoint validates its input.
- Use the standard error response shape.

Rule wey no get paths field go load when launch happen, with the same priority as .claude/CLAUDE.md. So the useful pattern na short unconditional rules, plus one paths list for anything wey matter only inside one directory.

Wen you want one skill

One skill na directory wey get one SKILL.md inside am. Personal skills dey for ~/.claude/skills/<name>/SKILL.md and dem apply to every project for your machine. Project skills dey for .claude/skills/<name>/SKILL.md, dem dey follow the repository, and you fit review dem for pull request like any other file.

mkdir -p ~/.claude/skills/summarize-changes
---
name: summarize-changes
description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---

Run `git status` and `git diff` against the merge base.
Group the changes by intent, not by file.
Call out anything touching auth, migrations or deletions.

The description na the only part of that file wey dey enter context before the skill run, so e dey do two jobs. E talk wetin the skill dey do, and e talk when you suppose use am. Description like "Helps with deploys" no give the model anything wey e fit match with request, so the skill no go ever run quietly and you go conclude say skills no work.

The directory name become the command, so the example above give you /summarize-changes. For personal or project skill, the frontmatter name only set the display label for listings.

Once you invoke one skill, the rendered content enter the conversation as one message and remain there for the rest of the session. Claude Code no go read the file again for later turns. Write standing instructions instead of steps wey na only for one time, and keep the body short, because from that point every line dey add recurring cost to each request. After auto-compaction, Claude Code attach the most recent invocation of each skill again, and e keep the first 5,000 tokens of each inside combined budget of 25,000 tokens. If you invoke several large skills for one session, the oldest ones go drop completely. Na why skill fit look like say e stop to matter after long conversation. Invoke am again and e go come back. When the same procedure apply to more than one codebase, share one skill across several repositories instead of copying the file around.

Wetin time you need an MCP server

To add one, na just one command, and the transport dey decide how e go work.

# Remote HTTP server
claude mcp add --transport http notion https://mcp.notion.com/mcp

# Remote HTTP server behind a bearer token
claude mcp add --transport http secure-api https://api.example.com/mcp \
  --header "Authorization: Bearer your-token"

# Local stdio server: everything after -- is passed through untouched
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

The -- dey important. For stdio server, e separate Claude Code own options from the command line wey start your server. If you leave am out, any --port 8080 wey suppose go to the server go parse as option for claude mcp add, and claude mcp add go reject am.

claude mcp list
claude mcp get notion

claude mcp add confirm with an Added ... line. This one only show say configuration don write to disk. claude mcp list na the command wey show the real status, because e print health status beside each server: ✔ Connected, ! Needs authentication, or ✘ Failed to connect. Failure status mean say Claude Code no fit reach that server; e no mean say the list command fail. Inside a session, /mcp show the same view for each server, plus the tool count.

Each call to an MCP server dey stand on im own and carry anything wey e need. Na why MCP server no remember your previous request be the reason. Na design choice, but e get consequence wey you must handle: any state wey worth keeping must live behind the server, inside database or file. And na you go operate that database or file.

MCP server na process wey you must run

Na here vendor comparison no dey count the cost. Skill na file. MCP server na software wey dey run somewhere. If that place na your VPS (virtual private server), na you dey responsible for whether e stay online.

stdio server na the cheaper case. Claude Code go start am as child process when session start, and e go stop when session end. You no need monitor anything, and e no need patch by its own schedule. Remote HTTP server na long-running service, and e need the same things every long-running service need.

[Unit]
Description=Notes MCP server
After=network-online.target
Wants=network-online.target

[Service]
User=mcp
WorkingDirectory=/srv/notes-mcp
ExecStart=/usr/bin/node /srv/notes-mcp/dist/server.js
Environment=PORT=8931
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now notes-mcp
systemctl is-active notes-mcp
journalctl -u notes-mcp -n 50 --no-pager

systemctl is-active suppose print active. If e print failed, journal get the reason. For first run, na almost always missing environment variable or port wey another process don already bind. Restart=on-failure no be optional for here, because crashed MCP server no dey announce itself. You go know only when agent tell you say e no fit read your issue tracker.

Bind the process to 127.0.0.1, then put reverse proxy with TLS (transport layer security) in front of am. MCP server wey fit reach your database and answer for public port without authentication na database wey you don publish. How to run MCP server for VPS cover the proxy, certificate, and firewall side properly.

Then count the recurring work honestly. The service dey take security updates on its own schedule, separate from the agent wey dey talk to am. Its OAuth token dey expire, and claude mcp list go start print ! Needs authentication for a bad time. Its credentials dey inside config file or Authorization header, so you must protect dem like any other secret. That matter alone big: how to keep secrets away from AI agent. Skill no get any of this work.

Compare am with the alternative before you build. If the data behind the proposed server dey change about once every quarter, skill wey tell agent where to look and wetin the fields mean cheaper than service wey you must keep alive.

How to measure your own context cost

Stop estimating and run /context inside a session. E go print the startup breakdown: system prompt, memory files, tools, and MCP servers, plus the token weight of each one.

Check two things. Under Memory files, confirm say every rules file wey you expect dey listed. If file dey missing, agent no fit see am, so na the first thing to rule out when instructions dey ignored. Then check how much your servers dey cost. If server wey you use twice a month dey among the biggest lines for that list, toggle am off for /mcp and turn am back on for sessions wey need am. The configuration still dey kept.

Remote server fit also report status like cached 2h ago · connects on first use · 5 tools. This one mean say Claude Code read the tool list from previous session instead of connecting during startup, and e go connect the first time you call tool. The tools dey available from your first message, so nothing dey to fix. Set MCP_DISCOVERY_CACHE=0 if you prefer make every server connect during startup. For the bigger picture, how to manage the Claude Code context window explain wetin dey remain after compaction, while wetin those tokens really cost you convert the numbers to money.

Why my skill no dey trigger?

The usual cause na description. Na the only text wey dey context before skill run, so if e no name the situation, nothing go match am. Put the trigger inside the sentence: "Use when the user asks what changed, wants a commit message, or asks to review their diff." Vague descriptions fail silently, and this one hard to notice.

The second cause na frontmatter typo, and this one loud. System go reject unknown key outright:

Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name

The third one na location. Project skills dey load from .claude/skills/ for your working directory and every parent directory up to repository root. Skills wey dey nested directories below where you start no dey load when agent launch. Dem go appear the first time agent read or edit file inside that subdirectory. Before then, dem no dey autocomplete and you no fit invoke dem by name.

The MCP equivalent of this silent failure na a .mcp.json entry wey get url but no type. Claude Code dey read any entry without type as a stdio server, so e skip the entry and report:

MCP server "notes" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entry

Make all three work together

These mechanisms no dey compete for the same place. Setup wey dey work na to use each one where e cheap. Rules file dey hold small number of lines wey true everywhere. Skills dey hold procedures and dem load only when dem apply. One MCP server, sometimes two, dey connect systems wey you no fit predict their contents ahead of time. If you still dey build your understanding of the first one, wetin agent skill really be explain the format well.

One test fit settle most arguments about where something belong. Delete am, start fresh session, then give agent the task. If agent only slow down, e belong inside skill. If agent dey confidently give wrong answer, e belong inside rules file. If agent no fit get the information at all, you need the server, and now you also need plan for keeping that server running.

FAQ

I fit write a skill, or I suppose stand up an MCP server?

Decide based on whether the information dey change between one invocation and the next. If agent must read live state wey another person fit edit, like issue tracker, database, or dashboard, you need MCP server, because anything wey you write down don stale as soon as the record change. If you fit write the answer once and e still correct six weeks later, write a skill. Skill na file for git. E no get process to run, port to expose, or patch schedule. So na cheaper option whenever e possible.

MCP servers still dey fill my context window?

E much less than before. Tool search dey enabled by default for current Claude Code, so na only tool names and server instructions field dey load when session start. Full schemas dey fetch when Claude search for dem. Upfront loading still happen when tool search off: with ENABLE_TOOL_SEARCH=false, when ANTHROPIC_BASE_URL point to proxy wey no be first party, or for model wey old pass Claude 4.5 generation. Run /context to see which situation apply to you, because the numbers for older comparison posts assume upfront loading.

Claude Code dey read AGENTS.md?

No. Claude Code dey read CLAUDE.md. If your repository already get AGENTS.md for other agents, make one point to the other instead of keeping two copies. Run ln -s AGENTS.md CLAUDE.md for plain symlink, or put @AGENTS.md for the first line of CLAUDE.md and add Claude-specific instructions below am. Then start session and run /context to confirm say CLAUDE.md dey show under Memory files.

Why my skill stop dey get any effect halfway through session?

Auto-compaction na the usual reason. When conversation get summary, Claude Code attach the most recent invocation of each skill again. E keep the first 5,000 tokens of each one, within combined budget of 25,000 tokens across all of dem. E dey fill that budget starting from the skill wey dem invoke most recently. So if you don invoke several large skills, e go drop the older ones completely. Invoke the skill again to restore the full content.

How I fit stop long rules file from loading for every session?

Move the parts wey only matter sometimes into .claude/rules/ files with paths field for their frontmatter, so each one go load only when agent touch matching file. Splitting the file into @path imports no go help, because imported files dey expand and load when launch happen, together with the file wey reference dem. Anything wey be multi-step procedure instead of standing fact suppose become skill, because skill body no cost anything until you invoke am.