Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
36bb0e2
feat(a2a): implement A2A transport and server bridge (Track 3)
MichielBugherJelli May 20, 2026
de3c693
build: regenerate lockfiles after A2A SDK dependency resolution
MichielBugherJelli May 20, 2026
fc06bd5
fix(a2a): address Copilot review feedback
MichielBugherJelli May 20, 2026
ddcbf0e
fix(a2a): add explicit Gson dependency to adcp-server
MichielBugherJelli May 20, 2026
02847df
fix(a2a): address round-3 Copilot review feedback
MichielBugherJelli May 20, 2026
75c5902
fix(a2a): address round-4 Copilot review feedback
MichielBugherJelli May 20, 2026
07f53b3
fix(a2a): address round-5 Copilot review feedback
MichielBugherJelli May 20, 2026
4ea9816
fix(a2a): eliminate lock gap in writeTimeoutResponse and move extract…
MichielBugherJelli May 20, 2026
926d09c
fix(a2a): validate sanitized tool name is non-blank and reject non-st…
MichielBugherJelli May 20, 2026
9864eca
fix(a2a): restrict synchronous-client latch guard to terminal task re…
MichielBugherJelli May 20, 2026
22c8236
fix(a2a): reject tab in tool names, normalize cache key header case, …
MichielBugherJelli May 20, 2026
a0741f3
fix(a2a): reject tool names with control characters instead of silent…
MichielBugherJelli May 21, 2026
e589c4d
fix(a2a): bump Jackson to 2.20.1, deterministic header normalization,…
MichielBugherJelli May 21, 2026
eafd26c
fix(a2a): exclude protected headers from cache hash and remove unreac…
MichielBugherJelli May 21, 2026
e6c2b9b
fix(a2a): remove unused imports from A2aCallerTest
MichielBugherJelli May 21, 2026
9578909
fix(a2a): address PR #22 review feedback
MichielBugherJelli May 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .wt-claim
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
claimed at 2026-05-29T20:38:59Z pid=54879
10 changes: 5 additions & 5 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Decisions made post-RFC that supersede or refine the merged text. The table belo
| D7 | `javax`/`jakarta` floor | **`jakarta` only**, Spring Boot 3.x floor. Single `adcp-spring-boot-starter` artifact, no compat starter, no community 2.7 port. Spring Boot 2.7 OSS support ended Nov 2025; anyone still on it has a vendor relationship. | Resolves RFC Open Question 6 in favor of option (a) |
| D8 | Mock-server CI deployment | **Sidecar via `npx adcp mock-server`.** GitHub Actions Node step installs a pinned `@adcp/sdk` version, backgrounds one mock-server per specialism on a port range, Java tests hit `localhost`. The pinned `@adcp/sdk` version is the CI conformance oracle for executable behavior, but never overrides D23's signed protocol bundle for schema/API truth. If they diverge, the release-blocking fix is to bump/patch the CI mock-server pin; a temporary exception requires WG maintainer approval in the same PR, an issue link, and an explicit statement that storyboard CI still passes or which compatibility assertion is intentionally skipped. Promote to a published Docker image if multi-specialism orchestration becomes unwieldy. | Specifies D5's deployment |
| D9 | MCP Java SDK | **`io.modelcontextprotocol.sdk:mcp-core:1.1.2` + `mcp-json-jackson2:1.1.2`** at the core (not the `mcp` bundle artifact, which pulls jackson3). Used by `adcp` (caller) and `adcp-server` (agent). The Spring AI MCP SDK was donated to the `modelcontextprotocol` org in Feb 2025 and rebranded as the official Java SDK; current `spring-ai-mcp-*` artifacts are now thin Spring Boot wrappers on top of it — no parallel implementation. **License: MIT** (compatible, flagged for foundation position). Both prototype questions closed in [`specs/mcp-prototype-findings.md`](specs/mcp-prototype-findings.md): (a) `HttpServletStreamableServerTransportProvider` in `mcp-core` is framework-neutral — no Jetty/Tomcat dep at compile time, adopter brings their own servlet container at runtime; (b) `mcp-json-jackson2` and `mcp-json-jackson3` are at identical 1.1.2 cadence with the same surface — we pin to jackson2 to match the rest of the SDK's Jackson tree. | Resolves RFC Open Question 2 |
| D10 | A2A pre-1.0 type strategy | **Keep A2A types in-tree until `a2aproject/a2a-java` cuts a stable ≥ 1.0.0 release**, then migrate to the upstream client in one shot and deprecate the in-tree fallback in the next minor. As of the latest check, `a2a-java` is at `1.0.0.Beta1` (Apr 2026) — package layout still churning, so we don't hard-depend on it yet. | RFC default for Open Question 3 |
| D10 | A2A pre-1.0 type strategy | **Depend directly on `a2aproject/a2a-java` at `1.0.0.CR1`**, skipping the in-tree fallback. CR1 (May 2026) shows a stable package layout — the Beta1→CR1 delta is bug fixes and dep bumps only, no API reshuffling. Pin to CR1 now; upgrade to `1.0.0` final (imminent) as a straight version bump. The original "keep types in-tree" plan is dropped: the in-tree fallback would have been throwaway code given how close 1.0 GA is. | RFC default for Open Question 3 |
| D11 | `TransitionGuard` narrowing protection | **Guards declare which spec edges they touch.** Conformance harness fails if a sandbox account's guards narrow any edge the storyboards exercise. Guards run after the spec edge check and can never relax a spec edge. | Resolves RFC Open Question 7 |
| D12 | Spring Security integration depth | **Recipes-only at v1.0.** No separate `adcp-spring-boot-starter-security` artifact. Auth models vary too much to pre-bake; recipes age better than autoconfig. Revisit if v0.3 design-partner feedback demands it. | RFC default for Open Question 5 |
| D13 | Reactor + Mutiny adapters | **At GA, not fast-follow.** `adcp-reactor` and `adcp-mutiny` both ship in v1.0. WebFlux shops left to wrap the sync API would own that complexity forever and we'd lose the canonical surface. | Confirms RFC §Async model |
Expand Down Expand Up @@ -202,7 +202,7 @@ Each track entry has:
| v0.1 alpha | M+3 | D23 target bundle compiles (`3.1.0-beta.5`, or 3.1 GA if cut before the codegen PR).<br>Wire-version negotiation works for stable and prerelease tokens, including `adcp_version` / `adcp_major_version` major mismatch rejection and `VERSION_UNSUPPORTED` data with `supported_versions` plus deprecated `supported_majors` through 3.x.<br>Multi-bundle validators can serve 3.0 and 3.1 traffic.<br>SSRF/auth discovery baseline lands.<br>Storyboards green against reference mock-server in CI.<br>Local Gradle artifacts only (per D6 — first Maven Central publish at v0.3). |
| v0.2 alpha | M+4 | L1: RFC 9421 signing/verification, AWS+GCP KMS providers (lazy-init, tenant-aware per-`adcp_use` key selector shape per D22; tenant resolver wiring lands in v0.3), webhook signing, typed webhook token / proof-of-control foundations |
| v0.3 alpha | M+6 | L2 + partial L3: account store, idempotency, async tasks, wholesale feed cache-scope semantics, canonical-format / signal-targeting helpers, Spring Boot starter alpha. **First Maven Central publish** (per D6). |
| v0.4 beta | M+9 | Full L3: transition validators, webhook emission, wholesale feed webhooks, `comply_test_controller`, A2A transport, 3.1 compliance bundle parity |
| v0.4 beta | M+9 | Full L3: transition validators, webhook emission, wholesale feed webhooks, `comply_test_controller`, A2A transport (implemented on `a2a-java` `1.0.0.CR1`), 3.1 compliance bundle parity |
| v1.0 GA | M+12 | L0–L3 parity, Reactor + Mutiny adapters, Kotlin co-release, Maven Central GA |

