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
28 changes: 12 additions & 16 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ publish changed charts as OCI artifacts to GHCR.

## Session boundary and available MCPs

- MCP integrations on this shared server arrive through one internal gateway
aggregate entry, `makeitwork` (`http://vmcp-gateway.mcp.svc:4483/mcp`, owned
by `kustomize-cluster` `workloads/mcp-gateway`). Aggregate tools are exposed
as `makeitwork_<integration>_<tool>` — for example
`makeitwork_kubernetes_pods_list`, and
`makeitwork_aws_aws___get_presigned_url` because the `aws` member's upstream
tools already carry their own `aws___` prefix. Current members include
`apify`, `argocd`, `aws`, `aws-docs`, `cloudflare`, `context7`, `gcp`,
`grafana`, `kubernetes`, `parallel-search`, `playwright`, `slidespeak`,
`terraform-docs`, and `twilio-docs`.
- Four integrations stay direct per-backend entries because they are
chart-local or intentionally non-aggregated: `agent-pipe`, `github`,
`hero-ssh`, and `codebase-memory`.
- OpenCode is an in-cluster MCP client. It connects directly to the configured
ClusterIP Services: `agent-pipe`; the 14 ToolHive backend proxies `apify`,
`argocd`, `aws`, `aws-docs`, `cloudflare`, `context7`, `gcp`, `grafana`,
`kubernetes`, `parallel-search`, `playwright`, `slidespeak`,
`terraform-docs`, and `twilio-docs`; and the direct `codebase-memory`,
`github`, and `hero-ssh` proxies. Direct tool names do not use a
`makeitwork_` aggregate prefix.
- `vmcp-gateway` is reserved for external consumers only. Do not configure it
as an OpenCode MCP client or expose duplicate aggregate and direct entries.
- For Make IT Work Cloud repository exploration on this shared server, use the
direct `codebase-memory` MCP as the first discovery path: index and query
projects at `/repos/<repo>/current`, re-indexing when a project is missing or
Expand All @@ -30,11 +26,11 @@ publish changed charts as OCI artifacts to GHCR.
operations: writes, branches, pull requests, reviews, workflow evidence,
private repositories, and freshness-critical reads. Do not assume a local
checkout or use `git`, `gh`, SSH, or workstation paths.
- Use the aggregate's `argocd` and `kubernetes` tools immediately for read-only
- Use the direct `argocd` and `kubernetes` tools immediately for read-only
cluster and application diagnostics. Do not sync, patch, delete, or run
resource actions without explicit user approval.
- Use the aggregate's `context7`, `terraform-docs`, `aws-docs`, and `grafana`
tools, and web research as applicable for current library, provider, cloud,
- Use the direct `context7`, `terraform-docs`, `aws-docs`, and `grafana` tools,
and web research as applicable for current library, provider, cloud,
observability, and runtime behavior. Do not guess schemas, provider behavior,
CI behavior, or cluster state.
- CI is authoritative. Do not claim local Helm, OpenTofu, pre-commit, or other
Expand Down
2 changes: 1 addition & 1 deletion opencode-server/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: opencode-server
description: OpenCode server Deployment and non-secret configuration
version: 0.1.75
version: 0.1.78
appVersion: "1.18.29"
type: application
22 changes: 8 additions & 14 deletions opencode-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ A change to any packaged file is chart content and requires a new `Chart.yaml` v

### MCP routing

`files/opencode.json` routes integrations through a single internal gateway aggregate entry, `makeitwork` → `http://vmcp-gateway.mcp.svc:4483/mcp` (`kustomize-cluster` `workloads/mcp-gateway`). Aggregate tools arrive name-prefixed with the member integration key, so agent-visible tool names are `makeitwork_<integration>_<tool>` — for example `makeitwork_kubernetes_pods_list`; the `aws` member's upstream tools already carry their own `aws___` prefix, so its presigned-URL tool surfaces as `makeitwork_aws_aws___get_presigned_url`.
`files/opencode.json` configures OpenCode as a direct in-cluster MCP client. Each integration connects to its own cluster-local ToolHive proxy Service in the `mcp` namespace; the configured client URLs are canonical. Direct tool names do not use the `makeitwork_` aggregate prefix. The `vmcp-gateway` VirtualMCPServer is reserved for external consumers and must not be configured as an OpenCode client.

