Self-hosting
Everything the hosted service runs is in the repository, and a document published on your own instance is the same document as one published here. The format is specified rather than owned, so an agent pointed at your registry needs nothing from us.
Being straight about the state of this: there is no one-command installer. What exists is a set of components that fit together, a config generator, and Helm charts that the hosted service itself is deployed with. If you are comfortable running a Kubernetes service, this is a normal afternoon. If you want a packaged appliance, it is not ready.
The pieces
| Piece | What it does | Required |
|---|---|---|
| Gateway | MCPG. Terminates MCP, verifies identity, applies per-tool governance. | yes |
| Registry plugin | A native plugin the gateway loads. All the registry logic lives here. | yes |
| Object store | The authoritative state. Filesystem or S3-compatible. | yes |
| Index | A derived, rebuildable index for listings and search. SQLite or in-memory. | yes |
| Identity provider | Any OIDC issuer. Keycloak realms are included as code. | for anything but anonymous reads |
| Web app | The editor, library and settings. The registry works fully without it. | no |
Note the last row. The whole surface is MCP, so agents and the command-line client talk to the gateway directly. The web app is one client among several, and an instance that only ever serves agents does not need it.
The smallest working instance
A filesystem store and a SQLite index, no object store and no identity provider. This is what the development environment runs, and it is a real registry: versions, refs, proposals, signing and MCP delivery all work.
# 1. build the registry plugin
cargo build --release -p instruction-s3
# 2. write a gateway config: filesystem store, SQLite index
python3 deploy/mcpg/gen-config.py
# 3. run the gateway
MCPG_CONFIG=$PWD/deploy/mcpg/dev.yaml mcpg # :8788Point an agent at http://localhost:8788/mcp and it will read. Do not run this shape in production: without an identity provider, callers are anonymous, and anonymous means public reads and nothing else.
The object store, and one requirement that matters
Publishing is a compare-and-swap against the manifest, which is how two people publishing at once cannot lose each other's work. That needs conditional writes: create-only, and replace-if-unchanged.
store:
kind: s3
endpoint: http://rgw.internal:7480
region: us-east-1
bucket: instructions
prefix: ""
access_key: ${env.IMD_S3_ACCESS_KEY}
secret_key: ${env.IMD_S3_SECRET_KEY}
path_style: trueCeph RGW and AWS S3 both support this. The wrinkle worth knowing before you pick a store: RGW requires the entity tag in the replace-if-unchanged header unquoted, which is stricter than the specification, and stores differ here. If yours rejects the conditional write, publishing fails closed rather than silently overwriting, so you will find out immediately rather than months later.
The index is derived from the store and rebuilt at boot, so losing it costs a restart and no data. The store is the thing to back up.
Identity
Any OIDC issuer works. What the gateway needs from a token is a stable subject, an audience bound to your MCP endpoint, and a claim saying whether the caller is a person, an agent or a service, because agents are capped below full administration no matter who they act for.
Keycloak realms ship as code, generated rather than hand-edited: one realm for users and their agents, one for administrators. Import them on first boot only. A replace-import on a live realm destroys organizations and federated identity links.
Signing
Give the plugin a master key and it derives a publisher key per organization, so no private key is ever stored: the public halves are served for verification and the private halves exist only inside the process while it signs.
signing:
master_key: ${env.IMD_SIGNING_MASTER_KEY}
delivery_key: ${env.IMD_DELIVERY_KEY}Omit the block and the platform signs nothing, which is a legitimate choice. Publishers can still bring their own keys and sign on their own machines, and consumers verify exactly the same way. Keep the master key out of the config file and out of your image.
Kubernetes
Four charts, one namespace. Images are pinned by digest rather than tag, and the plugin is a signed artifact the gateway admits against a key you control.
helm upgrade --install imd-keycloak deploy/k8s/imd-keycloak -n instruction-md
helm upgrade --install imd-gateway deploy/k8s/imd-gateway -n instruction-md \
--set image.tag=<digest> -f deploy/k8s/imd-gateway/values-prod.yaml
helm upgrade --install imd-web deploy/k8s/imd-web -n instruction-md \
--set image.tag=<digest> -f deploy/k8s/imd-web/values-prod.yamlSecrets come from your secret manager into a Kubernetes secret the charts read. None of them belong in values files, and the charts will not take them there.
Upgrades and operations
The runbooks the hosted service uses are in the repository under docs/runbooks: deploying, rolling back, canary promotion, key rotation, incident response and decommissioning an organization. They are written for our environment, and the shape transfers.
Licence
The specification is Creative Commons Attribution 4.0. Implement it, quote it, fork it, sell it.
The platform source is under the Business Source License 1.1. In practice: you may run it, modify it and use it for your own purposes, including commercially, and the one thing you may not do is offer it to third parties as a competing hosted service. Each release converts to Apache 2.0 four years after publication. It is not an open-source licence today and the notice in the repository says so plainly.
Commercial support and alternative licensing are not settled yet, so if you need either, the answer right now is a conversation rather than a page.