The RFC's M+12 target is the realistic line. Pre-committing M+9 and slipping is worse than committing M+12 and beating it. Slippage concentrates on: MCP Java SDK churn, RFC 9421 canonicalization edge cases, shared lifecycle YAML coordination, Spring Boot starter scope creep.
Expand Down Expand Up @@ -268,8 +268,8 @@ The RFC's M+12 target is the realistic line. Pre-committing M+9 and slipping is
**Scope:**

- **MCP:** depend on `io.modelcontextprotocol.sdk:mcp` pinned `1.1.2` (per D9). Used by both `adcp` (caller) and `adcp-server` (agent). Plan a deliberate 2.x migration PR ~6 months out (the 2.0 line removes sealed interfaces from message types, replaces `JsonSchema` with `Map`, flips the tool-input-validation default, removes server-transport builder methods). License is MIT — flagged for foundation position. Two open prototype questions land harness Week 1: whether the servlet-based streamable-HTTP server transport works without pulling Jetty/Tomcat, and whether `mcp-json-jackson2` is feature-equivalent to the Jackson 3 module.
- **A2A pre-1.0:** minimal SSE consumer + JSON-RPC framer in `adcp-server`. Default: keep types in-tree until `a2a-java` cuts its first stable release (≥ 1.0.0), then migrate in one shot (RFC Open Question 3).
- **A2A post-1.0:** swap transport to `a2aproject/a2a-java`; deprecate the in-tree fallback in the next minor.
- **A2A (implemented):** caller-side `A2aConnectionManager` + `A2aCaller` in `adcp`, plus server-side `A2aAgentExecutor` + `A2aServerBuilder` + `A2aServlet` in `adcp-server`, now ship on upstream `a2aproject/a2a-java` pinned `1.0.0.CR1` (per D10). No in-tree fallback ships.
- **A2A version bump path:** upgrade from `1.0.0.CR1` to `1.0.0` final is a straight version bump once the upstream GA tag is cut.
- HTTP transport on `java.net.http.HttpClient`. No third-party HTTP client in the core.
- Jackson `ObjectMapper` with `StreamReadConstraints` / `StreamWriteConstraints` widened to AdCP-shaped defaults (RFC §JSON).
- Wire `adcp_version` on every request/response, accepting and echoing release-precision stable and prerelease values normalized per spec while storing the full bundle pin separately from the wire token. Keep the legacy `adcp_major_version` mirror through 3.x. Server dispatch validates requested version before handler execution, rejects major-level `adcp_version` / `adcp_major_version` disagreement, and returns typed `VERSION_UNSUPPORTED` with `supported_versions` plus deprecated `supported_majors` through 3.x.
Expand All @@ -282,7 +282,7 @@ The RFC's M+12 target is the realistic line. Pre-committing M+9 and slipping is

