Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@

## MCP routing

For Hatch resources, use only `aws-staging`, `aws-prod`, `argocd-staging-eks`, `argocd-prod-eks`, and `grafana` (`grafana_*`). For Make IT Work Cloud resources, use only `makeitwork-aws`, `makeitwork-argocd`, `makeitwork-kubernetes`, and `makeitwork-grafana` (`makeitwork-grafana_*`). `apify`, `aws-docs`, `context7`, `parallel-search`, and `terraform-docs` are environment-neutral. Select by the named target environment; if it is unspecified, ask before querying or changing anything.
Select by the named target environment. If it is unspecified, ask before querying or changing anything.

**Hatch** resources: use only `aws-staging`, `aws-prod`, `argocd-staging-eks`, `argocd-prod-eks`, and `grafana`. These are separate servers, so their tools are named `<server>_<tool>` with no extra prefix — Hatch Grafana is `grafana_query_prometheus`.

**Make IT Work Cloud** resources: use only `makeitwork`. It is an aggregating gateway, so every integration reaches you through it as `makeitwork_makeitwork-<integration>_<tool>` — for example `makeitwork_makeitwork-grafana_query_prometheus`, `makeitwork_makeitwork-argocd_list_applications`, `makeitwork_makeitwork-kubernetes_pods_list`. AWS itself is one such integration, reached as `makeitwork_makeitwork-aws_aws___<tool>`; the gateway is not AWS-specific despite that prefix. There are no standalone `makeitwork-argocd`, `makeitwork-kubernetes`, or `makeitwork-grafana` servers.

**Environment-neutral** tooling also arrives through the `makeitwork` gateway: `makeitwork_makeitwork-parallel-search_*` (web), `makeitwork_makeitwork-context7_*` (library docs), `makeitwork_makeitwork-aws-docs_*`, `makeitwork_makeitwork-terraform-docs_*`, `makeitwork_makeitwork-apify_*`. `opentofu-docs` is a standalone server.

Because these integrations share one server entry, they can no longer be enabled or
disabled individually via `mcp.<name>.enabled`. A project or profile that must opt out
of one integration denies its tools instead:
`"tools": { "makeitwork_makeitwork-apify_*": false }`.

## context-mode routing

