Skip to content

Follow semver, or document that rmcp doesn't follow it #813

Closed

Description

@jh-block

There have been multiple breaking changes in 1.x releases (fields added to pub structs, structs marked non-exhaustive, etc), which means projects depending on rmcp can introduce build failures just by running cargo update. Based on the typical semver approach taken by Rust crates, each of these should have been a new major version.

If rmcp has a different policy than following semver, it would be good to document that clearly so that people can be aware of the risk and consider pinning the version more precisely than the default caret requirement.

Activity

  1. alexhancock commented on Apr 20, 2026

    @alexhancock
    Contributor

    Yeah let's discuss!

    Our plan after #715 and associated followups and the move to 1.0 was to use release-plz (which uses https://crates.io/crates/cargo-semver-checks) to follow semver in the standard way, but if we've shipped things that should have been majors and weren't it seems like a miss to me.

    Adding fields to pub structs as long as they are optional should in theory be OK if the struct has appropriate constructors etc. This was the plan with non_exhaustive and new new_with_X constructors. But let's find where we've been missing.

    @DaleSeo @jamadeo Do you have opinions/views?

  2. jh-block commented on Apr 20, 2026

    @jh-block
    ContributorAuthor

    Really good to know that following semver is a goal. To ground it a bit, the main breaking change I noticed (these caused a build failure after cargo update in goose, and also a packaging failure for Fedora) was that v1.3.0 marked a lot of pub structs as non_exhaustive (this is a breaking change, since any existing struct literals now fail to compile until they are modified to deal with possible future extra fields), e.g. PromptContext: rmcp-v1.2.0...rmcp-v1.3.0#diff-4a77e2940c44e190cc85d449d090c1ef6f46e61f161af436d6447956448dbe97R23 (there are a lot more in that same diff, any addition of #[non_exhaustive] to a pub struct where all fields are pub is a breaking change).

    There was also breaking change with the macros; there was some code in a goose test that (possibly erroneously) used the tool_handler attribute macro without the router argument, and it built correctly on 1.2.0 but failed to build on 1.5.0.

    The PR where I updated rmcp in goose is here, in case the build logs and commits adapting to the breaking changes are helpful

  3. DaleSeo commented on Apr 21, 2026

    @DaleSeo
    Member

    Thanks for bringing this up, @jh-block! Your feedback is helpful to understand the impact of breaking changes.

    @alexhancock That was the plan but we noticed some structs/enums were missing #[non_exhaustive] and constructors after the v1.0 release and ended up backfilling those in a couple of follow-up PRs.

    I also remember we discussed this internally and realized that Rust presents unique challenges compared to other languages when supporting a rapidly evolving MCP spec. Our concern was that strict SemVer might lead us to version fatigue (e.g., hitting v10 in a few months), which can be a frustrating experience for the ecosystem in its own way. So, we were learning towards not following semver strctly. @jamadeo Please correct me if I'm mistaken.

    Said that, I feel like #[non_exhaustive] will stabilize the API for the long haul and the release-plz setup will help us at least catch breaking changes before shipping. So, we'll be able to document when any deviations from semver with rationale in the release notes.

  4. linked a pull request that will close this issueci: add semver check job for pull requests #819on Apr 21, 2026
  5. DaleSeo commented on Apr 21, 2026

    @DaleSeo
    Member

    As a quick follow-up, I opened #819 to check semver in PRs. Should help prevent breaking changes ealrier in the process.

  6. alexhancock commented on Apr 21, 2026

    @alexhancock
    Contributor

    Nice @DaleSeo I have taken that change in!

    I remember that conversation but perhaps didn't have a clear preference, or didn't voice it well enough at the time.

    Thinking about it now, I think we should just do semver the standard way even if means the version numbers run up quickly. Because the alternative feels like we do breaking changes anyway but the versioning is misaligned with the way those changes are usually communicated (with major version number bumps). This carries its own risk of fatiguing the community.

  7. jh-block commented on Apr 21, 2026

    @jh-block
    ContributorAuthor

    Yeah, I think it's a bigger fatigue to need to think about versioning differently for one dependency than to have large major version numbers. I'd rather be able to use the default caret version constraint, be able to freely cargo update without breaking the build, and get PRs from dependabot/etc when there's a new major version, where any breaking changes can be easily evaluated and dealt with.

    If a dep doesn't follow semver in the standard way, then I have to read and understand what they are doing instead, and choose a different version constraint (e.g. an exact match, or a tilde constraint so that I can still get patch-level updates) to match their policy. And, more likely, if I don't notice at first that they don't follow semver and leave it on the default version constraint, my build just breaks unexpectedly at some point.

    If doing standard semver means that the major version gets to v10, I would just take that as an indicator that the 0.x -> 1.0 transition maybe happened too early in the life of the project (this issue is exactly why the special semver rules for 0.x.y exist in Rust), but it doesn't matter in any real sense.

  8. DaleSeo commented on Apr 22, 2026

    @DaleSeo
    Member

    @alexhancock @jh-block Agreed. We'll make sure to follow semver moving forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions