Building an MCP server is straightforward.

Define your tools, wire up your handlers, ship it. The protocol is clean, the docs are solid, and most developers can get a working server running in an afternoon.

The hard part comes after.

Getting the Agent to Actually Show Up

Once your MCP tool exists, you need the AI agent to discover it, understand when to use it, and behave consistently across sessions. This is where the current ecosystem falls apart.

The standard pattern for distributing an MCP tool today looks something like this:

  1. User installs your npm package
  2. A postinstall script runs a setup command
  3. That setup command drops a skill file or configuration into the project
  4. The agent reads the skill file at the start of a session
  5. The agent follows the instructions in that file to invoke your MCP server

Every step in that chain is a potential failure point. The install might not trigger the postinstall. The setup might not have write permissions. The skill file might land in a directory the agent doesn’t check. And even when everything lands perfectly, the agent might just not read it.

This is dependency injection through the filesystem. It’s about as reliable as that sounds.

~90% Reliability Isn’t Enough

In my experience building and distributing MCP tools, this pattern works roughly 90% of the time. That sounds fine until you think about what the other 10% looks like. A user installs your tool, tries to use it, and nothing happens. No error message. No fallback. The agent just doesn’t know the tool exists.

The failure mode is silence. That’s the worst kind of failure when you’re trying to build trust with users.

Instruction Adherence Drifts

Even when the skill file gets discovered and read, consistent behavior isn’t guaranteed. A well-crafted skill file might produce perfect tool usage nine sessions out of ten, then completely ignore it on the tenth. The model treats your instructions as suggestions, not contracts.

This isn’t a bug. It’s just how language models process context. Your skill file is competing with everything else in the context window, and on any given session, it might lose.

What Actually Works Better

A few patterns reduce the flakiness.

Slash commands beat passive discovery. Dropping a file into .claude/commands/ creates an explicit invocation path. The user types a command, the tool fires. No discovery step, no hoping the agent notices your skill file. The tradeoff is that users need to know the command exists.

CLAUDE.md beats nested skill files. Instructions in the project root CLAUDE.md get loaded with higher priority than files buried in subdirectories. If your setup script writes to CLAUDE.md, your instructions are more likely to be seen.

Self-describing tool schemas beat prose explanations. The less your MCP server depends on a markdown file to explain itself, the more robust the integration becomes. Rich tool descriptions, well-named parameters, and clear type annotations let the agent figure out when and how to use your tool on its own.

The Architectural Gap

The deeper issue is that we’re in a transitional period. The current architecture asks tools to teach the model how to use them via text files. This is the equivalent of writing README-driven APIs before we had type systems or OpenAPI specs.

What the ecosystem needs is a declarative registration layer. Something that sits between “here’s a markdown file explaining my tool” and the model’s tool dispatch logic. MCP already provides structured tool definitions, but the bridge between those definitions and consistent agent behavior is still built on hope and prompt engineering.

Where This Is Heading

The MCP spec will probably evolve toward stronger guarantees around tool registration and invocation. Tools that can declare their own activation conditions, priority hints for tool selection, standardized discovery mechanisms that don’t depend on filesystem conventions.

Until then, if you’re building MCP tools for distribution, invest as much time in the integration story as you do in the tool itself. The server is the easy part. Getting the agent to reliably use it is the real engineering challenge.