Skip to main content

Block Shadow MCP & Validate Governance

Overview

You've created the sanctioned path (portal). Now block the unsanctioned direct path using Cloudflare Gateway / SWG so that only the portal remains as the approved way to access MCP tools.

What You Are Configuring

  • Gateway HTTP policy to allow portal traffic
  • Gateway HTTP policies to block shadow MCP traffic at three layers:
    • Hostname layer — known MCP servers and mcp.* subdomains
    • URI path layer — standard MCP endpoint paths (/mcp, /mcp/sse)
    • DLP body layer — MCP JSON-RPC protocol signatures in HTTP request bodies

Step 1: Create Gateway Allow Rule for Portal

First, explicitly allow your sanctioned portal domain.

  1. Go to dash.cloudflare.com/one
  2. Navigate to Traffic policies > Firewall policies > HTTP
  3. Click Add a policy
  4. Configure:
FieldValue
Policy nameAllow sanctioned MCP portal
SelectorHost
Operatoris
Valuemcp-portal.<your-lab-domain>
ActionAllow

Allow policy configuration

  1. Click Create policy
Policy ordering

This Allow rule must be above the Block rule you create next. Gateway evaluates policies top-to-bottom.


Step 2: Create Defense-in-Depth Shadow MCP Block Policies

A single host-based block rule only catches the one server you already know about. Real shadow MCP servers won't announce themselves — an employee could stand up tools-api.internal-corp.com/v2/invoke with no "mcp" anywhere in the URL or path.

Use three layers of detection. Only your sanctioned portal is allowed; anything that looks like MCP traffic is blocked.

Layer 3 First — Create the DLP Detection Entries

DLP scans the HTTP request body for MCP JSON-RPC signatures. This is the deepest layer — it catches stealthy servers that bypass hostname and URI checks.

Create Detection Entries

  1. Navigate to Data Loss Prevention > Detection entries
  2. Click Add entry

Add entry

  1. Select Patterns > click Add new
  2. A new tab opens — configure the first pattern:
FieldValue
NameMCP Initialize
Regex"method"\s{0,5}:\s{0,5}"initialize"

MCP Initialize regex

  1. Click Validate regex to confirm the pattern is valid

  2. Click Save

  3. Repeat Add entry > Patterns > Add new for the remaining 4 patterns:

Entry NameRegex Pattern
MCP Tools Call"method"\s{0,5}:\s{0,5}"tools/call"
MCP Tools List"method"\s{0,5}:\s{0,5}"tools/list"
MCP Resources Read"method"\s{0,5}:\s{0,5}"resources/read"
MCP Protocol Version"protocolVersion"\s{0,5}:\s{0,5}"202[4-9]

Create the DLP Profile

  1. Navigate to Data Loss Prevention > Profiles
  2. Click Create profile
  3. Name it: MCP Protocol Detection
  4. Click Add existing entries
  5. Select all 5 MCP pattern entries you just created:
    • MCP Initialize
    • MCP Tools Call
    • MCP Tools List
    • MCP Resources Read
    • MCP Protocol Version

Add existing entries

  1. Click Confirm
  2. Click Save profile

We will use this new DLP profile in HTTP policies to detect and block MCP traffic in Layer C section.

Layer A — Block Known MCP Hostnames

Catches obvious MCP services and wildcard mcp.* subdomains.

  1. Navigate to Traffic policies > Firewall policies > HTTP
  2. Click Add a policy
  3. Configure:
FieldValue
Policy nameBlock MCP hostnames
SelectorHTTP Host
Operatormatches regex
Valuemcp\..*
ActionBlock

Block MCP hostnames

  1. Click Create policy
tip

The regex mcp\..* catches any hostname starting with mcp.. In production you can also add specific known services like mcp.stripe.com using the in operator.

Layer B — Block MCP URI Paths

Catches standard MCP endpoint paths even when the hostname is generic.

  1. Click Add a policy
  2. Configure:
FieldValuecomment
Policy nameBlock MCP URI paths
SelectorURL Path
Operatorin
Value/mcp, /mcp/sse, /sseuse tab for next entry
ActionBlock

Block MCP URI paths

  1. Click Create policy

Layer C — Block MCP JSON-RPC Traffic via DLP

Catches stealthy MCP servers that hide their hostname and path but still speak MCP JSON-RPC in the request body.

  1. Click Add a policy
  2. Configure:
FieldValue
Policy nameBlock shadow MCP via DLP
SelectorDLP Profile
Operatorin
ValueMCP Protocol Detection
ActionBlock

Block shadow MCP via DLP

  1. Click Create policy

Verify Policy Order

Gateway evaluates policies top-to-bottom. Your order should be:

  1. Allow sanctioned MCP portal (top)
  2. Block MCP hostnames
  3. Block MCP URI paths
  4. Block shadow MCP via DLP (bottom)
Reordering policies

If your policies are not in the correct order, click and drag them up or down in the Gateway policy list to reorder.

Why Three Layers?

LayerCatchesMisses
Hostname (mcp.*, known services)Obvious MCP serversServers with generic hostnames
URI path (/mcp, /mcp/sse)Standard MCP endpointsCustom paths like /v1/tools
DLP body ("method": "tools/call")Any MCP JSON-RPC trafficNothing — if it speaks MCP, the body reveals it

Shadow MCP servers can disguise their hostname as api.company.com and their path as /v2/invoke. Layers A and B miss this entirely. But they still send "method": "tools/call" in the HTTP body. Layer C catches them because the protocol signature is in the payload.


