Back to all posts
7 min read

Skills Are Not Skills: The MCP Misunderstanding Nobody Wants to Correct

Skills Are Not Skills: The MCP Misunderstanding Nobody Wants to Correct

TL;DR: It’s Sunday. I open my feed. Hundreds of posts praising Skills like some innovative invention. Skills are prepackaged tutorials—Claude follows instructions. MCP servers are executables—they do things. One requires the LLM to reason through 4 linting tools and read documents for trailing spaces. The other runs lint() and everything screams. Anyone telling you Skills replace MCP is not misinformed. They’re lying.


The Sunday Feed Problem

Another week, another “game-changer” announcement. This time it’s Skills.

The influencer chorus sings in harmony:

  • “Skills are bigger than MCP!”
  • “The Cambrian explosion is here!”
  • “Just write markdown and you’re done!”

And I’m sitting here watching my Dictator MCP server enforce code discipline across Go, Rust, Ruby, and this very blog—with a single tool call—while Skills enthusiasts explain how markdown files are revolutionary.

Let me be precise about what’s happening here.


Skills Are Tutorials, Not Skills

When you follow a tutorial on deploying WordPress with Kamal, you haven’t acquired a skill. You’ve followed instructions.

That’s what Claude Skills are: prepackaged instructions. The LLM reads them. The LLM follows them. The LLM reasons through each step, burning tokens, making decisions, potentially hallucinating edge cases.

A Skill that says “lint this code” means Claude must:

  1. Figure out what language it’s looking at
  2. Decide which linting tool to invoke
  3. Read configuration files to check for trailing spaces, CRLF issues
  4. Run multiple tools
  5. Parse outputs
  6. Hope it understood the context correctly

That’s not a skill. That’s homework.


MCP Servers Are Executables

My Dictator MCP server does one thing: enforce discipline.

The LLM runs one tool: lint(). Everything screams. Go, Rust, Ruby, markdown—it doesn’t matter. The server handles language detection, configuration, execution, and returns structured results.

No reasoning required. No token burn on “should I check for trailing whitespace?” The server knows. The server decides. The server executes.

Try to do this with Skills.

You can’t. The LLM would need to:

  • Run 4 different linting tools
  • Read documentation to understand each tool’s output format
  • Check for trailing spaces, CRLF, file size limits
  • Coordinate results
  • Hope nothing hallucinated along the way

Skills are instructions. MCP servers are execution.


The Spec Nobody Reads

Here’s what kills me.

The 2024 MCP spec—The Original Voyager—had tools/listChanged. Dynamic tool registration. A server starts with 1 tool. Client runs it. Server notifies: “Hey, refresh your tool list.” Now there are 3 tools.

Dictator does exactly this. First tool: occupy() to initialize the repo. Once run, the client gets notified to refresh. Now the LLM sees the actual linting tools, configured for this specific codebase.

Does Claude Code implement this? No. Does Codex implement this? No.

They call it a “feature” while ignoring the spec they claim to support. Meanwhile, Charm’s Crush actually implements it correctly. You can literally log in with Claude through Crush while Claude Code pretends dynamic tools don’t exist.

I documented all of this in The Hitchhiker’s Guide to MCP. Every spec version. Every capability. Every lie of omission.


The Vibe-Coded MCP Epidemic

Most MCP servers are built with what I call Vibe-Based Development.

“If the 40 tools show up, we ship it.”

No thought about:

  • Which tools should be available when
  • Dynamic registration based on context
  • Progressive disclosure
  • Token efficiency

Just dump everything into tools/list and let the LLM figure it out. The same LLM that confidently returns 15 when the calculator says 57.

This is why MCP got a bad reputation. Not because the protocol is limited—it’s remarkably well-designed. But because the ecosystem built garbage on top of it and called it innovation.


This Is Not Hallucination

Let me be clear about something.

This is not me hallucinating. This is based on real specs and provider documentation. When Anthropic publishes a doc, I read it. All of it. Every word.

I don’t ask Claude to “fetch page and give me summary.” I read everything.

The 2024 spec exists. tools/listChanged exists. Dynamic tool registration exists. The fact that major clients ignore it doesn’t make it not exist—it makes them incomplete implementations parading as reference clients.


Why I Call Them Liars

Not misinformed. Liars.

It’s 2025. You can run benchmarks in 10 minutes. You can test whether Skills actually replace MCP functionality. You can verify claims before amplifying them.

Instead, the cycle continues:

  1. Anthropic announces something
  2. Influencers parrot the marketing without testing
  3. Others repeat what influencers said
  4. The echo chamber crystallizes into “common knowledge”
  5. Anyone who disagrees is “not getting it”

