Skip to content

feat: seed repo with Java SDK RFC, roadmap, and harness foundation#1

Merged
bokelley merged 12 commits into
mainfrom
bokelley/rfc-import-impl-plan
May 13, 2026
Merged

feat: seed repo with Java SDK RFC, roadmap, and harness foundation#1
bokelley merged 12 commits into
mainfrom
bokelley/rfc-import-impl-plan

Conversation

@bokelley

@bokelley bokelley commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Seeds the empty repo with: the merged RFC, a contributor-facing roadmap covering 14 tracks across v0.1→v1.0, the AAO-conventional CODEOWNERS, and the harness Week 1 foundation — a working Gradle 9.5 multi-module skeleton with CI green on JDK 21.

What's here

Docs

  • docs/rfc/java-sdk-rfc.md — RFC text from merged adcontextprotocol/adcp#4279; relative spec links rewritten to absolute GitHub URLs.
  • ROADMAP.md — 14 claimable tracks, dependency graph, 7.x parity deltas vs the RFC's 6.x baseline, pre-contributor harness plan, and 21 confirmed post-RFC decisions (D1–D21).

Governance

Build foundation (harness Week 1 first slice)

  • Gradle 9.5.1 multi-module skeleton, eight published artifacts per D3:
    • adcp, adcp-server, adcp-testing, adcp-spring-boot-starter, adcp-cli, adcp-reactor, adcp-mutiny, adcp-kotlin
  • Convention plugins in build-logic/ centralize JDK 21 toolchain (D2), JSpecify nullability annotations, manifest stamping, and Xlint:all -Werror (minus processing/options to tolerate package-info-only skeleton modules).
  • gradle/libs.versions.toml pins every external dependency in one place: io.modelcontextprotocol.sdk:mcp:1.1.2 (D9), Jackson 2.18.2 (RFC §JSON ≥2.15 floor), networknt json-schema-validator 1.5.6, SLF4J 2.0.16, JSpecify 1.0.0, JUnit 5.11.4, Spring Boot 3.4.4 (D7 jakarta only), Reactor 3.7.2, Mutiny 2.7.0, Kotlin 2.1.10.
  • .github/workflows/ci.yml — JDK 21 Temurin, gradle/actions/setup-gradle@v4 with validate-wrappers: true (supply-chain guard).

Verified

  • ./gradlew build green locally and on GH Actions (cdf1c2f, 1m59s).
  • All 8 modules produce main + sources + javadoc JARs.
  • JAR manifests stamp Automatic-Module-Name = org.adcontextprotocol.<dot>.
  • ./gradlew :adcp-cli:run runs the placeholder Main.

21 confirmed decisions (in ROADMAP §Confirmed decisions)

