MCP Connectors

Validate MCP output against policies

Validate MCP response data against configured policies without having executed the query through AxonFlow.

This endpoint enables external orchestrators to apply AxonFlow's output-side policy enforcement (PII redaction, exfiltration limits, SQLi response scanning) to data they fetched from MCP connectors independently.

Policy Evaluation

The following checks are applied in order:

  1. SQLi response scanning: Detects SQL injection artifacts in response data
  2. Static response policies: PII detection and redaction (SSN, credit card, Aadhaar, etc.)
  3. Exfiltration limits (query-style only): Row count and byte size limits

If PII is detected, the response includes redacted_data with masked values. If exfiltration limits are exceeded, the response returns allowed: false.

Query vs Execute Responses

  • Query responses (response_data): Full policy evaluation including exfiltration checks
  • Execute responses (message): SQLi scanning and PII checks only (no exfiltration limits)

Audit Logging

All check-output evaluations are logged to the mcp_query_audits table with operation: "check-output" for compliance tracking.

post/api/v1/mcp/check-output

Request

Headers

X-Axonflow-Clientstring
Example:mcp-proxy/0.3.1

Optional client-version telemetry header (<client>/<version>, e.g. mcp-proxy/0.3.1 or claude-code/1.9.1). Enterprise deployments with the client_version_telemetry capability count validated values in the axonflow_client_version_requests_total metric on the decide and MCP check-output planes. Telemetry only — never used for authentication or authorization; invalid values are ignored.

X-Axonflow-PEP-Handshakestring

base64url (padding optional) of the PEPHandshake document.

The ADR-065 PEP capability handshake: base64url of a compact JSON document in which an external enforcement point declares what it is and which obligations it can discharge. See PEPHandshake for the document.

Absent is the default and changes nothing. A caller that omits the header takes byte-for-byte the path it took before this header existed.

What an absent header means for a redaction depends on the plane, by design (PRD v11 section 1 item 16, #4257). The MCP passes discharge a redaction of the content they hand back: the request pass (check-input, check_policy) masks the statement, and a redaction that masks nothing in the statement is refused unsupported_obligation to every caller, and one that masks a request parameter to every caller that has not declared field_redact at version 2 (on Community, to every caller) (#4264); the response passes (check-output, the MCP server's check_output) mask the rows or the message. /api/v1/decide and the gateway pre-check return a decision rather than content, so a required redaction is a field_redact obligation for the enforcement point, and a caller that has not declared field_redact is refused unsupported_obligation. A caller that declares NO redaction (capabilities: []) is refused on each of these planes; on Community the MCP passes still return a checksum validator's masked content to it (reachable only through a directly inserted detection_action_overrides row) until #4122.

A header that is PRESENT and cannot be read is refused, never treated as absent: degrading a malformed declaration to "legacy caller" would go on handing an enforcement point obligations it had just said it cannot discharge. The refusal is 400 and its message names this header, which matters on /api/v1/access/evaluation where the refusal is rendered through that surface's existing incomplete_evaluation code and the message is the only thing distinguishing a malformed HEADER from a malformed body ENVELOPE.

Present more than once is refused: RFC 7230 permits an intermediary to join repeated field lines with a comma, and a comma is outside the base64 alphabet, so a joined pair can only decode to malformed. That is why the document is base64 rather than raw JSON, which would join into something a lenient parser might accept.

When a decision carries a mandatory obligation the declared set does not cover, the request is answered 200 with verdict: deny and the reason unsupported_obligation (ADR-065 invariant 8) - a decision about the request, not a transport error. That holds on every edition. An Enterprise deployment adds a second reason beginning pep_capability_unsupported naming the gap, and refuses a checksum validator's mask on the MCP passes; a Community deployment hands that masked content over (#4257 split 2, #4122).

Request body

OR

Response

Output passed all policy checks (may include redacted data)

allowedboolean

Whether the output passed all policy checks

block_reasonstring

Human-readable reason if blocked (omitted when allowed)

redacted_dataunknown
policies_evaluatedinteger

Total number of policies evaluated

decision_idstring

Unique audit correlator for this policy decision.

redaction_evaluatedboolean

Whether the response-phase redaction pipeline actually ran (#2865). Mirrors MCPCheckInputResponse.redaction_evaluated for the response leg. A PEP fulfilling a response-phase redact_pii obligation MUST fail closed when this is false/absent — the redactor did not run (detection disabled for the connector, or no policy engine), so absence of redacted_data cannot be trusted as "nothing to mask." Omitted (false) preserves the pre-#2865 shape.

engine'anchored'

Which policy engine authored this verdict: the ADR-065 decision plane, the only author on this route (PRD v11 §1.1). It rides this body and the 403 envelope of a refusal by the same pass. Omitted on a refusal no engine decided - an authentication failure, or a request refused before the policy pass ran.

subject_typestring

The type of principal the verdict was decided for (PRD v11 §1.6): User for a verified user token, Client when the request presented no user identity and its client credential is the principal. Omitted wherever engine is.

policy_bundlestring

The digest of the policy set that decided: the system corpus's restriction for this route and the organization root - the organization's active typed document composed with the deployment's baseline permission pack, or, while it has published nothing, the implicit bundle of that pack and the organization template. A rollback reinstates an earlier digest. Omitted wherever engine is.

policy_packsstring[]

The add-on policy packs (PRD v11 §1.9) whose controls composed into policy_bundle on the response pass, each as <pack id>@<digest of the pack document the deployment instantiated>, sorted. Omitted when the deployment installs no pack or none binds on this route.

Changes

No recorded changes to this operation across all 1 revision of this API.