|
| 1 | +# Breaking Change Classification Guide |
| 2 | + |
| 3 | +This guide defines how to identify and classify breaking changes in the C# MCP SDK. It is derived from the [dotnet/runtime breaking change guidelines](https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/breaking-changes.md). |
| 4 | + |
| 5 | +## Two Categories of Breaking Changes |
| 6 | + |
| 7 | +### API Breaking Changes (Compile-Time) |
| 8 | +Changes that alter the public API surface in ways that break existing code at compile time: |
| 9 | + |
| 10 | +- **Renaming or removing** a public type, member, or parameter |
| 11 | +- **Changing the return type** of a method or property |
| 12 | +- **Changing parameter types, order, or count** on a public method |
| 13 | +- **Sealing** a type that was previously unsealed (when it has accessible constructors) |
| 14 | +- **Making a virtual member abstract** |
| 15 | +- **Adding `abstract` to a member** when the type has accessible constructors and is not sealed |
| 16 | +- **Removing an interface** from a type's implementation |
| 17 | +- **Changing the value** of a public constant or enum member |
| 18 | +- **Changing the underlying type** of an enum |
| 19 | +- **Adding `readonly` to a field** |
| 20 | +- **Removing `params` from a parameter** |
| 21 | +- **Adding/removing `in`, `out`, or `ref`** parameter modifiers |
| 22 | +- **Renaming a parameter** (breaks named arguments and late-binding) |
| 23 | +- **Adding the `[Obsolete]` attribute** or changing its diagnostic ID |
| 24 | +- **Adding the `[Experimental]` attribute** or changing its diagnostic ID |
| 25 | +- **Removing accessibility** (making a public/protected member less visible) |
| 26 | + |
| 27 | +### Behavioral Breaking Changes (Runtime) |
| 28 | +Changes that don't break compilation but alter observable behavior: |
| 29 | + |
| 30 | +- **Throwing a new/different exception type** in an existing scenario (unless it's a more derived type) |
| 31 | +- **No longer throwing an exception** that was previously thrown |
| 32 | +- **Changing return values** for existing inputs |
| 33 | +- **Decreasing the range of accepted values** for a parameter |
| 34 | +- **Changing default values** for properties, fields, or parameters |
| 35 | +- **Changing the order of events** being fired |
| 36 | +- **Removing the raising of an event** |
| 37 | +- **Changing timing/order** of operations |
| 38 | +- **Changing parsing behavior** and throwing new errors |
| 39 | +- **Changing serialization format** or adding new fields to serialized types |
| 40 | + |
| 41 | +## Classification Buckets |
| 42 | + |
| 43 | +### Bucket 1: Clear Public Contract Violation |
| 44 | +Obvious breaking changes to the public API shape. **Always flag these.** |
| 45 | + |
| 46 | +### Bucket 2: Reasonable Grey Area |
| 47 | +Behavioral changes that customers would have reasonably depended on. **Flag and discuss with user.** |
| 48 | + |
| 49 | +### Bucket 3: Unlikely Grey Area |
| 50 | +Behavioral changes that customers could have depended on but probably wouldn't (e.g., corner case corrections). **Flag with lower confidence.** |
| 51 | + |
| 52 | +### Bug Fixes (Exclude) |
| 53 | +Changes that correct incorrect behavior, fix spec compliance, or address security issues are **not breaking changes** even if they alter observable behavior. Examples: |
| 54 | +- Fixing encoding to match a specification requirement |
| 55 | +- Correcting a logger category or metric name that was wrong |
| 56 | +- Fixing exception message leaks that were a security concern |
| 57 | +- Moving data to the correct location per protocol spec evolution |
| 58 | +- Setting a flag that should have been set automatically (e.g., `IsError` for error content) |
| 59 | +- Returning a more specific/informative exception for better diagnostics |
| 60 | + |
| 61 | +If a change is primarily a bug fix or spec compliance correction, exclude it from the breaking changes list even though the observable behavior changes. |
| 62 | + |
| 63 | +### Bucket 4: Clearly Non-Public |
| 64 | +Changes to internal surface or behavior (e.g., internal APIs, private reflection). **Generally not flagged** unless they could affect ecosystem tools. |
| 65 | + |
| 66 | +## SDK Versioning Policy |
| 67 | + |
| 68 | +The classification rules above are derived from the dotnet/runtime breaking change guidelines, but the MCP SDK has its own versioning policy (see `docs/versioning.md`) that provides additional context for classification decisions. |
| 69 | + |
| 70 | +### Pre-1.0 Preview Status |
| 71 | + |
| 72 | +Prior to a stable 1.0.0 release, the SDK is in preview and breaking changes can be introduced without prior notice. This does **not** change how breaks are classified — they should still be flagged, labeled, and documented — but it affects the **severity assessment**. Preview consumers expect breaks, so migration guidance matters more than avoidance. |
| 73 | + |
| 74 | +### Experimental APIs |
| 75 | + |
| 76 | +APIs annotated with `[Experimental]` (using `MCP`-prefixed diagnostic codes) can change at any time, including within PATCH or MINOR updates. Changes to experimental APIs should still be **noted** in the audit, but classified as **Bucket 3 (Unlikely Grey Area)** or lower unless the API has been widely adopted despite its experimental status. |
| 77 | + |
| 78 | +### Obsoletion Lifecycle |
| 79 | + |
| 80 | +The SDK follows a three-step obsoletion process: |
| 81 | + |
| 82 | +1. **MINOR update**: API marked `[Obsolete]` producing _build warnings_ with migration guidance |
| 83 | +2. **MAJOR update**: API marked `[Obsolete]` producing _build errors_ (API throws at runtime) |
| 84 | +3. **MAJOR update**: API removed entirely (expected to be rare) |
| 85 | + |
| 86 | +When auditing, classify each step appropriately: |
| 87 | +- Step 1 (adding `[Obsolete]` warning) → API breaking change (new build warning) |
| 88 | +- Step 2 (escalating to error) → API breaking change (previously working code now fails) |
| 89 | +- Step 3 (removal) → API breaking change; migration guidance should note prior deprecation |
| 90 | + |
| 91 | +In exceptional circumstances — especially during the pre-1.0 preview period — the obsoletion lifecycle may be compressed (e.g., marking obsolete and removing in the same MINOR release). This should still be flagged as a breaking change but the migration guidance should explain the rationale. |
| 92 | + |
| 93 | +### Spec-Driven Changes |
| 94 | + |
| 95 | +Breaking changes necessitated by MCP specification evolution should be flagged and documented normally, but the migration guidance should reference the spec change. If a spec change forces an incompatible API change, preference is given to supporting the most recent spec version. |
| 96 | + |
| 97 | +## Compatibility Switches |
| 98 | + |
| 99 | +When a breaking change includes an `AppContext` switch or other opt-in/opt-out mechanism, always note it in the migration guidance. Search for `AppContext.TryGetSwitch`, `DOTNET_` environment variables, and similar compat patterns in the diff. Include the switch name and the value that alters the behavior: |
| 100 | + |
| 101 | +``` |
| 102 | +* Compat switch: `ModelContextProtocol.AspNetCore.AllowNewSessionForNonInitializeRequests` = `true` restores previous behavior |
| 103 | +``` |
| 104 | + |
| 105 | +## What to Study for Each PR |
| 106 | + |
| 107 | +For every PR in the range, examine: |
| 108 | + |
| 109 | +1. **PR description** — Authors often describe breaking changes here |
| 110 | +2. **Linked issues** — May contain discussion about breaking impact |
| 111 | +3. **Review comments** — Reviewers may have flagged breaking concerns |
| 112 | +4. **Code diff** — Look at changes to: |
| 113 | + - Public type/member signatures |
| 114 | + - Exception throwing patterns |
| 115 | + - Default values and constants |
| 116 | + - Return value changes |
| 117 | + - Parameter validation changes |
| 118 | + - Attribute changes (`[Obsolete]`, `[Experimental]`, etc.) |
| 119 | + - `AppContext.TryGetSwitch` or environment variable compat switches |
| 120 | +5. **Labels** — Check if `breaking-change` is already applied |
0 commit comments