--- name: add-mcp-server description: Use when adding or changing an MCP server in mcp-config/opencode.gateway.json (gitea, proxmox, …). Covers the {env:VAR} secret rule, the npx/node dependency, the shared-vs-personal boundary, and how to tell a dead server apart from a model that just can't call tools. --- # Adding an MCP server `mcp-config/opencode.gateway.json` is the **shared** opencode config, synced to every covert-gpt user by `mcp-config/sync.sh`. Read `mcp-config/README.md` before changing it. ## Secrets: `{env:VAR}`, never a literal ```jsonc "environment": { "GITEA_HOST": "https://git.nic-oconnor.com", "GITEA_ACCESS_TOKEN": "{env:GITEA_KEY}" // <- resolved from the user's shell } ``` This file is shared and committed. A literal token here leaks it to every user and into git history. The `{env:VAR}` indirection is what lets one shared config give each person tools that act **as them** — opencode resolves the var from the invoking user's environment and passes it to the server it spawns. When you add a server that needs a credential: 1. Reference it as `{env:NEW_VAR}` in the config. 2. Add `NEW_VAR` to `zsh/zshrc.local.example`. 3. Document it in the root `README.md` variable list **and** in `mcp-config/README.md`. Users keep the value in `~/.zshrc.local` (mode 0600), which bootstrap never overwrites. It is never written into any config file. ## Shared vs personal This tree is identical for every user. A server that only makes sense for one person's cluster, kubeconfig, or local paths belongs in that user's own `~/.config/opencode/`, which sync never touches. Same rule as `skills/`. ## It needs `npx` Servers are spawned as `npx -y @`, so `node/install.sh` must have run. **Pin the version** — `npx -y` otherwise runs whatever the registry serves, and this process receives the user's tokens. See the `bump-pinned-version` skill. ## Debugging: dead server vs. bad model The failure modes look alike from the chat window, so distinguish them first: - **Server dead** — the tool isn't in the model's tool list at all. Usual cause: `npx` missing from `PATH`, a bad package name, or an unset env var. opencode reports this only as absent tools, which reads like a config problem. - **Server fine, model weak** — the tool *is* called and the server answers, including with errors like `user 'x' does not exist`. That round trip proves MCP works. A model that invents required arguments (owner, repo) rather than discovering them, or retries the same wrong call verbatim, is a tool-use capability limit, not a config bug. Smaller / non-agentic models (e.g. VL or low-active-param MoE variants) do this; coder-tuned models generally don't. Check the tool list before touching the config: ```sh opencode debug skill # skills opencode can see npx -y @ # does the server even start standalone? ``` Fix argument-guessing in `AGENTS.md` (give the model the default owner/host), not in `opencode.gateway.json`.