.md

Adopt in a host

One command gives a coding agent the HCP Skill, the hcpx binary and one MCP tool, and an in-process loop gets one typed tool per command.

On this page

A host is an agent product such as an IDE assistant, a coding agent or a TypeScript tool loop, and adopting HCP takes about as much work as adding an MCP server. For a supported host one command is the whole integration: it writes one Skill that teaches the CLI and one tool, hcp, that runs it, both generated from the activated packs, and a pack activated later changes the Skill's catalog without adding a tool. Pick your agent below, or embed the runtime if you build your own loop.

Set up in one command#

Terminal
hcpx activate transit ledger
hcpx adopt claude --write        # or: codex, cursor, opencode, grok, mcp, agent
Terminal
hcpx activate transit ledger
hcpx adopt claude --write       # .claude/skills/hcp + one hcp server in .mcp.json

On its next start, Claude Code asks you to approve the hcp server in the project .mcp.json. The Skill also teaches it to run hcp from its shell.

Claude Code setup in detail

To inspect what adopt would write, run any target with --json and without --write (hcpx adopt cursor --json), or run hcpx generate --json. What a host gets depends on whether its agent has a terminal.

HostWhat it getsAdding a pack later
Coding agent with a terminal (Claude Code, Cursor, Codex, OpenCode, Grok Bot)The agent plugin: one Skill and the hcpx binary, plus the one-tool MCP exportChanges the catalog the Skill points at; no new tools
MCP-only clientThe same plugin exposed as one MCP tool, hcpSame; tools/list stays [hcp]
In-process loop (AI SDK)HarnessAgent: one typed tool per executable command, named <pack_id>__<verb_key>Adds that pack's executable commands as tools

Both shapes come from one generator, under the normative rules in Projections, and run through the same runtime, the open reference or a company's own, which holds Binding, grants and the sandbox.

activated packs ──► generateHarnessSurfaces() ──┬── .hcp/plugin.json         one bash wrap (`hcpx`)
                                                ├── .hcp/surface.json        catalog
                                                ├── Cursor                    Skill + .cursor/mcp.json
                                                ├── OpenCode                  one tool `hcp`
                                                ├── Grok Bot / Grok Build     terminal → hcpx · one MCP tool
                                                └── AI SDK                    HarnessAgent tool map (in-process)

The agent plugin#

Every coding agent adopts HCP through the plugin, and its three faces reach the same runtime.

FaceWhat it is
SkillOne SKILL.md that teaches lint, install, and exec
BashOne binary, hcpx, also installed as hcp (two names)
MCPOne tool named hcp (served by hcpx mcp) that runs the same commands
Terminal
bun add -g @harnesscontextprotocol/cli
bun add @harnesscontextprotocol/plugin
hcpx adopt agent --write

During the preview both packages are on GitHub Packages, where @harnesscontextprotocol/plugin is restricted, and Install the CLI shows the .npmrc.

.hcp/plugin.json
{
  "id": "hcp",
  "wrap": { "bin": "hcpx", "kind": "bash" },
  "skill": ".hcp/skills/hcp/SKILL.md",
  "mcp": { "command": "hcpx", "args": ["mcp"], "tool": "hcp" },
  "home": "/home/you/.hcp",
  "activated": ["transit", "ledger"]
}

mcp.command and wrap.bin are hcpx, and adopt writes hcp instead only for an older install that answers to no other name. The host targets (claude, codex, cursor, opencode, grok, mcp) write this same plugin into the paths each host reads, listed in Coding agents.

Embed the runtime in your own loop#

If you build your own agent loop, HarnessAgent wraps the runtime as a tool-loop agent with grant-filtered tools, progressive Skill disclosure and approval on write commands.

TypeScript
import { Hcp, HarnessAgent } from '@harnesscontextprotocol/sdk'

const hcp = await Hcp.create({ packDirs: ['./packs/transit'], sandbox: true })
await hcp.activate(['transit'])

const agent = await HarnessAgent.create({
  hcp,
  harness: 'my-product-v1',
  runtime: 'ai-sdk',
  model,
  context: { skillLeadChars: 480 },
})

const run = await agent.send('Plan a route from A to B')
await run.wait()

