# Publishing to the HotStack Catalogue

A HotStack listing is one JSON entry in a registry repository. There are two
entry kinds:

- **Inline-MCP entry** — you publish the *config* for an MCP server (command
  or endpoint URL). Nothing is downloaded from the registry; users copy the
  config into their client. This is the lightest way to list an MCP server,
  and it needs no signature.
- **Bundle entry** — you publish a downloadable plugin bundle (MCP config,
  skill packs, capability modules, CLI plugins) hosted at an `https` source.

The full field reference is in [`docs/schema.md`](../schema.md). Both examples
below are validated verbatim by this repo's test suite, so they stay
copy-pasteable.

## Minimal unsigned inline-MCP entry

[`examples/inline-mcp-entry.json`](examples/inline-mcp-entry.json):

```json
{
  "id": "acme/postgres-inspector",
  "kind": "inline-mcp",
  "name": "Postgres Inspector",
  "publisher": { "name": "Acme Tools" },
  "summary": "Read-only Postgres schema and query inspection over MCP.",
  "categories": ["data", "development"],
  "tags": ["postgres", "sql", "database"],
  "sourceUrl": "https://github.com/acme/postgres-inspector-mcp",
  "mcp": {
    "transport": "stdio",
    "command": "npx",
    "args": ["-y", "@acme/postgres-inspector-mcp@latest"],
    "envVarNames": ["DATABASE_URL"],
    "auth": "None",
    "setupNotes": "Runs the published package through npx. Point DATABASE_URL at the database you want to inspect."
  }
}
```

For a remote server, use the `http` transport instead of `command`/`args`:

```json
"mcp": {
  "transport": "http",
  "url": "https://mcp.example.com/mcp",
  "auth": "OAuth",
  "setupNotes": "Authenticate in your MCP client when prompted."
}
```

Rules that catch people out:

- `envVarNames` lists the *names* of environment variables your server reads.
  Never put values (secrets) in an entry.
- `url` and `sourceUrl` must be `https`.
- `command`/`args` are only valid with `transport: "stdio"`; `url` only with
  `transport: "http"`.

## Signed bundle entry

[`examples/signed-bundle-entry.json`](examples/signed-bundle-entry.json):

```json
{
  "id": "acme/review-skills",
  "kind": "bundle",
  "name": "Review Skills Pack",
  "publisher": { "name": "Acme Tools" },
  "summary": "Code review skill pack for Multicode agents: diff triage, finding verification, and review summaries.",
  "categories": ["code", "productivity"],
  "tags": ["skills", "code-review"],
  "icon": "icons/review-skills.svg",
  "latest": 3,
  "source": "https://github.com/acme/marketplace/tree/main/plugins/review-skills",
  "provides": ["skills"],
  "integrity": {
    "commit": "9b1dce7f04a2b83c5e6d7f8a90b1c2d3e4f5a6b7"
  },
  "signature": {
    "algorithm": "ed25519",
    "publicKey": "MCowBQYDK2VwAyEAexampleEXAMPLEexampleEXAMPLEexam",
    "signature": "ZXhhbXBsZS1zaWduYXR1cmUtcmVwbGFjZS1tZQ=="
  }
}
```

The `publicKey` and `signature` values above are placeholders with the right
shape — replace them with the real output of your signing tool. The catalogue
validates the shape at submission and verifies the signature cryptographically
at ingest; a valid signature earns your publisher the `verified` signal.

### Integrity is mandatory for code-bearing bundles

If `provides` includes `skills`, `module`, or `cli`, your entry ships
executable content and **must** pin it:

- `integrity.commit` — the 40-hex git commit SHA your `source` URL resolves
  to, and/or
- `integrity.files` — per-file SHA-256 digests:

```json
"integrity": {
  "files": [
    { "path": "skills/review/SKILL.md", "sha256": "a3f5…(64 hex chars)…" }
  ]
}
```

A bundle providing only `mcp` config may omit `integrity`, but pinning is
still recommended.

## What you must NOT author

`tier`, `provenance`, and `verified` (including `publisher.verified`) are
computed by the catalogue service at ingest. Entries that author them are
rejected — trust signals cannot be self-declared.

## Checklist before you submit

1. `id` is `your-publisher-namespace/entry-name`, all lowercase.
2. `categories` uses only the controlled vocabulary: `code`, `communication`,
   `data`, `design`, `development`, `productivity`, `sales-marketing`.
   Anything finer-grained goes in `tags`.
3. All URLs are `https`.
4. No secrets anywhere — `envVarNames` holds names only.
5. Code-bearing bundles declare `integrity`.
6. No `tier`, `provenance`, or `verified` fields.
