---
season: 3
season_name: "Season 3 — October 2026 (Autumn / Halloween Edition)"
day: 19
title: "Dynamic MCP Governance: Eliminating Hardcoded Tool Endpoints"
summary: "Replace fragile hardcoded tool URLs and scattered credentials with runtime MCP discovery and centralized AuthProvider bindings using the Cloud Agent Registry MCP server."
tags: ["Agent Registry", "Dynamic MCP", "Governance", "ADK"]
canonical_url: "https://adventofagents.com/2026/10/19"
markdown_url: "https://adventofagents.com/2026/10/19.md"
video_url: "https://www.youtube.com/embed/5GPvyWraUiY"
primary_video:
  title: "Day 19: Centralized Tool Governance via Dynamic MCP — 5-Minute Google Cloud Kata"
  creator_name: "Google Cloud Engineering"
  duration: "6:14"
  video_url: "https://www.youtube.com/embed/5GPvyWraUiY"
---

# 🧭 Day 19: Dynamic MCP Governance: Eliminating Hardcoded Tool Endpoints

> **Season 3 — October 2026 (Autumn / Halloween Edition)** · [Interactive Web View](https://adventofagents.com/2026/10/19?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19) · [Raw Markdown](https://adventofagents.com/2026/10/19.md?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)

**Summary:** Replace fragile hardcoded tool URLs and scattered credentials with runtime MCP discovery and centralized AuthProvider bindings using the Cloud Agent Registry MCP server.

**Day 19 of Google's Advent of Agents — Season 3**

Hardcoding MCP server URLs and authentication secrets directly inside agent code or `.env` files creates an operational and security time bomb. When platform teams rotate endpoints, upgrade a vulnerable tool server, or revoke a compromised integration, hardcoded agents either crash in production or continue calling unvetted shadow endpoints outside security oversight.

**How It Works**

**Cloud Agent Registry** exposes a managed remote MCP server (`https://agentregistry.googleapis.com/mcp`) that centralizes tool discovery, credential bindings, and runtime enforcement across four pillars:

- **Three Scalable Registration Pipelines**: Populate **Cloud Agent Registry** via zero-touch auto-discovery (Vertex AI Agent Engine, Cloud Run, GKE, Dialogflow, and Apigee API Hub), the declarative `Services` REST API (`create_service`) for external MCP servers like GitHub (`https://api.githubcopilot.com/mcp/`), or Terraform (`google_agent_registry_service` and `google_agent_registry_binding`).
- **Centralized AuthProvider Bindings**: Attach an `AuthProviderBinding` linking an MCP server in Agent Registry to **Agent Auth Manager** (supporting API Keys/PATs, 3LO OAuth 2.0 user delegation, and Google IAM) so credentials never live inside agent repositories.
- **Runtime Discovery via Meta-MCP**: Point ADK agents to Agent Registry's built-in remote MCP server (`https://agentregistry.googleapis.com/mcp`) to call `search_mcp_servers`, `get_mcp_server`, and `fetch_available_bindings` at runtime using `roles/mcp.toolUser` and `roles/agentregistry.viewer`.
- **Inline Model Armor Protection**: Enable **Model Armor Floor Settings** on `GOOGLE_MCP_SERVER` (`INSPECT_AND_BLOCK`) to automatically sanitize prompt injections and sensitive data leaks flowing through MCP tool calls.

**Resources:**

- [Demo Repository](https://github.com/arobinson12/advent-of-agents-s3-day19-mcp-governance?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)
- [Use the Agent Registry MCP Server](https://docs.cloud.google.com/agent-registry/use-agentregistry-mcp?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)
- [Agent Registry MCP Tools Reference](https://docs.cloud.google.com/agent-registry/reference/mcp?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)
- [ADK MCP Tools Documentation](https://google.github.io/adk-docs/tools/mcp-tools/?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)

## Code & Commands

```bash
#!/usr/bin/env bash
set -euo pipefail

# Day 19: Centralized Tool Governance via Dynamic MCP (300-Second Kata)
export CLOUDSDK_METRICS_ENVIRONMENT="advent-of-agents-s3-day19"
export PROJECT_ID="${GOOGLE_CLOUD_PROJECT:-$(gcloud config get-value project)}"
export REGION="${GOOGLE_CLOUD_LOCATION:-us-central1}"

echo "=== 1. Enable Agent Registry (Automatically enables https://agentregistry.googleapis.com/mcp) ==="
gcloud services enable agentregistry.googleapis.com modelarmor.googleapis.com \
  --project="${PROJECT_ID}"

echo "=== 2. Enforce Model Armor Floor Settings on Google MCP Servers ==="
gcloud model-armor floorsettings update \
  --full-uri="projects/${PROJECT_ID}/locations/global/floorSetting" \
  --enable-floor-setting-enforcement=true \
  --add-integrated-services=GOOGLE_MCP_SERVER \
  --google-mcp-server-enforcement-type=INSPECT_AND_BLOCK \
  --malicious-uri-filter-settings-enforcement=ENABLED

echo "=== 3. Register an Approved External MCP Server (GitHub MCP) via Agent Registry MCP ==="
TOKEN="$(gcloud auth print-access-token)"

curl -sS -X POST "https://agentregistry.googleapis.com/mcp" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "x-goog-user-project: ${PROJECT_ID}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d "{
    \"jsonrpc\": \"2.0\",
    \"id\": 1,
    \"method\": \"tools/call\",
    \"params\": {
      \"name\": \"create_service\",
      \"arguments\": {
        \"parent\": \"projects/${PROJECT_ID}/locations/${REGION}\",
        \"serviceId\": \"github-enterprise-mcp\",
        \"service\": {
          \"displayName\": \"GitHub Enterprise Official MCP Server\",
          \"description\": \"SecOps-approved remote GitHub MCP server with centralized AuthProvider binding\",
          \"interfaces\": [
            {
              \"url\": \"https://api.githubcopilot.com/mcp/\",
              \"protocolBinding\": \"HTTP_JSON\"
            }
          ],
          \"mcpServerSpec\": {
            \"type\": \"NO_SPEC\"
          }
        }
      }
    }
  }" | jq .

echo "=== 4. Dynamically Discover Approved MCP Servers via search_mcp_servers ==="
curl -sS -X POST "https://agentregistry.googleapis.com/mcp" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "x-goog-user-project: ${PROJECT_ID}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d "{
    \"jsonrpc\": \"2.0\",
    \"id\": 2,
    \"method\": \"tools/call\",
    \"params\": {
      \"name\": \"search_mcp_servers\",
      \"arguments\": {
        \"parent\": \"projects/${PROJECT_ID}/locations/${REGION}\",
        \"searchString\": \"github\"
      }
    }
  }" | jq .
```

```python
"""Day 19: ADK Agent with Zero Hardcoded Tool URLs via Agent Registry MCP."""

import json
import os
import urllib.request
import google.auth
import google.auth.transport.requests
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams

PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT", "my-gcp-project")
REGION = os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1")
MODEL_ID = os.environ.get("GEMINI_MODEL", "gemini-3-flash-preview")  # or gemini-3.1-pro-preview
AGENT_REGISTRY_MCP_URL = "https://agentregistry.googleapis.com/mcp"


def get_iam_bearer_token() -> str:
    """Obtain an OAuth 2.0 token with cloud-platform scope for IAM-governed MCP calls."""
    creds, _ = google.auth.default(
        scopes=["https://www.googleapis.com/auth/cloud-platform"]
    )
    creds.refresh(google.auth.transport.requests.Request())
    return creds.token


def discover_approved_mcp_endpoint(search_term: str) -> str:
    """Query Agent Registry's remote MCP server at runtime to resolve a vetted tool URL."""
    token = get_iam_bearer_token()
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "search_mcp_servers",
            "arguments": {
                "parent": f"projects/{PROJECT_ID}/locations/{REGION}",
                "searchString": search_term,
            },
        },
    }
    req = urllib.request.Request(
        AGENT_REGISTRY_MCP_URL,
        data=json.dumps(payload).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {token}",
            "x-goog-user-project": PROJECT_ID,
            "Content-Type": "application/json",
            "Accept": "application/json, text/event-stream",
        },
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=15) as resp:
        rpc_result = json.loads(resp.read().decode("utf-8"))

    text_blocks = rpc_result.get("result", {}).get("content", [])
    if not text_blocks:
        raise PermissionError(f"No approved MCP server found for query: '{search_term}'")

    registry_data = json.loads(text_blocks[0]["text"])
    servers = registry_data.get("mcpServers", [])
    if not servers:
        raise PermissionError(
            f"Governance Block: '{search_term}' is not registered in Agent Registry."
        )

    approved_server = servers[0]
    interfaces = approved_server.get("interfaces", [])
    if not interfaces or "url" not in interfaces[0]:
        raise KeyError(
            f"Approved server '{approved_server.get('displayName')}' has no valid interface URL."
        )

    endpoint_url = interfaces[0]["url"]
    print(f"[GOVERNANCE] Dynamically resolved '{approved_server.get('displayName')}' -> {endpoint_url}")
    return endpoint_url


def build_governed_agent() -> LlmAgent:
    """Construct an ADK agent that binds to admin-approved MCP tools at runtime."""
    registry_discovery_toolset = McpToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=AGENT_REGISTRY_MCP_URL,
            headers={
                "Authorization": f"Bearer {get_iam_bearer_token()}",
                "x-goog-user-project": PROJECT_ID,
            },
        ),
        tool_filter=["search_mcp_servers", "get_mcp_server", "fetch_available_bindings"],
    )

    vetted_mcp_url = discover_approved_mcp_endpoint("github")
    github_token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN", "")
    governed_toolset = McpToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=vetted_mcp_url,
            headers={"Authorization": f"Bearer {github_token}"} if github_token else {},
        )
    )

    return LlmAgent(
        name="governed_release_auditor",
        model=MODEL_ID,
        instruction=(
            "You are a release security auditor. Never use hardcoded or unverified endpoints. "
            "Use Agent Registry discovery tools to inspect registered MCP servers and bindings, "
            "and execute actions only through approved MCP toolsets."
        ),
        tools=[registry_discovery_toolset, governed_toolset],
    )


if __name__ == "__main__":
    print("Initializing ADK Agent with Dynamic MCP Governance...")
    agent = build_governed_agent()
    print(f"Agent '{agent.name}' ready with {len(agent.tools)} governed MCP toolsets.")
```

## Resources & Links

- **[Day 19 Code Kata](https://github.com/arobinson12/advent-of-agents-s3-day19-mcp-governance?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)** — Full runnable demo of dynamic MCP discovery and AuthProvider bindings.
- **[Use the Agent Registry MCP Server](https://docs.cloud.google.com/agent-registry/use-agentregistry-mcp?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)** — Connect agents to https://agentregistry.googleapis.com/mcp for runtime discovery.
- **[Agent Registry MCP Tools Reference](https://docs.cloud.google.com/agent-registry/reference/mcp?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)** — Schema reference for search_mcp_servers, create_service, and bindings.
- **[ADK MCP Tools Documentation](https://google.github.io/adk-docs/tools/mcp-tools/?utm_source=adventofagents&utm_medium=markdown&utm_campaign=adventofagents_s3_2026&utm_content=day19)** — Configure McpToolset and StreamableHTTPConnectionParams in ADK.