Step 3: Test — Stealthy Direct MCP Is Now Blocked

  1. Go back to MCP Inspector
  2. Enter the stealthy direct MCP server URL (no "mcp" in hostname or path):
    https://kiwistore-shadow.mythingy.io/pcm
  3. Set Transport Type to Streamable HTTP
  4. Click Connect

Stealthy direct MCP server

Expected Result

Connection fails. Gateway blocks the request.

Which layer caught it?

This URL deliberately avoids "mcp" in both hostname (kiwistore-shadow) and path (/pcm):

  • Layer A (mcp.* hostnames) → misses — hostname doesn't start with mcp.
  • Layer B (/mcp paths) → misses — path is /pcm, not /mcp
  • Layer C (DLP body inspection) → blocks — the HTTP request body contains "method": "tools/call" and other MCP JSON-RPC signatures

This proves that even when shadow MCP servers try to hide, DLP body inspection catches them.

info

For this to work, your device's traffic must flow through Cloudflare Gateway (WARP client connected). If WARP is not active, the facilitator will demonstrate the blocked behavior.


Step 4: Test — Portal MCP Still Works

  1. In MCP Inspector, enter the portal URL:
    https://mcp-portal.<your-lab-domain>/mcp
  2. Set Transport Type to Streamable HTTP
  3. Click Connect
  4. Authenticate through Access
  5. Verify tools are visible and callable

Expected Result

Portal connection works. Direct connection is blocked. Only the sanctioned path remains.


Step 5: Review Gateway Logs

  1. Navigate to Insights > Logs > HTTP request logs
  2. Filter by policy name or action
  3. You should see:
EventHostActionPolicyLayer
Stealthy MCP attemptkiwistore-shadow.mythingy.ioBlockBlock shadow MCP via DLPC (DLP)
Portal MCP accessmcp-portal.<your-lab-domain>AllowAllow sanctioned MCP portal

Expected Result

Clear audit trail: blocked direct access, allowed portal access, with user and timestamp attribution.


Step 6: Complete the Story

Summarize what you've built in M5:

LayerControlWhat It Does
MCP PortalCentralized discoveryCurated tools, user auth, logged access
AccessIdentity enforcementOnly authorized users reach the portal
Gateway Layer AHostname blockingCatches obvious MCP servers (mcp.*)
Gateway Layer BURI path blockingCatches standard MCP endpoints (/mcp)
Gateway Layer CDLP body inspectionCatches stealthy MCP traffic by protocol signature

The customer message:

"Employees and AI agents can use MCP tools — but only through the sanctioned portal. Direct access to MCP servers is blocked at multiple layers. Even stealthy servers that hide their hostname and path are caught by DLP body inspection. All activity is logged with user identity."


Step 7: Customer Talk Track

Practice this 30-second pitch:

"AI agents are calling tools via MCP. Without governance, any agent can connect to any server — no identity check, no audit, no control. We put your approved MCP servers behind a portal protected by Access. Gateway blocks direct connections at three layers: hostnames, URI paths, and DLP body inspection. Even stealthy servers that try to hide are caught. The result: governed, identity-aware, logged MCP access."


Validation

  • Gateway Allow rule for portal domain is in place (top of policy list)
  • Gateway Block rule for MCP hostnames (mcp.*) is in place
  • Gateway Block rule for MCP URI paths (/mcp, /mcp/sse) is in place
  • DLP profile MCP Protocol Detection created with regex patterns
  • Gateway Block rule for DLP profile is in place with portal exception
  • Policy order verified: Allow → Hostname Block → URI Block → DLP Block
  • Stealthy direct MCP connection is blocked
  • Portal MCP connection still works after auth
  • Gateway logs show which layer blocked the direct attempt
  • Can explain the three-layer defense story to a customer

Troubleshooting

Direct MCP still works after creating block rules
  • Verify WARP is connected and routing through Gateway
  • Check policy order: Allow rule must be above all Block rules
  • Verify the direct URL uses path /pcm — the DLP body inspection catches it
  • Check that policies are enabled (not in draft)
  • Give it 30 seconds — policy propagation can take a moment
  • If using DLP-based rule, verify the request body is being scanned (POST requests only)
Portal is also blocked
  • The Allow rule for the portal domain must be above all Block rules
  • Verify the portal domain in the Allow rule exactly matches your portal URL
  • If using the DLP-based rule, ensure the exception Host is not mcp-portal.<your-lab-domain> is configured
  • Gateway evaluates top-to-bottom: Allow → Hostname Block → URI Block → DLP Block
DLP profile doesn't match
  • DLP only scans POST request bodies (first 1,024 bytes)
  • MCP traffic must flow through Gateway (WARP connected)
  • Verify regex syntax — Cloudflare DLP uses Rust regex
  • Test with a simple pattern first like "method" before adding the full regex
  • Verify the DLP profile is attached to the Gateway policy
Which layer blocked my test?

Check Gateway HTTP logs:

  • If blocked by Block MCP hostnamesLayer A caught it (hostname matched mcp.*)
  • If blocked by Block MCP URI pathsLayer B caught it (path was /mcp or /mcp/sse)
  • If blocked by Block shadow MCP via DLPLayer C caught it (body contained MCP JSON-RPC)

The KiwiCart direct URL (kiwistore-mcp.mythingy.io/mcp) is typically caught by Layer B (URI path /mcp) because the hostname doesn't start with mcp..

Congratulations

You've completed the full AI Security Bootcamp lab:

ModuleWhat You Did
M1Attacked a vulnerable AI app
M2Detected attacks with AI Security for Apps
M3Blocked attacks with WAF rules
M4Governed workforce AI with Gateway + DLP
M5Secured MCP access with portal + blocked shadow MCP

You can now explain, demonstrate, and position the complete Cloudflare AI security story to customers.