Skip to content

SEP-1575: Tool Semantic Versioning #1575

Closed

Description

@malaykurwa

Title: Tool Semantic Versioning
Author: Malay Kurwa (@malaykurwa), Anu Sreepathy (@asreepathy), Pramod Narasimha (@pramod79)
Status: Proposal
Type: Standards Track
Created: 2025-09-29

Abstract

This SEP introduces a mechanism for versioning MCP (Model Context Protocol) Tools and allows MCP Clients to specify the version constraints of the tools they are designed to work with. By adding a version metadata field to tool definitions and a tool_requirements field to client requests, this proposal aims to prevent breakages caused by un-versioned, dynamic tool updates. The proposed versioning scheme is based on Semantic Versioning (SemVer 2.0.0), and the dependency specification syntax is inspired by modern package managers like Poetry and npm.

Motivation

Currently, the MCP specification lacks a formal versioning system. Tools can be updated on the server-side at any time, with changes ranging from minor patches to significant, breaking alterations in functionality. This presents several critical problems:

  1. Instability: A client developed against a specific version of a tool may fail unexpectedly if the tool is updated with a breaking change.
  2. Lack of Reproducibility: It is difficult to guarantee a consistent execution environment for a client, as the underlying tools it depends on can change without notice.
  3. No Opt-in for Updates: Clients have no mechanism to specify their compatibility, meaning they are always subject to the "latest" version of a tool, for better or worse.

This SEP addresses these issues by establishing a clear contract between the tool provider and the client, ensuring that clients can operate against a known and compatible set of tools.

Specification

This proposal introduces two primary changes: a new metadata field for tool definitions and a new property for client requests.

1. Tool-Side: Version Declaration

A new optional field, version, MUST be added to the tool's definition metadata, typically returned via the tools/list endpoint.

  • Field: version
  • Type: string
  • Format: The version string MUST adhere to the Semantic Versioning 2.0.0 standard (e.g., MAJOR.MINOR.PATCH). Examples: "1.2.3", "2.0.0", "0.1.0-alpha.1".

Example Tool Definition:

{  
  "name": "image_generator",  
  "description": "Generates an image from a text prompt.",  
  "version": "2.1.0", 
  "inputSchema": {
    "type": "object",  
    "properties": {  
      "prompt": {  
        "type": "string",  
        "description": "The text prompt to generate an image from."  
      }  
    },  
    "required": ["prompt"] 
  }      
}

2. Client-Side: Version Requirement Specification

A new optional field, tool_requirements, MAY be added to the client's request object when making a tool call.

  • Field: tool_requirements
  • Type: object
  • Format: A key-value map where the key is the tool name (string) and the value is a version specifier (string).

The version specifier string SHOULD follow the conventions established by modern package managers. The following operators MUST be supported:

  • Caret (^): Allows non-breaking updates. ^1.2.3 is equivalent to >=1.2.3 <2.0.0.
  • Tilde (~): Allows patch-level updates. ~1.2.3 is equivalent to >=1.2.3 <1.3.0.
  • Comparison Operators: >, >=, <, <=
  • Exact Version: A version number without any operator (e.g., "1.2.3").

Example Client Request:

{  
  "prompt": "Generate an image of a cat wearing a hat.",  
  "tool_requirements": {  
    "image_generator": "^2.0.0",  
    "data_analyzer": "~1.4.1"  
  }  
}

3. Protocol Flow and Validation

The interaction between client and server for version validation MUST follow this sequence:

  1. Tool Discovery: The client fetches the list of available tools from the server (e.g., via tools/list). The server response SHOULD include the version field for each tool that has one.
  2. Client-Side Pre-validation (Recommended): Before making a tool call, the client SHOULD evaluate the available tool versions against its tool_requirements. This allows the client to identify potential mismatches early and adjust its strategy without making a failing request.
  3. Tool Call with Requirements: The client sends the tool call request, including the tool_requirements object. This object serves as the definitive, authoritative requirement for the server to validate.
  4. Server-Side Validation (Mandatory): Upon receiving a request with tool_requirements, the server MUST perform the following validation before execution:
    • For each key (tool name) in the tool_requirements object, the server MUST check if it has a version of that tool that satisfies the specified version constraint.
    • If multiple versions satisfy a constraint, the server MUST select the latest, stable version that satisfies it. Pre-release versions (e.g., 1.2.4-beta.1) should only be selected if explicitly allowed by the constraint.
    • If all constraints are satisfied, the server proceeds with execution using the selected tool versions.
    • If any constraint cannot be satisfied, the server MUST NOT execute the tool call and MUST return an error.