Architecture / protocol:

  • D1 repo home (this repo, feature branches → main)
  • D2 JDK 21 only (drops the RFC's 17 floor → no *Async mirrors, ScopedValue for UpstreamRecorder)
  • D3 Maven coords (org.adcontextprotocol:adcp etc., base pkg org.adcontextprotocol.adcp.*)
  • D4 Sigstore on protocol tarball confirmed signed; no checksum fallback
  • D5 reference mock-server = @adcp/sdk/mock-server
  • D9 MCP SDK = io.modelcontextprotocol.sdk:mcp pinned 1.1.2 (MIT-licensed, flagged for foundation)
  • D10 A2A pre-1.0 types in-tree until a2aproject/a2a-java ≥1.0 (currently at 1.0.0.Beta1)
  • D11 TransitionGuard narrowing protection via declared touched edges
  • D12 Spring Security recipes-only at v1.0; no -security starter
  • D13 Reactor + Mutiny adapters at GA, not fast-follow
  • D14 Kotlin co-release at v1.0 as thin extension

Build / release:

  • D6 first Maven Central publish at v0.3 (OSSRH setup still happens Week 1 — slow path)
  • D7 jakarta only, Spring Boot 3.x floor
  • D8 mock-server CI sidecar via npx adcp mock-server
  • D15 ≤2 weeks spec-rev tracking SLO
  • D20 Sonatype namespace claim via DNS TXT verification

Repo conventions:

  • D16 design decisions land in specs/<topic>.md (AdCP convention), not docs/adr/
  • D17 trunk-based branching
  • D18 Conventional Commits + commitlint + Changesets (matches TS SDK)
  • D19 AAO IPR Bot replication (matches adcp, adcp-client, adcp-client-python, adcp-go) — no DCO, no CLA
  • D21 branch protection: 1 code-owner review, required build + IPR Policy / Signature checks

7.x parity deltas vs the RFC's 6.x baseline (in ROADMAP §7.x deltas)

The TS SDK has shipped to 7.2.0 since the RFC was authored. Highlights folded into the roadmap:

  • AuthenticationRequiredError.challenge + probeAuthChallenge (WWW-Authenticate parsing for non-Bearer 401s).
  • HTTP Basic auth (RFC 7617, auth-scheme).
  • resolveAgentProperties / validateAdAgents (ads.txt MANAGERDOMAIN one-hop fallback).
  • IDEMPOTENCY_IN_FLIGHT AdCP 3.1 wire code (replaces legacy SERVICE_UNAVAILABLE).
  • upstream-recorder (new artifact surface; producer-side reference middleware for the upstream_traffic storyboard check).
  • parallel_dispatch storyboard step + RunnerNotice / NoticeCode taxonomy.
  • Storyboard output shape split: storyboards_missing_tools vs. storyboards_not_applicable.
  • SSRF baseline as v0.1, not v1.x: DNS pin, address-guards, redirect: 'manual', 4 KiB probe body cap on every discovery probe.

Still open (kept honest in ROADMAP §Decisions wanted)

  • Funding / staffing (RFC feat: seed repo with Java SDK RFC, roadmap, and harness foundation #1) — contributed engineer at 50%+ for ~12 months
  • Named maintainer with post-GA merge rights
  • WG vote on Java as fourth officially supported language (recommend: at v0.1 alpha milestone)
  • 2–3 design partners (publisher / SSP / broadcaster middleware archetypes)
  • Cross-SDK lifecycle YAML buy-in (TS + Python maintainers, decides lifecycle track path 1 vs 2)
  • Foundation position on MIT-licensed deps (introduced by D9)
  • Two harness Week 1 prototype questions under D9: servlet streamable-HTTP without Jetty/Tomcat; Jackson 2 vs 3 module parity

Test plan

  • RFC content matches PR #4279 head (gh api verified).
  • All 15 ../docs/... relative links in the RFC rewritten to absolute github.com/adcontextprotocol/adcp/blob/main/... URLs.
  • ./gradlew build green locally on JDK 21.0.11 + Gradle 9.5.1.
  • ./gradlew build green on GH Actions (Temurin 21, cdf1c2f run 25824676945, 1m59s).
  • All 8 modules produce main + sources + javadoc JARs.
  • JAR manifests stamp Automatic-Module-Name correctly.
  • Wrapper validation (validate-wrappers: true) passes — supply-chain guard against tampered gradle-wrapper.jar.
  • CODEOWNERS triggers reviewer auto-add — verify after merge by opening a tiny follow-up PR.
  • @MichielDean confirmed as collaborator on adcontextprotocol/adcp-sdk-java.
  • AAO IPR Bot installed on this repo (foundation admin action per D19).
  • DNS TXT record added on adcontextprotocol.org for Sonatype namespace verification (foundation admin action per D20).

🤖 Generated with Claude Code

bokelley and others added 12 commits May 13, 2026 14:18
Brings the merged adcontextprotocol/adcp#4279 RFC into this repo as the
seed for implementation, alongside a contributor-facing roadmap that
divides the v0.1 → v1.0 work into 14 claimable tracks and lays out the
pre-contributor harness scope.

- docs/rfc/java-sdk-rfc.md — RFC text from the merged spec PR; relative
  ../docs/... links rewritten to absolute github.com/adcontextprotocol/adcp
  URLs since those targets live in the spec repo.
- ROADMAP.md — milestones, tracks, dependency graph, 7.x deltas vs. the
  RFC's 6.x baseline (auth challenge, HTTP Basic, upstream-recorder,
  IDEMPOTENCY_IN_FLIGHT, SSRF baseline as v0.1 not v1.x), confirmed
  post-RFC decisions D1-D5 (repo home, JDK 21 baseline, Maven coords
  group=org.adcontextprotocol artifact=adcp, Sigstore confirmed,
  @adcp/sdk/mock-server as the storyboard CI target).
- .github/CODEOWNERS — default review on every PR to @bokelley and
  @MichielDean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds four confirmed decisions to the post-RFC table and propagates them
through the body:

- D6 — first Maven Central publish at v0.3 (not v0.1); Sonatype OSSRH
  namespace + GPG setup still happens harness Week 1 since approval is
  the slow path. v0.1 and v0.2 ship local Gradle artifacts only.
- D7 — jakarta only / Spring Boot 3.x floor. SB 2.7 is 6 months past
  OSS EOL; no compat starter, no community 2.7 port.
- D8 — mock-server CI sidecar via `npx adcp mock-server`. Pinned
  @adcp/sdk version becomes the conformance oracle. Confirmed seven
  specialisms (signal-marketplace, creative-template, sales-guaranteed,
  sales-non-guaranteed, sales-social, sponsored-intelligence,
  creative-ad-server).
- D9 — io.modelcontextprotocol.sdk:mcp pinned 1.1.2. 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 thin Spring Boot wrappers on top. Two prototype questions remain
  for harness Week 1: servlet streamable-HTTP transport without
  Jetty/Tomcat, and Jackson 2 vs. 3 module feature parity. License is
  MIT — surfaced as a new open question (#9) for the foundation.

Resolves RFC Open Questions 2 and 6. Crosses out the resolved items in
Decisions Wanted; remaining open: funding/staffing, design partners, WG
vote, named maintainer, lifecycle YAML buy-in, Reactor/Mutiny/Kotlin GA
scope, MIT-dep position.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds twelve more confirmed decisions to the post-RFC table.

Protocol / architecture:
- D10 A2A pre-1.0 types: in-tree until a2aproject/a2a-java cuts ≥1.0.0
  (currently 1.0.0.Beta1 — pre-stable, package layout still churning).
- D11 TransitionGuard: guards declare touched edges; conformance harness
  fails if a sandbox account's guards narrow a storyboard edge.
- D12 Spring Security: recipes-only at v1.0; no separate -security
  starter. Revisit on v0.3 feedback.
- D13 Reactor + Mutiny adapters at GA, not fast-follow.
- D14 Kotlin co-release at v1.0 as a thin extension.
- D15 Spec-rev tracking: ≤2 weeks from spec rev to Java release.

Repo conventions (matched to existing AdCP family practice):
- D16 Design decisions filed in specs/<topic>.md, not docs/adr/. The
  Java SDK RFC itself lives at specs/java-sdk-rfc.md in the adcp repo;
  match that convention. ROADMAP table is the at-a-glance index; specs/
  doc only when the row isn't enough.
- D17 Trunk-based branching; semver tags from main.
- D18 Conventional Commits + commitlint + Changesets, matching TS SDK.
- D19 AAO IPR Bot pattern, not DCO. Replicates the same flow installed
  on adcp / adcp-client / adcp-client-python / adcp-go: contributors
  comment "I have read the IPR Policy" on first PR, App enforces via
  required status check. Harness Week 1 installs the bot on this repo
  and adds the ~15-line caller workflow.

Infra:
- D20 Sonatype OSSRH namespace claim for org.adcontextprotocol via DNS
  TXT verification (foundation adds the record). Maven Central confirms
  the namespace is currently unclaimed (zero artifacts).
- D21 Branch protection on main: 1 code-owner review, required CI
  checks including IPR Policy / Signature, no force-push.

Harness §Pre-contributor table updated to drop the ADR-directory item
(superseded by D16) and add IPR caller workflow, DNS-TXT, branch
protection, and commitlint/Changesets items.

Decisions wanted reduced to the three foundation-owned + two
cross-team items plus the MIT-dep position.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First piece of harness Week 1 work. Eight published artifacts wired
per D3 with the build graph in place; convention plugins centralize
the JDK-21 toolchain (D2) and shared compile/test config.

Modules (all building, all stamping Automatic-Module-Name):
- adcp                          main library: caller, types, schemas
- adcp-server                   agent-side: signing, idempotency, async
- adcp-testing                  storyboard runner, JUnit 5 fixtures
- adcp-spring-boot-starter      Spring Boot 3.x autoconfig (D7 jakarta)
- adcp-cli                      runnable jar (placeholder main today)
- adcp-reactor                  Project Reactor adapter (D13)
- adcp-mutiny                   SmallRye Mutiny adapter (D13)
- adcp-kotlin                   Kotlin coroutine + DSL extensions (D14)

Build-logic:
- adcp.java-base-conventions   JDK 21 toolchain, JSpecify on the compile
                               classpath, manifest stamping, lint+Werror
                               (minus -processing/-options to tolerate
                               package-info-only skeleton modules)
- adcp.java-library-conventions library plugin + JUnit 5 test wiring
- adcp.kotlin-library-conventions Kotlin variant for adcp-kotlin

Version catalog (gradle/libs.versions.toml) pins:
- io.modelcontextprotocol.sdk:mcp 1.1.2 (D9)
- Jackson 2.18.2 (RFC §JSON — >=2.15 floor for records support)
- com.networknt:json-schema-validator 1.5.6
- SLF4J 2.0.16, JSpecify 1.0.0, JUnit 5.11.4
- Spring Boot 3.4.4 (D7 — 3.x / jakarta only)
- Reactor 3.7.2, Mutiny 2.7.0, Kotlin 2.1.10, kotlinx-coroutines 1.10.1

Verified locally:
- `./gradlew build` green across all 8 modules
- JAR manifests show Automatic-Module-Name = org.adcontextprotocol.<dot>
- `./gradlew :adcp-cli:run` prints the placeholder usage stub
- All modules produce main + sources + javadoc JARs

CI (.github/workflows/ci.yml):
- JDK 21 Temurin via actions/setup-java
- gradle/actions/setup-gradle with validate-wrappers (supply-chain
  guard against tampered gradle-wrapper.jar)
- Runs ./gradlew build on every PR and push to main

This is the foundation everything else builds on. Next harness items
land on top: schema-bundle fetcher, codegen MVP, SSRF-safe HttpClient
wrapper, storyboard CI gate with @adcp/sdk/mock-server sidecar (D8).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CONTRIBUTING.md covers the AAO IPR comment ritual (per D19), dev setup,
the track-claim flow into ROADMAP.md, code conventions, Conventional
Commits + Changesets workflow, and the schema/codegen pointer.

CLAUDE.md gives coding agents the precedence order (D-decisions > RFC
> tracks), build commands, module layout, conventions, and a "don't do
this" list pulled from the locked decisions (no *Async mirrors, no
Spring Boot 2.7, no Bouncy Castle, no Optional<T> returns, no docs/adr/).

Issue templates:
- track-claim.yml — structured form: track ID, experience, availability,
  milestone, WG sync, open questions
- bug-report.yml — SDK version, JDK version, framework, repro
- config.yml — disables blank issues; links protocol questions to the
  spec site, design discussion to AdCP Slack, sister-SDK bugs to those
  repos

PR template prompts the IPR check, Conventional Commits, changeset
addition, and the standard ./gradlew build + test plan checklist.

.gitignore adds .claude/ and .context/ — coding-agent and Conductor
workspace side channels that shouldn't be committed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three workflows mirrored from adcp-client, matching the conventions
locked by D18 (Conventional Commits + Changesets) and D19 (AAO IPR
Bot pattern).

ipr-agreement.yml delegates to the reusable workflow at
adcontextprotocol/adcp/.github/workflows/ipr-check-callable.yml@main.
Signatures land in the central ledger at adcp:signatures/ipr-signatures.json
once the foundation admin (1) installs the AAO IPR Bot on this repo and
(2) scopes IPR_APP_ID + IPR_APP_PRIVATE_KEY org secrets to it.

commitlint.yml validates PR titles and all PR commits against the
Conventional Commits config in commitlint.config.js. Type enum,
header-max-length 120, and footer-leading-blank exception all match
the @adcp/sdk config so the two SDK changelogs read the same way.

changeset-check.yml requires a changeset on PRs that change adopter-
visible behavior. Skips for changeset-release/main automation branches.

package.json + package-lock.json define the npm-side tooling — explicit
"private: true", scoped to commitlint + changesets devDeps only. The SDK
itself is Java; this is the same shape adcp / adcp-client / adcp-go use
for their release-notes machinery.

.changeset/config.json points at the public Changesets schema with
baseBranch main, restricted access (Java artifacts don't publish to npm),
and the tools package ignored. README in the same directory explains
when contributors should add a changeset vs skip.

.gitignore adds node_modules/ — only for the Node-side tooling, the SDK
remains pure Java.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First piece of the 7.x SSRF baseline that ROADMAP §7.x deltas pinned
as a v0.1 release-gate requirement (not v1.x hardening). Lands the
address-guard half today; DNS-pin connect-binding and redirect handling
land on the transport track.

specs/ssrf-baseline.md is the design doc (per D16 — design notes live
in specs/, not docs/adr/). Covers the threat model, the four
mitigations (DNS-resolve-once, pin-connect, redirect:manual, body cap),
the full RFC-grounded block table, the harness/transport split, and
the references back to the TS SDK migration PRs.

adcp module gains org.adcontextprotocol.adcp.http with:

- SsrfPolicy — sealed interface; strict() is the v0.1 baseline,
  permissive() is opt-in for local dev (deliberately not env-driven so
  a misconfigured production deploy can't silently disable the guard).
- SsrfDecision — sealed Allow/Deny; Deny reasons describe ranges, not
  specific addresses, so the reason text doesn't leak host structure
  when echoed in logs.
- StrictSsrfPolicy — walks InetAddress's built-in range predicates
  (loopback / link-local / site-local / multicast / any-local) and
  layers in the JDK-not-covered cases by hand:
  - RFC 6598 CGN (100.64/10)
  - RFC 2544 benchmark (198.18/15)
  - RFC 6890 IETF protocol assignments (192.0.0/24)
  - Reserved class E (240/4)
  - IPv6 unique local (fc00::/7)
  - IPv4-mapped IPv6 (::ffff:a.b.c.d/96) — unmapped and re-evaluated
    against the v4 rules. NB: deliberately not using
    Inet6Address.isIPv4CompatibleAddress() because it matches the
    deprecated "::a.b.c.d" form (including ::1), which would cause
    loopback to be treated as 0.0.0.1 and pass the guard.
- PermissiveSsrfPolicy — every address allowed; documented opt-in only.

Tests cover 26 literal block-list addresses, four allowed public ones,
the no-host-structure-leak property, and the permissive policy's
allow-everything behavior. 35 tests, all green.

Build-logic gains junit-jupiter-params on the test classpath so
parameterized tests can express the block-list table compactly.

.gitignore picks up .kotlin/ (build cache from the Kotlin DSL).

The DNS-rebinding and redirect-follow integration tests are deferred to
the transport track per the spec doc's harness/track split table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `./gradlew :adcp:fetchSchemaBundle` — downloads the AdCP protocol
tarball at the version pinned in ADCP_VERSION (or via -PadcpVersion=X.Y.Z),
verifies SHA-256 and Sigstore signatures per
https://github.com/adcontextprotocol/adcp/blob/main/docs/reference/verifying-protocol-tarballs.mdx,
and extracts to build/schemas/.

The Sigstore verification matches the spec doc's invocation exactly:
- Identity regex pinned to release.yml@refs/(heads|tags)/.* on the adcp
  repo (matches the maintenance branches 3.0.x, 2.6.x; forward-compat
  for tag-triggered re-signing)
- OIDC issuer pinned to GitHub Actions' token endpoint
- cosign verify-blob fails the task if anything other than the AdCP
  release workflow produced the signature

Sidecars (.sha256, .sig, .crt) are confirmed live for versioned releases
on https://adcontextprotocol.org/protocol/{version}.* — verified
end-to-end locally against 3.0.11 with the local cosign binary.

ADCP_VERSION at the repo root pins 3.0.11 (current latest at time of
import). Same shape the TS SDK uses for its pin file. Bumping it is a
deliberate PR — D15 cadence (≤2 weeks spec-rev tracking).

-PskipCosign=true is a documented offline-dev escape hatch only; logs
a warning and is never silent. The convention is registered as
adcp.schema-bundle-conventions and applied to the adcp module today;
other modules can pick it up when they need raw schema access.

CI doesn't yet install cosign — that lands when the codegen track wires
fetchSchemaBundle as a dependency of compile. Today the task runs only
when explicitly invoked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First piece of the D8 storyboard CI gate. Adds:

- .github/workflows/storyboard.yml — boots `npx adcp mock-server
  sales-guaranteed --port 4500` as a sidecar process before running
  ./gradlew :adcp-testing:test. Waits up to 30s for the sidecar to
  respond on /, captures logs on failure, kills the PID on cleanup.
- adcp-testing/src/test/.../MockServerReachableTest.java — JUnit 5
  test gated on the ADCP_MOCK_SERVER_URL env var. Asserts the sidecar
  is reachable and responds <500. Locally the test is skipped (no env
  var); CI sets it via the workflow step. As the testing track lands
  StoryboardRunner, the runner replaces this one-line assertion while
  the workflow shape stays unchanged.
- package.json + package-lock.json: pin @adcp/sdk 7.2.0 as a devDep so
  `npm ci` brings the `adcp` CLI into the workflow's PATH. The pinned
  version is the conformance oracle — bumping it is a deliberate PR
  per D8.

The other six specialisms (signal-marketplace, sales-non-guaranteed,
sales-social, creative-template, sponsored-intelligence,
creative-ad-server) come online as the testing track adds storyboards
that exercise them; the workflow shape extends to a port-range pattern
(4500–4506) at that point.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…quest/Response)

First piece of the codegen track. Proves the architecture; the full
surface lands on Track 2 (L0 types & codegen).

What it does:
- JavaPoet-based generator (build-logic/src/main/kotlin/codegen/SchemaCodegen.kt)
  reads a JSON Schema file and emits one Java record.
- *Request types get a static `builder()` factory + a nested `Builder`
  class (per RFC §Type generation: *Request always has a builder).
- *Response types are records only, no builder.
- Required fields are non-null components; optional fields get
  @org.jspecify.annotations.Nullable.
- Snake_case schema names map to camelCase Java via @JsonProperty —
  the wire format never sees camelCase.
- JavaDoc generated from the schema's description + per-field
  descriptions as @param tags.
- @javax.annotation.processing.Generated annotation cites the source
  schema file.

MVP scope (2 schemas, both flat scalar):
- core/pagination-request.json → PaginationRequest
- core/pagination-response.json → PaginationResponse

Wired as a Gradle task `:adcp:generateSchemas` that depends on
`fetchSchemaBundle` (per D4). Output lands in
adcp/build/generated/sources/codegen/main/java/ and is added to the main
source set so compileJava picks it up. Not checked in — regenerated
from the pinned ADCP_VERSION every build.

Round-trip smoke test in adcp/src/test/.../GeneratedPaginationTest.java
covers:
- Builder produces a record that serializes snake_case
- camelCase Java names never leak to the wire
- Required field deserializes when present, nulls for optional
- Symmetric round-trip with all optional fields populated
- Unset optional fields default to null

4 codegen tests + 35 SSRF tests all green. 39 tests total in :adcp.

CI gets cosign installed via sigstore/cosign-installer@v3 in both ci.yml
and storyboard.yml so fetchSchemaBundle (and now compileJava) works
end-to-end on GitHub Actions.

Polymorphism (oneOf with discriminator), $ref resolution, nested
objects, arrays of complex types, format-asset-slot unions (per 7.x
deltas), and the rest of the generator surface — Track 2.

.gitignore picks up .local/ — coding-agent state side channel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… R1, R2)

Closes both prototype questions D9 left open for harness Week 1.

R1 — HTTP server transport without Jetty/Tomcat: **Yes.**
mcp-core 1.1.2 ships three framework-neutral server transport providers
in the JAR itself:

- HttpServletStreamableServerTransportProvider (current MCP spec)
- HttpServletSseServerTransportProvider (older SSE form)
- HttpServletStatelessServerTransport (stateless variant)
- StdioServerTransportProvider (no HTTP at all)

They compile against jakarta.servlet-api 6.x but don't depend on Jetty,
Tomcat, Undertow, or anything Spring. Adopters bring their own Servlet
container at runtime. mcp-spring-webmvc and mcp-spring-webflux exist as
optional artifacts for Spring-specific integration — we don't need
them. The 0.x line had a separate `server-servlet` artifact; 1.x folded
it into mcp-core itself.

R2 — Jackson 2 vs Jackson 3 module parity: **Both at 1.1.2, identical
cadence, neither lags.** Same surface; choice is which Jackson tree the
consumer's other deps use. We pick mcp-json-jackson2 because RFC §JSON
pins Jackson 2.15+. Pulling mcp-json-jackson3 would create a dual-
Jackson dep graph for adopters — exactly the class of problem RFC's
Jackson pin prevents.

Build wiring:
- gradle/libs.versions.toml — replaces `mcp` (the bundle, which pulls
  jackson3) with explicit mcp-core + mcp-json-jackson2 entries.
- adcp-server/build.gradle.kts — same swap; comments cite findings doc.

specs/mcp-prototype-findings.md is the full write-up — closes the open
questions per D16 (longer-form decisions in specs/).

Smoke test in adcp-server: 12 tests covering presence of the four
server transports, three client transports, three spec interfaces, the
stdio-no-servlet load path, and the Jackson 2 (not 3) classpath
assertion. Uses getResource(name + ".class") instead of Class.forName
because the servlet-extending classes need jakarta.servlet-api at
runtime — a compileOnly dep adopters provide. The contract we test is
"the SDK ships the class," not "we provide the adopter's runtime."

Full build green: 51 tests across :adcp (4 codegen + 35 SSRF + 12 MCP
imports). On JDK 21 + Gradle 9.5.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
D9's two prototype questions are answered in
specs/mcp-prototype-findings.md and the row in §Confirmed decisions
now points at the findings instead of leaving them open. Status table
gains a "Confirmed decisions D1-D21 locked" row and the pre-contributor
harness item moves to 🟡 In progress with a one-liner of what's landed
vs the foundation-admin items still outstanding (IPR Bot install,
DNS TXT for Sonatype, @MichielDean collaborator).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley changed the title Seed repo: Java SDK RFC + contributor roadmap + CODEOWNERS feat: seed repo with Java SDK RFC, roadmap, and harness foundation May 13, 2026
@bokelley
bokelley merged commit 7a774da into main May 13, 2026
4 of 6 checks passed
@bokelley
bokelley deleted the bokelley/rfc-import-impl-plan branch May 13, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant