Skip to main content
Guide6 min read

How to share MCP server configs across a team (Git-based workflow)

Stop pasting configs in Slack. A repeatable pattern for team-wide MCP setup: Git-versioned server definitions, one-command bootstrap for new hires, secret isolation.

As soon as your team hits three MCP-curious developers, "paste this config into Claude Desktop" in Slack breaks down. Here is the workflow we use — Git-versioned, secret-safe, one command for new hires.

The goal

A new hire runs one command on day one and ends up with the team’s full MCP loadout: GitHub, Postgres (dev DB), Slack, internal tools. Per-user secrets never touch the repo.

Repo layout

your-repo/
  mcp/
    servers.d/
      00-github.json
      10-postgres-dev.json
      20-slack.json
      30-internal-tools.json
    secrets.example.env
    install.sh
  .gitignore   # contains secrets.env

One file per server

Each JSON is a fragment — just mcpServers with one key. Example servers.d/00-github.json:

{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server:v1.4.2"
      ]
    }
  }
}

Notice — no token in the file. Secrets come from the local secrets.env.

secrets.example.env

Committed, has no actual secrets:

# Each dev copies this to secrets.env and fills their own values
GITHUB_PERSONAL_ACCESS_TOKEN=
POSTGRES_DEV_URL=
SLACK_BOT_TOKEN=

Add secrets.env to .gitignore.

install.sh — the bootstrap

#!/bin/sh
set -e

# 1. Detect Claude config path
case "$(uname)" in
  Darwin)   CFG="$HOME/Library/Application Support/Claude/claude_desktop_config.json" ;;
  Linux)    CFG="$HOME/.config/Claude/claude_desktop_config.json" ;;
  *)        CFG="$APPDATA/Claude/claude_desktop_config.json" ;;
esac

# 2. Load secrets into env
set -a; . ./mcp/secrets.env; set +a

# 3. Merge all servers.d/*.json into one config
mkdir -p "$(dirname "$CFG")"
jq -s '{ mcpServers: ([.[].mcpServers] | add) }' \
   mcp/servers.d/*.json > "$CFG"

# 4. Substitute env vars (optional — only for templated values)
envsubst < "$CFG" > "$CFG.tmp" && mv "$CFG.tmp" "$CFG"

echo "✔ MCP config written to $CFG"
echo "  Restart Claude Desktop to pick up changes."

A new hire runs:

cp mcp/secrets.example.env mcp/secrets.env
# fill in tokens
./mcp/install.sh

CI check: don’t commit broken JSON

Add a workflow that runs jq '.' servers.d/*.json — fails the PR on invalid JSON. Saves a weekly "why does the config break for half the team" meeting.

Secrets via 1Password / Vault

For mature teams, don’t even let devs copy tokens into files. Use 1Password CLI or Vault:

# in install.sh
export GITHUB_PERSONAL_ACCESS_TOKEN=$(op read "op://Eng/GitHub-MCP/token")
export POSTGRES_DEV_URL=$(op read "op://Eng/Postgres-Dev/url")

Tokens never hit disk. Rotation is just a 1Password update.

Per-env configs

If you have dev / staging / prod databases, split into subfolders:

mcp/
  servers.d/
    common/       # GitHub, Slack — same everywhere
    dev/          # dev Postgres, dev Sentry
    staging/      # staging Postgres

Accept ENV=dev|staging env var in install.sh, merge common/ + $ENV/.

Read me before you ship to devs

  • Never share the same MCP token across devs — per-user PATs only. Rotating one user’s token should not break others.
  • Scope tokens hard: GitHub PATs with minimum-needed permissions; Postgres role read-only.
  • Document what each server does in a top-level mcp/README.md. Especially call out any server that can write.

Related reads

Loadout

Build your AI agent loadout

Directory
Contact
© 2026 Loadout. Built on Angular 21 SSR.