---
title: The Complete Guide to Agent Plugins
description: Package Agent Skills and MCP servers into portable plugins that work across compatible AI agent clients with the Agent Plugins specification.
url: /kb/guide/agent-plugins
canonical_url: "https://vercel.com/kb/guide/agent-plugins"
published: 2026-08-07
last_updated: 2026-08-07
authors: Ben Sabic
related: []
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

AI agent clients each developed their own plugin formats, even when plugins contain the same underlying components. Authors rearrange or duplicate skills and MCP server configuration for every client, so a plugin packaged for one tool often needs adaptation before another can use it.

Agent Plugins solves this with an open, vendor-neutral specification for portable plugins. Version 1.0 defines a shared format for [Agent Skills](https://agentskills.io/specification) and [MCP servers](https://modelcontextprotocol.io/specification) that any compatible client can discover and load consistently.

## Overview

In this guide, you'll learn:

- What Agent Plugins is and the problem it solves
  
- The structure of a plugin package and its manifest
  
- How skills and MCP servers work as portable components
  
- How client extensions add client-specific behavior without breaking portability
  
- How clients load plugins and isolate failures
  
- How to build your first plugin
  

## What is Agent Plugins?

Agent Plugins is a specification that defines a small interoperability floor for the parts of a plugin that can be portable across clients. An Agent Plugin is a self-contained directory with a required manifest (`plugin.json`) and optional components in fixed locations. Version 1.0 defines exactly two portable component types, both built on established specifications:

| Component type | Fixed location | Governed by                                                                           |
| -------------- | -------------- | ------------------------------------------------------------------------------------- |
| Skills         | `skills/`      | [Agent Skills specification](https://agentskills.io/specification)                    |
| MCP servers    | `mcp.json`     | [Model Context Protocol specification](https://modelcontextprotocol.io/specification) |

Agent Plugins doesn't redefine either format. It defines where components live inside a plugin, how clients discover and validate them, and how failures are isolated so one broken component doesn't take down the rest.

The specification is openly licensed and developed in public. Its initial Technical Steering Committee includes Core Maintainers from Amazon, Cursor, Microsoft, OpenAI, and Vercel, and proposals begin in [GitHub Discussions](https://github.com/agentplugins/agent-plugins-spec/discussions) where anyone can participate and help shape the specification.

## Why a portable format matters

The specification separates portable behavior from client-owned behavior:

- **Portable**: package structure, manifest validation, component discovery, MCP configuration, plugin environment variables, and failure isolation.
  
- **Client-owned**: installation sources and marketplaces, enablement and update flows, permission prompts and sandboxing, and how skills are surfaced.
  

This split lets shared components use one predictable structure while clients keep full control of distribution, trust policy, and user experience. Clients can also adopt component types incrementally, so a skills-only client conforms without supporting MCP servers, as long as it supports at least one of the two.

## Anatomy of a plugin

A plugin is a directory rooted at a single filesystem location. A complete plugin with skills, an MCP server, and a client extension looks like this:

```plaintext
my-plugin/
├── plugin.json
├── skills/
│   └── summarize/
│       ├── SKILL.md
│       ├── scripts/
│       └── references/
├── mcp.json
└── com.example.client/
    └── hooks/
```

Each part has a fixed role:

- `plugin.json` identifies the plugin and the Agent Plugins version it targets. It's the only required file.
  
- `skills/` contains Agent Skills, one per immediate child directory.
  
- `mcp.json` configures stdio, Streamable HTTP, or legacy HTTP+SSE MCP servers.
  
- Reverse-domain directories like `com.example.client/` hold client-specific files that other clients can safely ignore.
  

One rule governs the whole package: every file a client discovers, reads, or executes must resolve within the plugin root, even after resolving symlinks and equivalent filesystem mechanisms. Plugin-relative paths in configuration begin with `./` and cannot escape the package.

## The plugin manifest

Every plugin contains exactly one portable manifest at `plugin.json`.

The minimal manifest sits in the plugin root and needs only two fields:

```json
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "deployment.tools"
}
```

The manifest schema is closed, meaning only these top-level fields are permitted:

| Field         | Required | Purpose                                                    |
| ------------- | -------- | ---------------------------------------------------------- |
| `$schema`     | Yes      | Selects the Agent Plugins version and validation contract. |
| `name`        | Yes      | Human-readable plugin name and package identifier.         |
| `version`     | No       | Plugin version; Semantic Versioning is recommended.        |
| `description` | No       | Short description of the plugin.                           |
| `author`      | No       | Object with optional `name`, `email`, and `url` strings.   |
| `homepage`    | No       | Documentation or homepage URL.                             |
| `repository`  | No       | Source repository URL.                                     |
| `license`     | No       | License string; an SPDX identifier is recommended.         |
| `keywords`    | No       | Array of search and discovery strings.                     |
| `extensions`  | No       | Client-owned data keyed by reverse-domain namespace.       |

### Name constraints

Plugin names are 1 to 64 characters and follow strict rules so they work as identifiers across different clients:

| Constraint    | Requirement                                                |
| ------------- | ---------------------------------------------------------- |
| Character set | Lowercase ASCII letters, digits, hyphens, and periods only |
| Start and end | First and last characters must be alphanumeric             |
| Repetition    | No consecutive hyphens (`--`) or periods (`..`)            |

For example, `my-plugin`, `acme.tools`, and `lint3r` are valid, while `My-Plugin`, `-start`, and `has--double` are not.

### How clients handle manifest errors

Only two schema violations are non-fatal: an unknown top-level field and a non-object `extensions` field. In both cases, the client reports and ignores the problem and continues loading. Any other violation, such as a missing `name` or an unsupported `$schema`, is fatal: the client rejects the plugin without discovering or executing any of its components. This closed design enables strict validation and typo detection while keeping client experiments contained under `extensions`.

## Skills

Agent Plugins uses the Agent Skills specification without redefining it. The plugin format defines only where skills are discovered and how failures are isolated.

Each skill lives in an immediate child directory of `skills/`:

```plaintext
skills/
└── deploy/
    ├── SKILL.md
    ├── scripts/
    │   └── rollback.sh
    └── references/
        └── runbook.md
```

Discovery follows three rules:

- An immediate child of `skills/` is a discovered skill when it has a `SKILL.md`
  
- Clients do not recursively search deeper descendants for additional skills.
  
- If one discovered skill is invalid, the client skips it, reports it when practical, and continues loading other skills and component types.
  

Skills can contain any additional files they need. Directories like `scripts/`, `references/`, and `assets/` are common conventions from the Agent Skills specification, not an exhaustive allowlist.

The plugin is still considered valid if the `skills/` directory is missing.

## MCP servers

The `mcp.json` file at the plugin root configures MCP connections in a closed format that clients map to their native configuration.

It contains only `$schema` and `mcpServers` at the top level:

```json
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "validator": {
      "type": "stdio",
      "command": "./bin/validator",
      "args": ["--data", "${PLUGIN_DATA}/validator"],
      "env": {
        "CONFIG": "${PLUGIN_ROOT}/config.json"
      },
      "cwd": "${PLUGIN_ROOT}"
    },
    "deployment-api": {
      "type": "streamable-http",
      "url": "https://deploy.example.com/mcp",
      "headers": {
        "X-Tenant": "public-tenant"
      }
    }
  }
}
```

### Transports

Each server entry declares its transport with a `type` field and only the fields allowed for that transport:

| Type              | Required fields   | Notes                                                           |
| ----------------- | ----------------- | --------------------------------------------------------------- |
| `stdio`           | `type`, `command` | Optional `args`, `env`, and `cwd`. Launches a local subprocess. |
| `streamable-http` | `type`, `url`     | Current remote MCP transport; optional literal `headers`.       |
| `sse`             | `type`, `url`     | Deprecated HTTP+SSE transport; client support is optional.      |

An MCP-capable client supports at least one of `stdio` and `streamable-http` and should support both. The declared transport is used for the initial connection attempt; Agent Plugins defines no fallback behavior if that attempt fails.

### stdio commands

The `command` field is one executable token, not a shell command string. It's either a bare executable name resolved by platform search rules or a plugin-relative path beginning with `./`. A plugin that bundles its own executable must use a plugin-relative command, since configured `PATH` behavior is client-defined. When `cwd` is omitted, the plugin root is the working directory.

### Plugin variables

Clients provide two environment variables to every stdio subprocess:

- `PLUGIN_ROOT`: the absolute, filesystem-resolved plugin root. Use it to reference bundled scripts, binaries, and config files.
  
- `PLUGIN_DATA`: a dedicated writable data directory that persists across plugin updates. Use it for installed dependencies, caches, and generated state.
  

Clients expand `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` in `args`, `env` values, and `cwd`. Expansion is textual, single-pass, and non-recursive, and it never applies to `env` keys, `command`, remote URLs, or headers. A plugin cannot override the two reserved variables; an `env` entry named `PLUGIN_ROOT` or `PLUGIN_DATA` invalidates that server entry.

### Remote connections and security

Remote configuration follows strict safety rules:

- URLs are absolute HTTP or HTTPS, without user information or fragments. Non-loopback endpoints use HTTPS.
  
- Configured headers are literal, visible package data. Plugins must not embed credentials or secrets in `headers` or `env`.
  
- Clients never forward configured headers to a different origin through redirects without explicit user authorization.
  
- Agent Plugins 1.0.0 defines no portable OAuth or credential-reference fields. Authentication remains client-managed, and an authorization failure is a connection failure, not invalid package configuration.
  

## Client extensions

Client extensions let a client add behavior without expanding the portable core. Reverse-domain identifiers avoid collisions without a central registry. For example, the client that controls `example.com` could use `com.example.client` as its namespace in two places:

- **Manifest data:** namespace-keyed object under `extensions` in `plugin.json`.
  
- **Extension directory:** top-level directory named exactly after the namespace.
  

```json
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "example-plugin",
  "extensions": {
    "com.example.client": {
      "setting": true
    }
  }
}
```

Clients can use either representation or both, and the namespace owner defines their contents, validation, and failure behavior. Other clients ignore namespaces they don't implement without validating their contents, so extensions never affect portability or conformance.

## How clients load plugins

Conformant clients follow a fixed loading sequence:

1. Establish the filesystem-resolved plugin root.
   
2. Locate and validate root `plugin.json` using the locally supported rules selected by `$schema`. Clients never retrieve schemas while loading a plugin.
   
3. Reject the plugin for fatal manifest violations and report the non-fatal cases.
   
4. Discover each supported component type from its fixed location.
   
5. Apply the failure boundary defined for each component type or entry.
   
6. Apply implemented client-extension namespaces and ignore all others.
   

### Failure isolation

Failures are scoped to the narrowest relevant boundary, so one broken piece never takes down independently valid components:

| Failure                                         | Scope of impact                                |
| ----------------------------------------------- | ---------------------------------------------- |
| Fatal `plugin.json` violation                   | Entire plugin rejected                         |
| Invalid top-level `mcp.json`                    | MCP disabled for the plugin; skills still load |
| Invalid individual MCP server entry             | Only that server skipped                       |
| Server fails to start, connect, or authenticate | Only that server affected; loading continues   |
| Invalid individual skill                        | Only that skill skipped; siblings still load   |
| Fixed location has wrong filesystem kind        | Only that component type invalid               |
| Missing fixed location                          | Not an error; valid absence                    |

## Versioning

One version number identifies the complete specification release, including its normative text and both schemas. This keeps compatibility simple:

- The `$schema` value in `plugin.json` declares the Agent Plugins version the package targets. For 1.0.0, it's `https://agent-plugins.org/schemas/1.0.0/plugin.schema.json`.
  
- When `mcp.json` is present, its `$schema` version must match the version declared by `plugin.json`. A mismatch invalidates only the MCP configuration, not other component types.
  
- Published canonical schema identifiers are never reassigned to different contents, and plugins may keep targeting older versions according to each client's compatibility policy.
  

For the plugin's own `version` field, Semantic Versioning is recommended: major for breaking changes, minor for backward-compatible features, and patch for fixes. Clients may use it for update checks and cache freshness.

## Build your first plugin

Only two files are needed for a minimal working plugin.

### 1\. Create the directory structure

```plaintext
hello-plugin/
├── plugin.json
└── skills/
    └── greet/
        └── SKILL.md
```

### 2\. Create the manifest

```json
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "hello-plugin"
}
```

### 3\. Create the skill

```markdown
---
name: greet
description: Greet the user and offer help.
---

Greet the user and offer help.
```

Skills-capable clients load the `plugin.json`, discover the immediate children of `skills/`, and validate each `SKILL.md` against the Agent Skills specification.

To add MCP servers, place `mcp.json` at the plugin root using the same Agent Plugins schema version. For a copyable package with a complete manifest and a real skill, see the [Agent Plugins example repository](https://github.com/agentplugins/agent-plugins-example).

You can validate your files against the canonical JSON Schemas:

- [`plugin.schema.json`](https://agent-plugins.org/schemas/1.0.0/plugin.schema.json) for the plugin manifest
  
- `mcp.schema.json` for MCP server configuration
  

The specification text is authoritative if it conflicts with a machine-readable schema.

## Next steps

- Read the complete [Agent Plugins specification](https://agent-plugins.org/specification) for the full normative contract.
  
- Learn the underlying [Agent Skills specification](https://agentskills.io/specification) to write effective skills.
  
- Explore the [Model Context Protocol documentation](https://modelcontextprotocol.io/specification) for MCP server development.
  
- Browse the [Agent Plugins repository](https://github.com/agentplugins/agent-plugins-spec) to follow proposals or contribute.
  
- Implementing a client? Start with the [client conformance checklist](https://agent-plugins.org/client-implementers/conformance).