Repository navigation
fix(acp)!: version-neutral wire envelopes and extensible proxy types - #478
Merged
Merged
Conversation
RawJsonRpcMessage::Notification wrapped the schema crate's v1::Notification<RawJsonRpcParams>, unlike its Request and Response variants. It now holds the SDK's own RawJsonRpcNotification with the same method and params fields. The wire format is unchanged. The raw envelope types also gain Eq, RawJsonRpcMessage gains PartialEq/Eq and From conversions from each envelope, and the rustdoc states that unknown request and notification envelope members are dropped. BREAKING CHANGE: RawJsonRpcMessage::Notification now holds RawJsonRpcNotification instead of schema::v1::Notification<RawJsonRpcParams>. Co-Authored-By: Claude <noreply@anthropic.com>
SuccessorMessage was an exhaustive struct with public fields and no constructor, so the proxy protocol could not add a field (the proxy-chains RFD already mentions a possible `peer`) without a major release. It is now `#[non_exhaustive]`, with `SuccessorMessage::new(message)` and a `.meta(..)` builder. `meta` is typed as a JSON object, matching ACP `_meta`, and the non-spec `meta` alias is no longer read. `schema::v1::InitializeProxyRequest` and `schema::v2::InitializeProxyRequest` are `#[non_exhaustive]` too; they already have `new()` and `From<InitializeRequest>`. Proxies now unwrap incoming `proxy/successor` envelopes with `json_cast_params`, so malformed envelope params are answered with Invalid params (-32602) instead of Parse error (-32700). BREAKING CHANGE: SuccessorMessage, schema::v1::InitializeProxyRequest and schema::v2::InitializeProxyRequest are #[non_exhaustive]; build them with `new()`. SuccessorMessage::meta is Option<serde_json::Map<String, Value>> and the `meta` alias for `_meta` is no longer accepted. Co-Authored-By: Claude <noreply@anthropic.com>
The v1 dispatch enum macros stripped the leading `_` from extension methods, so a parsed `_vendor/x` reported and re-sent `vendor/x` and the peer answered -32601. They now keep the wire method name, as the v2 macros do. The v1 and v2 dispatch enum macros also delegate `JsonRpcMessage::method` to the schema enum's inherent `method()`, so variants the macro does not list are sent with their real method name instead of `"_unknown"`. BREAKING CHANGE: `ExtMethodRequest` / `ExtNotification` values parsed by the v1 dispatch enums now carry the full `_`-prefixed method name. Co-Authored-By: Claude <noreply@anthropic.com>
MCP_SERVER_UNAVAILABLE and MCP_BACKEND_FAILURE were bare i32 constants, unlike every other SDK error code. They are now ErrorCode constants, and MCP_RESOURCE_LIMIT_EXCEEDED adds the RFD's -33000 code. BREAKING CHANGE: mcp_server::MCP_SERVER_UNAVAILABLE and mcp_server::MCP_BACKEND_FAILURE are ErrorCode instead of i32. Co-Authored-By: Claude <noreply@anthropic.com>
…rate The derive macros called the public `util::json_cast` and `util::json_cast_params`, and the core crate required the derive crate with a caret requirement. A newer derive could emit calls the resolved core version lacks, and the util helpers could not change without breaking derived impls. The derive output now calls `__private::json_cast*`, and the core crate depends on the derive crate released with it exactly. Co-Authored-By: Claude <noreply@anthropic.com>
`util::internal_error` and `util::parse_error` duplicated the `Error` constructors; the SDK keeps a crate-private `internal_error` for its own use. `util::TypeNotification` duplicated `MatchDispatch::if_notification`. `util::json_cast` now documents that it is not for incoming params, which take `json_cast_params`. BREAKING CHANGE: `util::internal_error`, `util::parse_error` and `util::TypeNotification` are removed. Use `Error::internal_error().data(..)`, `Error::into_internal_error`, `Error::parse_error()` and `MatchDispatch::new(Dispatch::Notification(message))`. Co-Authored-By: Claude <noreply@anthropic.com>
…g the message A proxy/successor whose envelope _meta is not an object now has that _meta ignored, as the schema crate does for _meta, instead of failing the whole forwarded message with -32602. The conductor uses Error::into_internal_error in place of hand-written closures, and the migration guide describes how to compare MCP error codes with ErrorCode. Co-Authored-By: Claude <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the pre-5.0.0 public API cleanup. This PR covers the wire envelopes, the schema dispatch enums, the proxy protocol types, and the derive-to-core contract.
Addressed
RawJsonRpcMessage::Notificationnow holds an SDK-ownedRawJsonRpcNotificationinstead ofschema::v1::Notification<RawJsonRpcParams>. The wire format does not change.SuccessorMessageis#[non_exhaustive]and gainsnew(message)and a.meta(..)builder._metais typed asOption<serde_json::Map<String, Value>>, and the non-specmetaalias is no longer read.schema::v1::InitializeProxyRequestandschema::v2::InitializeProxyRequestare also#[non_exhaustive].proxy/successorparams withjson_cast_params, so malformed params get -32602 instead of -32700. The duplicateutil::internal_errorandutil::parse_errorare removed. Theutil::json_castdocs now say it is not for inbound params._on extension methods, as v2 already does. A v1 regression test is added.method()to the schema enum, so variants the macro doesn't list are sent with their real method name instead of"_unknown".MCP_SERVER_UNAVAILABLEandMCP_BACKEND_FAILUREareErrorCodeconstants. AddsMCP_RESOURCE_LIMIT_EXCEEDED(-33000).agent_client_protocol::__private::json_cast*instead of publicutilhelpers. The workspace pins the derive crate exactly (=3.6.0). I checked this with release-plz 0.4.2:release-plz set-versionrewrites the pin to=5.0.0and keeps the=operator. Both crates are in theacpversion_group, so they always get the same version and the pin stays in sync.Eq.RawJsonRpcMessagegainsPartialEq/EqandFromconversions from each envelope.util::TypeNotification. UseMatchDispatch::if_notificationinstead.Every breaking change has a section in
md/migration-v5.md.Skipped
ComponentIndexderives: fix(conductor)!: narrow the conductor API and fix multi-version chains #475 (cleanup-conductor) makesComponentIndexpub(crate)and adds the derives there, so it is left out here to avoid a conflict.Checks
These were run locally on this head:
cargo fmt --check-D warnings)cargo hack checkover the feature powerset at depth 2cargo test --workspace --all-features --lockedcargo test -p agent-client-protocol --no-default-featurescargo docwith-D warningsfor the core, derive, and conductor cratesmdbook buildAll passed except one target.
agent-client-protocol-derive --libaborts at load time (dyld) under the local build-cache runner. The same thing happens onmain, so it is not caused by this change.Review follow-up (3c913a5)
proxy/successorwhose envelope_metais not an object now has that_metaignored, matching how the schema crate treats_meta, instead of failing the forwarded message with -32602.Error::into_internal_error.error.code == MCP_BACKEND_FAILURE, with.value()where ani32is needed.release-plz updateon a scratch clone. It rewrote the derive pin from=3.6.0to=5.0.0and moved core and derive to 5.0.0 together.