Skip to content

Commit 856362b

Browse files
authored
Merge branch 'modelcontextprotocol:main' into main
2 parents ceefc46 + 4140c6d commit 856362b

File tree

64 files changed

+2641
-304
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2641
-304
lines changed

.config/dotnet-tools.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
"isRoot": true,
44
"tools": {
55
"docfx": {
6-
"version": "2.78.4",
6+
"version": "2.78.5",
77
"commands": [
88
"docfx"
99
],
1010
"rollForward": false
1111
}
1212
}
13-
}
13+
}

.github/skills/breaking-changes/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Look for both categories of breaking changes:
3333
- **API (compile-time)** — changes to public type signatures, parameter types, return types, removed members, sealed types, new obsoletion attributes, etc.
3434
- **Behavioral (runtime)** — new/changed exceptions, altered return values, changed defaults, modified event ordering, serialization changes, etc.
3535

36-
See [references/classification.md](references/classification.md) for the full classification guide, including SDK-specific versioning policies (pre-1.0 preview flexibility, experimental APIs, obsoletion lifecycle, and spec-driven changes) that influence how breaks are assessed.
36+
See [references/classification.md](references/classification.md) for the full classification guide, including SDK-specific versioning policies (experimental APIs, obsoletion lifecycle, and spec-driven changes) that influence how breaks are assessed.
3737

3838
### Step 2: Assess Impact
3939

@@ -63,7 +63,7 @@ Present the final list of confirmed breaking changes, sorted from most impactful
6363

6464
## Output
6565

66-
The audit produces a structured list of breaking changes that can be consumed by other skills (e.g. the release-notes skill) or presented directly to the user.
66+
The audit produces a structured list of breaking changes that can be consumed by other skills (e.g. the **prepare-release** and **publish-release** skills) or presented directly to the user.
6767

6868
Each entry contains:
6969
- PR number and description

