Buff Development
Connector

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: 1BXYNH8PA7ZYNZGN

Top level

FieldDescription
middleware_urlOptional. The Buff relay address — built into the agent; set it only for your own installation.
state_dirThe directory for the agent’s key, secrets, installed integrations and their working directories. Must survive restarts.
providersThe git providers the bridge serves.
webhooksThe event receiver: listen — the address and port on this machine, host — how the tracker sees this port. Empty — the receiver is off.
pluginsIntegration connections.

providers[]

FieldDescription
kindgithub, ghe, gitlab, gitea, bitbucket, bitbucket-server.
base_urlThe address of your git server (or cloud provider).
reposRepositories (owner/name, for Bitbucket Server — PROJECT/slug).
token_env / token_fileWhere 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.

FieldDescription
idThe 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.
pluginThe integration’s name in the catalogue (jira, github, redmine, …). Empty for your own server: instead of plugin/version it has an mcp block.
versionThe version the connection is pinned to. Required: “latest” is not a configuration but a lottery.
aliasA human-readable name. Changes freely and breaks nothing.
slugA short name: it goes into the names of the tools the model sees. Derived from alias if not set; must be unique.
dev_projectThe development project or space in Buff where the work goes. The name within the organisation, without the organisation and without a slash.
enabledfalse — the connection is configured but not started. On by default.
configThe 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.
webhookWhether the connection accepts calls. Where the connector listens — in webhooks above.
webhook_secretThe 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_secondsHow often to read this connection. Empty — as the integration suggests, otherwise the connector’s default.
ai_notesNotes 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_unboundedtrue 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[]

FieldDescription
nameThe name the integration asks for (usually api).
kindbearer, 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.
usernameThe account for basic (for example, the Jira Cloud email). Not a secret.
headerThe header name for the header kind (for example, X-Redmine-API-Key).
token_env / token_fileWhere 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_fileThe 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-token

mcp — 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
FieldDescription
sourceWhere the server comes from: archive, github, url, command.
originThe archive name or the repository address — for you; the connector does not use it.
name, versionWhat its packaging called the server. A started server introduces itself, and the report carries its own words.
command, args, envWhat 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.
urlThe address of a remote server (Streamable HTTP) instead of command. The Authorization header is a credential of the header kind.
read_onlyThe 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.
acceptedtrue — 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

On this page