Plugins

Plugins are remote MCP packages (Claude or Cursor format) that you reference in your capabilities file. When you run capa install, CAPA clones each plugin, parses its manifest, copies its skill files onto disk, and registers its MCP servers under capa. Tools from a plugin are not auto-exposed, rather you opt in to each one explicitly under the top-level tools section. This keeps the agent's context lean and gives you full control over what the model can see and call.

Browse from a Registry (Easiest)

If you have a registry adapter installed (for example, the bundled Cursor Marketplace adapter), you can browse and install plugins from the web UI's Registries tab without editing any files. From the CLI:

capa add cursor-marketplace:anthropic/claude-helpers

That appends a fully-formed plugin entry to your capabilities file. You can then declare the tools and skills you want exposed.

Declaring Plugins

Add a plugins array to your capabilities file. Each entry points at a GitHub or GitLab repository that contains a plugin manifest:

plugins:
  - id: slack-mcp
    type: github
    def:
      repo: slackapi/slack-mcp-plugin

  - id: devops-skills
    type: gitlab
    def:
      repo: acme/platform/devops-skills
      version: 1.2.0
{
  "plugins": [
    {
      "id": "slack-mcp",
      "type": "github",
      "def": { "repo": "slackapi/slack-mcp-plugin" }
    },
    {
      "id": "devops-skills",
      "type": "gitlab",
      "def": { "repo": "acme/platform/devops-skills", "version": "1.2.0" }
    }
  ]
}

Plugin fields

  • id (optional): Stable id used in attribution and the lockfile. Defaults to a slug derived from the manifest name.
  • type: github or gitlab.
  • def.repo: Repository reference. Three shapes — see Locating a plugin inside a multi-plugin repo below.
  • def.subpath (optional, legacy): Exact path inside the repo when the manifest is not at the root. Equivalent to writing repo: owner/repo::<subpath>. Mostly kept around for back-compat with hand-edited capabilities files; prefer the combined-string form below.
  • def.version (optional): Tag or branch.
  • def.ref (optional): Commit SHA — pins the install to an exact commit.
  • servers (optional): Per-server overrides — see below.

Private repositories are supported when you have GitHub or GitLab OAuth configured. CAPA uses your token to clone.

Locating a plugin inside a multi-plugin repo

