Gateway
Gatewaybeta6 min

Config templates

Ready-made gateway configs you fill in rather than write. What a template folder holds, how ${var.KEY} placeholders become either an environment variable or a credential token, and how to run one on a gateway you host yourself.

A template is a complete gateway config with holes in it. Somebody already chose the bindings, the plugins and the trust floor for one upstream service; what is left for you is the handful of values only you have — a token, a workspace id, the URL of your identity provider.

Browse them at mcpg.cloud/configs/t. Every template declares which destinations it supports, and self-hosting is a first-class one: a template that lists self_host gives you back a config.yaml that reads its secrets from the environment and never sends a value anywhere.

What a template is, on disk

Templates live in templates/<slug>/ in the repository, one folder each:

arduino
templates/notion-workspace/
  template.yaml    the manifest — the variables, the category, the icon
  README.md        the article you read on the site
  config.yaml      a complete gateway config carrying ${var.KEY} placeholders
  assets/          optional images the README references

config.yaml is the whole config, not a fragment. It declares its own plugins[], its bindings and its governance block, so nothing is inherited from a base file you would have to find.

Placeholders, and the two things they can become

A template binds by token. Wherever a value goes, config.yaml carries ${var.KEY}:

yaml
headers:
  Authorization: "Bearer ${var.NOTION_TOKEN}"
  Notion-Version: "${var.NOTION_API_VERSION}"

and template.yaml declares that key once:

yaml
variables:
  - key: NOTION_TOKEN
    label: Notion integration token
    help: >-
      Create an internal integration at Settings → Connections, then copy its
      secret. Share the pages you want reachable with that integration.
    required: true
    secret: true
    example: ntn_00000000000000000000000000000000000000000
    env: NOTION_TOKEN
    credential:
      target: notion

What a filled token turns into is not an author's choice. It falls out of secret, per destination:

variablefilled for self-hostfilled for the managed cloud
secret: falsethe value, written into the configthe value, written into the config
secret: true${env.<env>}${cred://dev.mcpg.credential.static/<target>}

A non-secret is a deployment knob, and a config you still have to edit before it runs is a config that was not finished. A secret is different in each direction: on your own gateway ${env.NOTION_TOKEN} resolves against an environment you control, and on the managed service it cannot — that pod's environment belongs to the platform, and a published config carrying ${env.…} is refused at publish.

Running one yourself

Fill the form, choose Run it yourself, and download the config.yaml. It carries ${env.NAME} for every secret and no values at all, so it is a file you can commit.

bash
export NOTION_TOKEN='ntn_…'
mcpg --config ./config.yaml

Two things worth doing before you start it:

bash
mcpg config check ./config.yaml

config check parses the file against the real config schema — unknown keys are an error, not a shrug — and warns about a binding whose trust floor no request can reach, which is valid config that serves nothing. Add --deny-warnings to make that warning an exit code, which is what CI does for every template in this repository.

You can also skip the download. Publishing to mcpg.cloud/configs encrypts the filled config in your browser and hands back an address; a gateway you host yourself boots from it just as happily as a managed one does:

bash
mcpg --config 'mcpg+enc:https://mcpg.cloud/configs/c/<id>#k=<secret>'

See encrypted remote config for how that address works and the better ways to supply the secret.

What a template is guaranteed to be

Every template in this repository passes one gate before it ships, and the two checks that matter are run against the filled config rather than the file with holes in it:

  • It is rendered for every destination it claims, from the example values its own manifest declares, and each render is handed to mcpg config check --deny-warnings. A renamed key, a binding nothing can reach, a plugin field that no longer exists — all of it fails here rather than at your boot.
  • The cloud render is run through the same publish guard the control plane applies, so a template offering a cloud destination cannot be one the cloud would refuse.
  • Its declared variables and its ${var.…} placeholders are compared in both directions. A form that asks for a value the config ignores, and a hole nothing fills, are both build failures.

Where to go next