**Depends on:** `codegen` for the request/response types.

**Milestone targets:** v0.1 needs MCP transport plus version negotiation, envelope stamping, SSRF baseline on discovery probes, `WWW-Authenticate` challenge parsing, Basic auth config, and private-agent-card auth forwarding. v0.4 swaps in upstream `a2a-java` if its 1.0 has cut by then; otherwise the in-tree fallback ships at v1.0 with the swap-trigger documented.
**Milestone targets:** v0.1 needs MCP transport plus version negotiation, envelope stamping, SSRF baseline on discovery probes, `WWW-Authenticate` challenge parsing, Basic auth config, and private-agent-card auth forwarding. v0.4 has A2A transport implemented on upstream `a2a-java` `1.0.0.CR1`; moving to `1.0.0` final is a straight version bump.

---

Expand Down
39 changes: 27 additions & 12 deletions adcp-cli/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,36 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.ethlo.time:itu:1.10.3=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,testCompileClasspath
com.fasterxml.jackson.core:jackson-annotations:2.20=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.18.2=compileClasspath,testCompileClasspath
com.fasterxml.jackson.core:jackson-core:2.20.1=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.18.2=compileClasspath,testCompileClasspath
com.fasterxml.jackson.core:jackson-databind:2.20.1=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.20=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.20.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.20.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.20.1=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2=compileClasspath,testCompileClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.2=compileClasspath,testCompileClasspath
com.fasterxml.jackson:jackson-bom:2.20.1=runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.20.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.66.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=runtimeClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.33.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:4.33.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.networknt:json-schema-validator:1.5.6=runtimeClasspath,testRuntimeClasspath
io.modelcontextprotocol.sdk:mcp-core:1.1.2=runtimeClasspath,testRuntimeClasspath
io.modelcontextprotocol.sdk:mcp-json-jackson2:1.1.2=runtimeClasspath,testRuntimeClasspath
io.projectreactor:reactor-core:3.7.0=runtimeClasspath,testRuntimeClasspath
jakarta.annotation:jakarta.annotation-api:3.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.el:jakarta.el-api:6.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.enterprise:jakarta.enterprise.lang-model:4.1.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.inject:jakarta.inject-api:2.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.interceptor:jakarta.interceptor-api:2.2.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-client-transport-spi:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-common:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-http-client:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-jsonrpc-common:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-spec-grpc:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.a2aproject.sdk:a2a-java-sdk-spec:1.0.0.CR1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=compileClasspath,testCompileClasspath
org.jspecify:jspecify:1.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.11.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
Expand All @@ -28,7 +43,7 @@ org.junit.platform:junit-platform-launcher:1.11.4=testRuntimeClasspath
org.junit:junit-bom:5.11.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reactivestreams:reactive-streams:1.0.4=runtimeClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-simple:2.0.16=runtimeClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-simple:2.0.17=runtimeClasspath,testRuntimeClasspath
org.yaml:snakeyaml:2.4=runtimeClasspath,testRuntimeClasspath
empty=annotationProcessor,testAnnotationProcessor
Loading
Loading