I’ve built MCP servers. I’ve written Skills. I know what each can do. And anyone claiming Skills replace MCP server functionality is either:

  • Lying for engagement
  • Too lazy to test their claims
  • Invested in a narrative that benefits them

Pick one. “Misinformed” isn’t on the menu anymore.


The Dictator: When Structure Is Not Negotiable

Let me show you what a real MCP server looks like.

Dictator is a pre-linter structural gatekeeper. It doesn’t replace RuboCop, ESLint, or Clippy—it runs before them. While those tools analyze code quality, Dictator enforces boundaries: file structure, naming conventions, ordering, basic hygiene.

Rules are meant to be broken. That’s why you have 1000 linters with 10000 rules and everyone disables half of them.

Decrees are absolute. The Dictator does not negotiate. Your file ends with a newline or it doesn’t pass. Your methods are ordered correctly or they aren’t. No “warn”, no “suggestion”, no “consider maybe perhaps”.

The MCP server exposes tools dynamically:

ToolDescriptionModeAvailability
occupyInitialize config (creates .dictate.toml)SetupAlways
stalintCheck files for structural violationsRead-onlyAlways
dictatorAuto-fix structural issuesDestructiveGit repos only

Multi-layer protection:

  • Git repository requirement: destructive tools only exposed when .git exists
  • Working directory boundary: rejects paths outside cwd
  • Sandbox mode support: hides destructive tools in read-only mode
  • Dynamic mode detection: supremecourt mode only available if external linters are installed

From the AI’s point of view, Dictator is the one calling the shots: external linters do the heavy lifting, Dictator orchestrates them, and then takes the credit.

Try to do this with a Skill.

A Skill would need Claude to:

  1. Detect language (reasoning tokens)
  2. Select appropriate linter (reasoning tokens)
  3. Execute linter (tool call)
  4. Parse output (reasoning tokens)
  5. Repeat for each check type
  6. Aggregate results (reasoning tokens)
  7. Hope nothing hallucinated

Dictator: stalint(). Done.


The Actual Relationship

Let me be constructive for a moment.

If you use a screwdriver to slice butter and cheese, then discover a knife exists, the screwdriver isn’t bad — your understanding of tools was. Skills aren’t bad. They’re being sold as something they’re not.

Skills are useful for:

  • Documenting workflows
  • Standardizing output formats
  • Teaching Claude domain-specific terminology
  • Reducing repetitive prompting

MCP Servers are useful for:

  • Executing code
  • Accessing external systems
  • Enforcing constraints the LLM can’t hallucinate around
  • Dynamic capability based on context

Use Skills to tell Claude how to think about a problem. Use MCP to solve the problem.

They’re complementary. But they’re not equivalent. And Skills absolutely cannot replace a well-built MCP server.


The Benchmark Challenge

Here’s my challenge to the Skills enthusiasts:

Build a Skill that does what Dictator does:

  • Lint any language (Go, Rust, Ruby, TypeScript, Markdown)
  • Enforce whitespace discipline
  • Check line endings
  • Validate file sizes
  • Return structured, actionable results
  • Do it in one tool call

I’ll wait.

Actually, I won’t. Because I know you can’t. That’s not a minor difference. That’s the difference between following instructions and having capability.


Conclusion

Skills are documentation. MCP servers are infrastructure.

One tells Claude what steps to follow. The other removes the need for steps.

The ecosystem is excited about Skills because they are new. MCP servers require coding ability. Skills can be copy-pasted from docs. Markdown files. No protocol complexity. No server implementation. Just write some instructions and ship.

But easy isn’t the same as powerful. And the influencers praising Skills as MCP’s successor are either confused about what each does, or deliberately misleading you because Skills content gets more engagement than “go read the spec.”

Stop calling tutorials “skills.” Start reading the spec before shipping. And for the love of engineering, run a benchmark before you parrot.


Part 2: Why Claude Code ignoring tools/listChanged is a bug, not a feature—and what Charm got right.


P.S. — Seven months ago I wrote about MCP not being just a tool registry and prompts being preloaded sanity. Everything I said then still applies. The ecosystem just got noisier.

🔗 Interstellar Communications

No transmissions detected yet. Be the first to establish contact!

• Link to this post from your site• Share your thoughts via webmention• Join the IndieWeb conversation

Related Posts

Agentic Dictatorship-Driven Development: Why You Need to Be a Tyrant with AI

LLMs are pattern matchers, not entropy generators. If you don't dictate specifics, you'll get purple gradients, Sarah Chen testimonials, and 47M$ Sequoia hallucinations. ADDD (Agentic Dictatorship-Driven Development) is the opposite of vibe coding - and it's the only way to get real results.

AILLMvibecoding