OpenCode: connect to DevGrail (MCP)
Points OpenCode at the DevGrail MCP server so the agent in this workspace can manage DevGrail itself — containers, projects, scripts, files and terminal sessions, scoped to whatever the supplied API key is granted. Writes the user-level config at `~/.config/opencode/opencode.json`. An existing config is backed up and **merged into** (when `jq` is available), so other MCP servers and model settings survive. Supply a DevGrail **API key** as the `API_KEY` parameter. The key is resolved at run time and redacted from the run log; it is never stored in the script. After it runs: start `opencode`, use the default model or choose a model with /connect, and ask it what it can see.
What it asks for
- DevGrail API keyrequired
- The key OpenCode authenticates to the DevGrail MCP server with. The agent can only see and act on what this key is granted, so pick one scoped to the containers and projects you want it to manage.
What it runs
The whole script, exactly as it will execute in your workspace. Nothing is hidden — read it before you run it.
#!/usr/bin/env sh
# Add the DevGrail MCP server to OpenCode's user-level config.
#
# Writes ~/.config/opencode/opencode.json, merging into an existing config when
# jq is available so other MCP servers and model settings survive.
set -eu
if [ -z "${DEVGRAIL_MCP_URL:-}" ]; then
echo "Error: DEVGRAIL_MCP_URL is not set." >&2
echo "This container predates the variable - recreate it (or upgrade its image) to pick it up." >&2
exit 1
fi
if [ -z "${API_KEY:-}" ]; then
echo "Error: no DevGrail API key was supplied." >&2
echo "Re-run this script and choose a key for the 'DevGrail API key' parameter." >&2
exit 1
fi
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/opencode"
CONFIG_FILE="$CONFIG_DIR/opencode.json"
mkdir -p "$CONFIG_DIR"
# "oauth": false is deliberate. DevGrail answers an unauthenticated /mcp with a
# WWW-Authenticate challenge, which an MCP client reads as an invitation to start
# an OAuth flow. This server is authenticated by the bearer header below, so a
# bad key should surface as a plain 401 rather than an OAuth attempt.
SERVER="$(cat <<EOF
{
"type": "remote",
"url": "$DEVGRAIL_MCP_URL",
"enabled": true,
"oauth": false,
"headers": {
"Authorization": "Bearer $API_KEY"
}
}
EOF
)"
if [ -f "$CONFIG_FILE" ]; then
cp "$CONFIG_FILE" "$CONFIG_FILE.bak"
echo "Existing config backed up to $CONFIG_FILE.bak"
fi
if command -v jq >/dev/null 2>&1; then
[ -s "$CONFIG_FILE" ] || printf '%s\n' '{}' > "$CONFIG_FILE"
tmp="$(mktemp)"
jq --argjson srv "$SERVER" \
'.["$schema"] //= "https://opencode.ai/config.json"
| .mcp //= {}
| .mcp.devgrail = $srv' \
"$CONFIG_FILE" > "$tmp"
mv "$tmp" "$CONFIG_FILE"
elif [ -s "$CONFIG_FILE" ]; then
echo "Error: jq is not installed and $CONFIG_FILE already has content." >&2
echo "Refusing to overwrite it. Install jq (sudo apt-get install -y jq) and re-run." >&2
exit 1
else
cat > "$CONFIG_FILE" <<EOF
{
"\$schema": "https://opencode.ai/config.json",
"mcp": {
"devgrail": $SERVER
}
}
EOF
fi
chmod 600 "$CONFIG_FILE"
echo "Wrote $CONFIG_FILE"
echo "MCP server \"devgrail\" -> $DEVGRAIL_MCP_URL"
echo
echo "Next steps in this workspace:"
echo " 1. Run: opencode"
echo " 2. Use the default free model or choose a model with /connect"
echo " 3. Ask it to list your DevGrail containers"
How to get it
Open your DevGrail workspace, go to Scripts → Official scripts, and choose Download. It is copied into your own library, where you can edit it, run it, or set it as a workspace default — the copy is yours, and later changes here do not touch it.