
Skill vs MCP Server vs Plugin: A Claude Decision Framework
Most teams pick a mechanism because their fastest engineer already knows it — then discover a read-only prompt became a shared credential. Here's the rule that would have stopped it.
Ask a platform lead why a particular Claude capability runs under a service account instead of the caller's identity. You'll usually get the same answer: that's what the first engineer to build it already knew how to build. Nobody chose the mechanism. It chose itself, in the order features shipped.
That's how a capability that should have been instructions-only ends up holding a long-lived credential. It's also how a genuinely stateful integration gets rebuilt three times as prompt text, because writing markdown felt faster than standing up a server. Both mistakes are cheap to avoid and expensive to unwind.
This is a claude extensions decision framework for choosing on purpose. Anthropic publishes no canonical decision table for this, so what follows is ours, built from what the documentation actually says each mechanism does. It runs three tests in order: trust boundary, statefulness, and blast radius.
What Each Mechanism Actually Is
The three mechanisms differ in what they are, not just how they get used, and that distinction is the foundation of the whole framework.
A Skill is a directory containing a SKILL.md file with YAML frontmatter. At startup, the agent pre-loads only each installed skill's name and description into its system prompt, and pulls in the full body only when the skill looks relevant. Anthropic calls this progressive disclosure. In Claude Code, custom commands have merged into skills: a file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and behave the same way. Skills were published as an open standard for cross-platform portability in a December 18, 2025 update to Anthropic's engineering post.
Here's the nuance: "a skill is just instructions" holds only until the skill bundles scripts. Skills can include code for Claude to run as tools at its own discretion. Anthropic's own PDF skill ships a Python script that extracts form fields.
An MCP server is a separate process or remote endpoint that authenticates on its own behalf. Claude Code supports OAuth 2.0 for remote servers, marking one as needing authentication when it responds with 401 or 403. Local stdio servers get credentials through env blocks or headers instead. Configuration lives in three scopes: local, project (.mcp.json at the repo root, checked into version control and shared), and user, with precedence local > project > user.
A Plugin is a packaging and distribution unit. Think of it as the shipping container, not the cargo. Anthropic's docs define it as a self-contained directory of components that extends Claude Code, where those components can include skills, agents, hooks, MCP servers, LSP servers, and monitors. Tellingly, Claude Code does not support the hooks, mcpServers, and permissionMode frontmatter fields for plugin-shipped agents. That's an explicit guardrail on what a distributed bundle may change about its host's trust configuration.
Test One, Trust Boundary: Whose Identity Executes?
This is the first question in the framework, because it's the one security review will ask.
A Skill introduces no new principal. It executes inside the session that's already running, with whatever permissions that agent already holds. Snyk puts the consequence bluntly: skills operate with the full permissions of the agent they extend, inheriting shell access, filesystem read/write, credentials sitting in environment variables and config files, messaging ability, and persistent memory.
An MCP server opens a new authenticated path into a system of record, with its own identity and its own token handling. That's exactly where the MCP specification's security guidance concentrates its warnings: the confused deputy problem in proxy servers, and "token passthrough." Token passthrough is a server accepting tokens from a client without validating they were issued for it, then forwarding them unmodified downstream. It's named as an anti-pattern. The spec states that MCP proxy servers must implement per-client consent before forwarding to third-party authorization.
On Google Cloud, the mapping is reasonably clean. Claude is available through Agent Platform's Model Garden, and Google Cloud has said, as reported in trade coverage rather than a single primary doc, that invoking Claude there uses the same IAM policies, VPC controls, Cloud Logging and Cloud Monitoring customers already run, with requests inheriting project-level IAM and VPC Service Controls. Model line-ups on that page move quickly; verify names and availability yourself before designing around a specific one.
The rule: if the capability needs a principal that isn't the caller, it's an MCP server. Writing it as a Skill doesn't remove the credential. It just hides it inside an inherited session.
Test Two, Statefulness: Instructions, Sessions, or Packaging
This test separates instructions from sessions from packaging. Skills are stateless by design and re-read on use, and that's a feature: nothing to reconnect, nothing to expire.
MCP servers carry connection lifecycle and session state, so authentication, refresh, and transport failures are theirs to manage. Plugins hold no runtime state at all; their state is a version number.
Here's the tell that a stateless choice is being stretched too far: the skill has grown a scripts directory, a credential it reads from the environment, and retry logic for a network call. At that point you've written an MCP server in markdown and lost the identity boundary a real one would have given you. Anthropic's enterprise Skills guidance points the same direction, its risk-tier table rates code execution, instruction manipulation, MCP server references, network access patterns, and hardcoded credentials all as High. It flags MCP references inside a Skill specifically because they extend access beyond the Skill itself.
There's a fair counter-argument here, and it isn't about trust. The loudest practical reason teams prefer Skills is context economics: Anthropic reports having seen tool definitions consume 134K tokens before optimization; in its example, loading all definitions upfront costs roughly 72K tokens for 50+ MCP tools, which on-demand tool search cuts to about 8.7K. That cost is real, and it belongs in the design conversation on its own terms rather than standing in for a trust-boundary argument.
Test Three, Blast Radius: What Breaks, and How Far
When two mechanisms look equally convenient, this is the tiebreaker.
- Skill failure is bounded by the session's permissions, which, per Snyk, is not a small bound. Its February 5, 2026 ToxicSkills research scanned 3,984 skills from ClawHub and skills.sh. It found 13.4% (534 skills) carried at least one critical-level issue, 36.82% at least one flaw, with 76 malicious payloads confirmed by human review. That corpus is community-published, not Anthropic-curated, so don't read it as a verdict on official or internal skills. But it does retire "it's only markdown."
- MCP server failure reaches whatever the server's credential reaches, for everyone using it. Anthropic states plainly that by default anyone running Claude Code can connect any MCP server they choose, and that while it reviews connectors against listing criteria for the Anthropic Directory, it does not security-audit or manage any MCP server. Directory listing reflects listing criteria, not a security audit.
- Plugin failure is fleet-wide by construction. One vetted bundle ships skills, hooks and servers to everyone, and the update path makes the marketplace a supply-chain dependency.
Simon Willison's "lethal trifecta", access to private data, exposure to untrusted content, and the ability to communicate externally, is the cleanest test to run per mechanism. Any extension holding all three deserves a design conversation, whichever form it takes.
The Verdict: Default Mappings
| The job | Default mechanism | Why |
|---|---|---|
| Encode judgement, house style, a repeatable procedure | Skill | Instructions under the caller's existing permissions |
| Query or write to a system of record | MCP server | New principal, session state, auditable path |
| Ship a vetted set of capabilities to a team | Plugin | Versioned distribution, one update path |
| Wrap an internal API a few people use ad hoc | MCP server, local scope | Contained to one developer's session |
Four cases break the defaults. Shared write access to a system of record should never sit behind a credential in a skill's environment, however convenient. Multi-team distribution of an MCP server that three teams have copy-pasted is a plugin waiting to happen. Regulated data paths need the identity of the caller preserved end to end, which rules out anything that collapses to a service account. And anything that fails the trifecta test gets designed, not defaulted.
One honest limit: Claude Enterprise organizations can enable Skill and plugin security scanning in claude.ai and Cowork. A Skill that fails, or whose scan hasn't finished, gets blocked, but the coverage has gaps. It doesn't cover Skills uploaded via the Skills API, Skills already present when scanning was switched on, or organizations using CMEK, ZDR, or HIPAA-readiness configurations. Treat scanning as a filter, not a backstop.
Making the Framework Stick
Applying this framework consistently is what turns a written rule into an enforced default. A written rule adds friction right when a team feels fastest, so keep the gate small: three questions before a new extension ships. What risk tier is it, which principal executes, and what's the rollback path.
Then build the inventory, because nothing ships it for you. Claude Code has no built-in MCP registry to browse and install from; Anthropic's guidance is to publish the approved list and its claude mcp add commands internally, or distribute approved servers as plugins through a managed marketplace. Admin-only controls exist to enforce the outcome: allowManagedMcpServersOnly, strictKnownMarketplaces, blockedMarketplaces, pluginTrustMessage, and strictPluginOnlyCustomization. That last one blocks skills, agents, hooks and MCP servers from user and project sources, so they can only arrive through plugins or managed settings. Note that managed-mcp.json is readable by any user on the machine, so credentials don't belong in its env blocks; pass per-user secrets through environment expansion instead. These keys are versioned in fine detail, so check them against current docs before writing them into a standard.
Migration usually beats a rewrite. A skill that has grown scripts and credentials becomes an MCP server with the same instructions and a real identity. A server three teams maintain separately becomes one plugin. The inventory-plus-automated-checks pattern will feel familiar to anyone already using the 200+ automated security checks and spend controls WALT Labs runs in Cloud Companion. It's the same operating discipline, applied to a new surface.
If you'd rather not assemble the gate, the registry, and the identity design from scratch, WALT Labs' Gemini Enterprise Agent Platform jumpstart and custom MCP connector builds wire these controls into the IAM, VPC-SC, and billing model you already run.