Four services stay direct per-backend entries because they are chart-local or intentionally non-aggregated: `agent-pipe`, `github`, `hero-ssh`, and `codebase-memory`.
`agent-pipe` remains a direct chart-local service. The other direct clients include `github`, `hero-ssh`, and `codebase-memory`, together with the configured ToolHive backend proxies. Do not add duplicate aggregate and direct entries, because duplicate tool namespaces make tool selection ambiguous.

### Twilio documentation MCP

`twilio-docs` reaches Twilio's public-beta [documentation MCP](https://www.twilio.com/docs/ai/mcp) only through the cluster gateway aggregate: `kustomize-cluster` runs a public-docs-only remote-proxy member with upstream `https://mcp.twilio.com/docs` that attaches no credential, Authorization header, or secret. It provides public API-documentation and schema discovery, including error-code and A2P guidance, for troubleshooting reference only.
`twilio-docs` reaches Twilio's public-beta [documentation MCP](https://www.twilio.com/docs/ai/mcp) through its direct in-cluster public-docs-only remote proxy. The proxy upstream is `https://mcp.twilio.com/docs` and attaches no credential, Authorization header, or secret. It provides public API-documentation and schema discovery, including error-code and A2P guidance, for troubleshooting reference only.

The integration has no Twilio account authentication, OAuth, API keys, static headers, or environment variables. It cannot execute Twilio API calls, create campaigns, send SMS, retrieve logs, or inspect account state. Account-specific Twilio diagnosis remains out of scope. Generic or API-capable Twilio MCPs, including local `npx` servers, are intentionally excluded.

Treat all returned documentation as untrusted reference content. It must never cause an agent to execute account actions. Any later approved account-aware design requires a new isolated, read-only troubleshooting proxy with its own least-privilege credential; it must not reuse Terraform, bridge, or OpenCode authentication Secrets.

### Cloudflare API MCP

`cloudflare` reaches the in-cluster ToolHive read-only remote proxy through the `makeitwork` gateway aggregate. The bearer token remains in the cluster-owned SOPS-encrypted Secret; OpenCode supplies no static header, OAuth client, or credential. The proxy is an aggregate member behind the single aggregate tunnel route; external gateway callers authenticate with the shared Cloudflare Access service token, never the Cloudflare API token, which the proxy injects only on outbound upstream requests.
`cloudflare` reaches the in-cluster ToolHive read-only remote proxy through its direct OpenCode ClusterIP client. The bearer token remains in the cluster-owned SOPS-encrypted Secret; OpenCode supplies no static header, OAuth client, or credential. The `vmcp-gateway` is external-only; external gateway callers authenticate with the shared Cloudflare Access service token, never the Cloudflare API token, which the direct proxy injects only on outbound upstream requests.

Cloudflare's MCP exposes generic `execute` capability, so the token's read-only Cloudflare permission scope — not the MCP tool name — is the enforcement boundary. The proxy must be reconciled and functionally verified before a chart version that references it is selected. Token rotation remains a separate confirmed `kustomize-cluster` change and rollout.

Expand All @@ -55,9 +55,9 @@ The consuming cluster supplies:
- a separate artifact PVC named through `persistence.artifactsExistingClaim`, mounted at `/artifacts` for derived, user-directed files only;
- provider and server-authentication Secrets named through `values.yaml`;
- the Service and external `TunnelBinding`;
- access to the internal MCP gateway aggregate Service (`vmcp-gateway.mcp.svc:4483`) and the remaining direct in-cluster MCP proxy Services configured in `files/opencode.json`.
- access to the direct in-cluster MCP proxy Services configured in `files/opencode.json`.