Expand Down Expand Up @@ -35,11 +46,13 @@ For Hatch resources, use only `aws-staging`, `aws-prod`, `argocd-staging-eks`, `
- Library and framework questions stay with Context7 even when phrased as "latest", "current", or "up to date" — freshness wording never reroutes documentation questions to web search.
- Resolve the Context7 library ID first, then query the docs.
- Do not use Context7 for AWS, Terraform, OpenTofu, or OpenCode documentation.
- For AWS, Terraform, and OpenTofu documentation, use the specialized tools instead: `aws-docs`, `terraform-docs`, and `opentofu-docs`. For OpenCode configuration, use the checked-in schema and repository validation.
- For AWS, Terraform, and OpenTofu documentation, use the specialized tools instead: `makeitwork_makeitwork-aws-docs_*`,
`makeitwork_makeitwork-terraform-docs_*`, and `opentofu-docs_*`. For OpenCode configuration, use the checked-in schema and repository validation.

## MCP integration changes (gateway-first)

- New MCP servers belong in the `mcp-gateway` repo (`servers.json` entry on the next free 87xx localhost port, plus a POSIX `bin/<name>` wrapper when the server needs credentials). Agent configs in `opencode-config`, `codex-config`, `claude-config`, and project `opencode.json` files only point at `http://127.0.0.1:<port>/mcp` with `oauth: false` — never put remote SaaS URLs, auth headers, or bearer-token plumbing in per-agent configs.
- New MCP servers belong in the `mcp-gateway` repo (`servers.json` entry on the next free 87xx localhost port, plus a POSIX `bin/<name>` wrapper when the server needs credentials). Agent configs in `opencode-config`, `codex-config`, `claude-config`, and project `opencode.json` files then point at `http://127.0.0.1:<port>/mcp` with `oauth: false`.
- The two exceptions are the remote `makeitwork` gateway (one entry, CF-Access headers from the environment, re-exporting every Make IT Work Cloud integration) and the OAuth SaaS servers `linear` and `notion`. Do not add a second remote entry for a backend the `makeitwork` gateway already re-exports, and never inline a secret value — headers reference environment variables only.
- Credentials for gateway wrappers come from `dotfiles` `encrypted_secrets.yaml.age` via `private_dot_shellenv.tmpl` (the `*_mcp_token` key convention); wrappers source `~/.shellenv` themselves. Secrets never appear in agent config repos.
- Disable-by-default in the global `opencode.json` (`enabled: false`); projects opt in. Keep `opencode-llama` opted out of non-essential servers.
- Project `opencode.json` files carry deltas only: configs deep-merge per server key, so an inherited server needs no project entry at all, `"name": { "enabled": true|false }` flips state, and full definitions (`type`/`url`/`command`) belong only to servers the global config does not define (e.g. a project-local stdio server).
Expand All @@ -54,26 +67,27 @@ For Hatch resources, use only `aws-staging`, `aws-prod`, `argocd-staging-eks`, `

## apify routing

- Apify (`apify_*` tools) is for structured marketplace and business-listing data that the free web tools cannot reach: Facebook Marketplace listings, Google Maps vendor/business discovery, and ecommerce price checks via `call-actor`. It is disabled globally and enabled only in projects that opt in; if the tools are absent, do not ask for them — use the normal web stack.
- Apify (`makeitwork_makeitwork-apify_*` tools) is for structured marketplace and business-listing data that the free web tools cannot reach: Facebook Marketplace listings, Google Maps vendor/business discovery, and ecommerce price checks via `call-actor`. It arrives through the shared gateway and cannot be disabled per project, so the guardrail is behavioural, not configuration: treat it as opt-in by judgement and fall back to the normal web stack unless the criteria below are met.
- Apify is pay-per-event with real money and returns bulk datasets. It is the LAST resort, not a search tool: exhaust context-mode fetch/index, Context7, and parallel-search first. Reach for Apify only when the target is login-walled or anti-bot (Facebook Marketplace, Google Maps) or when structured listing records are the actual deliverable.
- Every Apify call must be tight: set result limits (`resultsLimit`/`maxItems`), price filters, and location radius up front. Unbounded actor runs waste money and can blow the context window with dataset dumps.
- Prefer the pinned first-class tools (`facebook-marketplace-scraper`, `google-maps-scraper`) over `call-actor` discovery; use `search-actors`/`call-actor` only for actors not pinned in the config.
- Never put credentials, private URLs, or personal account cookies into actor inputs. Searches go out as generic buyer/research queries only.

## parallel-search routing

- `parallel-search_web_search` and `parallel-search_web_fetch` are the fallback
- `makeitwork_makeitwork-parallel-search_web_search` and
`makeitwork_makeitwork-parallel-search_web_fetch` are the fallback
for the open web. Lookup order: dedicated documentation MCPs, then Context7
for any library or framework documentation, then context-mode fetch/indexing
for known URLs, then parallel-search; prefer parallel-search over the
built-in `webfetch` and `google_search` tools when available.
- Use `parallel-search_web_search` for general web discovery and current
- Use `makeitwork_makeitwork-parallel-search_web_search` for general web discovery and current
information — news, prices, listings, vendors, and similar open-web topics.
"Current information" never includes library or framework documentation;
that belongs to Context7 regardless of how the question is phrased. Search
excerpts are usually sufficient; follow up with `parallel-search_web_fetch`
excerpts are usually sufficient; follow up with `makeitwork_makeitwork-parallel-search_web_fetch`
only when excerpts are truncated, conflicting, or exact wording is required.
- Use `parallel-search_web_fetch` for known public URLs when context-mode is
- Use `makeitwork_makeitwork-parallel-search_web_fetch` for known public URLs when context-mode is
unavailable or direct retrieval is sufficient. Always pass URLs the user
provides via the `urls` parameter (up to 20 per request).
- Generate one `session_id` per conversation (UUID or 32+ character hex) and
Expand Down
129 changes: 25 additions & 104 deletions opencode.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
"pwd *": "allow",
"pre-commit *": "allow"
},
"aws-docs_*": "allow",
"makeitwork-aws_*": "allow",
"makeitwork_makeitwork-aws-docs_*": "allow",
"makeitwork_makeitwork-aws_*": "allow",
"codesearch": "allow",
"context7_*": "allow",
"parallel-search_*": "allow",
"makeitwork_makeitwork-context7_*": "allow",
"makeitwork_makeitwork-parallel-search_*": "allow",
"context-mode_ctx_doctor": "allow",
"context-mode_ctx_search": "allow",
"context-mode_ctx_stats": "allow",
Expand Down Expand Up @@ -110,12 +110,12 @@
"grafana_tempo_traceql-metrics-instant": "allow",
"grafana_tempo_traceql-metrics-range": "allow",
"grafana_tempo_traceql-search": "allow",
"makeitwork-kubernetes_kubectl_describe": "allow",
"makeitwork-kubernetes_kubectl_get": "allow",
"makeitwork-kubernetes_kubectl_logs": "allow",
"makeitwork-kubernetes_explain_resource": "allow",
"makeitwork-kubernetes_list_api_resources": "allow",
"makeitwork-kubernetes_ping": "allow",
"makeitwork_makeitwork-kubernetes_kubectl_describe": "allow",
"makeitwork_makeitwork-kubernetes_kubectl_get": "allow",
"makeitwork_makeitwork-kubernetes_kubectl_logs": "allow",
"makeitwork_makeitwork-kubernetes_explain_resource": "allow",
"makeitwork_makeitwork-kubernetes_list_api_resources": "allow",
"makeitwork_makeitwork-kubernetes_ping": "allow",
"linear_extract_images": "allow",
"linear_get_attachment": "allow",
"linear_get_document": "allow",
Expand Down Expand Up @@ -149,7 +149,7 @@
"opentofu-docs_*": "allow",
"read": "allow",
"skill": "allow",
"terraform-docs_*": "allow",
"makeitwork_makeitwork-terraform-docs_*": "allow",
"tmux_find-session": "allow",
"tmux_list-sessions": "allow",
"tmux_list-panes": "allow",
Expand All @@ -175,20 +175,20 @@
"argocd-prod-eks_get_resource_events": "allow",
"argocd-prod-eks_get_resources": "allow",
"argocd-prod-eks_get_resource_actions": "allow",
"makeitwork-argocd_list_applications": "allow",
"makeitwork-argocd_get_application": "allow",
"makeitwork-argocd_get_application_resource_tree": "allow",
"makeitwork-argocd_get_application_managed_resources": "allow",
"makeitwork-argocd_get_application_workload_logs": "allow",
"makeitwork-argocd_get_application_events": "allow",
"makeitwork-argocd_get_resource_events": "allow",
"makeitwork-argocd_get_resources": "allow",
"makeitwork-argocd_get_resource_actions": "allow",
"makeitwork_makeitwork-argocd_list_applications": "allow",
"makeitwork_makeitwork-argocd_get_application": "allow",
"makeitwork_makeitwork-argocd_get_application_resource_tree": "allow",
"makeitwork_makeitwork-argocd_get_application_managed_resources": "allow",
"makeitwork_makeitwork-argocd_get_application_workload_logs": "allow",
"makeitwork_makeitwork-argocd_get_application_events": "allow",
"makeitwork_makeitwork-argocd_get_resource_events": "allow",
"makeitwork_makeitwork-argocd_get_resources": "allow",
"makeitwork_makeitwork-argocd_get_resource_actions": "allow",
"todoread": "allow",
"todowrite": "allow",
"webfetch": "allow",
"websearch": "allow",
"makeitwork-kubernetes_*": "allow"
"makeitwork_makeitwork-kubernetes_*": "allow"
},
"agent": {
"plan": {
Expand All @@ -201,19 +201,11 @@
"mcp": {
"context-mode": {
"type": "local",
"command": ["context-mode"],
"command": [
"context-mode"
],
"enabled": true
},
"apify": {
"type": "remote",
"url": "https://mcp-makeitwork-apify.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"linear": {
"type": "remote",
"url": "https://mcp.linear.app/mcp",
Expand All @@ -238,17 +230,7 @@
"oauth": false,
"timeout": 100000
},
"aws-docs": {
"type": "remote",
"url": "https://mcp-makeitwork-aws-docs.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"makeitwork-aws": {
"makeitwork": {
"type": "remote",
"url": "https://mcp.makeitwork.cloud/mcp",
"enabled": true,
Expand Down Expand Up @@ -276,32 +258,11 @@
"enabled": false,
"oauth": false
},
"terraform-docs": {
"type": "remote",
"url": "https://mcp-makeitwork-terraform-docs.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"opentofu-docs": {
"type": "remote",
"url": "https://mcp.opentofu.org/mcp",
"enabled": true
},
"parallel-search": {
"type": "remote",
"url": "https://mcp-makeitwork-parallel-search.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}",
"User-Agent": "makeitwork-mcp-client/1.0"
}
},
"argocd-staging-eks": {
"type": "remote",
"url": "http://127.0.0.1:8774/mcp",
Expand All @@ -313,46 +274,6 @@
"url": "http://127.0.0.1:8775/mcp",
"enabled": true,
"oauth": false
},
"makeitwork-argocd": {
"type": "remote",
"url": "https://mcp-makeitwork-argocd.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"context7": {
"type": "remote",
"url": "https://mcp-makeitwork-context7.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"makeitwork-kubernetes": {
"type": "remote",
"url": "https://mcp-makeitwork-kubernetes.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
},
"makeitwork-grafana": {
"type": "remote",
"url": "https://mcp-makeitwork-grafana.makeitwork.cloud/mcp",
"enabled": true,
"oauth": false,
"headers": {
"CF-Access-Client-Id": "{env:CF_ACCESS_CLIENT_ID}",
"CF-Access-Client-Secret": "{env:CF_ACCESS_CLIENT_SECRET}"
}
}
}
}