Many repos host more than one plugin in a plugins/ directory (Anthropic's claude-code is a typical example). Capa's def.repo field accepts three shapes — the same grammar skills use:

  • owner/repo — the plugin manifest lives at the repo root.
  • owner/repo@plugin-name — recursive search. Capa walks the cloned snapshot for any directory containing a .claude-plugin/plugin.json or .cursor-plugin/plugin.json whose containing-directory basename or manifest name field equals plugin-name. The search target must be a single segment with no slashes.
  • owner/repo::sub/path — exact path inside the repo. Use this when two plugins share a basename or when you want the install to fail loudly if the layout shifts.
plugins:
  # Recursive search — survives directory restructures
  - id: code-review
    type: github
    def:
      repo: anthropics/claude-code@code-review

  # Exact path — disambiguates when two plugins share a basename
  - id: frontend-design
    type: github
    def:
      repo: anthropics/claude-plugins-official::plugins/frontend-design
{
  "plugins": [
    {
      "id": "code-review",
      "type": "github",
      "def": { "repo": "anthropics/claude-code@code-review" }
    },
    {
      "id": "frontend-design",
      "type": "github",
      "def": { "repo": "anthropics/claude-plugins-official::plugins/frontend-design" }
    }
  ]
}

From the CLI, the equivalent shortcuts are capa add --plugin owner/repo@code-review and capa add --plugin owner/repo::plugins/code-review. Both accept :version or #sha pinning suffixes (capa stores those in dedicated def.version / def.ref fields, keeping def.repo readable). The grammar is identical for GitLab (gitlab:group/project@name / gitlab:group/project::sub) and covers both Claude (.claude-plugin/plugin.json) and Cursor (.cursor-plugin/plugin.json) plugin manifests.

Renaming Plugin Servers

Each plugin manifest declares one or more MCP servers under mcpServers. By default, capa registers each server under its manifest key (e.g. a plugin whose manifest exposes mcpServers.slack becomes reachable as @slack). Add a servers block to rename a server or to resolve collisions with other servers in your project.

plugins:
  - id: slack-mcp
    type: github
    def:
      repo: slackapi/slack-mcp-plugin
    servers:
      slack:           # key from the plugin manifest's mcpServers section
        as: slack-bot  # capa server id you'll reference from tools
{
  "plugins": [
    {
      "id": "slack-mcp",
      "type": "github",
      "def": { "repo": "slackapi/slack-mcp-plugin" },
      "servers": {
        "slack": { "as": "slack-bot" }
      }
    }
  ]
}

Omit the servers block entirely if you're happy with the manifest defaults.

Exposing Plugin Tools

Plugin servers are merged into your project's MCP servers, but the individual tools they offer are not exposed automatically. Declare the ones you want under the top-level tools section, pointing at the plugin server with @server-id:

tools:
  - id: send_message
    type: mcp
    description: Send a message to a Slack channel
    def:
      server: "@slack"        # matches the plugin's server id (or its 'as' alias)
      tool: slack_send_message  # original tool name from the plugin manifest
{
  "tools": [
    {
      "id": "send_message",
      "type": "mcp",
      "description": "Send a message to a Slack channel",
      "def": {
        "server": "@slack",
        "tool": "slack_send_message"
      }
    }
  ]
}

Treat plugin tools like any other MCP tool: pick a short, agent-friendly id, write a clear description, and reference the qualified name (server.id) from a skill's requires array.

Binding Plugin Skills

Plugins can ship SKILL.md files that capa copies into each provider's skills directory. To associate a plugin skill with a set of tools — add a type: plugin entry under skills:

skills:
  - id: slack-messaging   # must match a skill id exposed by a configured plugin
    type: plugin
    def:
      requires:
        - "@slack.send_message"  # qualified id of a tool you declared above
{
  "skills": [
    {
      "id": "slack-messaging",
      "type": "plugin",
      "def": {
        "requires": ["@slack.send_message"]
      }
    }
  ]
}

If the skill id doesn't match any skill exposed by the resolved plugins, capa install prints a warning (it does not fail) so you can catch typos and stale references after a plugin upgrade.

End-to-End Example

In this example, we're using the Slack plugin, which comes with an MCP server and a set of skills. We expose a single tool from that server: slack_send_message and then associate it with the relevant skill

plugins:
  - id: slack-mcp
    type: github
    def:
      repo: slackapi/slack-mcp-plugin
    servers:
      slack:
        as: slack

tools:
  - id: send_message
    type: mcp
    description: Send a message to a Slack channel
    def:
      server: "@slack"
      tool: slack_send_message

skills:
  - id: slack-messaging
    type: plugin
    def:
      requires:
        - "@slack.send_message"
{
  "plugins": [
    {
      "id": "slack-mcp",
      "type": "github",
      "def": { "repo": "slackapi/slack-mcp-plugin" },
      "servers": { "slack": { "as": "slack" } }
    }
  ],
  "tools": [
    {
      "id": "send_message",
      "type": "mcp",
      "description": "Send a message to a Slack channel",
      "def": { "server": "@slack", "tool": "slack_send_message" }
    }
  ],
  "skills": [
    {
      "id": "slack-messaging",
      "type": "plugin",
      "def": { "requires": ["@slack.send_message"] }
    }
  ]
}

What Happens at Install

When you run capa install:

  1. CAPA resolves each plugin against the lockfile + on-disk cache. If the resolved commit is already cached, no network call is made.
  2. It detects and parses the plugin manifest (Cursor or Claude format).
  3. Plugin skill directories are copied to each provider's skills folder (e.g. .cursor/skills/, .claude/skills/).
  4. Plugin MCP servers are registered under their as alias (or their manifest key by default).
  5. CAPA validates that every type: plugin skill matches a skill id from some plugin manifest, and warns on mismatches.
  6. CAPA warns when a plugin's server is contributed but no user-declared tool references it — usually a sign you forgot to expose the tools you want.
  7. The plugin's resolved commit SHA is recorded in capabilities.lock for reproducibility.

Your own skills, servers, and tools in the capabilities file are preserved. Plugin-derived entries are tagged with plugin attribution.

Supported Plugin Formats

  • Cursor plugins: manifests and skill layout used by Cursor (.cursor-plugin/plugin.json).
  • Claude plugins: Claude Desktop plugin format (.claude-plugin/plugin.json). CAPA normalizes them into the same merged capabilities model.

OAuth for Private Repos

To use private GitHub or GitLab plugin repositories:

  • Connect GitHub or GitLab in the CAPA web UI (project credentials / OAuth).
  • After connecting, capa install will use your token to clone private plugin repos.

See Credentials and GitHub Integration or GitLab Integration for setup.

Related Documentation

  • Capabilities File: file structure and plugins section.
  • capa install: resolves and installs plugins.
  • Registries: browse plugins from marketplaces (Cursor Marketplace, custom registries).
  • Lockfile: reproducible plugin installs via locked SHAs.
  • Skills: how skills from plugins are installed.
  • Tools: declaring and exposing tools from plugin servers.