Skip to content

feat(mcp): CNAMEs and wildcard Access app for per-backend MCP endpoints - #27

Merged
xnoto merged 1 commit into
mainfrom
feat/mcp-backend-endpoints
Aug 26, 2026
Merged

feat(mcp): CNAMEs and wildcard Access app for per-backend MCP endpoints#27
xnoto merged 1 commit into
mainfrom
feat/mcp-backend-endpoints

Conversation

@xnoto

@xnoto xnoto commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds edge prerequisites for per-backend MCP endpoints behind the existing cluster-apps tunnel:

  • cf-tunnels.tf: 9 new CNAMEs under mcp.makeitwork.cloud — apify, argocd-makeitwork, aws-docs, context7, github, grafana-makeitwork, kubernetes, parallel-search, terraform-docs. The aggregate VirtualMCPServer stays at the bare mcp hostname.
  • cf-access-mcp.tf: new Access application mcp_gateway_backends covering *.mcp.makeitwork.cloud, reusing the existing mcp-gateway service token (non_identity policy) plus the admins group policy.

Why: MCP clients get one config entry per integration with natural tool names, instead of one aggregate entry with gateway-prefixed tools.

Ordering constraint (per AGENTS.md)

This must apply before the matching TunnelBinding subjects merge in kustomize-cluster (commit ready, held locally). If cloudflare-operator creates the DNS records first, this apply fails with 81053 and records would need importing.

After merge

Verify CNAMEs exist → push kustomize-cluster TunnelBinding → push client config repos.

Verified: terraform fmt clean, terraform validate passing, terraform-docs README updated by hook.

@xnoto
xnoto requested a review from a team as a code owner August 26, 2026 17:38
@github-actions

Copy link
Copy Markdown

OpenTofu Plan

OpenTofu will perform the following actions:

  # cloudflare_dns_record.cluster_apps["alertmanager"] will be updated in-place
  ~ resource "cloudflare_dns_record" "cluster_apps" {
      - comment             = "Managed by cloudflare-operator" -> null
      - comment_modified_on = "2026-08-26T09:10:52Z" -> null
        id                  = "92132bbb5cd95e2ee6a44a491cb188f5"
      ~ modified_on         = "2026-08-26T09:10:52Z" -> (known after apply)
        name                = "alertmanager.makeitwork.cloud"
        tags                = []
        # (9 unchanged attributes hidden)
    }

  # cloudflare_dns_record.cluster_apps["apify.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "apify.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["argocd-makeitwork.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "argocd-makeitwork.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["aws-docs.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "aws-docs.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["context7.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "context7.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["github.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "github.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["grafana-makeitwork.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "grafana-makeitwork.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["kubernetes.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "kubernetes.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["parallel-search.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "parallel-search.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_dns_record.cluster_apps["terraform-docs.mcp"] will be created
  + resource "cloudflare_dns_record" "cluster_apps" {
      + content          = "7a3b548e-734f-427c-bd37-b360199f5433.cfargotunnel.com"
      + created_on       = (known after apply)
      + id               = (known after apply)
      + meta             = (known after apply)
      + modified_on      = (known after apply)
      + name             = "terraform-docs.mcp"
      + proxiable        = (known after apply)
      + proxied          = true
      + settings         = (known after apply)
      + tags             = (known after apply)
      + tags_modified_on = (known after apply)
      + ttl              = 1
      + type             = "CNAME"
      + zone_id          = (sensitive value)
    }

  # cloudflare_zero_trust_access_application.mcp_gateway_backends will be created
  + resource "cloudflare_zero_trust_access_application" "mcp_gateway_backends" {
      + account_id                 = (sensitive value)
      + allowed_idps               = [
          + "e584ea47-1251-4939-95f4-4daf4a58cd31",
        ]
      + app_launcher_visible       = true
      + aud                        = (known after apply)
      + destinations               = (known after apply)
      + domain                     = "*.mcp.makeitwork.cloud"
      + http_only_cookie_attribute = true
      + id                         = (known after apply)
      + name                       = "MCP Gateway Backends"
      + policies                   = [
          + {
              + decision   = "non_identity"
              + include    = [
                  + {
                      + service_token = {
                          + token_id = "96ab3739-d013-45f8-9ee5-f7e2ae003495"
                        }
                    },
                ]
              + name       = "mcp-gateway-clients"
              + precedence = 1
            },
          + {
              + decision   = "allow"
              + include    = [
                  + {
                      + group = {
                          + id = "e0d9e873-31d7-4536-9234-3dad8a99d84d"
                        }
                    },
                ]
              + name       = "makeitworkcloud-admins"
              + precedence = 2
            },
        ]
      + self_hosted_domains        = (known after apply)
      + session_duration           = "24h"
      + type                       = "self_hosted"
    }

Plan: 10 to add, 1 to change, 0 to destroy.

@xnoto
xnoto merged commit 06a7d54 into main Aug 26, 2026
4 checks passed
@xnoto
xnoto deleted the feat/mcp-backend-endpoints branch August 26, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant