mirror of
https://github.com/cole-maxwell1/dotfiles.git
synced 2026-08-02 12:23:54 -04:00
Add: gate ibmi-server MCP on required env vars
opencode's config schema types mcp.<name>.enabled as a static boolean and only interpolates {env:VAR} for string values, so conditional enablement is not expressible in opencode.jsonc alone.
Add a config-hook plugin that flips ibmi-server.enabled to true only when DB2i_HOST, DB2i_USER, and DB2i_PASS are all set. The config retains enabled: false as a fallback if the plugin fails to load.
This commit is contained in:
+112
-111
@@ -1,116 +1,117 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"permission": {
|
"permission": {
|
||||||
"bash": {
|
"bash": {
|
||||||
"*": "ask",
|
"*": "ask",
|
||||||
"git log *": "allow",
|
"git log *": "allow",
|
||||||
"git commit *": "ask",
|
"git commit *": "ask",
|
||||||
"git status *": "allow",
|
"git status *": "allow",
|
||||||
"git diff *": "allow",
|
"git diff *": "allow",
|
||||||
"git show *": "allow",
|
"git show *": "allow",
|
||||||
"git push *": "ask",
|
"git push *": "ask",
|
||||||
"sudo *": "deny",
|
"sudo *": "deny",
|
||||||
"curl *": "ask",
|
"curl *": "ask",
|
||||||
"wget *": "ask",
|
"wget *": "ask",
|
||||||
"diff *": "allow",
|
"diff *": "allow",
|
||||||
"npm *": "allow",
|
"npm *": "allow",
|
||||||
"rm -rf *": "deny",
|
"rm -rf *": "deny",
|
||||||
"rm *": "ask",
|
"rm *": "ask",
|
||||||
"grep *": "allow",
|
"grep *": "allow",
|
||||||
"sort *": "allow",
|
"sort *": "allow",
|
||||||
"head *": "allow",
|
"head *": "allow",
|
||||||
"tail *": "allow",
|
"tail *": "allow",
|
||||||
"ls *": "allow",
|
"echo *": "allow",
|
||||||
"wc *": "allow",
|
"ls *": "allow",
|
||||||
"go build *": "allow",
|
"wc *": "allow",
|
||||||
"go test *": "allow",
|
"go build *": "allow",
|
||||||
"go vet *": "allow",
|
"go test *": "allow",
|
||||||
"go mod tidy": "allow",
|
"go vet *": "allow",
|
||||||
"go mod download": "allow",
|
"go mod tidy": "allow",
|
||||||
"dotnet *": "allow",
|
"go mod download": "allow",
|
||||||
"docker ps *": "allow",
|
"dotnet *": "allow",
|
||||||
"docker logs *": "allow",
|
"docker ps *": "allow",
|
||||||
"docker compose logs *": "allow",
|
"docker logs *": "allow",
|
||||||
},
|
"docker compose logs *": "allow",
|
||||||
"read": {
|
|
||||||
".env": "deny",
|
|
||||||
".secrets": "deny",
|
|
||||||
"*.key": "deny",
|
|
||||||
"*.pem": "deny",
|
|
||||||
"id_rsa": "deny",
|
|
||||||
"id_ed25519": "deny",
|
|
||||||
".aws/credentials": "deny",
|
|
||||||
"opencode.jsonc": "deny",
|
|
||||||
"~/.ssh/known_hosts": "allow",
|
|
||||||
},
|
|
||||||
"grep": "allow",
|
|
||||||
"glob": "allow",
|
|
||||||
"question": "allow",
|
|
||||||
"lsp": "allow",
|
|
||||||
"websearch": "allow",
|
|
||||||
},
|
},
|
||||||
"mcp": {
|
"read": {
|
||||||
"zai-mcp-server": {
|
".env": "deny",
|
||||||
"type": "local",
|
".secrets": "deny",
|
||||||
"command": ["npx", "-y", "@z_ai/mcp-server"],
|
"*.key": "deny",
|
||||||
"environment": {
|
"*.pem": "deny",
|
||||||
"Z_AI_API_KEY": "{env:ZAI_API_KEY}",
|
"id_rsa": "deny",
|
||||||
"Z_AI_MODE": "ZAI",
|
"id_ed25519": "deny",
|
||||||
},
|
".aws/credentials": "deny",
|
||||||
},
|
"opencode.jsonc": "deny",
|
||||||
"web-search-prime": {
|
"~/.ssh/known_hosts": "allow",
|
||||||
"type": "remote",
|
|
||||||
"url": "https://api.z.ai/api/mcp/web_search_prime/mcp",
|
|
||||||
"headers": {
|
|
||||||
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"web-reader": {
|
|
||||||
"type": "remote",
|
|
||||||
"url": "https://api.z.ai/api/mcp/web_reader/mcp",
|
|
||||||
"headers": {
|
|
||||||
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"zread": {
|
|
||||||
"type": "remote",
|
|
||||||
"url": "https://api.z.ai/api/mcp/zread/mcp",
|
|
||||||
"headers": {
|
|
||||||
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"ibmi-server": {
|
|
||||||
"type": "local",
|
|
||||||
"command": [
|
|
||||||
"npx",
|
|
||||||
"-y",
|
|
||||||
"@ibm/ibmi-mcp-server@latest",
|
|
||||||
"--tools",
|
|
||||||
"/home/colem/mcp/ibmi-mcp-server/tools/custom-tools.yaml",
|
|
||||||
],
|
|
||||||
"enabled": true,
|
|
||||||
"environment": {
|
|
||||||
"DB2i_HOST": "{env:DB2i_HOST}",
|
|
||||||
"DB2i_USER": "{env:DB2i_USER}",
|
|
||||||
"DB2i_PASS": "{env:DB2i_PASS}",
|
|
||||||
"DB2i_PORT": "8076",
|
|
||||||
"DB2i_IGNORE_UNAUTHORIZED": "true",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"lsp": true,
|
"grep": "allow",
|
||||||
"formatter": true,
|
"glob": "allow",
|
||||||
"model": "zai-coding-plan/glm-5.2",
|
"question": "allow",
|
||||||
"small_model": "zai-coding-plan/glm-4.5-air",
|
"lsp": "allow",
|
||||||
"agent": {
|
"websearch": "allow",
|
||||||
"explore": {
|
},
|
||||||
"model": "zai-coding-plan/glm-4.5-air",
|
"mcp": {
|
||||||
},
|
"zai-mcp-server": {
|
||||||
"scout": {
|
"type": "local",
|
||||||
"model": "zai-coding-plan/glm-4.5-air",
|
"command": ["npx", "-y", "@z_ai/mcp-server"],
|
||||||
},
|
"environment": {
|
||||||
|
"Z_AI_API_KEY": "{env:ZAI_API_KEY}",
|
||||||
|
"Z_AI_MODE": "ZAI",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"share": "disabled",
|
"web-search-prime": {
|
||||||
"snapshot": true,
|
"type": "remote",
|
||||||
"plugin": ["opencode-glm-quota"],
|
"url": "https://api.z.ai/api/mcp/web_search_prime/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"web-reader": {
|
||||||
|
"type": "remote",
|
||||||
|
"url": "https://api.z.ai/api/mcp/web_reader/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"zread": {
|
||||||
|
"type": "remote",
|
||||||
|
"url": "https://api.z.ai/api/mcp/zread/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer {env:ZAI_API_KEY}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ibmi-server": {
|
||||||
|
"type": "local",
|
||||||
|
"command": [
|
||||||
|
"npx",
|
||||||
|
"-y",
|
||||||
|
"@ibm/ibmi-mcp-server@latest",
|
||||||
|
"--tools",
|
||||||
|
"/home/colem/mcp/ibmi-mcp-server/tools/custom-tools.yaml",
|
||||||
|
],
|
||||||
|
"enabled": false,
|
||||||
|
"environment": {
|
||||||
|
"DB2i_HOST": "{env:DB2i_HOST}",
|
||||||
|
"DB2i_USER": "{env:DB2i_USER}",
|
||||||
|
"DB2i_PASS": "{env:DB2i_PASS}",
|
||||||
|
"DB2i_PORT": "8076",
|
||||||
|
"DB2i_IGNORE_UNAUTHORIZED": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"lsp": true,
|
||||||
|
"formatter": true,
|
||||||
|
"model": "zai-coding-plan/glm-5.2",
|
||||||
|
"small_model": "zai-coding-plan/glm-4.5-air",
|
||||||
|
"agent": {
|
||||||
|
"explore": {
|
||||||
|
"model": "zai-coding-plan/glm-4.5-air",
|
||||||
|
},
|
||||||
|
"scout": {
|
||||||
|
"model": "zai-coding-plan/glm-4.5-air",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"share": "disabled",
|
||||||
|
"snapshot": true,
|
||||||
|
"plugin": ["opencode-glm-quota", "./plugin/ibmi-gate.ts"],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Gate the ibmi-mcp-server on its required environment variables.
|
||||||
|
|
||||||
|
opencode's config schema types `mcp.<name>.enabled` as a static boolean and
|
||||||
|
only interpolates `{env:VAR}` for string values (headers, environment
|
||||||
|
entries), never for the `enabled` flag. Conditionally enabling a server is
|
||||||
|
therefore not expressible in opencode.jsonc alone.
|
||||||
|
|
||||||
|
This plugin uses the `config` hook, which runs once at startup with the live
|
||||||
|
merged config (before MCP servers spawn), to flip `ibmi-server.enabled` to
|
||||||
|
`true` only when every required credential is present. The config keeps
|
||||||
|
`enabled: false` as a fallback default, so the server stays off if this
|
||||||
|
plugin fails to load.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Plugin } from "@opencode-ai/plugin";
|
||||||
|
|
||||||
|
// Credentials the ibmi-server MCP needs to connect. All must be non-empty.
|
||||||
|
const REQUIRED_ENV = ["DB2i_HOST", "DB2i_USER", "DB2i_PASS"] as const;
|
||||||
|
const SERVER = "ibmi-server";
|
||||||
|
|
||||||
|
export default (async () => {
|
||||||
|
return {
|
||||||
|
config: (cfg) => {
|
||||||
|
const ready = REQUIRED_ENV.every((name) => {
|
||||||
|
const value = process.env[name];
|
||||||
|
return typeof value === "string" && value.length > 0;
|
||||||
|
});
|
||||||
|
const server = cfg.mcp?.[SERVER];
|
||||||
|
if (server && typeof server === "object") {
|
||||||
|
(server as { enabled?: boolean }).enabled = ready;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}) satisfies Plugin;
|
||||||
Reference in New Issue
Block a user