Model Context Protocol (MCP) traffic is increasingly moving from local developer environments into enterprise HTTP infrastructure.
A production MCP deployment may look like:
MCP Client
↓
API Gateway
↓
WAF
↓
Load Balancer
↓
MCP Server
↓
Enterprise APIs
This creates a practical security problem.
Traditional API gateways already understand HTTP methods, paths, authentication headers, and common API metadata. MCP requests, however, traditionally carried much of their semantic information inside the JSON-RPC body.
MCP 2.0 changes that model.
The July 28, 2026 MCP specification revision standardizes HTTP headers that mirror important MCP request information. A tools/call request can expose values such as:
Mcp-Method: tools/call
Mcp-Name: get_order_status
Mcp-Param-Region: eastus2
This allows gateways, proxies, WAFs, load balancers, and observability systems to make decisions without parsing the JSON-RPC body.
That capability is useful, but it also introduces a new security boundary.
The key question is:
How should enterprise gateways use MCP parameter headers without trusting attacker-controlled metadata incorrectly?
Why MCP Headers Matter
Consider a tool:
[McpServerTool(Name = "get_order_status")]
public static async Task<string> GetOrderStatus(
string region,
string orderId)
{
// Call regional order service.
return await GetStatusAsync(region, orderId);
}
The MCP 2.0 HTTP model can expose selected parameters as HTTP headers.
Conceptually:
POST /mcp
Mcp-Method: tools/call
Mcp-Name: get_order_status
Mcp-Param-Region: eastus2
The advantage is that infrastructure can make decisions without understanding the complete JSON-RPC payload.
For example:
Gateway
↓
Read Mcp-Param-Region
↓
Route to eastus2 backend
This is particularly useful for geographically distributed deployments. Microsoft describes this header design specifically as enabling ordinary HTTP infrastructure to route MCP traffic without deep inspection of request bodies.
Headers Are Not a Security Boundary by Themselves
The first security principle is simple:
Do not assume an MCP header is trustworthy merely because it uses a standardized name.
HTTP headers ultimately arrive as part of a client request.
An attacker may attempt to send:
Mcp-Param-Region: internal
or:
Mcp-Name: privileged_tool
The gateway must therefore distinguish between:
Client-supplied metadata
and:
Validated MCP request metadata
This distinction becomes especially important when a gateway uses the header to make an authorization or routing decision.
The JSON-RPC Body Remains Authoritative
MCP 2.0 deliberately avoids creating two independent sources of truth.
The standardized headers mirror information already represented in the MCP request.
For example:
Header:
Mcp-Name: get_order_status
Body:
tool = get_order_status
If they disagree, the request should not be interpreted by choosing whichever value is convenient.
The MCP 2.0 design makes the JSON-RPC body authoritative and rejects mismatched headers rather than guessing. Microsoft documents this behavior as a HeaderMismatch error condition.
This is an important security property.
Without this rule, an attacker could potentially attempt:
Gateway sees:
Mcp-Name: public_tool
Server receives:
tool: privileged_tool
or the reverse.
The infrastructure and application could make different security decisions.
The Confused-Deputy Problem
Consider an enterprise gateway:
Client
↓
Gateway
↓
MCP Server
The gateway reads:
Mcp-Name: get_customer_profile
and applies a policy:
Allowed
But the actual request body contains a different tool.
If the gateway and MCP server make decisions using different representations, the system can become vulnerable to a confused-deputy-style authorization problem.
The secure model is:
HTTP Metadata
↓
Routing / preliminary policy
↓
MCP validation
↓
Authoritative request
↓
Authorization
↓
Tool execution
A gateway should not become the sole authority for MCP authorization simply because it can see the tool name.
Separate Routing From Authorization
This distinction is important.
A gateway can use headers for:
Routing
Rate limiting
Traffic classification
Observability
Basic policy enforcement
But authorization should ultimately be based on validated identity, claims, scopes, resource ownership, and the authoritative MCP operation.
For example:
Mcp-Name: get_order_status
can help route the request.
It should not automatically imply:
User is authorized to view every order.
Authentication and authorization remain separate security decisions.
Validate Authentication Before Sensitive Routing
An enterprise deployment may use OAuth 2.0 or OpenID Connect.
A simplified request path is:
Client
↓
Authorization Header
↓
Gateway
↓
MCP Server
↓
Token Validation
↓
Authorization
↓
Tool
Validate at the appropriate trust boundary:
Issuer
Audience
Lifetime
Signature
Scopes
Claims
The MCP C# SDK has built-in support for OAuth-related authorization patterns, including incremental scope consent. Microsoft recommends validating issuer, audience, lifetime, and signing keys when configuring JWT bearer authentication.
Do Not Authorize Based Only on Tool Name
A weak policy might look like:
if Mcp-Name == "delete_customer"
allow
This is not authorization.
A production policy should consider:
Authenticated principal
+
Required scope
+
Tool
+
Resource
+
Tenant
+
Business policy
For example:
User
↓
Scope = customer.delete
↓
Tool = delete_customer
↓
Customer belongs to user's tenant
↓
Allow
The exact authorization model depends on the application.
Parameter Headers Can Become Security-Sensitive
A parameter that looks harmless can affect authorization or routing.
For example:
Mcp-Param-TenantId: tenant-a
If the gateway uses this value to select a tenant-specific backend, the parameter becomes security-sensitive.
An attacker might attempt:
Authenticated user:
tenant-a
Header:
tenant-b
The gateway must not assume that the header value establishes tenant identity.
Instead:
Authenticated identity
↓
Authorized tenant
↓
Validated MCP parameter
↓
Resource access check
Tenant identity should come from trusted authentication and authorization context wherever possible.
Do Not Trust Tenant IDs From Tool Arguments
Consider:
public static Task<string> GetCustomer(
string tenantId,
string customerId)
The presence of:
tenantId = tenant-b
does not prove the caller belongs to tenant B.
The server should derive or validate tenant context from the authenticated principal.
For example:
var userTenant =
User.FindFirst("tenant_id")?.Value;
if (userTenant != requestedTenantId)
{
throw new UnauthorizedAccessException();
}
The exact claim name and authorization mechanism depend on the identity provider.
The principle remains the same:
A request parameter identifies a resource; it does not establish authorization to access it.
Protect Region-Based Routing
Regional routing is one of the useful applications for Mcp-Param-*.
For example:
Mcp-Param-Region: eu-west
The gateway can route:
eu-west → EU backend
us-east → US backend
But routing must not bypass security controls.
A safer model is:
Authenticated request
↓
Validate requested region
↓
Check tenant/resource policy
↓
Route
Do not allow arbitrary region values to become arbitrary internal network destinations.
Otherwise, a parameter that was intended for routing can become an SSRF-like infrastructure control.
Use an Allowlist for Routing Values
Avoid:
var backend =
$"https://{region}.internal.example.com";
where region is directly controlled by the request.
Prefer a fixed mapping:
var endpoints =
new Dictionary<string, Uri>
{
["us-east"] =
new("https://orders-us.internal"),
["eu-west"] =
new("https://orders-eu.internal")
};
if (!endpoints.TryGetValue(
region,
out var endpoint))
{
throw new ArgumentException(
"Unsupported region.");
}
This prevents arbitrary input from becoming an internal destination.
Treat Mcp-Param-* as Untrusted Input
A useful security classification is:
Mcp-Method
↓
Untrusted until validated
Mcp-Name
↓
Untrusted until validated
Mcp-Param-*
↓
Untrusted until validated
After MCP validation and application authorization:
Validated request
↓
Trusted application context
This prevents infrastructure metadata from accidentally becoming an implicit trust mechanism.
Protect Against Header Injection
Header values can create problems if they are copied into other HTTP requests without validation.
For example:
Incoming:
Mcp-Param-Region: value
↓
Outgoing:
X-Backend-Region: value
If the value is not validated, an application can accidentally propagate malformed or dangerous data.
Use strict validation:
if (!AllowedRegions.Contains(region))
{
throw new InvalidOperationException(
"Invalid region.");
}
For structured values, use strongly typed parsing rather than string manipulation.
Avoid Reflection-Based Policy Names
A gateway policy such as:
Mcp-Name = "delete_customer"
should map to a known policy.
Avoid dynamically constructing policy names from untrusted values without validation:
var policy =
"Mcp_" + toolName;
Instead, use explicit mappings:
var policies =
new Dictionary<string, string>
{
["get_order_status"] =
"Orders.Read",
["create_order"] =
"Orders.Write",
["delete_order"] =
"Orders.Delete"
};
This makes security behavior auditable.
Use Least Privilege
MCP tools should not automatically receive broad permissions.
For example:
get_order_status
→ orders.read
create_order
→ orders.write
delete_order
→ orders.delete
This aligns the tool surface with the principle of least privilege.
The MCP C# SDK's authorization capabilities also support incremental scope consent, allowing clients to request additional permissions when an operation requires them instead of requesting every possible scope upfront.
Validate Scope at the Correct Layer
A gateway can perform coarse-grained scope checks:
/orders/*
The MCP server may still need fine-grained authorization:
Tool
+
Resource
+
Tenant
+
User
For example:
Gateway:
scope = mcp:tools
MCP Server:
scope = orders.read
+
tenant ownership
+
order access
This layered model avoids putting all authorization logic into the gateway.
Beware of Header Rewriting
Enterprise proxies sometimes normalize, remove, or rewrite headers.
For MCP traffic, this can create unexpected behavior.
For example:
Client
↓
Mcp-Name: get_order_status
↓
Gateway
↓
Mcp-Name: GetOrderStatus
If the server compares values strictly, the request could fail.
More importantly, a security policy may interpret the values differently.
Document gateway behavior for:
Case sensitivity
Header normalization
Header removal
Duplicate headers
Header size limits
Proxy forwarding
Do not assume that every intermediary preserves the exact wire representation.
Reject Duplicate or Ambiguous Metadata
Security-sensitive HTTP metadata should not have multiple competing interpretations.
A request containing ambiguous values such as:
Mcp-Name: tool-a
Mcp-Name: tool-b
should not be silently resolved by selecting one.
Configure the gateway and application stack to reject malformed or ambiguous requests.
The exact behavior depends on the HTTP server and proxy configuration.
Enforce Header Size Limits
Enterprise gateways should have sensible limits for:
Total header size
Individual header size
Number of headers
This is important because MCP parameter headers can expose selected tool arguments.
Do not allow arbitrary tool parameters to produce unbounded HTTP header sizes.
A tool argument containing a very large payload should generally remain in the request body rather than being promoted into a header.
Only Promote Appropriate Parameters
The [McpHeader] mechanism exists specifically to identify parameters that clients can mirror into headers. Microsoft describes it as a way to expose selected tool parameters for infrastructure routing and inspection.
Not every parameter should be promoted.
Good candidates:
Region
Routing key
Request classification
Low-risk category
Poor candidates:
Password
Access token
Payment information
Large document
Personal data
Secret
A simple rule is:
If you would not want a reverse proxy to inspect the value, do not promote it into a header.
Do Not Put Secrets in MCP Headers
Never use:
Mcp-Param-ApiKey
Mcp-Param-Password
Mcp-Param-AccessToken
for sensitive credentials.
HTTP headers commonly appear in:
Gateway logs
Proxy logs
Tracing systems
Debugging tools
Network captures
Secrets should use appropriate authentication mechanisms instead.
Protect Gateway Logs
Once MCP headers become observable by infrastructure, they can appear in gateway access logs.
For example:
Mcp-Param-Region: eastus2
may be harmless.
But:
Mcp-Param-Email: [email protected]
could be personal information.
And:
Mcp-Param-Token: ...
could be a credential.
Configure logging policies to:
Allow safe metadata
Redact sensitive headers
Avoid full request logging
Do not assume the gateway automatically knows which MCP parameters are sensitive.
Use Explicit Redaction
For example, define:
Safe:
Mcp-Method
Mcp-Name
Mcp-Param-Region
Sensitive:
Mcp-Param-Email
Mcp-Param-AccountNumber
Then configure infrastructure accordingly.
The exact redaction mechanism depends on your gateway or WAF.
The important point is to treat MCP metadata as part of your overall data-classification policy.
Prevent Header-Based Policy Bypass
Consider a gateway rule:
Mcp-Name: public_search
→ allow anonymous traffic
An attacker sends:
Mcp-Name: public_search
while the JSON-RPC body requests another operation.
The MCP protocol's header/body consistency validation is important here, but the gateway should still avoid treating client-supplied metadata as final authorization.
A safer architecture is:
Gateway
↓
Basic request filtering
↓
MCP validation
↓
Authentication
↓
Authorization
↓
Tool execution
Do not place irreversible authorization decisions solely on metadata supplied by the client.
Rate Limit by Tool
MCP tools can have dramatically different costs.
For example:
search_products
→ inexpensive
generate_report
→ expensive
delete_customer
→ sensitive
A gateway can use Mcp-Name for traffic classification:
Tool Limit
search_products Higher
generate_report Lower
delete_customer Strict
But remember that rate limiting is not authorization.
A user allowed to call a tool can still be limited according to operational policy.
Rate Limit by Identity and Tool
A stronger model is:
User
+
Tenant
+
Tool
+
Time window
For example:
tenant-a
search_products
100 requests/minute
rather than:
search_products
1000 requests/minute globally
The exact limits should be based on measured capacity.
Do not publish arbitrary numbers as universal recommendations.
Validate Parameters Before Routing
Suppose:
Mcp-Param-Region: eastus2
The gateway uses it to route the request.
Validate:
Allowed value
Allowed tenant
Allowed deployment
before making the routing decision.
For example:
region
↓
AllowedRegions
↓
Tenant policy
↓
Backend mapping
↓
Route
This reduces the chance that user-controlled data becomes an infrastructure control.
Do Not Parse MCP JSON at Every Gateway
One of the advantages of the standardized headers is avoiding deep inspection of the JSON-RPC body.
A gateway can often perform basic routing using:
Mcp-Method
Mcp-Name
Mcp-Param-Region
while leaving full protocol validation to the MCP server.
This creates a clean separation:
Gateway
→ HTTP-level policy
MCP Server
→ Protocol-level validation
Application
→ Business authorization
That separation can simplify infrastructure and reduce duplicate parsing.
Maintain Consistency Between Gateway and Server Policies
If the gateway says:
get_order_status
→ Orders.Read
but the server says:
get_order_status
→ Orders.Query
you have policy drift.
Maintain a centralized or version-controlled mapping:
Tool
Required Scope
Resource
Tenant Rule
Rate Limit
For example:
| Tool | Scope | Resource | Rate Limit |
|---|
| get_order_status | orders.read | Order | Standard |
| create_order | orders.write | Order | Restricted |
| delete_order | orders.delete | Order | Strict |
The actual policy values should come from the application's security model.
Test Header and Body Mismatch
This should be an explicit security test.
Send:
Header:
Mcp-Name: get_order_status
and:
{
"method": "tools/call",
"params": {
"name": "delete_order"
}
}
The server should reject the mismatch rather than execute one interpretation.
MCP 2.0 explicitly defines the JSON-RPC body as authoritative and rejects inconsistent standardized headers.
This test should exist in your integration suite.
Test Parameter Mismatch
Perform the same test with a promoted parameter:
Header:
Mcp-Param-Region: eastus2
while the body contains another value.
Verify that:
Mismatch
↓
Rejected
rather than:
Header wins
or:
Body wins silently
The rejection behavior prevents infrastructure and application layers from making inconsistent decisions.
Test Header Removal
Some enterprise gateways remove unknown headers.
Test:
Client
↓
Gateway
↓
MCP Server
with MCP headers removed.
Determine whether the server and client behavior remains correct according to the negotiated protocol and deployment requirements.
Do not assume that every network intermediary preserves the MCP metadata.
Test Header Injection
Attempt:
Mcp-Name: legitimate_tool
combined with malformed or duplicate values.
Also test:
Mcp-Param-Region:
Mcp-Param-Region: malicious
The objective is to ensure that the gateway and server do not interpret duplicate or malformed metadata differently.
Test Authorization Bypass
Create negative tests such as:
Valid token
+
Invalid scope
+
Valid tool header
Expected:
403 Forbidden
Another test:
Valid scope
+
Wrong tenant
+
Valid tool
Expected:
Denied
The exact status code and response depend on the authorization architecture.
Test Routing Bypass
Attempt to provide:
Mcp-Param-Region: internal-admin
when the authenticated identity is only authorized for:
public-region
The request should not reach an unauthorized backend.
This is particularly important if the gateway dynamically constructs backend URLs.
Test Sensitive Header Logging
Send a deliberately classified sensitive test value and verify:
Gateway logs
Application logs
Tracing
WAF logs
do not expose it unnecessarily.
Security testing should include the entire telemetry path, not only request processing.
Build a Security Test Matrix
A practical test matrix is:
| Test | Expected Result |
|---|
| Valid headers/body | Accepted |
| Tool-name mismatch | Rejected |
| Parameter mismatch | Rejected |
| Invalid region | Rejected |
| Unauthorized tool | Denied |
| Missing scope | Denied |
| Wrong tenant | Denied |
| Duplicate headers | Rejected or safely normalized |
| Oversized header | Rejected |
| Sensitive parameter | Not logged |
| Malicious routing value | Not routed |
| Expired token | Denied |
This turns MCP header security into something measurable rather than theoretical.
Common Mistakes
Trusting Mcp-Name
A tool name identifies an operation.
It does not establish authorization.
Using Tenant Headers as Identity
Tenant context should be derived from trusted identity and authorization information.
Putting Secrets in Mcp-Param-*
Headers are frequently logged and inspected.
Building Dynamic Backend URLs From Headers
Use fixed allowlisted mappings.
Letting Gateway and Server Have Different Policies
Policy drift can create authorization gaps.
Ignoring Header/Body Mismatches
This defeats one of the important consistency protections in MCP 2.0.
Logging Every MCP Header
Some parameters may contain sensitive data.
Using Headers for Large Parameters
Headers are not a replacement for request bodies.
Treating Routing as Authorization
Routing determines where traffic goes.
Authorization determines what the caller is allowed to do.
These are different decisions.
Troubleshooting
The Gateway Cannot See MCP Tool Information
Check whether the client is sending the standardized MCP headers and whether an intermediary is stripping them.
The 2026-07-28 protocol revision defines headers specifically to expose MCP metadata to ordinary HTTP infrastructure.
Requests Fail With Header Mismatch
Compare:
Mcp-Method
Mcp-Name
Mcp-Param-*
against the JSON-RPC request.
The body is authoritative, and mismatched metadata should be corrected rather than worked around.
Routing Works but Authorization Fails
This can be correct.
Routing and authorization are separate layers.
Verify:
Identity
Scope
Tenant
Resource
Tool
Sensitive Data Appears in Gateway Logs
Review access-log configuration and redact MCP parameter headers that contain sensitive information.
Better still, do not promote sensitive parameters into headers in the first place.
A Parameter Is Too Large for the Header
Keep large values in the MCP request body.
Promote only small, low-risk parameters that infrastructure genuinely needs.
Recommended Enterprise Architecture
A robust deployment can use:
MCP Client
|
v
+---------------------+
| API Gateway / WAF |
| |
| - TLS |
| - Rate limits |
| - Basic filtering |
| - Routing |
+----------+----------+
|
v
+---------------------+
| MCP Server |
| |
| - MCP validation |
| - Authentication |
| - Authorization |
| - Tool execution |
+----------+----------+
|
+----------+----------+
| |
v v
Enterprise APIs Data Stores
The security responsibilities should remain clear:
Gateway
→ Transport and infrastructure controls
MCP layer
→ Protocol validation
Identity layer
→ Authentication
Authorization layer
→ Permissions and scopes
Application
→ Business rules and resource ownership
Best Practices
Treat all incoming MCP headers as untrusted until validated.
Keep the JSON-RPC body authoritative.
Test header/body mismatch explicitly.
Use MCP headers primarily for routing, classification, and observability.
Do not use tool names as authorization by themselves.
Validate authentication independently.
Apply least-privilege scopes.
Validate tenant ownership separately from tenant parameters.
Use allowlists for routing values.
Never construct arbitrary backend URLs from request headers.
Do not put credentials or secrets into Mcp-Param-*.
Avoid promoting sensitive parameters into headers.
Configure header-size limits.
Reject ambiguous duplicate metadata.
Protect gateway and WAF logs from sensitive MCP parameters.
Keep gateway and MCP-server policies synchronized.
Rate-limit expensive tools separately.
Test malformed, conflicting, and malicious headers.
Test the complete gateway-to-server authorization path.
Treat routing and authorization as separate security decisions.
Frequently Asked Questions
What are MCP parameter headers?
MCP 2.0 standardizes HTTP headers that can mirror selected MCP request information. These include headers for the MCP method, tool name, and selected tool parameters. Their purpose is to let HTTP infrastructure such as gateways, proxies, WAFs, and load balancers inspect MCP traffic without parsing the JSON-RPC body.
Can a gateway trust Mcp-Name?
No.
It can use the value for routing or preliminary policy decisions, but the server must validate the actual MCP request and authorization context.
What happens if the header and JSON-RPC body disagree?
The MCP 2.0 design treats the JSON-RPC body as authoritative and rejects inconsistent standardized headers rather than selecting one value.
Should I put tenant IDs in Mcp-Param-* headers?
Only when there is a clear infrastructure requirement, and even then the value should not establish tenant authorization by itself.
The authenticated identity and server-side authorization policy should determine which tenant resources the caller can access.
Can MCP headers contain sensitive information?
Technically, HTTP headers can carry many types of values, but sensitive information should generally not be promoted into MCP headers because headers can be exposed to gateways, proxies, logging, tracing, and security infrastructure.
Can MCP headers be used for routing?
Yes.
This is one of their intended uses. Microsoft specifically describes routing based on promoted MCP parameters such as region without requiring intermediaries to parse the request body.
Should I authorize requests at the API gateway or MCP server?
For enterprise deployments, use layered controls.
The gateway can perform coarse-grained controls, while the MCP application should perform authoritative protocol and business-level authorization.
How does this relate to OAuth?
MCP authorization uses OAuth-based mechanisms, and the MCP C# SDK supports authentication and incremental scope consent. Token validation and authorization should be configured independently of MCP parameter headers.
Conclusion
MCP 2.0's standardized HTTP headers make MCP traffic much easier to operate inside conventional enterprise infrastructure.
A request can expose:
Mcp-Method
Mcp-Name
Mcp-Param-*
so that:
Gateway
WAF
Load Balancer
Proxy
Observability Platform
can understand important MCP metadata without parsing the JSON-RPC body.
That capability is powerful, but it should not create a new trust assumption.
The safest architecture is:
Incoming Header
↓
Treat as Untrusted
↓
Gateway Policy
↓
MCP Protocol Validation
↓
Authentication
↓
Authorization
↓
Business Validation
↓
Tool Execution
The most important rule is:
MCP headers are metadata, not proof of authorization.
A Mcp-Name header can identify the operation the infrastructure expects to see. A Mcp-Param-Region header can help route traffic. Neither one establishes that the caller is authorized to perform the operation or access the specified resource.
Enterprise deployments should therefore combine:
Standardized MCP Headers
+
OAuth / Identity
+
Least-Privilege Scopes
+
Tenant Validation
+
Resource Authorization
+
Allowlisted Routing
+
Header/Body Consistency
+
Secure Logging
The MCP 2.0 header model is most valuable when it is treated as an extension of existing HTTP infrastructure rather than as a replacement for established security controls.
With that separation, organizations can gain the operational advantages of MCP-aware gateways while preserving the security principles already expected from production ASP.NET Core and enterprise API architectures.