.github/skills/breaking-changes/references/classification.md

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,21 @@ Changes to internal surface or behavior (e.g., internal APIs, private reflection
6767

6868
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.
6969

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-
7470
### Experimental APIs
7571

7672
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.
7773

74+
#### APIs exclusively reachable through `[Experimental]` gates
75+
76+
A change to a non-experimental public API is **not considered breaking** if it only affects consumers who have already opted into an `[Experimental]` code path. The key question is: *can a consumer reach the breaking impact without suppressing an experimental diagnostic?*
77+
78+
For example, adding an abstract member to a public abstract class is normally a Bucket 1 break (anyone deriving from the class must implement the new member). However, if the class's only accessible constructor is marked `[Experimental]`, then deriving from it already requires suppressing the experimental diagnostic — meaning the consumer has explicitly accepted that the API is subject to change.
79+
80+
**How to identify this pattern:**
81+
1. A change would normally be classified as a breaking change (e.g., CP0005 — adding abstract member to abstract type)
82+
2. Trace the code path a consumer must follow to be affected by the break
83+
3. If **every** such path requires the consumer to use an `[Experimental]`-annotated API (constructor, method, type, etc.), the break is dismissed
84+
7885
### Obsoletion Lifecycle
7986

8087
The SDK follows a three-step obsoletion process:
@@ -88,7 +95,7 @@ When auditing, classify each step appropriately:
8895
- Step 2 (escalating to error) → API breaking change (previously working code now fails)
8996
- Step 3 (removal) → API breaking change; migration guidance should note prior deprecation
9097

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.
98+
In exceptional circumstances, 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.
9299

93100
### Spec-Driven Changes
94101

@@ -102,19 +109,40 @@ When a breaking change includes an `AppContext` switch or other opt-in/opt-out m
102109
* Compat switch: `ModelContextProtocol.AspNetCore.AllowNewSessionForNonInitializeRequests` = `true` restores previous behavior
103110
```
104111

112+
## Dismissing Potential Breaking Changes
113+
114+
When a change appears to be breaking but is dismissed (e.g., as a bug fix, clearly non-public, or exclusively gated by `[Experimental]` APIs), the audit must present the full rationale to the user for verification.
115+
116+
### Gathering Supporting Evidence
117+
118+
Before dismissing a potential break, review the PR description and all PR comments (both review comments and general comments) for discussion about the breaking change. Authors and reviewers often explain *why* a change is acceptable — for example, noting that the affected type is gated by an experimental constructor, that the previous behavior was incorrect per the spec, that no external consumers exist yet, or that compatibility suppressions were added intentionally. This discussion serves as supporting evidence for the dismissal and should be cited in the audit findings.
119+
120+
### Presenting Dismissals
121+
122+
Every dismissed potential break must be reported to the user with enough detail for them to verify the conclusion. The audit must:
123+
124+
1. **Identify what would normally be breaking and why** (e.g., "CP0005 — adding abstract member `Completion` to abstract class `McpClient`")
125+
2. **Explain the specific reason for dismissal** (e.g., "Bug fix correcting incorrect behavior per the MCP spec" or "`McpClient`'s only accessible constructor is `protected` and marked `[Experimental(MCPEXP002)]` with message 'Subclassing McpClient and McpServer is experimental and subject to change.'")
126+
3. **Cite any supporting discussion** from the PR description or comments (e.g., "Reviewers discussed the addition and did not flag it as a breaking concern; compatibility suppressions were added for CP0005")
127+
4. **Conclude with the dismissal and its category** (e.g., "Dismissed — bug fix correcting spec-non-compliant behavior" or "Dismissed — exclusively gated by `[Experimental]` API. Do not apply the `breaking-change` label.")
128+
129+
This transparency allows the user to verify each dismissal rationale and override it if the justification is insufficient.
130+
105131
## What to Study for Each PR
106132

107133
For every PR in the range, examine:
108134

109-
1. **PR description** — Authors often describe breaking changes here
135+
1. **PR description** — Authors often describe breaking changes here, or explain why a potentially breaking change is acceptable
110136
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:
137+
3. **Review comments** — Reviewers may have flagged breaking concerns or discussed why a change is acceptable despite appearing breaking (e.g., experimental gates, no external consumers, compatibility suppressions). These discussions are critical evidence when dismissing potential breaks.
138+
4. **General comments** — Authors and reviewers sometimes discuss breaking change justification in the PR conversation thread rather than in review comments
139+
5. **Code diff** — Look at changes to:
113140
- Public type/member signatures
114141
- Exception throwing patterns
115142
- Default values and constants
116143
- Return value changes
117144
- Parameter validation changes
118145
- Attribute changes (`[Obsolete]`, `[Experimental]`, etc.)
119146
- `AppContext.TryGetSwitch` or environment variable compat switches
120-
5. **Labels** — Check if `breaking-change` is already applied
147+
- Compatibility suppressions (e.g., `CompatibilitySuppressions.xml` for ApiCompat CP0005 etc.)
148+
6. **Labels** — Check if `breaking-change` is already applied

.github/skills/bump-version/SKILL.md

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,60 @@
11
---
22
name: bump-version
3-
description: Bump the SDK version after publishing a release. Reads the current version from src/Directory.Build.props, suggests the next minor version, and creates a pull request with the change. Use when asked to bump the version, prepare for the next release, or increment the version number.
4-
compatibility: Requires gh CLI with repo access for creating branches and pull requests.
3+
description: Assess and bump the SDK version using Semantic Versioning 2.0.0. Evaluates queued changes to recommend PATCH/MINOR/MAJOR, updates src/Directory.Build.props, and creates a pull request. Owns the SemVer assessment logic shared by prepare-release and publish-release. Use when asked to bump the version, assess the version, or determine what the next version should be.
4+
compatibility: Requires gh CLI with repo access for creating branches and pull requests. GitHub API access for PR details when performing SemVer-informed assessment.
55
---
66

77
# Bump Version
88

9-
Bump the SDK version in `src/Directory.Build.props` after publishing a release and create a pull request with the change.
9+
Assess and bump the SDK version in `src/Directory.Build.props` to prepare for the next release. This skill owns the [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) assessment logic — the [SemVer assessment guide](references/semver-assessment.md) is the single source of truth for version assessment criteria used across the release workflow by both the **prepare-release** and **publish-release** skills.
10+
11+
> **Note**: For comprehensive release preparation — including ApiCompat/ApiDiff, documentation review, and release notes — use the **prepare-release** skill, which incorporates version assessment as part of its broader workflow.
1012
1113
## Process
1214

13-
### Step 1: Read Current Version
15+
### Step 1: Read Current Version and Previous Release
1416

1517
Read `src/Directory.Build.props` on the default branch and extract:
1618
- `<VersionPrefix>` — the `MAJOR.MINOR.PATCH` version
17-
- `<VersionSuffix>` — the prerelease suffix (e.g. `preview.1`), if present
1819

19-
Display the current version to the user: `{VersionPrefix}-{VersionSuffix}` or `{VersionPrefix}` if no suffix.
20+
Display the current version to the user.
21+
22+
Determine the previous release tag from `gh release list` (most recent **published** release). Draft releases must be ignored — they represent a pending release that has not yet shipped. Use `--exclude-drafts` or filter to only published releases when querying.
23+
24+
### Step 2: Assess and Determine Next Version
25+
26+
If the user provided a target version in their prompt, use it directly. Otherwise, determine the next version using one of two approaches:
27+
28+
#### SemVer-Informed Assessment (Preferred)
29+
30+
When context about queued changes is available or can be gathered, assess the version following the [SemVer assessment guide](references/semver-assessment.md):
31+
32+
1. Get the list of PRs merged between the previous release tag and the target commit (typically HEAD).
33+
2. Classify the release level:
34+
- **MAJOR** — if any confirmed breaking changes (API or behavioral), excluding `[Experimental]` APIs
35+
- **MINOR** — if new public APIs, features, or obsoletion warnings are present
36+
- **PATCH** — otherwise
37+
3. Compute the recommended version from the previous release tag (see the assessment guide for increment rules).
38+
4. Compare against the current version in `Directory.Build.props` and flag any discrepancy.
39+
5. Present the assessment with a summary table and rationale, then get user confirmation.
40+
41+
#### Default Suggestion (Fallback)
2042

21-
### Step 2: Determine Next Version
43+
When a quick bump is needed without full change analysis, suggest the next **minor** version:
2244

23-
If the user provided a target version in their prompt, use it. Otherwise, suggest the next **minor** version with the same suffix pattern:
45+
- Current `1.0.0` → suggest `1.1.0`
46+
- Current `1.2.3` → suggest `1.3.0`
2447

25-
- Current `0.9.0` with suffix `preview.1` → suggest `0.10.0-preview.1`
26-
- Current `1.0.0` with no suffix → suggest `1.1.0`
27-
- Current `1.2.3` with suffix `rc.1` → suggest `1.3.0-rc.1`
48+
Present the suggestion and let the user confirm or provide an alternative.
2849

29-
Present the suggestion and let the user confirm or provide an alternative. Parse the confirmed version into its `VersionPrefix` and `VersionSuffix` components.
50+
Parse the confirmed version into its `VersionPrefix` component.
3051

3152
### Step 3: Create Pull Request
3253

33-
1. Create a new branch named `bump-version-to-{version}` (e.g. `bump-version-to-0.10.0-preview.1`) from the default branch
54+
1. Create a new branch named `bump-version-to-{version}` (e.g. `bump-version-to-1.1.0`) from the default branch
3455
2. Update `src/Directory.Build.props`:
35-
- Set `<VersionPrefix>` to the new prefix
36-
- Set `<VersionSuffix>` to the new suffix, or remove the element if there is no suffix
56+
- Set `<VersionPrefix>` to the new version
57+
- Update `<PackageValidationBaselineVersion>` if the MAJOR version has changed
3758
3. Commit with message: `Bump version to {version}`
3859
4. Push the branch and create a pull request:
3960
- **Title**: `Bump version to {version}`
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Semantic Versioning Assessment Guide
2+
3+
This reference describes how to assess the appropriate [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) (SemVer) release level for the C# MCP SDK based on the changes queued since the previous release.
4+
5+
## SemVer Summary
6+
7+
The SDK follows SemVer 2.0.0 as documented in the [C# SDK Versioning](https://csharp.sdk.modelcontextprotocol.io/versioning.html) documentation. Given a version `MAJOR.MINOR.PATCH`:
8+
9+
- **MAJOR**: Increment when incompatible API changes are included
10+
- **MINOR**: Increment when functionality is added in a backward-compatible manner
11+
- **PATCH**: Increment when only backward-compatible bug fixes are included
12+
13+
When incrementing:
14+
- MAJOR resets MINOR and PATCH to 0 (e.g., `1.2.3``2.0.0`)
15+
- MINOR resets PATCH to 0 (e.g., `1.2.3``1.3.0`)
16+
- PATCH increments only the PATCH component (e.g., `1.2.3``1.2.4`)
17+
18+
## Assessment Criteria
19+
20+
Evaluate every PR in the release range against these criteria, ordered from highest to lowest precedence.
21+
22+
### MAJOR — Incompatible API Changes
23+
24+
Recommend a MAJOR version increment if **any** of the following are present:
25+
26+
- Confirmed breaking changes from the breaking change audit (API or behavioral)
27+
- Removal of public types, members, or interfaces
28+
- Changes to parameter types, order, or count on public methods
29+
- Return type changes on public methods or properties
30+
- Sealing of previously unsealed types (with accessible constructors)
31+
- Escalation of `[Obsolete]` from warning to error
32+
- Removal of previously obsolete APIs
33+
34+
**Exception — Experimental APIs**: Changes to APIs annotated with `[Experimental]` do not require a MAJOR increment, even if they would otherwise be considered breaking. This includes changes that only affect consumers who have opted into an `[Experimental]` code path — for example, adding an abstract member to a public abstract class whose only accessible constructor is `[Experimental]`. If every path to the breaking impact requires suppressing an experimental diagnostic, the change is not considered breaking for versioning purposes. Note these changes but classify the release level based on the non-experimental changes.
35+
36+
### MINOR — Backward-Compatible New Functionality
37+
38+
Recommend a MINOR version increment if no MAJOR criteria are met but **any** of the following are present:
39+
40+
- Any new public APIs
41+
- New MCP capabilities or protocol features
42+
- Addition of `[Obsolete]` attributes producing build warnings (step 1 of obsoletion lifecycle)
43+
- Changes to `[Experimental]` APIs (regardless of whether they would be breaking outside the experimental surface)
44+
45+
### PATCH — Everything Else
46+
47+
Recommend a PATCH version increment if no MAJOR or MINOR criteria are met.
48+
49+
**Note**: Releases that contain _only_ documentation, test, or infrastructure changes may not warrant a release at all. Flag this to the user if no shipped-package changes are present.
50+
51+
## Computing the Recommended Version
52+
53+
1. Parse the previous release tag to extract `MAJOR.MINOR.PATCH`.
54+
2. Apply the assessed level:
55+
- MAJOR: `(MAJOR+1).0.0`
56+
- MINOR: `MAJOR.(MINOR+1).0`
57+
- PATCH: `MAJOR.MINOR.(PATCH+1)`
58+
59+
**Examples** from previous release `v1.2.0`:
60+
61+
| Level | Recommended |
62+
|-------|-------------|
63+
| PATCH | `v1.2.1` |
64+
| MINOR | `v1.3.0` |
65+
| MAJOR | `v2.0.0` |
66+
67+
## Comparing Against the Candidate Version
68+
69+
After computing the recommended version:
70+
71+
1. Compare it against the candidate version (from `src/Directory.Build.props` or an existing draft release tag).
72+
2. Present one of three outcomes:
73+
- **Match**: The candidate aligns with the assessment. Proceed with confidence.
74+
- **Under-versioned**: The candidate uses a lower increment level than the changes warrant (e.g., candidate is `1.2.1` but changes include new APIs requiring `1.3.0`). Flag this as a concern — the version should be corrected.
75+
- **Over-versioned**: The candidate uses a higher increment level than strictly required (e.g., candidate is `2.0.0` but no breaking changes). This is permitted by SemVer but worth noting for the user's awareness.
76+
77+
## Presentation Format
78+
79+
Present the assessment as a summary table followed by a rationale:
80+
81+
```
82+
### Version Assessment
83+
84+
| Aspect | Finding |
85+
|--------|---------|
86+
| Previous release | v1.0.0 |
87+
| Breaking changes | None confirmed |
88+
| New API surface | Yes — 3 PRs add new public APIs |
89+
| Bug fixes | Yes — 2 PRs fix runtime behavior |
90+
| Recommended level | **MINOR** |
91+
| Recommended version | `v1.1.0` |
92+
| Candidate version | `1.1.0` ✅ matches |
93+
94+
**Rationale**: Three PRs introduce new public API surface (#101, #105, #112)
95+
including new extension methods and configuration options. No confirmed breaking
96+
changes. The candidate version in Directory.Build.props aligns with the MINOR
97+
assessment.
98+
```
99+
100+
When the candidate does not match, flag the discrepancy:
101+
102+
```
103+
| Candidate version | `1.0.1` ⚠️ under-versioned (PATCH < MINOR) |
104+
```

0 commit comments

Comments
 (0)