diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e337c4..13cf6f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,19 @@ All notable changes to the AxonFlow Java SDK will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [3.7.0] - 2026-02-28
+
+### Added
+
+- **MCP Policy-Check Endpoints** (Platform v4.6.0+): Standalone policy validation for external orchestrators (LangGraph, CrewAI) to enforce AxonFlow policies without executing connector queries
+ - `mcpCheckInput(connectorType, statement)`: Validate SQL/commands against input policies (SQLi detection, dangerous query blocking, PII in queries, dynamic policies). Returns `MCPCheckInputResponse` with `isAllowed()` or `getBlockReason()`
+ - `mcpCheckOutput(connectorType, responseData)`: Validate MCP response data against output policies (PII redaction, exfiltration limits, dynamic policies). Returns original or redacted data with `PolicyInfo`
+ - New types: `MCPCheckInputRequest`, `MCPCheckInputResponse`, `MCPCheckOutputRequest`, `MCPCheckOutputResponse`
+ - Sync + async variants with overloads for additional options (`parameters`, `operation`)
+ - Supports both query-style (`responseData`) and execute-style (`message` + `metadata`) output validation
+
+---
+
## [3.6.0] - 2026-02-22
### Added
diff --git a/src/main/java/com/getaxonflow/sdk/AxonFlow.java b/src/main/java/com/getaxonflow/sdk/AxonFlow.java
index c494000..3c371bb 100644
--- a/src/main/java/com/getaxonflow/sdk/AxonFlow.java
+++ b/src/main/java/com/getaxonflow/sdk/AxonFlow.java
@@ -1405,6 +1405,210 @@ public ConnectorResponse mcpExecute(String connector, String statement) {
return mcpQuery(connector, statement);
}
+ // ========================================================================
+ // MCP Policy Check (Standalone)
+ // ========================================================================
+
+ /**
+ * Validates an MCP input statement against configured policies without executing it.
+ *
+ *
This method calls the agent's {@code /api/v1/mcp/check-input} endpoint to pre-validate
+ * a statement before sending it to the connector. Useful for checking SQL injection
+ * patterns, blocked operations, and input policy violations.
+ *
+ * Example usage:
+ *
{@code
+ * MCPCheckInputResponse result = axonflow.mcpCheckInput("postgres", "SELECT * FROM users");
+ * if (!result.isAllowed()) {
+ * System.out.println("Blocked: " + result.getBlockReason());
+ * }
+ * }
+ *
+ * @param connectorType name of the MCP connector type (e.g., "postgres")
+ * @param statement the statement to validate
+ * @return MCPCheckInputResponse with allowed status, block reason, and policy info
+ * @throws ConnectorException if the request fails (note: 403 is not an error, it means blocked)
+ */
+ public MCPCheckInputResponse mcpCheckInput(String connectorType, String statement) {
+ return mcpCheckInput(connectorType, statement, null);
+ }
+
+ /**
+ * Validates an MCP input statement against configured policies with options.
+ *
+ * @param connectorType name of the MCP connector type (e.g., "postgres")
+ * @param statement the statement to validate
+ * @param options optional parameters: "operation" (String), "parameters" (Map)
+ * @return MCPCheckInputResponse with allowed status, block reason, and policy info
+ * @throws ConnectorException if the request fails (note: 403 is not an error, it means blocked)
+ */
+ public MCPCheckInputResponse mcpCheckInput(String connectorType, String statement, Map options) {
+ Objects.requireNonNull(connectorType, "connectorType cannot be null");
+ Objects.requireNonNull(statement, "statement cannot be null");
+
+ return retryExecutor.execute(() -> {
+ MCPCheckInputRequest request;
+ if (options != null) {
+ String operation = (String) options.getOrDefault("operation", "query");
+ @SuppressWarnings("unchecked")
+ Map parameters = (Map) options.get("parameters");
+ request = new MCPCheckInputRequest(connectorType, statement, parameters, operation);
+ } else {
+ request = new MCPCheckInputRequest(connectorType, statement);
+ }
+
+ Request httpRequest = buildRequest("POST", "/api/v1/mcp/check-input", request);
+ try (Response response = httpClient.newCall(httpRequest).execute()) {
+ ResponseBody responseBody = response.body();
+ if (responseBody == null) {
+ throw new ConnectorException("Empty response from MCP check-input", connectorType, "mcpCheckInput");
+ }
+ String responseJson = responseBody.string();
+
+ // 403 means policy blocked — the body is still a valid response
+ if (!response.isSuccessful() && response.code() != 403) {
+ try {
+ Map errorData = objectMapper.readValue(responseJson,
+ new TypeReference