Config by hand (YAML)
The full reference of the settings file: providers, the event receiver and integration connections.
For automated installations the config is written directly. This is an equal path: the local page and the commands edit the same file, under the same check.
Example
# middleware_url can be omitted — the relay address is built into the agent.
state_dir: /var/lib/connector
providers:
- kind: gitlab
base_url: https://gitlab.corp.local
token_env: GITLAB_TOKEN # the token from an environment variable
repos:
- group/app
- group/lib
- kind: bitbucket-server
base_url: https://bitbucket.corp.local
token_file: /run/secrets/bb.token # …or from a file
repos:
- PROJ/service
# The webhook receiver is one for the whole connector. Empty — off, polling works.
# Required for GitLab commit comments and for Figma without a list of files and projects
# (for Figma — an address reachable from the internet).
webhooks:
listen: 0.0.0.0:8766
host: connector.corp.local:8766
plugins:
- id: 8GXN8BECS24D392A # GUID; the connector assigns it itself if omitted
plugin: jira
version: 1.4.1
alias: Jira prod
slug: jira_prod # derived from alias if not given
dev_project: backend
enabled: true
config: # checked against the integration's schema
base_url: https://jira.corp.local
project_keys: [PROJ, OPS]
mention_alias: buff
credentials:
- name: api
kind: bearer
token_file: /var/lib/connector/secrets/jira-8GXN8BECS24D392A-api.token
webhook: true
webhook_secret: 1BXYNH8PA7ZYNZGNTop level
| Field | Description |
|---|---|
middleware_url | Optional. The Buff relay address — built into the agent; set it only for your own installation. |
state_dir | The directory for the agent’s key, secrets, installed integrations and their working directories. Must survive restarts. |
providers | The git providers the bridge serves. |
webhooks | The event receiver: listen — the address and port on this machine, host — how the tracker sees this port. Empty — the receiver is off. |
plugins | Integration connections. |
providers[]
| Field | Description |
|---|---|
kind | github, ghe, gitlab, gitea, bitbucket, bitbucket-server. |
base_url | The address of your git server (or cloud provider). |
repos | Repositories (owner/name, for Bitbucket Server — PROJECT/slug). |
token_env / token_file | Where to take the token from: an environment variable or a file. Exactly one of the two. |
plugins[] — connections
An integration is code, a connection is a link. Two Jiras are two connections of one integration: the same code, different credentials, different allowed addresses, a different webhook link, a different OS user.
| Field | Description |
|---|---|
id | The connection’s GUID. The webhook link, the working directory and charges are tied to it, so it does not change on renaming. If not given, the connector assigns one. |
plugin | The integration’s name in the catalogue (jira, github, redmine, …). Empty for your own server: instead of plugin/version it has an mcp block. |
version | The version the connection is pinned to. Required: “latest” is not a configuration but a lottery. |
alias | A human-readable name. Changes freely and breaks nothing. |
slug | A short name: it goes into the names of the tools the model sees. Derived from alias if not set; must be unique. |
dev_project | The development project or space in Buff where the work goes. The name within the organisation, without the organisation and without a slash. |
enabled | false — the connection is configured but not started. On by default. |
config | The integration’s own settings. Checked against its schema: an extra key or a wrong value is an error, not a silent save. A field that has a default value in the manifest (for example, Figma’s API address) can be omitted — the connector fills it in itself, the same way for the form, the command line and the outbound rules. |
credentials[] | References to secrets (see below). Values never go into the YAML. |
webhook | Whether the connection accepts calls. Where the connector listens — in webhooks above. |
webhook_secret | The secret in the link. The connector mints it itself; it survives renaming, so the link pasted into the tracker does not have to change. |
poll_seconds | How often to read this connection. Empty — as the integration suggests, otherwise the connector’s default. |
ai_notes | Notes for the AI: free text about what the model should know about this system. Goes to the model together with the description of the connection’s tools. Up to 2048 characters unless the limit is lifted. |
ai_notes_unbounded | true lifts the length limit on ai_notes. This is your acceptance of the risk: excess text makes the model work worse and costs more; the connector truncates nothing. A file with ai_notes over the limit and without this flag will not be loaded. |
credentials[]
| Field | Description |
|---|---|
name | The name the integration asks for (usually api). |
kind | bearer, basic or header — how the tracker accepts the secret; service_account (a service account’s JSON key) or oauth2 (your own OAuth client and a refresh token) — kinds for which the connector issues tokens itself. Taken from the integration’s manifest; where the integration offers several kinds, it is chosen in the form or with the --kind flag. |
For your own server: env — the secret reaches the server as an environment variable named name; secret — only where there is a ${user_config.name} for it; header — the remote server’s Authorization header. | |
username | The account for basic (for example, the Jira Cloud email). Not a secret. |
header | The header name for the header kind (for example, X-Redmine-API-Key). |
token_env / token_file | Where to take the secret from. For service_account — the whole JSON key; for oauth2 — JSON {"client_id","client_secret","refresh_token"}, where the connector itself adds the refresh token after sign-in. |
password_env / password_file | The password for basic, if it is kept separately from the token. |
Secrets are not stored in the YAML — only a reference to an environment variable or a file. This way the config can be copied, compared and kept in version control.
The simplest way to write a secret is with a command — it sets the right kind of access from the manifest itself:
connector instance secret jira_prod --secret api \
--config /etc/connector/connector.yaml < /run/secrets/jira-tokenmcp — your own server
A connection to an MCP server you brought yourself. Such
a connection does not name plugin and version; what to run is described here. Exactly one of
command and url.
plugins:
- id: 7QK3M9XBWZ0FVT2H
alias: Weather
slug: weather_mcp
dev_project: backend
config:
units: metric
credentials:
- name: api_key
kind: secret
token_file: /var/lib/connector/secrets/mcp-7QK3M9XBWZ0FVT2H-api_key.token
mcp:
source: archive
origin: weather-mcp.mcpb
name: weather-mcp
version: 1.0.0
command: node
args: ["${__dirname}/server/index.js"]
env:
API_KEY: ${user_config.api_key}
UNITS: ${user_config.units}
read_only: [forecast]
accepted: true| Field | Description |
|---|---|
source | Where the server comes from: archive, github, url, command. |
origin | The archive name or the repository address — for you; the connector does not use it. |
name, version | What its packaging called the server. A started server introduces itself, and the report carries its own words. |
command, args, env | What to run. node, npx, python, uvx are replaced by the connector with the ones found on the machine; ${__dirname} is the code directory, ${user_config.name} is a value from config or a secret from credentials. A missing setting is a start-up error with its name. |
url | The address of a remote server (Streamable HTTP) instead of command. The Authorization header is a credential of the header kind. |
read_only | The tools you marked as read-only. Only they reach the model; the server’s own word is a hint on the page, not a decision. Changes without a restart. |
accepted | true — your consent: the code has not been checked, the network is not limited. Without it the connection does not start, even if written in by hand. |
What the connector adds itself
The file is not only yours: the agent normalises it on save. It assigns id, derives
slug, mints webhook_secret and turns secret references into files it created itself.
Edits apply on the fly: the agent watches the file, no restart is needed.
Two integrations named the same do not conflict: the slug is made unique automatically, and each has its own GUID.
A section the agent does not know is kept untouched and not used — so that
a config from a newer version is not lost on a rollback. That is exactly why the old
jira: section stays in the file and the local page mentions it: it does not work and does not
get in the way.
Pairing and running
connector pair --config /etc/connector/connector.yaml --code bufc_…
connector run --config /etc/connector/connector.yaml --admin 127.0.0.1:8765