diff --git a/AGENTS.md b/AGENTS.md index 643dec0..a40f55f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,14 +10,11 @@ Select by the named target environment. If it is unspecified, ask before queryin **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 `_` 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-_` — 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___`; the gateway is not AWS-specific despite that prefix. There are no standalone `makeitwork-argocd`, `makeitwork-kubernetes`, or `makeitwork-grafana` servers. +**Make IT Work Cloud** resources: use the direct `makeitwork-` servers — `makeitwork-apify`, `makeitwork-argocd`, `makeitwork-aws`, `makeitwork-aws-docs`, `makeitwork-cloudflare`, `makeitwork-context7`, `makeitwork-gcp`, `makeitwork-grafana`, `makeitwork-kubernetes`, `makeitwork-parallel-search`, `makeitwork-playwright`, `makeitwork-slidespeak`, `makeitwork-terraform-docs`, and `makeitwork-twilio-docs`. Each is its own remote server at `https://mcp-.makeitwork.cloud/mcp`, authenticating with `CF-Access-Client-*` headers referenced from the `CF_ACCESS_CLIENT_ID` and `CF_ACCESS_CLIENT_SECRET` environment variables. Their tools are named `_` — for example `makeitwork-grafana_query_prometheus`, `makeitwork-argocd_list_applications`, `makeitwork-kubernetes_pods_list`. AWS itself is one such server, reached as `makeitwork-aws_aws___`; the server is not AWS-specific despite that prefix. `github`, `hero-ssh`, and `codebase-memory` have no external endpoint and stay on internal or client-local transports. -**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. +**Environment-neutral** tooling also arrives through direct servers: `makeitwork-parallel-search_*` (web), `makeitwork-context7_*` (library docs), `makeitwork-aws-docs_*`, `makeitwork-terraform-docs_*`, `makeitwork-apify_*`, `makeitwork-cloudflare_*`, `makeitwork-gcp_*`, `makeitwork-playwright_*`, `makeitwork-slidespeak_*`, and `makeitwork-twilio-docs_*`. `opentofu-docs` is a standalone server. -Because these integrations share one server entry, they can no longer be enabled or -disabled individually via `mcp..enabled`. A project or profile that must opt out -of one integration denies its tools instead: -`"tools": { "makeitwork_makeitwork-apify_*": false }`. +Each integration is its own server entry again, so `mcp.makeitwork-.enabled` can enable or disable it individually per project or profile; the former aggregate `makeitwork` entry no longer exists. A project or profile can still deny one integration's tools instead: `"tools": { "makeitwork-apify_*": false }`. ## context-mode routing @@ -46,13 +43,13 @@ of one integration denies its tools instead: - 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: `makeitwork_makeitwork-aws-docs_*`, - `makeitwork_makeitwork-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-aws-docs_*`, + `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/` 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:/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. +- The exceptions are the fourteen direct `makeitwork-` remote entries (one per external endpoint at `https://mcp-.makeitwork.cloud/mcp`, CF-Access headers from the environment) and the OAuth SaaS servers `linear` and `notion`. Do not add a second remote entry for a backend a direct `makeitwork-*` endpoint already serves, 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). @@ -67,7 +64,7 @@ of one integration denies its tools instead: ## apify routing -- 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 (`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 its own direct `makeitwork-apify` server entry, so a project or profile can disable it via `mcp.makeitwork-apify.enabled`; keep the guardrail behavioural regardless: 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. @@ -75,19 +72,19 @@ of one integration denies its tools instead: ## parallel-search routing -- `makeitwork_makeitwork-parallel-search_web_search` and - `makeitwork_makeitwork-parallel-search_web_fetch` are the fallback +- `makeitwork-parallel-search_web_search` and + `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 `makeitwork_makeitwork-parallel-search_web_search` for general web discovery and current +- Use `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 `makeitwork_makeitwork-parallel-search_web_fetch` + excerpts are usually sufficient; follow up with `makeitwork-parallel-search_web_fetch` only when excerpts are truncated, conflicting, or exact wording is required. -- Use `makeitwork_makeitwork-parallel-search_web_fetch` for known public URLs when context-mode is +- Use `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 diff --git a/opencode.json b/opencode.json index f2f037e..12d6c75 100644 --- a/opencode.json +++ b/opencode.json @@ -48,11 +48,11 @@ "pwd *": "allow", "pre-commit *": "allow" }, - "makeitwork_makeitwork-aws-docs_*": "allow", - "makeitwork_makeitwork-aws_*": "allow", + "makeitwork-aws-docs_*": "allow", + "makeitwork-aws_*": "allow", "codesearch": "allow", - "makeitwork_makeitwork-context7_*": "allow", - "makeitwork_makeitwork-parallel-search_*": "allow", + "makeitwork-context7_*": "allow", + "makeitwork-parallel-search_*": "allow", "context-mode_ctx_doctor": "allow", "context-mode_ctx_search": "allow", "context-mode_ctx_stats": "allow", @@ -110,12 +110,64 @@ "grafana_tempo_traceql-metrics-instant": "allow", "grafana_tempo_traceql-metrics-range": "allow", "grafana_tempo_traceql-search": "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", + "makeitwork-grafana_fetch_pyroscope_profile": "allow", + "makeitwork-grafana_find_error_pattern_logs": "allow", + "makeitwork-grafana_find_slow_requests": "allow", + "makeitwork-grafana_get_alert_group": "allow", + "makeitwork-grafana_get_alert_rule_by_uid": "allow", + "makeitwork-grafana_get_annotation_tags": "allow", + "makeitwork-grafana_get_annotations": "allow", + "makeitwork-grafana_get_assertions": "allow", + "makeitwork-grafana_get_current_oncall_users": "allow", + "makeitwork-grafana_get_dashboard_by_uid": "allow", + "makeitwork-grafana_get_dashboard_panel_queries": "allow", + "makeitwork-grafana_get_dashboard_property": "allow", + "makeitwork-grafana_get_dashboard_summary": "allow", + "makeitwork-grafana_get_datasource_by_name": "allow", + "makeitwork-grafana_get_datasource_by_uid": "allow", + "makeitwork-grafana_get_incident": "allow", + "makeitwork-grafana_get_oncall_shift": "allow", + "makeitwork-grafana_get_panel_image": "allow", + "makeitwork-grafana_get_sift_analysis": "allow", + "makeitwork-grafana_get_sift_investigation": "allow", + "makeitwork-grafana_list_alert_groups": "allow", + "makeitwork-grafana_list_alert_rules": "allow", + "makeitwork-grafana_list_contact_points": "allow", + "makeitwork-grafana_list_datasources": "allow", + "makeitwork-grafana_list_incidents": "allow", + "makeitwork-grafana_list_loki_label_names": "allow", + "makeitwork-grafana_list_loki_label_values": "allow", + "makeitwork-grafana_list_oncall_schedules": "allow", + "makeitwork-grafana_list_oncall_teams": "allow", + "makeitwork-grafana_list_oncall_users": "allow", + "makeitwork-grafana_list_prometheus_label_names": "allow", + "makeitwork-grafana_list_prometheus_label_values": "allow", + "makeitwork-grafana_list_prometheus_metric_metadata": "allow", + "makeitwork-grafana_list_prometheus_metric_names": "allow", + "makeitwork-grafana_list_pyroscope_label_names": "allow", + "makeitwork-grafana_list_pyroscope_label_values": "allow", + "makeitwork-grafana_list_pyroscope_profile_types": "allow", + "makeitwork-grafana_list_sift_investigations": "allow", + "makeitwork-grafana_query_loki_logs": "allow", + "makeitwork-grafana_query_loki_patterns": "allow", + "makeitwork-grafana_query_loki_stats": "allow", + "makeitwork-grafana_query_prometheus": "allow", + "makeitwork-grafana_query_prometheus_histogram": "allow", + "makeitwork-grafana_search_dashboards": "allow", + "makeitwork-grafana_search_folders": "allow", + "makeitwork-grafana_tempo_docs-traceql": "allow", + "makeitwork-grafana_tempo_get-attribute-names": "allow", + "makeitwork-grafana_tempo_get-attribute-values": "allow", + "makeitwork-grafana_tempo_get-trace": "allow", + "makeitwork-grafana_tempo_traceql-metrics-instant": "allow", + "makeitwork-grafana_tempo_traceql-metrics-range": "allow", + "makeitwork-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", "linear_extract_images": "allow", "linear_get_attachment": "allow", "linear_get_document": "allow", @@ -149,7 +201,7 @@ "opentofu-docs_*": "allow", "read": "allow", "skill": "allow", - "makeitwork_makeitwork-terraform-docs_*": "allow", + "makeitwork-terraform-docs_*": "allow", "tmux_find-session": "allow", "tmux_list-sessions": "allow", "tmux_list-panes": "allow", @@ -175,20 +227,20 @@ "argocd-prod-eks_get_resource_events": "allow", "argocd-prod-eks_get_resources": "allow", "argocd-prod-eks_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", + "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", "todoread": "allow", "todowrite": "allow", "webfetch": "allow", "websearch": "allow", - "makeitwork_makeitwork-kubernetes_*": "allow" + "makeitwork-kubernetes_*": "allow" }, "agent": { "plan": { @@ -230,9 +282,139 @@ "oauth": false, "timeout": 100000 }, - "makeitwork": { + "makeitwork-apify": { "type": "remote", - "url": "https://mcp.makeitwork.cloud/mcp", + "url": "https://mcp-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}" + } + }, + "makeitwork-argocd": { + "type": "remote", + "url": "https://mcp-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}" + } + }, + "makeitwork-aws": { + "type": "remote", + "url": "https://mcp-aws.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-docs": { + "type": "remote", + "url": "https://mcp-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-cloudflare": { + "type": "remote", + "url": "https://mcp-cloudflare.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-context7": { + "type": "remote", + "url": "https://mcp-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-gcp": { + "type": "remote", + "url": "https://mcp-gcp.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-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}" + } + }, + "makeitwork-kubernetes": { + "type": "remote", + "url": "https://mcp-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-parallel-search": { + "type": "remote", + "url": "https://mcp-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}" + } + }, + "makeitwork-playwright": { + "type": "remote", + "url": "https://mcp-playwright.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-slidespeak": { + "type": "remote", + "url": "https://mcp-slidespeak.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-terraform-docs": { + "type": "remote", + "url": "https://mcp-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}" + } + }, + "makeitwork-twilio-docs": { + "type": "remote", + "url": "https://mcp-twilio-docs.makeitwork.cloud/mcp", "enabled": true, "oauth": false, "headers": {