← Writing
How Agent Plugins Could Bring learnmcp to Every AI Client
AI6 min read

How Agent Plugins Could Bring learnmcp to Every AI Client

agent-plugins.org's client extensions could let learnmcp keep its Claude Code hooks while shipping one portable plugin manifest everywhere else, from Codex to Cursor.

ShareXLinkedInFacebook

Build an OpenAPI spec in Postman with learnmcp installed in Claude Code, and before you've even finished typing the follow-up prompt, a badge pops up. Spec Author, plus ten points, plus the next thing worth trying. You never told the agent what you did. learnmcp just noticed.

A Claude Code session showing learnmcp awarding a First Contact badge and Apprentice rank right after a Postman API request runs, with no explicit prompt asking it to track anything.

learnmcp catching a Postman API call as it happens and awarding a badge, mid session, with nothing telling it to look.

Do the exact same thing in Codex, on the same project, with the same cartridges and the same points system underneath, and nothing happens. You build the spec and learnmcp sits there, silent, until you say "log that with learnmcp" out loud to the model. That one sentence is the entire gap between learnmcp feeling like magic and learnmcp feeling like a tool you have to remember to use.

That gap is Claude Code's hooks, and only Claude Code's hooks. I've written before about why learnmcp is vibe learning: it's supposed to happen beside the work, not instead of it. Hooks are what make that true. Everywhere else, it's still genuinely useful, just one manual step short of automatic. agent-plugins.org is a new vendor-neutral plugin standard, and one part of it, called client extensions, might be the thing that closes that step for good.

Why hooks are the whole trick

learnmcp's Claude Code plugin wires into three hook events: SessionStart, UserPromptSubmit, and PostToolUse. Here's the actual config, straight out of the repo:

{
  "hooks": {
    "SessionStart": [
      { "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/learnmcp-hook.mjs\" session-start" }] }
    ],
    "PostToolUse": [
      {
        "matcher": "Bash|Edit|Write|MultiEdit|NotebookEdit|Skill|SlashCommand|mcp__.*",
        "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/learnmcp-hook.mjs\" post-tool-use" }]
      }
    ]
  }
}

Every time you run a bash command, edit a file, or call any MCP tool, that PostToolUse matcher fires and a script watches for anything a cartridge cares about. No polling, no asking the model to remember, no separate step. That's the whole trick, and it's a genuinely good one.

Take that away and you're left with a plain MCP server, which still works everywhere MCP works: Codex, Cursor, your own agent. But the model has to explicitly decide to call record_activity after the fact, or run scan_project at the start of a session. As learnmcp's own README puts it, plainly: "No passive detection. Nothing is watching your session, so nothing is recorded automatically." Same badges, same points, same leaderboard once you ask. It's just an ask instead of a notice.

What agent-plugins.org is actually proposing

I've been watching agent-plugins.org for a few months, and what got my attention is the Technical Steering Committee: Amazon, Cursor, Microsoft, OpenAI, and Vercel, developing it openly on GitHub. That's not a spec one vendor wrote and hoped others would adopt. It's the companies who'd otherwise keep inventing incompatible plugin folders, agreeing on a floor everyone can build on top of: a portable plugin.json manifest anchoring Agent Skills and MCP servers, read the same way by any client. For learnmcp, that's most of what matters: the cartridges, learn_next, record_activity, the whole engine. Standardize the manifest and that part just works, identically, wherever someone installs it.

Client extensions: the part that matters for learnmcp

The piece I actually care about is client extensions. Its problem statement is close to word for word what I ran into with learnmcp: some platforms have real, useful, client-specific features, hooks being exactly one, and a portable plugin needs a legitimate way to use them without becoming unusable everywhere else.

The mechanism is a reverse-domain namespace, the same trick Java packages and Android app IDs have used for decades so two vendors never collide on a name. A plugin can own a whole directory under that namespace:

example-plugin/
├── plugin.json
└── com.example.client/
    └── hooks/hooks.json

The part that makes it work is what a client does with a namespace it doesn't recognize: nothing. It ignores it, without even validating what's inside. Claude Code reads its own namespace and gets hooks. Codex reads the same plugin, skips that folder entirely, and still gets a fully working MCP server and skill set. Nobody has to reject the plugin or half-support it. It's the difference between a plugin that's secretly Claude Code only and one that says so on the label while staying portable everywhere else.

What this would look like inside learnmcp

Today, learnmcp's plugin lives entirely inside Claude Code's own convention:

packages/plugin/.claude-plugin/plugin.json
packages/plugin/hooks/hooks.json

That works, but only because Claude Code happens to know to look in .claude-plugin/ and hooks/. There's no declared boundary between "this is the portable core" and "this only makes sense here." Under the agent-plugins.org model, I'd move the manifest to the plugin root as the portable piece, MCP server and skills included, and move the hooks into a namespaced extension folder:

packages/plugin/plugin.json
packages/plugin/com.anthropic.claude-code/hooks/hooks.json

Same hook script, same three events, same passive detection inside Claude Code. Nothing about how learnmcp works today changes. What changes is that the plugin now says, explicitly, "the hooks are Claude Code's thing, take the rest." A Cursor or Codex client reading that same package doesn't choke on a directory it doesn't understand. It just gets the MCP server and skills, the same thing it gets today, minus the confusion about why part of the folder does nothing there.

The frontier this doesn't cross yet

agent-plugins.org does not give Codex or Cursor a hooks equivalent. Nothing in the spec makes another client start watching sessions the way Claude Code does. If you're on a client without that capability, you still tell the model what you did, the same way you do today.

What it fixes is the packaging, and that's not nothing. Right now, building a plugin that behaves well in Claude Code and doesn't quietly break somewhere else means guessing at conventions. Client extensions turn that guess into a declared boundary: here's the part guaranteed to work everywhere, here's the part that's Claude Code specific, and every other client can tell the difference without reading your source. If Cursor or Codex ever ships its own equivalent of hooks, a plugin built this way doesn't need a rewrite. It needs one more namespaced folder sitting next to the one Claude Code already has.

That's what gets me excited about a standard like this. learnmcp already works for a Postman engineer on Claude Code, a Cursor user on the plain MCP server, and someone running it from source with a local SQLite database. Agent Plugins is a chance to make that same plugin declare its intent honestly instead of leaning on one vendor's folder structure, and that matters more once you're thinking about developers on tools you don't personally use every day.

If you're building an MCP server or a Claude Code plugin of your own, go read the client extensions spec. And if you want to see the current setup this post is about, the whole thing, hooks and cartridges included, is on GitHub.

Subscribe to quintonwall.com if you want more of this as I work through it, and follow along on YouTube at @seeqcode for the build-along version.

ShareXLinkedInFacebook

Subscribe

New posts on AI, developer relations, photography, and the odd long walk, straight to your inbox. No spam.

More on AI

All AI