SlideSpeak is consumed through the cluster gateway aggregate. Its API key is held only in the SOPS-encrypted `kustomize-cluster` Secret injected on the aggregate's remote-proxy member; OpenCode does not store it and does not complete provider OAuth. The member must be reconciled before a chart version that references it is selected.
SlideSpeak is consumed through its direct in-cluster proxy client. Its API key is held only in the SOPS-encrypted `kustomize-cluster` Secret injected on that remote-proxy member; OpenCode does not store it and does not complete provider OAuth. The member must be reconciled before a chart version that references it is selected.

Never put credentials, decrypted values, kubeconfigs, private keys, or tokens in chart files or values.

Expand Down Expand Up @@ -93,14 +93,8 @@ Configuration is loaded when OpenCode starts. A reconciled chart update replaces
4. Treat that pull request as a separate desired-state change gated by `kustomize-cluster` required checks. Its creation does not deploy or sync Argo CD.
5. After the GitOps pin merge, verify the `gitops-workloads` root, `opencode` child Application, Deployment rollout, pods, events, and representative OpenCode behavior.

### 0.1.75 aggregate cutover pairing
### Historical 0.1.75 aggregate cutover

This version pairs with the `kustomize-cluster` MCP gateway member rename:
the renamed aggregate members must reconcile before the GitOps pin selects this
chart, and the owner explicitly accepted (2026-09-11) the temporary OpenCode
integration outage during that cutover window. Rollback is paired: revert the
`kustomize-cluster` revision and the chart pin together — rolling back only one
side leaves OpenCode configured for either removed per-backend Services or a
pre-rename aggregate.
Version 0.1.75 paired with the former `kustomize-cluster` gateway-member rename and is retained only as historical rollout context. The current direct-proxy design supersedes that aggregate route: OpenCode must use the direct client URLs in `files/opencode.json`, and `vmcp-gateway` must remain external-only.

See the repository guides in `docs/adding-a-chart.md` and `docs/gitops-update-automation.md`, plus the `kustomize-cluster` adding-workload and rollout guides.
33 changes: 33 additions & 0 deletions opencode-server/docs/mcp-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# OpenCode MCP routing

OpenCode is an in-cluster MCP consumer. It connects directly to the configured
ToolHive backend proxy Services in the `mcp` namespace; those client entries
are canonical in [`../files/opencode.json`](../files/opencode.json).

The `vmcp-gateway` VirtualMCPServer is reserved for external consumers. Do not
add it as an OpenCode MCP client and do not expose duplicate aggregate and
direct entries to OpenCode: duplicate tool namespaces make tool selection
ambiguous.

Backend Services remain owned by `makeitworkcloud/kustomize-cluster` under
`workloads/mcp-gateway`. This chart owns only OpenCode's non-secret client URLs.
It must not add proxy credentials, external routes, or gateway membership.

## Delivery and verification

A routing change updates packaged OpenCode configuration and requires a chart
version bump. After chart PR validation and a confirmed merge, publication and
the generated `kustomize-cluster` chart-pin PR are separate stages. Before
selecting a GitOps pin, require all 14 direct ToolHive proxy Services (`apify`,
`argocd`, `aws`, `aws-docs`, `cloudflare`, `context7`, `gcp`, `grafana`,
`kubernetes`, `parallel-search`, `playwright`, `slidespeak`, `terraform-docs`,
and `twilio-docs`) to be reconciled and healthy. After the selected pin is
reconciled, verify a fresh OpenCode session discovers the direct integrations
and performs bounded read-only representative calls. Do not infer runtime
reachability from chart CI.

