---
title: "§3 Manifest"
description: "Normative schema for surface.json (identity, adapter, Binding, commands, triggers, protocol metadata) and the validation a runtime performs."
canonical: https://harnesscontextprotocol.io/docs/specification/manifest
---

# §3 Manifest

> Normative schema for surface.json (identity, adapter, Binding, commands, triggers, protocol metadata) and the validation a runtime performs.

The manifest is `surface.json` at the pack root. It MUST be a JSON object.

## 3.1 Top-level fields

| Field | Type | Req | Constraint |
|-------|------|-----|------------|
| `id` | string | MUST | `pack_id`, 1 to 128 chars, lower-case |
| `name` | string | MAY | Display name |
| `cliBin` | string | SHOULD | The CLI binary the Skill teaches |
| `kind` | enum | SHOULD | `wrap` \| `composite` \| `openapi` \| `sense_only`. Alias `adapter_kind`. Default `composite` |
| `plane` | enum | MAY | `runtime` \| `control`. Default `runtime` |
| `transports` | array | MAY | Subset of `cli`, `json_exec`, `mcp`; at most 4 entries |
| `binding` | object | SHOULD | §3.3 |
| `wrap` | object | conditional | MUST when `kind` is `wrap` |
| `openapi` | object | conditional | MUST when `kind` is `openapi` |
| `pass_through` | object | MAY | §3.5; wrap only |
| `verbs` | object | MUST | Map `verb_key` → command (§3.4). MAY be empty only when `kind` is `sense_only` |
| `stimulusTriggers` | array | MAY | `{ ref: string }[]` |
| `skill_url` | string | MAY | URL to a hosted copy of the Skill |
| `harness` | string | MAY | Inline Skill text (deprecated in favour of `HARNESS.md`) |

Runtimes MUST ignore unknown top-level fields in `surface.json` for forward
compatibility, and SHOULD report them.

## 3.2 Adapter fields

### `wrap`

| Field | Type | Req | Constraint |
|-------|------|-----|------------|
| `bin` | string | MUST | 1 to 128 chars. Relative paths (`.`-prefixed) resolve against the pack root |
| `argv_template` | string[] | MAY | ≤ 64 entries. `{{verb}}` and `{{name}}` placeholders. Default `["{{verb}}"]` |
| `agent_env` | object | MAY | String → string. Merged into the child environment |

### `openapi`

| Field | Type | Constraint |
|-------|------|------------|
| `url` | string (URL) | One of `url` or `path` MUST be present |
| `path` | string | Relative to the pack root |

## 3.3 Binding fields

| Field | Type | Constraint |
|-------|------|------------|
| `mode` | enum | `user` \| `mothership` \| `local` \| `public` \| `mock` |
| `hub` | enum | `keyring` \| `local-credential` \| `public` \| `none` |
| `family` | string | 1 to 128 chars |
| `connect_provider_id` | string | 1 to 128 chars |

Unknown Binding fields MUST fail validation.

## 3.4 Command entry

Each value of `verbs` is an object.

| Field | Type | Req | Constraint |
|-------|------|-----|------------|
| `description` | string | SHOULD | One sentence |
| `cli` | string[] | SHOULD for `wrap` | First token is the bin. Placeholders `{{name}}` and `--flag={{name}}` |
| `args` | object | MAY | JSON Schema for the command's arguments |
| `policy` | enum | MAY | `read` \| `write`. Informative hint; `policy.json` is authoritative |

## 3.5 Pass-through (HCP/1.1)

| Field | Type | Req |
|-------|------|-----|
| `allowedSubcommands` | string[] | MUST, ≥ 1 |
| `maxArgv` | integer | MUST, > 0 |

1. A `wrap` pack MUST declare either a non-empty `verbs` map or `pass_through`.
2. A pack relying on `pass_through` MAY be installed as a bootstrap but is not a
   conforming HCP/1.1 pack until its hot path is promoted to named commands.

## 3.6 Protocol metadata

A manifest MAY carry, or a runtime MUST derive, the following object. It is
validated strictly: unknown fields MUST fail.

```ts
type HarnessPackMeta = {
  hcp: 1
  pack_id: string                         // = id
  adapter_kind: 'composite' | 'wrap' | 'openapi' | 'sense_only'
  binding?: HarnessBinding
  wrap?: HarnessWrapTarget
  openapi?: HarnessOpenApiRef
  pass_through?: HarnessPassThrough
  plane?: 'runtime' | 'control'
  transports?: ('cli' | 'json_exec' | 'mcp')[]
  skill_url?: string
}
```

## 3.7 Validation

A runtime MUST reject the manifest when any of the following holds.

| Condition | Issue |
|-----------|-------|
| `id` missing or ≠ Policy `surface_id` | `invalid_meta` / `missing_verb` (id) |
| `kind: wrap` without `wrap.bin` | `binding: wrap adapter requires wrap.bin` |
| `kind: wrap` with empty `verbs` and no `pass_through` | `wrap: wrap requires named commands or pass_through` |
| `plane: control` with `binding.mode` ≠ `mothership` | `binding: control plane packs default Binding mothership` |
| `kind: openapi` without `openapi` | `invalid_meta: openapi adapter requires openapi ref` |
| `kind: sense_only` with no `stimulusTriggers` | `invalid_meta: sense_only adapter requires at least one stimulus trigger_ref` |
| Metadata schema violation | `invalid_meta` |

## 3.8 Example (informative)

```json
{
  "id": "ledger",
  "name": "Ledger",
  "kind": "wrap",
  "cliBin": "ledger",
  "plane": "runtime",
  "transports": ["cli", "json_exec"],
  "binding": { "mode": "local", "hub": "local-credential", "family": "ledger" },
  "wrap": { "bin": "../../bins/ledger.mjs", "argv_template": ["{{verb}}"] },
  "verbs": {
    "setup.status": { "description": "Idempotent installer status.", "cli": ["ledger", "setup", "status"] },
    "setup.apply":  { "description": "Apply installer.", "cli": ["ledger", "setup", "all", "-y"], "policy": "write" },
    "connect":      { "description": "Connect Binding.", "cli": ["ledger", "connect", "{{provider}}"], "policy": "write" },
    "status":       { "description": "Connect health.", "cli": ["ledger", "status"] },
    "list":         { "description": "Domain read.", "cli": ["ledger", "list"] },
    "transfer":     { "description": "Gated write.", "cli": ["ledger", "transfer", "{{amount}}", "--to", "{{payee}}", "--confirm"], "policy": "write" }
  }
}
```

## Sitemap

- [Documentation](https://harnesscontextprotocol.io/docs)
- [Packs](https://harnesscontextprotocol.io/packs)
- [Glossary](https://harnesscontextprotocol.io/docs/reference/glossary)
- [llms.txt](https://harnesscontextprotocol.io/llms.txt)
- [llms-full.txt](https://harnesscontextprotocol.io/llms-full.txt)
- [OpenAPI](https://harnesscontextprotocol.io/openapi.json)
- [MCP](https://harnesscontextprotocol.io/mcp)
