Skip to content

Commit 6886caf

Browse files
feat(types): Plugin Batch 1 / ADR-043 explainability fields on MCP responses (v6.1.0) (#141)
* feat(types): Plugin Batch 1 / ADR-043 explainability fields on MCP responses (v6.1.0) Surfaces fields the AxonFlow agent has emitted since v7.1.0 that the MCP response types didn't declare. Pure Cat B field-additions on existing methods — all optional, no breaking changes. Pre-existing constructors preserved as source-compat overloads. Documented in OpenAPI via platform v7.4.3 (axonflow-enterprise#1714); SDK catches up here. Coordinated cycle: TypeScript v6.1.0 / Python v6.8.0 / Go v5.8.0 ship same day with the same field set. MCPCheckInputResponse gains 5 fields (decisionId, riskLevel, policyMatches List<ExplainPolicy>, overrideAvailable Boolean, overrideExistingId). overrideAvailable is boxed so callers can distinguish "unset" from "false" on older platforms. MCPCheckOutputResponse gains 3 fields (decisionId, policyMatches, redactedMessage — text-redaction counterpart to redactedData). ExplainPolicy already shipped — same Jackson record reused on MCP responses. Java's @JsonProperty + camelCase getter convention handles the wire mapping naturally. Source compatibility preserved on both types: 4-arg constructor (Input) and 6-arg constructor (Output) kept as overloads that delegate to the new @JsonCreator constructors with null for the new fields. equals/hashCode/toString updated to include new fields. ExplainDecision tool surface (client.explainDecision + ExplainRule + DecisionExplanation full type surface) is feature work tracked separately in axonflow-enterprise#1716 — not this release's scope. 1200 tests pass; validate-version-alignment green. * chore(wire-shape): bump baseline SHA to v7.4.3 + regen * ci: retrigger with spec-pin-bump label visible
1 parent 7314dea commit 6886caf

5 files changed

Lines changed: 276 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [6.1.0] - 2026-04-25 — Plugin Batch 1 / ADR-043 explainability fields on MCP responses
11+
12+
Minor release. Surfaces fields the AxonFlow agent has emitted since v7.1.0 (Plugin Batch 1 / ADR-042 / ADR-043) but the SDK didn't declare. Pure Cat B field-additions on existing methods — additive only, no breaking changes. The pre-existing constructors are preserved as source-compat overloads. Documented in OpenAPI via platform v7.4.3 (axonflow-enterprise#1714); SDK catches up here.
13+
14+
Coordinated cycle: TypeScript v6.1.0 / Python v6.8.0 / Go v5.8.0 ship same day with the same field set.
15+
16+
### Added
17+
18+
- **`MCPCheckInputResponse`** gains 5 optional Plugin Batch 1 fields:
19+
- `decisionId: String` — audit correlator
20+
- `riskLevel: String``low` | `medium` | `high` | `critical`
21+
- `policyMatches: List<ExplainPolicy>` — per-policy explainability records
22+
- `overrideAvailable: Boolean` — whether session override is permitted for the matched policies (boxed so callers can distinguish "unset" from `false` on older platforms)
23+
- `overrideExistingId: String` — already-active override consumed by this decision (if any)
24+
- **`MCPCheckOutputResponse`** gains 3 optional fields:
25+
- `decisionId: String`
26+
- `policyMatches: List<ExplainPolicy>`
27+
- `redactedMessage: String` — text-redaction counterpart to `redactedData` (used when the connector returned a string message rather than tabular rows; e.g. execute-style responses)
28+
29+
`ExplainPolicy` already shipped — same Jackson-annotated record now reused on the MCP response types. Pre-v7.1.0 platforms leave all new fields as `null`; callers should treat `null` as "context not available" rather than an error.
30+
31+
### Source compatibility
32+
33+
Both `MCPCheckInputResponse` and `MCPCheckOutputResponse` retain their v6.0.0 constructor signatures as overloads that delegate to the new `@JsonCreator` constructors with `null` for the new fields. Existing callers that build response instances locally compile unchanged. `equals()` / `hashCode()` / `toString()` updated to include the new fields.
34+
35+
### Deferred
36+
37+
`client.explainDecision(decisionId)` and the full `ExplainRule` / `DecisionExplanation` type surface are tracked separately as feature work — see axonflow-enterprise#1716. This release ships only field-surfacing on existing methods.
38+
1039
## [6.0.0] - 2026-04-25 — Major: WebhookSubscription identity-based equality
1140

1241
This is a major release. The bump is driven by a single observable-contract change: `WebhookSubscription.equals()` and `.hashCode()` now compare on `id` only, not every field. Coordinated with the TypeScript SDK v6.0.0 release (PolicyInfo rename) as a v6 alignment cycle for the SDKs that needed breaking changes; Python (v6.7.0) and Go (v5.7.0) ship as minor on the same day because their changes are purely additive.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.getaxonflow</groupId>
88
<artifactId>axonflow-sdk</artifactId>
9-
<version>6.0.0</version>
9+
<version>6.1.0</version>
1010
<packaging>jar</packaging>
1111

1212
<name>AxonFlow Java SDK</name>

src/main/java/com/getaxonflow/sdk/types/MCPCheckInputResponse.java

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.fasterxml.jackson.annotation.JsonCreator;
1919
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2020
import com.fasterxml.jackson.annotation.JsonProperty;
21+
import java.util.List;
2122
import java.util.Objects;
2223

2324
/**
@@ -26,6 +27,11 @@
2627
* <p>Indicates whether the input statement is allowed by configured policies. A 403 HTTP response
2728
* still returns a valid response body with {@code allowed=false} and details in {@code blockReason}
2829
* and {@code policyInfo}.
30+
*
31+
* <p>The five Plugin Batch 1 / ADR-042 / ADR-043 fields ({@code decisionId}, {@code riskLevel},
32+
* {@code policyMatches}, {@code overrideAvailable}, {@code overrideExistingId}) are populated
33+
* when the AxonFlow platform is v7.1.0+. Pre-v7.1.0 platforms leave these as {@code null}.
34+
* Source of truth: {@code platform/agent/mcp_server_handler.go:880-940}.
2935
*/
3036
@JsonIgnoreProperties(ignoreUnknown = true)
3137
public final class MCPCheckInputResponse {
@@ -42,16 +48,52 @@ public final class MCPCheckInputResponse {
4248
@JsonProperty("policy_info")
4349
private final ConnectorPolicyInfo policyInfo;
4450

51+
@JsonProperty("decision_id")
52+
private final String decisionId;
53+
54+
@JsonProperty("risk_level")
55+
private final String riskLevel;
56+
57+
@JsonProperty("policy_matches")
58+
private final List<ExplainPolicy> policyMatches;
59+
60+
@JsonProperty("override_available")
61+
private final Boolean overrideAvailable;
62+
63+
@JsonProperty("override_existing_id")
64+
private final String overrideExistingId;
65+
4566
@JsonCreator
4667
public MCPCheckInputResponse(
4768
@JsonProperty("allowed") boolean allowed,
4869
@JsonProperty("block_reason") String blockReason,
4970
@JsonProperty("policies_evaluated") int policiesEvaluated,
50-
@JsonProperty("policy_info") ConnectorPolicyInfo policyInfo) {
71+
@JsonProperty("policy_info") ConnectorPolicyInfo policyInfo,
72+
@JsonProperty("decision_id") String decisionId,
73+
@JsonProperty("risk_level") String riskLevel,
74+
@JsonProperty("policy_matches") List<ExplainPolicy> policyMatches,
75+
@JsonProperty("override_available") Boolean overrideAvailable,
76+
@JsonProperty("override_existing_id") String overrideExistingId) {
5177
this.allowed = allowed;
5278
this.blockReason = blockReason;
5379
this.policiesEvaluated = policiesEvaluated;
5480
this.policyInfo = policyInfo;
81+
this.decisionId = decisionId;
82+
this.riskLevel = riskLevel;
83+
this.policyMatches = policyMatches;
84+
this.overrideAvailable = overrideAvailable;
85+
this.overrideExistingId = overrideExistingId;
86+
}
87+
88+
/**
89+
* Source-compat overload. Callers that build {@code MCPCheckInputResponse} instances locally
90+
* with the v6.0.0 4-argument shape continue to compile — the five Plugin Batch 1 fields default
91+
* to {@code null}. Server-side responses always go through the {@code @JsonCreator} 9-arg
92+
* constructor regardless.
93+
*/
94+
public MCPCheckInputResponse(
95+
boolean allowed, String blockReason, int policiesEvaluated, ConnectorPolicyInfo policyInfo) {
96+
this(allowed, blockReason, policiesEvaluated, policyInfo, null, null, null, null, null);
5597
}
5698

5799
/** Returns whether the input is allowed by policies. */
@@ -74,6 +116,46 @@ public ConnectorPolicyInfo getPolicyInfo() {
74116
return policyInfo;
75117
}
76118

119+
/**
120+
* Returns the audit correlator for this policy decision (Plugin Batch 1, v7.1.0+). Null on
121+
* older platforms.
122+
*/
123+
public String getDecisionId() {
124+
return decisionId;
125+
}
126+
127+
/**
128+
* Returns the highest risk level across matched policies ({@code low} | {@code medium} |
129+
* {@code high} | {@code critical}; Plugin Batch 1, v7.1.0+). Null on older platforms.
130+
*/
131+
public String getRiskLevel() {
132+
return riskLevel;
133+
}
134+
135+
/**
136+
* Returns the per-policy explainability records (ADR-043, v7.1.0+). Null on older platforms.
137+
*/
138+
public List<ExplainPolicy> getPolicyMatches() {
139+
return policyMatches;
140+
}
141+
142+
/**
143+
* Returns whether at least one matched policy permits a session override (Plugin Batch 1,
144+
* v7.1.0+). Null on older platforms; callers should treat null as "context not available"
145+
* rather than {@code false}.
146+
*/
147+
public Boolean getOverrideAvailable() {
148+
return overrideAvailable;
149+
}
150+
151+
/**
152+
* Returns the ID of an active override consumed by this decision, if any (Plugin Batch 1,
153+
* v7.1.0+). Null on older platforms or when no override was consumed.
154+
*/
155+
public String getOverrideExistingId() {
156+
return overrideExistingId;
157+
}
158+
77159
@Override
78160
public boolean equals(Object o) {
79161
if (this == o) return true;
@@ -82,12 +164,26 @@ public boolean equals(Object o) {
82164
return allowed == that.allowed
83165
&& policiesEvaluated == that.policiesEvaluated
84166
&& Objects.equals(blockReason, that.blockReason)
85-
&& Objects.equals(policyInfo, that.policyInfo);
167+
&& Objects.equals(policyInfo, that.policyInfo)
168+
&& Objects.equals(decisionId, that.decisionId)
169+
&& Objects.equals(riskLevel, that.riskLevel)
170+
&& Objects.equals(policyMatches, that.policyMatches)
171+
&& Objects.equals(overrideAvailable, that.overrideAvailable)
172+
&& Objects.equals(overrideExistingId, that.overrideExistingId);
86173
}
87174

88175
@Override
89176
public int hashCode() {
90-
return Objects.hash(allowed, blockReason, policiesEvaluated, policyInfo);
177+
return Objects.hash(
178+
allowed,
179+
blockReason,
180+
policiesEvaluated,
181+
policyInfo,
182+
decisionId,
183+
riskLevel,
184+
policyMatches,
185+
overrideAvailable,
186+
overrideExistingId);
91187
}
92188

93189
@Override
@@ -102,6 +198,19 @@ public String toString() {
102198
+ policiesEvaluated
103199
+ ", policyInfo="
104200
+ policyInfo
201+
+ ", decisionId='"
202+
+ decisionId
203+
+ '\''
204+
+ ", riskLevel='"
205+
+ riskLevel
206+
+ '\''
207+
+ ", policyMatches="
208+
+ policyMatches
209+
+ ", overrideAvailable="
210+
+ overrideAvailable
211+
+ ", overrideExistingId='"
212+
+ overrideExistingId
213+
+ '\''
105214
+ '}';
106215
}
107216
}

src/main/java/com/getaxonflow/sdk/types/MCPCheckOutputResponse.java

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,20 @@
1818
import com.fasterxml.jackson.annotation.JsonCreator;
1919
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2020
import com.fasterxml.jackson.annotation.JsonProperty;
21+
import java.util.List;
2122
import java.util.Objects;
2223

2324
/**
2425
* Response from the MCP output policy check endpoint.
2526
*
26-
* <p>Indicates whether the output data passes configured policies. May include redacted data if PII
27-
* redaction policies are active, and exfiltration check information if data volume limits are
28-
* configured.
27+
* <p>Indicates whether the output data passes configured policies. May include redacted data
28+
* (tabular) or a redacted message (text) if PII redaction policies are active, and exfiltration
29+
* check information if data volume limits are configured.
30+
*
31+
* <p>The three Plugin Batch 1 / ADR-043 fields ({@code decisionId}, {@code policyMatches},
32+
* {@code redactedMessage}) are populated when the AxonFlow platform is v7.1.0+. Pre-v7.1.0
33+
* platforms leave these as {@code null}. Source of truth: {@code
34+
* platform/agent/mcp_server_handler.go:988, 1005, 1051}.
2935
*/
3036
@JsonIgnoreProperties(ignoreUnknown = true)
3137
public final class MCPCheckOutputResponse {
@@ -39,6 +45,9 @@ public final class MCPCheckOutputResponse {
3945
@JsonProperty("redacted_data")
4046
private final Object redactedData;
4147

48+
@JsonProperty("redacted_message")
49+
private final String redactedMessage;
50+
4251
@JsonProperty("policies_evaluated")
4352
private final int policiesEvaluated;
4453

@@ -48,20 +57,57 @@ public final class MCPCheckOutputResponse {
4857
@JsonProperty("policy_info")
4958
private final ConnectorPolicyInfo policyInfo;
5059

60+
@JsonProperty("decision_id")
61+
private final String decisionId;
62+
63+
@JsonProperty("policy_matches")
64+
private final List<ExplainPolicy> policyMatches;
65+
5166
@JsonCreator
5267
public MCPCheckOutputResponse(
5368
@JsonProperty("allowed") boolean allowed,
5469
@JsonProperty("block_reason") String blockReason,
5570
@JsonProperty("redacted_data") Object redactedData,
71+
@JsonProperty("redacted_message") String redactedMessage,
5672
@JsonProperty("policies_evaluated") int policiesEvaluated,
5773
@JsonProperty("exfiltration_info") ExfiltrationCheckInfo exfiltrationInfo,
58-
@JsonProperty("policy_info") ConnectorPolicyInfo policyInfo) {
74+
@JsonProperty("policy_info") ConnectorPolicyInfo policyInfo,
75+
@JsonProperty("decision_id") String decisionId,
76+
@JsonProperty("policy_matches") List<ExplainPolicy> policyMatches) {
5977
this.allowed = allowed;
6078
this.blockReason = blockReason;
6179
this.redactedData = redactedData;
80+
this.redactedMessage = redactedMessage;
6281
this.policiesEvaluated = policiesEvaluated;
6382
this.exfiltrationInfo = exfiltrationInfo;
6483
this.policyInfo = policyInfo;
84+
this.decisionId = decisionId;
85+
this.policyMatches = policyMatches;
86+
}
87+
88+
/**
89+
* Source-compat overload. Callers that build {@code MCPCheckOutputResponse} instances locally
90+
* with the v6.0.0 6-argument shape continue to compile — {@code redactedMessage}, {@code
91+
* decisionId}, and {@code policyMatches} default to {@code null}. Server-side responses always
92+
* go through the {@code @JsonCreator} 9-arg constructor regardless.
93+
*/
94+
public MCPCheckOutputResponse(
95+
boolean allowed,
96+
String blockReason,
97+
Object redactedData,
98+
int policiesEvaluated,
99+
ExfiltrationCheckInfo exfiltrationInfo,
100+
ConnectorPolicyInfo policyInfo) {
101+
this(
102+
allowed,
103+
blockReason,
104+
redactedData,
105+
null,
106+
policiesEvaluated,
107+
exfiltrationInfo,
108+
policyInfo,
109+
null,
110+
null);
65111
}
66112

67113
/** Returns whether the output data is allowed by policies. */
@@ -74,11 +120,24 @@ public String getBlockReason() {
74120
return blockReason;
75121
}
76122

77-
/** Returns the redacted version of the data, or null if no redaction was applied. */
123+
/**
124+
* Returns the redacted tabular data with PII fields masked (used when the connector returned
125+
* rows; e.g. SQL/CSV results). Null if no redaction was applied or if the response was a text
126+
* message.
127+
*/
78128
public Object getRedactedData() {
79129
return redactedData;
80130
}
81131

132+
/**
133+
* Returns the redacted text message with PII fields masked (used when the connector returned a
134+
* string message rather than tabular rows; e.g. execute-style responses). Null if no redaction
135+
* was applied or if the response was tabular.
136+
*/
137+
public String getRedactedMessage() {
138+
return redactedMessage;
139+
}
140+
82141
/** Returns the number of policies evaluated. */
83142
public int getPoliciesEvaluated() {
84143
return policiesEvaluated;
@@ -94,6 +153,21 @@ public ConnectorPolicyInfo getPolicyInfo() {
94153
return policyInfo;
95154
}
96155

156+
/**
157+
* Returns the audit correlator for this policy decision (Plugin Batch 1, v7.1.0+). Null on
158+
* older platforms.
159+
*/
160+
public String getDecisionId() {
161+
return decisionId;
162+
}
163+
164+
/**
165+
* Returns the per-policy explainability records (ADR-043, v7.1.0+). Null on older platforms.
166+
*/
167+
public List<ExplainPolicy> getPolicyMatches() {
168+
return policyMatches;
169+
}
170+
97171
@Override
98172
public boolean equals(Object o) {
99173
if (this == o) return true;
@@ -103,14 +177,25 @@ public boolean equals(Object o) {
103177
&& policiesEvaluated == that.policiesEvaluated
104178
&& Objects.equals(blockReason, that.blockReason)
105179
&& Objects.equals(redactedData, that.redactedData)
180+
&& Objects.equals(redactedMessage, that.redactedMessage)
106181
&& Objects.equals(exfiltrationInfo, that.exfiltrationInfo)
107-
&& Objects.equals(policyInfo, that.policyInfo);
182+
&& Objects.equals(policyInfo, that.policyInfo)
183+
&& Objects.equals(decisionId, that.decisionId)
184+
&& Objects.equals(policyMatches, that.policyMatches);
108185
}
109186

110187
@Override
111188
public int hashCode() {
112189
return Objects.hash(
113-
allowed, blockReason, redactedData, policiesEvaluated, exfiltrationInfo, policyInfo);
190+
allowed,
191+
blockReason,
192+
redactedData,
193+
redactedMessage,
194+
policiesEvaluated,
195+
exfiltrationInfo,
196+
policyInfo,
197+
decisionId,
198+
policyMatches);
114199
}
115200

116201
@Override
@@ -127,6 +212,11 @@ public String toString() {
127212
+ exfiltrationInfo
128213
+ ", policyInfo="
129214
+ policyInfo
215+
+ ", decisionId='"
216+
+ decisionId
217+
+ '\''
218+
+ ", policyMatches="
219+
+ policyMatches
130220
+ '}';
131221
}
132222
}

0 commit comments

Comments
 (0)