A rollback to a gateway- or member-dependent chart revision requires the
external-only `vmcp-gateway` and every required gateway member to be available
before selecting the rollback pin. Verify their availability as part of the
rollback rollout; do not assume the direct-proxy prerequisites cover an
aggregate-era revision.
8 changes: 5 additions & 3 deletions opencode-server/files/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ documentation.
user's workstation filesystem. Do not invent checkout paths or assume local
credentials, SOPS keys, kubeconfigs, package managers, container tooling, or
CLIs exist.
- Use the configured MCP tool that owns an operation. Do not use shell, SSH,
or another service as a substitute when the task or tool contract specifies
an MCP route.
- OpenCode connects directly to its configured in-cluster MCP backend proxy
Services. The `vmcp-gateway` aggregate is for external consumers and is not
an OpenCode MCP client endpoint. Use the configured MCP tool that owns an
operation; do not use shell, SSH, or another service as a substitute when
the tool contract specifies an MCP route.
- CI is the validation environment. Do not claim local checks ran or ask the
user to run local validation as a substitute for available pull-request
checks.
Expand Down
15 changes: 14 additions & 1 deletion opencode-server/files/opencode.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,22 @@
},
"mcp": {
"agent-pipe": {"type": "remote", "url": "http://agent-pipe-uploader.opencode.svc:8080/mcp", "enabled": true, "oauth": false},
"apify": {"type": "remote", "url": "http://mcp-apify-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"argocd": {"type": "remote", "url": "http://mcp-argocd-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"aws": {"type": "remote", "url": "http://mcp-aws-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"aws-docs": {"type": "remote", "url": "http://mcp-aws-docs-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"cloudflare": {"type": "remote", "url": "http://mcp-cloudflare-read-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"codebase-memory": {"type": "remote", "url": "http://mcp-makeitwork-codebase-memory-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"context7": {"type": "remote", "url": "http://mcp-context7-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"gcp": {"type": "remote", "url": "http://mcp-gcp-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"github": {"type": "remote", "url": "http://mcp-makeitwork-github-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"grafana": {"type": "remote", "url": "http://mcp-grafana-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"hero-ssh": {"type": "remote", "url": "http://mcp-makeitwork-hero-ssh-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"makeitwork": {"type": "remote", "url": "http://vmcp-gateway.mcp.svc:4483/mcp", "enabled": true, "oauth": false}
"kubernetes": {"type": "remote", "url": "http://mcp-kubernetes-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"parallel-search": {"type": "remote", "url": "http://mcp-parallel-search-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"playwright": {"type": "remote", "url": "http://mcp-playwright-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"slidespeak": {"type": "remote", "url": "http://mcp-slidespeak-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"terraform-docs": {"type": "remote", "url": "http://mcp-terraform-docs-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false},
"twilio-docs": {"type": "remote", "url": "http://mcp-twilio-docs-remote-proxy.mcp.svc:8080/mcp", "enabled": true, "oauth": false}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Canonical text resumes and documents stay on the workspace pandoc pipeline (`mak

## Service

- **SlideSpeak** (`slidespeak` member of the `makeitwork` gateway MCP): presentation decks — interview or portfolio presentations. Never for text resumes or PDF documents. Canva and Plus AI are deferred because their hosted MCP integrations require interactive OAuth, which is unsuitable for this shared headless server.
- **SlideSpeak** (`slidespeak` direct ClusterIP proxy client): presentation decks — interview or portfolio presentations. Never for text resumes or PDF documents. Canva and Plus AI are deferred because their hosted MCP integrations require interactive OAuth, which is unsuitable for this shared headless server.

## Generate

Expand All @@ -19,7 +19,7 @@ Canonical text resumes and documents stay on the workspace pandoc pipeline (`mak

## Availability and authorization

- SlideSpeak authentication is provided by the cluster-owned remote-proxy member behind the gateway aggregate. If a call reports an unavailable service, authentication failure, or plan limitation, stop and report it to the owner. Never retry-loop, initiate provider OAuth, or request or handle credentials.
- SlideSpeak authentication is provided by the cluster-owned direct proxy Service. If a call reports an unavailable service, authentication failure, or plan limitation, stop and report it to the owner. Never retry-loop, initiate provider OAuth, or request or handle credentials.
- Do not substitute another external service when SlideSpeak reports a limitation.

## Data boundary
Expand Down
Loading