FeaturesFlex Gateway PoliciesMCP Tool Drift Detection (via A²D)

MCP Tool Drift Detection (via A²D)

A Mulesoft Flex / Omni Gateway custom policy that detects MCP tool drift — runtime tools/list responses that have diverged from the spec approved in A²D — and (optionally) strips the drifted tools from the response before they reach the LLM client.

What it catches

The policy intercepts every tools/list response, computes a canonical SHA-256 hash per tool descriptor (name, description, inputSchema, outputSchema, annotations), and compares it to the hash stored in A²D at the moment the MCP server was approved. Any mismatch is a drift event.

The classifier reports which field changeddescription_changed, input_schema_changed, output_schema_changed, annotation_changed — so an A²D reviewer immediately sees whether the change is cosmetic or structurally meaningful.

Decision sources

The interesting axis of this policy is where the decision comes from. Three sources are supported, configured via decision.source:

SourceWhat it doesLatency costFreshness
cacheDecides locally from a refreshed spec cache (last-known-good).~0 msBounded by refreshIntervalSec (default 5 min).
remote-pdpCalls A²D’s PDP per request (/api/platform/{assetId}/mcp/validate).One round-trip; capped at pdpTimeoutMs (default 250 ms).Real-time.
hybridDecides locally, also calls the PDP asynchronously for a sampled fraction of requests. Divergence raises pdp_disagreement evidence.~0 ms on the hot path.LKG on the hot path; sampled real-time audit.

hybrid is the recommended default: latency of cache with the auditability of remote-pdp. The sample rate is deterministic per request via an FNV-1a hash of method + path so a hot tool doesn’t repeatedly tax the PDP.

Decision modes

Orthogonal to source — what to do once the verdict is known.

  • enforce — strip the drifted tool from the response.
  • warn — pass through with an x-mcp-drift-warning header.
  • observe — emit evidence only.

Configuration

PathTypeDefaultNotes
a2d.baseUrlstringhttps://a2d-ai.comA²D platform base URL.
a2d.assetIdstringrequiredA²D MCP asset id.
a2d.apiKeySecretRefstringrequiredPer-instance API key (Flex secrets entry).
a2d.refreshIntervalSecint 30–86400300Cache mode spec refresh.
a2d.pdpTimeoutMsint 25–5000250Per-request PDP timeout.
decision.sourceenumcachecache / remote-pdp / hybrid.
decision.hybridSampleRatefloat 0–10.1Hybrid PDP audit rate.
enforce.exactMatchbooltrueStrict hash equality.
enforce.allowAddedToolsboolfalseUnpinned tools blocked by default.
enforce.allowRemovedToolsbooltrueDeprecation allowed.
evidence.reportToA2dbooltruePOST every event to A²D.
evidence.logLocallybooltrueEmit JSON log lines.
modeenumenforceenforce / observe / warn.
failOpen.onSpecUnavailableboolfalseAllow traffic when cache is empty.
failOpen.onPdpUnavailablebooltrueFall back to cache when PDP is down.

Evidence

Every decision lands as a JSON log line and (when reportToA2d=true) POSTs to {baseUrl}/api/platform/{assetId}/mcp/evidence.

{
  "class": "descriptor_drift",
  "severity": "critical",
  "decision": "stripped",
  "source": "hybrid",
  "asset_id": "demo-mcp-asset",
  "asset_version": "1.4.2",
  "tool_name": "lookup_account",
  "local_verdict": "descriptor_drift",
  "pdp_verdict": "descriptor_drift"
}

classdescriptor_drift | unpinned_tool | removed_tool | spec_unavailable | spec_stale | pdp_unavailable | pdp_disagreement.

Failure modes

  • PDP slow / down (remote-pdp). Times out at pdpTimeoutMs; if failOpen.onPdpUnavailable=true falls back to the LKG cache and emits pdp_unavailable. Otherwise the response is blocked.
  • Spec never loaded (cold start). failOpen.onSpecUnavailable controls allow/block; evidence event always fires.
  • PDP disagrees with cache (hybrid). The local verdict is acted on, the PDP verdict is recorded, and pdp_disagreement evidence fires for post-hoc review.

Reference deployment

FieldValue
Gatewayagent-network-ingress-gw (id 35755bec-3177-4d32-a8c9-c9705f5b1c0b, gw 1.13.2)
Public URLhttps://agent-network-ingress-gw-zovwbn.jeg62f.usa-e2.cloudhub.io/mcp-drift-via-a2d-demo
API instance20999089
A²D mock asset7b26e0d0-dfcf-4c6a-8484-8c907724366d (drift-demo)
Policy versionomni-policy-mcp-tool-drift-via-a-2-d-dev/0.1.0-20260629203620

The upstream A²D mock declares three tools (lookup_account, search_accounts, get_account_balance) which form the pinned set.

curl -sS -X POST \
  https://agent-network-ingress-gw-zovwbn.jeg62f.usa-e2.cloudhub.io/mcp-drift-via-a2d-demo \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

To exercise drift, edit one tool’s description in the A²D mock UI and re-issue the request. The policy strips the drifted tool and emits a descriptor_drift event that surfaces in A²D Test Lab.

Pair with

Next Steps

Drift detection turns A²D’s approval gate into a runtime guarantee.