Each executable command becomes one tool named <pack_id>__<verb_key>, with dots turned into underscores (transit__plan), and long results are compacted between steps (Context optimization). AI SDK has the options, approvals and events.

Adding native support to a new host#

A host with no adopt target can attach the plugin by hand: put the Skill where the host reads Skills and hcpx on its PATH, or register MCP as { "command": "hcpx", "args": ["mcp"] }. Native intake takes little more work. A host that meets the host checklist:

  1. Presents packs in one of the two shapes: the hcpx binary plus its Skill, for hosts whose agent has a terminal, or one tool per executable command named hcpToolName(pack_id, verb_key), for in-process loops. Both come from generateHarnessSurfaces() or the catalog at .hcp/surface.json.
  2. Executes through the runtime (hcpx exec <pack> <verb> on the CLI face, Hcp.exec() in-process) and never spawns the wrap binary itself.
  3. Exposes the Skill (the copied SKILL.md) progressively, lead first and full text on demand.
  4. Surfaces write commands as approvals and passes confirm: true only after the user has agreed.
  5. Reads availability before offering a tool, so the agent never sees a command it cannot run.
  6. Never embeds credentials, adds a second policy for the same command, or hand-registers tools that bypass the pack.

A host may also subscribe to Sense for chrome, such as an inbox badge or a "credential stale" banner, through the runtime's sink, but it never owns mint. New hcpx adopt <host> targets go through the RFC process.

Why MCP is not the install path#

Adding an MCP serverAdopting HCP
SetupA config fragment per serverhcpx install, hcpx activate, then hcpx adopt once
tools/listN tools per server[hcp], or the hcpx binary
CredentialsThe server holds themThe runtime mints them; the pack names a mode
WritesTool annotations hint at side effectsPolicy confirm is enforced before exec

MCP-only hosts use the single-tool export, hcpx mcp. It runs every call through the runtime but installs no pack, because it only forwards to a runtime that already has packs installed and activated. Native adopt also keeps Policy, Binding, Sense and Skill visible to the host, so it can show approvals and teaching correctly.

Context optimization#

Ten activated packs with ten commands and a one-screen Skill each are more text than an agent should see every turn, so the generated context loads them in layers.

┌──────────────────────────────────────────────┐
│ STABLE PREFIX (cache-friendly, rarely changes)│
│  · doctrine: activate packs, never hand-wire  │
│  · pack / command index (executable only)     │
│  · Skill leads (~480 chars each)              │
│  · "call hcp__read_skill for full teaching"   │
├──────────────────────────────────────────────┤
│ TOOLS                                         │
│  · hcp__read_skill                            │
│  · <pack>__<verb> … grant-filtered            │
│  · write commands: needsApproval              │
├──────────────────────────────────────────────┤
│ CONVERSATION (compacted by prepareStep)       │
└──────────────────────────────────────────────┘

The prefix holds only what changes with the activated set, the pack index and the Skill leads, so prompt caches stay warm across turns; your own instructions follow it. Each lead is the first skillLeadChars characters of the pack's HARNESS.md (default 480) and often the only part the agent sees before it acts, which is why the Skill file guide insists it stand alone. The always-present hcp__read_skill tool returns the full Skill for a pack_id (the hot-path table, examples and anti-patterns), which is progressive disclosure in the Agent Skills sense with no per-pack code in the host.

Only commands that are executable for the current grants become tools (executableOnly: true by default), so the agent never wastes steps on tools it would be denied. Every operation: write command carries needsApproval: true, which the host renders while the runtime still enforces confirm. Between tool-loop steps, prepareStep shortens old tool outputs such as long list results and verbose doctor reports, keeps hcp__read_skill results intact, and can narrow activeTools to the packs the conversation is using.

TypeScript
type ContextOptimizationOptions = {
  skillLeadChars?: number        // default 480
  // further knobs: compaction thresholds, activeTools narrowing
}

The whole bundle comes from buildHcpContextBundle(hcp, options), which is also what hcpx generate inspects and hcpx adopt writes for Cursor and OpenCode. A hand-rolled context kit drifts from the packs, so regenerate it instead.

Terminal
hcpx generate --json