sequenceDiagram  
    participant Client  
    participant Server

    %% Step 1: Tool Discovery  
    Client->>Server: GET /tools/list  
    Server-->>Client: 200 OK (List of tools with versions)

    %% Step 2: Client-Side Pre-validation  
    Note over Client: (Recommended) Pre-validates<br />tool versions against its requirements

    %% Step 3: Tool Call  
    Client->>Server: POST /tool/call (with tool_requirements)

    %% Step 4: Server-Side Validation & Execution  
    activate Server  
    Note over Server: (Mandatory) Validates tool_requirements  
    alt Requirements Satisfied  
        Server-->>Client: 200 OK (Tool call result)  
    else Requirements Not Satisfied  
        Server-->>Client: ERROR (UNSATISFIED_TOOL_VERSION)  
    end  
    deactivate Server
Loading

4. Error Handling

If server-side validation fails, the server MUST return an error response with a specific error code. This SEP proposes a new error type for this purpose.

  • Error Code: UNSATISFIED_TOOL_VERSION
  • Error Message: The response body SHOULD include a detailed message explaining which tool's version requirement could not be met.

Example Error Response:

{  
  "error": {  
    "code": "UNSATISFIED_TOOL_VERSION",  
    "message": "Tool requirement for 'data_analyzer' (~1.4.1) could not be satisfied. Available versions: [1.3.2, 2.0.0]"  
  }  
}

Backwards Compatibility

This proposal is designed to be fully backwards compatible:

  • Un-versioned Tools: If a tool definition does not include a version field, it will only satisfy a request that does not specify a version for that tool (or uses a wildcard * specifier).
  • Legacy Clients: If a client request does not include the tool_requirements field, the server MUST default to providing the latest stable version of the requested tools, preserving existing behavior.

Rationale

  • Explicit Validation Flow: The specified protocol flow removes ambiguity. It defines a recommended client-side check and a mandatory server-side validation, ensuring that version constraints are always enforced.
  • SemVer: Adopting Semantic Versioning is the industry standard, providing a clear framework for communicating the nature of changes.
  • Familiar Syntax: Aligning with specifiers like ^ and ~ lowers the learning curve for developers by leveraging existing best practices.
  • Actionable Errors: A specific error code and detailed message allow clients to implement robust error handling and provide clearer feedback to users or developers.

