Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
84 changes: 84 additions & 0 deletions CONTRIBUTING.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
# Contributing

Thanks for considering a contribution to the PHP SDK for the Model Context Protocol. This is a
collaboration between [the PHP Foundation](https://thephp.foundation/) and the
[Symfony project](https://symfony.com/), and it follows Symfony's conventions throughout.

## Ways to contribute

- **Report a bug** or **propose a feature** by [opening an issue](https://github.com/modelcontextprotocol/php-sdk/issues).
Check existing issues first — many spec-driven changes are already tracked under the relevant
`2026-07-28`-style release label.
- **Send a pull request** for a fix, a new capability, or a docs improvement.
- **Improve the guides** under `docs/` — see [Documentation](#documentation) below for how they're built.
- **Help close a conformance gap** — `make conformance-tests` runs the official MCP conformance
suite against this SDK; a failing scenario there is a concrete, well-scoped contribution.

## Development setup

Requires PHP 8.1+.

```bash
composer install
```

## Before opening a pull request

Run the full CI suite locally:

```bash
make ci
```

This runs, in order: `make cs` (PHP CS Fixer, auto-fixes style), `make phpstan` (static analysis),
and `make tests` (unit + inspector tests). All three must pass. If your change touches
protocol-observable behavior, also run:

```bash
make conformance-tests # requires Docker
```

## Coding standards

This project follows [Symfony's coding standards](https://symfony.com/doc/current/contributing/code/standards.html)
and [backward compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html). In short:

See [CLAUDE.md](CLAUDE.md) for a fuller tour of the codebase's architecture and layout.

## Tests

New capabilities need unit tests (`tests/Unit/`) covering the core logic, and — for anything
reachable over the wire — inspector tests (`tests/Inspector/`) for end-to-end coverage. If you're
adding a documented pattern, consider adding or updating an example under `examples/`.

## Documentation

The guides under `docs/` are built with [Zensical](https://zensical.org/) in `--strict` mode,
which fails the build on a broken internal link:

```bash
make docs-guides
```

Links between guide pages must be relative paths that resolve within `docs/` (e.g.
`protocol-versions.md`, `../CLAUDE.md` will *not* resolve — Zensical only follows the `docs/` tree).
For anything at the repo root (`CLAUDE.md`, `ROADMAP.md`, `CHANGELOG.md`), link to it by its GitHub
URL instead, matching the pattern already used across `docs/`. The class-level API reference is
generated separately by phpDocumentor (`make docs-api`) and isn't hand-written.

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/) — see
[SDK tier target](docs/sdk-tier.md#versioning) for what that means pre- and post-1.0, and how it
lines up with Symfony's backward compatibility promise.

## Licensing

New contributions are licensed under Apache License, Version 2.0. Existing code predating this
policy remains under the MIT License — see [LICENSE](LICENSE) for the details. By opening a pull
request, you agree your contribution is provided under those terms.

## Getting help

If something is unclear or you want early feedback on an approach before writing code, open an
issue or a draft pull request — that's the right place to ask, rather than guessing at scope.
4 changes: 3 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,7 +126,9 @@ Building something on top of the SDK? Open a pull request to add it to this list

We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. Start by [reporting issues](https://github.com/modelcontextprotocol/php-sdk/issues) or
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
[sending pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls). See
[CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and what to run before
opening a PR.

## Credits

Expand Down
28 changes: 28 additions & 0 deletions docs/deprecation-policy.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
# Deprecation policy

The MCP specification (SEP-2596) defines a formal feature lifecycle: **Active → Deprecated → Removed**,
with a minimum of twelve months between a feature being marked deprecated and its earliest possible removal.
Each stage transition gets its own SEP — deprecating a feature and removing it are separate proposals, never
bundled into one.

The PHP SDK mirrors that window for anything it deprecates, whether the deprecation originates in the spec
or is SDK-internal (an API shape the SDK wants to retire independently of the protocol).

## What a deprecation looks like here

A deprecated element carries a PHP `@deprecated` tag naming the protocol revision (or SDK version, for an
SDK-internal deprecation) that introduced the deprecation and the earliest removal date, twelve months out:

```php
/**
* @deprecated since protocol revision 2026-07-28 (SEP-2577), earliest removal 2027-07-28.
*/
```

## The SDK's own BC promise

The SDK is pre-1.0 and experimental, and the public
API can still change without a deprecation cycle where the spec itself hasn't moved. Once past 1.0, the SDK
follows [Symfony's backward-compatibility promise](https://symfony.com/doc/current/contributing/code/bc.html),
and the twelve-month deprecation window above becomes the
floor for any BC break the SDK introduces on its own, not just ones the spec forces.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,6 +97,9 @@ around in.
**[Clients](client/index.md)**.
* The two protocol eras, and what revision `2026-07-28` changed, are
**[Protocol versions](protocol-versions.md)**.
* What gets deprecated, for how long, and where the SDK stands on spec-tier
support are under **Project**: **[Deprecation policy](deprecation-policy.md)**
and **[SDK tier target](sdk-tier.md)**.
* Complete, runnable projects are in **[Examples](examples.md)**.
* Hunting for an exact signature? The **[API Reference](https://php.sdk.modelcontextprotocol.io/api/)**
is generated from the source.
68 changes: 68 additions & 0 deletions docs/sdk-tier.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
# SDK Tier Target (SEP-1730)

The MCP spec defines three SDK tiers: Tier 1 (Fully Supported), Tier 2
(Commitment to Full Support), and Tier 3 (Experimental). This document tracks
where the PHP SDK stands and what's still missing to move up a tier.

## Current standing

**Tier 3**, per the official audit in
[modelcontextprotocol/modelcontextprotocol#3274](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/3274)
(2026-08-19, superseding the earlier Tier 3 assessment in #2305). Two things
block Tier 2:

- **Client conformance is 20% (10/50)**, against the ≥80% bar. Almost
entirely OAuth: 38 of 39 scored auth scenarios fail. Every one of those
failures is pre-declared in the SDK's own
[`tests/Conformance/conformance-baseline-*.yml`](https://github.com/modelcontextprotocol/php-sdk/tree/main/tests/Conformance)
files and tracked in `ROADMAP.md` — a known, scoped gap, not silent
breakage. Server conformance is 100% (67/67).
- **No stable release ≥ 1.0.0 has ever shipped** (latest: v0.7.1). Tier 2
requires at least one.

Tier 1 needs both of those plus full (not ≥80%) client conformance and
closing 10 documentation gaps the audit lists by name (mostly small
per-feature additions — legacy SSE transport and the elicitation
complete-notification need either an implementation or an explicit
"intentionally not implemented" note).

## Target

**Tier 2 next, Tier 1 after the 1.0 release.** Tier 1's "stable release"
requirement is structurally out of reach until 1.0 ships regardless of how
complete every other Tier 1 criterion is.

## Path to Tier 2

Roughly in priority order, per the audit's own recommendation:

1. **OAuth client conformance.** The single highest-leverage fix — it
accounts for 38 of 40 client failures and blocks both tiers on its own.
Already scoped: token endpoint auth methods, scope handling (step-up,
retry-limit, from-`WWW-Authenticate`, from `scopes_supported`), dynamic
client registration, issuer validation, `offline_access`,
authorization-server migration — see `ROADMAP.md` and the
`2026-07-28`-labeled auth issues.
2. **Fix the two non-auth client failures** (`sse-retry`,
`elicitation-sep1034-client-defaults`, both scored at 2025-11-25).
3. **Ship a stable 1.0.0+ release.**

## Versioning

The SDK follows [Semantic Versioning](https://semver.org/):
`MAJOR.MINOR.PATCH`. Pre-1.0, that means any digit can carry a breaking
change per SemVer §4 — every one is logged with a `[BC Break]` marker in
[`CHANGELOG.md`](https://github.com/modelcontextprotocol/php-sdk/blob/main/CHANGELOG.md).

Once at 1.0, the SDK adopts Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html):
PATCH releases never break BC, MINOR releases only add functionality (gated
by the deprecation window in [Deprecation policy](deprecation-policy.md)),
and a breaking change ships only in a MAJOR release.

## Roadmap

See [ROADMAP.md](https://github.com/modelcontextprotocol/php-sdk/blob/main/ROADMAP.md)
for the feature-level plan toward 1.0. This document only tracks the
process/tier-classification gap, which is narrower and more mechanical than
the feature roadmap.
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,6 +54,9 @@ nav:
- Events: advanced/events.md
- Protocol extensions: advanced/extensions.md
- Custom message handlers: advanced/custom-handlers.md
- Project:
- Deprecation policy: deprecation-policy.md
- SDK tier target: sdk-tier.md
- Examples: examples.md
- API Reference: https://php.sdk.modelcontextprotocol.io/api/

Expand Down