> ## Documentation Index
> Fetch the complete documentation index at: https://usefused.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent plugins

> Add portable Agent Plugins containing skills, MCP servers, or both.

Add an [Agent Plugins 1.0](https://agent-plugins.org/specification) package to `plugins/` to give your managed ADK or LangGraph agent reusable skills, MCP servers, or both. Harnest reads its declarations and connects them to the framework's native runtime. You do not import the plugin or register its components in Python. Advanced-mode applications retain their native composition and must wire equivalent capabilities themselves.

<Note>
  Need Python APIs, SDK dependencies, typed context, or lifecycle behavior? Build a [Harnest Extension](/docs/harnest/build/extensions) in `extensions/`. Application hooks and resource factories belong in `lifecycle/`.
</Note>

## Add a plugin

From the agent folder, install a reviewed local package into the project:

```bash theme={null}
harnest plugins install ../downloads/warehouse
```

Harnest validates the Agent Plugins 1.0 manifest without importing or executing
package code, then copies ordinary files into
`plugins/<manifest-name>` through same-filesystem staging. It
rejects links, special files, and an existing destination. Pass `--force` only
when you intend to replace that complete installed package; a failed final swap
restores the previous package.

The installer currently accepts local directories. It does not invent a
registry or download protocol that the Agent Plugins specification does not
define. `harnest extensions search` remains the separate discovery command for
executable Harnest Extensions.

Place each package in its own directory. Keep the package's root `plugin.json` intact:

```text theme={null}
plugins/
└── warehouse/
    ├── plugin.json
    ├── mcp.json                 # optional
    └── skills/                  # optional
        └── query-warehouse/
            ├── SKILL.md
            └── references/     # optional
```

```json plugins/warehouse/plugin.json theme={null}
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "warehouse",
  "version": "1.0.0",
  "description": "Query the shared warehouse"
}
```

The manifest requires the canonical `$schema` shown above and a `name`. That name identifies the plugin, even when its enclosing directory has a different name. Both component locations are optional: a skills-only, MCP-only, or manifest-only package is valid.

Plugin skills join the agent's skill registry and load on demand through `list_skills`, `load_skill`, and `load_skill_resource`. Plugin MCP servers join direct connections from `mcp/`. Use a skill to explain when to call its tools, which inputs they need, and how to interpret their output.

Rebuild after adding a package, or use [development reload](/docs/harnest/runtime/serving/development-reload) while serving locally.

## Attach a plugin after compilation

Agent Desktop can attach Agent Plugins when it creates a session. The desktop client owns discovery and download: it resolves the user-provided Git or marketplace URL, creates a ZIP with `plugin.json` at its root, and sends that immutable snapshot to Harnest. Harnest does not fetch a plugin URL.

```json POST /sessions theme={null}
{
  "id": "desktop-session",
  "plugins": [
    {
      "type": "inline",
      "name": "warehouse",
      "sha256": "<64 lowercase hexadecimal characters>",
      "source": {
        "type": "base64",
        "media_type": "application/zip",
        "data": "<base64 ZIP>"
      }
    }
  ]
}
```

`sha256` is optional. When supplied, it must match the decoded ZIP. Harnest always computes its own digest and returns each plugin's `name` and `sha256` in the session `metadata.plugins` array. The archive itself stays in private session application data so a durable session can recover its exact environment after a server restart.

The plugin set is fixed when the session is created. Create another session to add, remove, or update a plugin. Dynamic attachment currently requires a managed root `Agent`; managed `Graph` and advanced applications retain their compiled capability wiring.

| Dynamic package content        | Runtime behavior                                                                     |
| ------------------------------ | ------------------------------------------------------------------------------------ |
| Agent Skills                   | Added to the session's progressive skill tools                                       |
| `streamable-http` or `sse` MCP | Added to that session's ADK or LangGraph target                                      |
| `stdio` MCP                    | Session creation fails because the package could execute code in the Harnest process |

Harnest accepts at most 16 plugins per session and regular files only. It rejects encrypted members, links, absolute or parent paths, case-insensitive path collisions, more than 256 files, files larger than 4 MiB, archives larger than 8 MiB, and expanded content larger than 32 MiB. The server's configured `limits.max_request_bytes` also applies to the base64 JSON request and may impose a lower effective limit.

<Warning>
  Treat the URL as untrusted input in Agent Desktop. Apply download timeouts, redirect and credential policy, and archive size limits before sending the snapshot. Do not forward a URL for Harnest to fetch.
</Warning>

## Configure MCP servers

Portable MCP declarations live in root `mcp.json`, not Python factories. Each server declares its transport explicitly:

```json plugins/warehouse/mcp.json theme={null}
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "warehouse": {
      "type": "streamable-http",
      "url": "https://warehouse.example.com/mcp",
      "headers": {"X-Tenant": "public-demo"}
    }
  }
}
```

| Transport         | Configuration                                             |
| ----------------- | --------------------------------------------------------- |
| `stdio`           | `command`, optional `args`, `env`, and `cwd`              |
| `streamable-http` | `url` and optional `headers`                              |
| `sse`             | `url` and optional `headers`; for legacy HTTP+SSE servers |

Harnest opens connections at runtime through the ADK or LangGraph adapter. Compilation reads configuration without starting an MCP server.

### Local processes and persistent data

For a package that includes `server.py`, a stdio declaration can use:

```json plugins/warehouse/mcp.json theme={null}
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "warehouse": {
      "type": "stdio",
      "command": "python",
      "args": ["${PLUGIN_ROOT}/server.py"],
      "env": {"CACHE_DIR": "${PLUGIN_DATA}"},
      "cwd": "${PLUGIN_DATA}"
    }
  }
}
```

The server and its dependencies must already be available. Harnest does not turn `mcp.json` into a dependency installer. `command` is one executable name, such as `python`, or a bundled executable path beginning with `./`; it is not a shell command string.

| Variable      | Harnest value                                                                                 |
| ------------- | --------------------------------------------------------------------------------------------- |
| `PLUGIN_ROOT` | Absolute package directory; use it for bundled files                                          |
| `PLUGIN_DATA` | Writable persistent directory dedicated to this installed plugin; use it for caches and state |

Harnest supplies both variables to each stdio subprocess. Persistent data lives below `$XDG_DATA_HOME/harnest/agent-plugins`, or `~/.local/share/harnest/agent-plugins` when `XDG_DATA_HOME` is unset. Set `HARNEST_PLUGIN_DATA_DIR` to override that base directory. Harnest separates data by installation and plugin; package updates do not erase it.

Only `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` expand, and only in stdio `args`, `env` values, and `cwd`. Other placeholders stay literal. Do not override the reserved variables in `env`. An omitted `cwd` uses the package directory. An explicit `cwd` must start with `./`, `${PLUGIN_ROOT}`, or `${PLUGIN_DATA}` and remain inside the corresponding directory after resolution.

<Warning>
  A plugin subprocess runs executable code with the server process's permissions. Package-path validation does not sandbox that process. Review packages before adding them.
</Warning>

### Remote connections and credentials

Remote URLs require HTTPS except for loopback hosts. URL and header values are literal: `${TOKEN}` does not read an environment variable. Do not embed secrets in plugin headers or stdio environment declarations.

Harnest-owned MCP HTTP clients inherit the process's standard uppercase and
lowercase HTTP(S) and `ALL_PROXY` variables. Released installs include SOCKS
transport support, including `socks5h://` proxy URLs. This preserves
operator-managed enterprise egress. Remove the relevant proxy variables from
the Harnest process when a connection must bypass environment proxy discovery;
proxy URLs and credentials are omitted from client-construction diagnostics.

Authentication is client-managed; Agent Plugins 1.0 does not define portable credential references or OAuth configuration. When your application needs custom credential resolution, configure a [direct MCP client](/docs/harnest/build/mcp-client) with Harnest's [credential providers](/docs/harnest/runtime/authentication-and-credentials).

## Validation and diagnostics

Harnest validates the manifest before discovering components. An invalid manifest rejects that plugin. Invalid skill entries or MCP server entries are skipped with diagnostics while valid siblings continue loading. An invalid `mcp.json` disables that plugin's MCP component without disabling its skills.

Unknown client namespaces in the manifest's `extensions` field and matching client-specific directories are ignored. They do not become Harnest Extensions or lifecycle hooks. Harnest does not import arbitrary Python modules from a standard plugin.

<CardGroup cols={2}>
  <Card title="Author Agent Skills" icon="book" href="/docs/harnest/build/agent-skills">
    Write focused instructions and load supporting resources on demand.
  </Card>

  <Card title="Build a Harnest Extension" icon="boxes-stacked" href="/docs/harnest/build/extensions">
    Package Python functionality, lifecycle behavior, and typed context.
  </Card>
</CardGroup>