Activity

  1. changed the title [-]Tool Semantic Versioning[/-] [+]SEP-1575: Tool Semantic Versioning[/+] on Sep 30, 2025
  2. pja-ant commented on Oct 6, 2025

    @pja-ant
    Contributor

    It seems that the proposal only returns a single tool version in tools/list but then in the server validation section it seems to allow for the server to have multiple available versions. However, if that's the case then client pre-validation can't really work since it only knows about the one version returned in tools/list?

    Perhaps tools/list request should contain the tools requirements and it returns a list of tools that satisfies those requirements? Would need to think through the implications on tool list updates though.

    Have you also considered versioning at the server level rather than tool? I think that might actually be necessary since different tools on the same server may interact in non-trivial ways (particularly stateful servers). Prompts may also reference tools, etc. - I do see the value at versioning at the tool level (would be a shame to bump a version on the server just because a single tool changed its API), but versioning at the tool level feels like the equivalent of trying to version a library at the function level: probably works for libraries that are just collections of pure functions, but perhaps not in general.

  3. bdoyle0182 commented on Oct 15, 2025

    @bdoyle0182

    I 100% agree with having server level versioning, but not sure I agree with the reasoning for tool or primitive level versioning. Having tool level versions will become unwieldy to manage, getting clients to upgrade over time so you can deprecate old versions will be more difficult to track, etc.

    As @pja-ant mentioned tools within a server can be tightly coupled and have dependencies on each other. I don't think having a change to the api contract of a single tool resulting in a server release is a big deal. If I were managing a piece of software that runs a web server and I changed the contract of one of the api's, I would have to update the server's version. The consumer that wants to run the server live is then responsible for how they want to roll that out. My personal opinion, this is an area where I don't think we need to reinvent the wheel on how to manage client / server relationship and change management and do what's worked for decades.

    If you feel differently, it would help to add more detail in the SEP explaining why MCP has different needs than the traditional web server model and has a unique requirement for more granular versioning.

  4. a-akimov commented on Oct 16, 2025

    @a-akimov
    Contributor

    I also agree with @bdoyle0182 - versioning at the tool level will make it very difficult to maintain compatibility and will create too many varations of tools&versions&mcp cleints. In my experience, it's much better to have versioning at the MCP server level, not lower. A similar problem exists in the API world, and usually the approach is to version the whole API/service, not every API endpoint.

  5. minherz commented on Dec 22, 2025

    @minherz

    It would make sense to discuss versioning of all primitives and not only for tools. Resources and prompts can benefit from versioning too.

    The proposal implicitly assumes that versioning is incremental only and tools are independent. I agree that tools within a server can be coupled although it seems to be a bad design in my opinion.
    I think that having primitive versions as a part of the protocol make sense as long as the protocol itself doesn't enforce version management. If a caller implements custom logic to not use the tool if specific version requirements do not met, it should be implementer's decision and not the protocol standard.

    Looking at the discussion about versioning for MCP server instead of per-tool, it is unclear how this is different from versioning of any software release. Would it mean that all primitives exposed by the server attribute the same version number in the */list calls?

  6. sep-automation-bot commented on Feb 23, 2026

    @sep-automation-bot

    Friendly Reminder

    Hi @malaykurwa!

    This SEP proposal has been inactive for 146 days.

    We wanted to check in:

    • Are you still working on this proposal?
    • Is there anything blocking progress?
    • Do you need help finding a sponsor?

    If this proposal is no longer being pursued, please let us know and we can close it. Otherwise, any update on the current status would be appreciated!


    This is an automated message from the SEP lifecycle bot.

  7. dgenio commented on Feb 28, 2026

    @dgenio

    Context: I filed python-sdk#1667 (version-aware discovery) and python-sdk#1681 (versioned tool layout patterns), both closed by SDK maintainers as dependent on this SEP landing first. Sharing practical data from auditing our MCP server template across 5 client implementations.

    I agree with @pja-ant and @bdoyle0182 that server-level versioning should be the primary contract. Tool-level versioning with full constraint resolution (caret, tilde, ranges) adds significant complexity for a problem the ecosystem isn't ready to solve at that granularity.

    Here's why — real client ecosystem data:

    We audited 5 MCP clients for version metadata support:

    • FastMCP: ✅ Full support (native version= param, stored in _meta.fastmcp.version)
    • OpenAI Agents SDK: ⚠️ Partial (supports tool_meta_resolver but doesn't surface versions natively)
    • Google ADK: ❌ No support (_meta used only for OTel tracing, not surfaced to consumers)
    • LlamaIndex: ❌ No support (strips all metadata during tool conversion)
    • Pipecat: ❌ No support (extracts only name, description, inputSchema)

    Result: 20% full support. The ecosystem isn't ready for constraint-based version resolution when 80% of clients can't even see a version field. The proposal currently writes a complex dependency resolution spec for clients that discard all metadata.

    What's working today in practice:

    In production, we use the _vN naming convention (e.g., get_driver_info_v2) because it's the only approach that works across all clients — the version is encoded in the tool name itself. It's ugly but universally compatible.

    FastMCP already implements native tool versioning via _meta.fastmcp.version and _meta.fastmcp.versions — this proves the concept works at tool level, but it's proprietary and invisible to non-FastMCP clients.

    Suggestion — a phased approach:

    1. Phase 1 (Server-level): Add a server_version field available during initialization/capability negotiation. This addresses @pja-ant's point about coupled tools and gives clients a clear contract. This is what traditional APIs do and it works.
    2. Phase 2 (Informational tool-level): Add an optional version field to Tool definitions as informational metadata only — no constraint resolution, no tool_requirements, no caret/tilde operators. Just a field that says "this tool is version 2.1.0". Clients can use it for display, logging, and decision-making.
    3. Phase 3 (Constraint resolution): Only after the ecosystem matures and clients actually surface version info, consider the full tool_requirements constraint resolution system proposed here.

    This phased approach lets the protocol evolve incrementally while delivering immediate value (Phase 1) without over-engineering for a client ecosystem that isn't ready (Phase 3).

    As @minherz noted, this should also consider all primitives (resources, prompts), not just tools. The same versioning gaps apply across the board.

  8. sep-automation-bot commented on Jun 1, 2026

    @sep-automation-bot

    Friendly Reminder

    Hi @malaykurwa!

    This SEP proposal has been inactive for 90 days.

    We wanted to check in:

    • Are you still working on this proposal?
    • Is there anything blocking progress?
    • Do you need help finding a sponsor?

    If this proposal is no longer being pursued, please let us know and we can close it. Otherwise, any update on the current status would be appreciated!


    This is an automated message from the SEP lifecycle bot.

  9. localden commented on Jun 26, 2026

    @localden
    Contributor

    Thank you for the work here. Closing, as this SEP is now classified as dormant, per guidelines. If in the future there is any desire to revisit this proposal, we recommend starting with our contributor Discord to gauge community interest and support.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions