Commit graph

263 commits

Author SHA1 Message Date
Paul Carleton
26e09df154
ci(traceability): enable corepack so the SDK build can use pnpm (#289)
The refresh run failed with 'pnpm: not found' — the reference SDK's
build command (typescript-sdk: pnpm install && pnpm run build:all) needs
pnpm on PATH. Add 'corepack enable' to the run job.
2026-05-19 23:02:24 +01:00
Den Delimarsky
1ef3cd34bd
SEP-2352: authorization-server migration scenario (#286)
* Add SEP-2352 authorization-server migration scenario

SEP-2352 requires that client credentials are bound to the issuing
authorization server: when PRM authorization_servers changes to a new
issuer, clients MUST re-register and MUST NOT reuse the previous AS's
client credentials.

- Traceability yaml: 3 checks, 3 excluded (internal state / UI)
- New auth/authorization-server-migration scenario (draft suite): two
  auth servers; PRM flips from AS1 to AS2 after the first authenticated
  request; AS2 asserts it received a fresh /register and never saw AS1's
  client_id at /authorize or /token
- ConformanceOAuthProvider gains invalidateCredentials and bindIssuer so
  the everything-client can key credentials by issuer (passing example)
- everything-client adds an issuer-aware handler for this scenario that
  re-reads PRM on each 401 and rebinds before re-authorizing
- auth-test-reuse-credentials negative client + vitest case

* Drop application_type from DCR metadata (not in SDK OAuthClientMetadata type)

---------

Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-05-19 22:59:31 +01:00
Yuan Teoh
91755d652c
feat: add server conformance tests for SEP-2575 (#271)
* feat: add server conformance tests for SEP-2575

* refactor and add new checks

* Fix stateless scenario source field and report SKIPPED for inapplicable capability checks

- Add the required `source` field (DRAFT) so the scenario typechecks and is
  selectable via --spec-version. Without it the class did not satisfy the
  ClientScenario interface and s.source was dereferenced by the spec-version
  filter at list time.
- Teach runCheck about a SKIPPED status and use it for the two client-capability
  checks when the server does not return -32003, instead of reporting a green
  PASS for a requirement that was never exercised.

* Remove unimplemented placeholder checks from stateless server scenario

The subscriptions/listen, statelessness-invariant, list-changed and
disconnect-is-cancel checks emitted SUCCESS without probing the server,
which inflated coverage in the traceability report. Drop them until they
have real assertions; the corresponding rows remain declared in
src/seps/sep-2575.yaml so traceability shows them as not-yet-covered.

Also fix the checkErrorId helper to push under the
sep-2575-http-server-error-jsonrpc-id slug so its failure path actually
short-circuits the aggregate SUCCESS check at the end of the scenario.

---------

Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-05-19 22:40:35 +01:00
Paul Carleton
442ba3b143
feat: add SEP conformance traceability manifest (#288)
squashed; see PR #288 body
2026-05-19 22:22:25 +01:00
Paul Carleton
cfcecdba2c
feat: sdk subcommand to run local conformance against any SDK ref (#277)
* feat: add sdk subcommand to run conformance against any SDK ref (#250)

* Revise sdk runner: explicit --mode, KNOWN_SDKS-only config, v1/v2 entries

Addresses review feedback on the sdk subcommand:

- Require --mode (client|server) and remove "both". Each invocation now
  tests exactly one side with its own exit code; the old default ran
  client then server but combined exit codes with ||=, which skipped the
  server side entirely whenever the client run failed.
- Resolve build/run config from KNOWN_SDKS + CLI flags only; drop the
  conformance.config.yaml loader (no SDK ships one yet). The Zod schema
  stays as the type for the built-in entries.
- Split the typescript entry by major version: typescript-sdk (v2/main,
  pnpm install + build:all, expected-failures.yaml) and typescript-sdk-v1
  (v1.x, npm ci + build, conformance-baseline.yml). An entry may set
  `repo` (real clone target for an alias) and `defaultRef` (branch used
  when no @ref is given). parseSdkSpec now leaves ref undefined when
  omitted so defaultRef can apply; a trailing @ is treated as no ref.
- Key the clone cache by ref (<repo>/<ref>) so different refs of the same
  repo no longer share one checkout.
- Bound the server readiness probe with a per-request AbortSignal timeout
  so a server that accepts the socket but never responds can't hang past
  the overall deadline.

* fix(sdk-runner): resolve -o to absolute path; add --expected-failures override; replaceAll for safeName
2026-05-19 22:08:06 +01:00
Paul Carleton
70f7ba0004
fix(sep-2243): collapse check IDs to one-per-requirement (#287)
The sep-2243 scenario check IDs drifted from the requirement-traceability
yaml in #259 — the code emitted one ID per test case while the yaml
declares one per normative requirement, so the IDs no longer matched.

Rename the emitted IDs so a check ID maps to a single MUST/SHOULD and is
emitted once per case (the per-case detail moves to name/description),
matching the repo's existing 'same id, vary status/message' convention:

- mcp-method-header-* / mcp-name-header-*  -> client-includes-standard-headers
- reject-invalid-tool-* / keep-valid-tool  -> client-reject-invalid-tool
- server-accepts-{lower,upper}case-name    -> header-name-case-insensitive
- server reject status checks (mismatch/missing/case x method/name)
                                            -> server-reject-invalid-headers
- their error-code variants                 -> server-reject-error-code

Merge the yaml's server-reject-mismatch + server-reject-status into one
server-reject-invalid-headers MUST (HTTP 400 on a header-validation
failure); keep server-reject-error-code as the SHOULD. Base64/custom-header
rejection checks keep their own param-validation IDs (out of scope here).

Gates and the whitespace-acceptance check keep their scenario-matching
names. No behavior change — only check IDs, descriptions, and the yaml.
2026-05-19 21:48:31 +01:00
Anubhav Dhawan
5c1b815cd1
feat: add client conformance tests for SEP-2575 (#270)
* feat: merge latest request-metadata scenario stacked branch

* test: implement optional capability conditional checks and simulated negotiation retry
2026-05-19 21:10:52 +01:00
Paul Carleton
fee585cf45
docs: add review-scenario skill for SEP scenario PR review (#276) 2026-05-15 14:38:23 +01:00
Mike Kistler
39f34b2c58
Add conformance tests for SEP-2243 HTTP Standardization (#259)
* Add prepare script for git dependency installs

* Add conformance tests for SEP-2243 HTTP Standardization

* Add traceability file for SEP-2243

* Fix prettier formatting in http-standard-headers.ts

* Improve SEP-2243 conformance test coverage

Close gaps in HTTP header conformance scenarios:

Client standard headers (http-standard-headers.ts):
- Enforce all expected methods in checks, failing any that were not observed
- Track Mcp-Name header per-method separately from Mcp-Method
- Advertise resources and prompts capabilities so clients exercise those endpoints
- Add a prompt entry for prompts/get testing

Client custom headers (http-custom-headers.ts):
- Add Base64 encoding checks for non-ASCII, whitespace, and control-char values
- Add null/omitted parameter test (second tool call with null value)
- Add client-keeps-valid-tool check verifying clients still call valid tools
  after filtering out invalid ones

Server header validation (server/http-standard-headers.ts):
- Replace fetch-based sendRawRequest with http.request to preserve exact
  header casing on the wire (fetch/Headers lowercases names)
- Compute defaultArgs and defaultHeaders from tool schema so test requests
  satisfy all required parameters while varying only the param under test

Traceability (sep-2243.yaml):
- Add 7 new spec-to-check mappings (nonascii, whitespace, controlchar,
  keeps-valid-tool, literal-missing-base64-prefix/suffix, no-mirror-unannotated)
- Fix 2 incorrect existing mappings

* Fill SEP-2243 conformance test coverage gaps

Add missing test cases identified by comparing the branch against the
SEP-2243 spec's Conformance Test Cases section:

- Mcp-Method on notifications: add notifications/initialized to
  expectedMethods so clients are checked for header on notifications
- Boolean true: add debug=true param to complement verbose=false
- Leading-space-only and trailing-space-only: separate checks for
  Base64 encoding when only one edge has whitespace
- Internal spaces only: verify plain ASCII (no Base64) for values
  like 'us west 1' that have spaces only in the middle
- CRLF string: add line1\r\nline2 test (complements existing \n test)
- Leading tab: add \tindented test for tab-triggered Base64 encoding
- Server rejects invalid Mcp-Param chars: mark as excluded in YAML
  since HTTP itself prevents these characters in headers

Register all new checks in sep-2243.yaml.

* Remove case-insensitive =?base64? prefix test

The spec states header values are case-sensitive (RFC 9110). The
=?base64? prefix is part of the header value, not the header name,
so it should be matched case-sensitively. This was identified as a
bug in the conformance tests per feedback on SEP-2243.

Changes:
- Remove server-accepts-case-insensitive-base64 check from server
  validation scenario
- Change base64 prefix regex from case-insensitive (/i) to
  case-sensitive in client header validation
- Remove corresponding entry from sep-2243.yaml

* Remove nested x-mcp-header rejection test

The spec constrains x-mcp-header to primitive types but does not
restrict it to top-level properties only. A nested string property
with x-mcp-header is valid per the spec. This was confirmed by
mikekistler in SEP-2243 PR discussion.

Removes invalid_nested_header from the invalid tool definitions
list and its corresponding sep-2243.yaml entry.

* Use numeric comparison for number header values

Compare number header values numerically instead of as strings to
accommodate cross-SDK floating point representation differences
(e.g., '42' vs '42.0'). For integers, exact numeric match is
required. For decimals, a tolerance of 1e-9 is allowed.

See SEP-2243 discussion on number precision.

* client/http-standard-headers: SKIPPED (not FAILURE) for unexercised methods; make getChecks() idempotent

A client that never calls prompts/list isn't violating SEP-2243 — the spec
sentence is 'The client MUST include the standard MCP request headers on each
POST request', and a request that was never sent can't fail it. The Mcp-Method
requirement is already proven by initialize/tools/list etc., so there's nothing
unique to prompts/list. SKIPPED keeps the gap visible without a false red.

Separately: getChecks() was pushing into this.checks on every call. The runner
may call it more than once (e.g. progress + final report); that produced
duplicate rows. Build a fresh array per call instead.

* client/http-standard-headers: de-dup guard in checkMcpNameHeader

checkMcpMethodHeader already has 'if (this.methodHeaderChecks.has(method)) return'.
checkMcpNameHeader was missing the equivalent. The test server advertises two
tools and two resources; a client that calls both produces two
'client-mcp-name-header-tools-call' / '...-resources-read' rows.

* client/http-standard-headers: replace -> /\//g for slug generation

String.replace with a string arg only replaces the first occurrence.
'notifications/initialized' is fine (one slash) but a method like
'notifications/resources/updated' would yield 'notifications-resources/updated'
in the check id. (replaceAll isn't in this project's TS lib target.)

* client/http-custom-headers: base64 regex (.+) -> (.*) so empty string round-trips

The spec doesn't forbid base64-encoding values that don't strictly need it.
A client that always wraps would send '=?base64??=' for empty_val: ''. The
'.+' wouldn't match, so the harness would compare '=?base64??=' === ''
literally and FAIL a compliant client. '(.*)' lets the empty payload decode
to '' and match.

* client/http-custom-headers: emit SUCCESS for no-mirror-unannotated

This check only pushed on FAILURE; a correct client produced no row at all,
so the pass was invisible in reports and couldn't be counted toward coverage.
Same-slug SUCCESS/FAILURE pair is the repo convention.

* client/http-custom-headers: drop redundant optional-present check

checkParamHeader('Verbose', ...) already pushes a FAILURE when the header is
missing. The explicit 'optional-present' block re-tests the same condition
under a second check id, doubling the row.

* server/http-standard-headers: defaultArgs must use real number/boolean, not strings

defaultArgs feeds the JSON-RPC body. With Record<string, string> + '0'/'false',
a server that validates inputSchema rejects on type mismatch — which is also a
400. Every header-rejection check then false-PASSes (server rejected for the
wrong reason), and server-accepts-valid-base64 false-FAILs a compliant server
because it never gets past schema validation.

Also handle 'integer' (JSON Schema distinguishes it from 'number').

* server/http-standard-headers: createAcceptanceCheck must also assert no JSON-RPC error in body

A server can return HTTP 200 with {error: {code: -32001, ...}} in the body.
Status-only acceptance lets that through as a pass.

* use DRAFT_PROTOCOL_VERSION constant instead of 'DRAFT-2026-v1' literal

The literal will rot when the draft cycle rolls over. types.ts already exports
DRAFT_PROTOCOL_VERSION for this.

* sep-2243.yaml: spec-first rewrite + move to src/seps/

Regenerated from the SEP-2243 spec diff (transports.mdx + tools.mdx) rather
than from the scenario implementations: 21 check rows + 4 excluded vs the
previous 46 + 2. Differences:

- one check id per spec sentence (test variants go in 'details', not new ids)
- 'text:' quotes the spec sentence verbatim instead of paraphrasing
- '-reject-status' (MUST 400) split from '-reject-error-code' (SHOULD -32001
  for standard headers, MUST for custom)
- rows with no spec backing dropped (whitespace, base64-padding/chars, prefix/
  suffix-literal, control-char-name)
- two more SHOULD excludes (log-warning, no-sensitive-params)
- check ids use sep-2243-<slug> convention
- check: key first, excludes grouped at bottom (matches sep-2164)

Moved to src/seps/ to match #272 layout (this branch predates it; will
reconcile cleanly on rebase).

* add negative test for HttpStandardHeadersScenario

Self-contained vitest that POSTs initialize with and without Mcp-Method,
asserts FAILURE/SUCCESS on the pinned check id, and proves getChecks() is
idempotent. No example client/server file needed for this one because the
scenario *is* the server — the test crafts the bad request directly.

This is the negative-test half of AGENTS.md §Testing your scenario; the
everything-client passing-example half is still TODO.

* server/http-standard-headers: severity fixes for whitespace + malformed-base64 tests

These five tests assert behavior the SEP-2243 text doesn't pin down. Kept
because they're useful consistency signals across SDKs, but adjusted so they
don't FAIL spec-compliant servers:

- server-accepts-whitespace-header-value: this IS a MUST, but per RFC 9110
  §5.5 (field parsing MUST exclude OWS), not SEP-2243. Kept as FAILURE,
  specReference now cites RFC 9110.

- server-rejects-invalid-base64-padding / -chars: downgraded to INFO.
  SEP-2243 says only 'MUST decode them accordingly' without picking RFC 4648
  strict vs lenient. Node's Buffer.from() accepts unpadded/dirty input and
  decodes to a matching value (server accepts); .NET's Convert.FromBase64String
  throws (server rejects). Either is currently compliant. WARNING would force
  Tier-1 SDKs into non-default strict decoding (#245); INFO records the
  behavior without prescribing it, so cross-SDK divergence is visible
  without tier impact.

- server-literal-missing-base64-prefix / -suffix: unchanged. The wrapper
  syntax is '=?base64?{x}?=' complete; treating partial wrappers as literal
  is the natural reading.

Plumbing: createRejectionCheck gains an optional failSeverity param;
testBase64Case gains a 'reject-info' mode. (This is also the hook for the
larger 400-MUST / -32001-SHOULD split that still needs doing.)

* server/http-standard-headers: split rejection check into status (MUST) + error-code (SHOULD/MUST)

SEP-2243 §Server Validation: 'servers MUST return HTTP status 400 ... and
SHOULD include a JSON-RPC error response using ... -32001'. So a server that
returns 400 with -32600 (or no error body) is compliant for standard headers.
The single conflated check FAILed it.

For custom headers (§Server Behavior for Custom Headers) -32001 IS a MUST,
so both halves stay FAILURE there.

createRejectionCheck → createRejectionChecks returning two rows: '<id>' for
the 400 status and '<id>-error-code' for -32001. testCase (standard) sets
errorCodeSeverity=WARNING; testBase64Case/testMissingCustomHeader (custom)
keep FAILURE; the two malformed-base64 INFO probes set both halves to INFO.

* rename check ids to sep-2243-* prefix; kebab-case throughout

Aligns with the sep-2243.yaml traceability ids and the repo convention
(sep-2164-*, sep-2207-*). Variant suffixes are kept (per-method, per-tool)
so per-case visibility isn't lost; the YAML's row id is a prefix of the
emitted ids, which is fine — extra ids not in the YAML are allowed.

Also fixes the mixed hyphen/underscore in reject-invalid-tool ids
(toolName has underscores; replace to hyphens).

* client: extract BaseHttpScenario to client/http-base.ts; both client scenarios extend it

http-standard-headers.ts had its own copy of the start/stop/handleRequest
boilerplate (~100 lines) that http-custom-headers.ts already abstracted as
BaseHttpScenario. Moved the abstract class to a shared file; both scenario
files now import it. HttpStandardHeadersScenario implements handlePost()
instead of handleRequest(); its handleInitialize() uses the base
sendInitialize() with the resources/prompts capability flags it needs.

Net: 465 → 361 lines for http-standard-headers.ts; the third inline copy of
the same HTTP-server scaffold is gone.

* use req.setEncoding('utf8') instead of per-chunk Buffer.toString()

Per-chunk .toString() corrupts a multi-byte UTF-8 char that straddles a TCP
chunk boundary (e.g. 0xC3 | 0xBC decodes to two replacement chars instead of
'ü'). The custom-headers scenario sends '日本語'/'naïve' in the body, so this
is reachable in principle. setEncoding('utf8') makes 'data' emit strings with
boundary handling done by Node's StringDecoder.

Fixed in both places: BaseHttpScenario.handleRequest (request body) and
sendRawRequest (response body).

* fix: migrate SEP-2243 scenarios from specVersions to source (introducedIn/removedIn)

The introducedIn/removedIn refactor (#265) replaced the specVersions array
with a source property on all scenario interfaces. The SEP-2243 scenarios
still used the old specVersions field, causing matchesSpecVersion() to
receive undefined and crash in spec-version.test.ts.

Replace specVersions with source = { introducedIn: DRAFT_PROTOCOL_VERSION }
in BaseHttpScenario and the two server ClientScenario classes. Remove the
now-unused SpecVersion imports.

* server/http-standard-headers: malformed-base64 padding/chars back to FAILURE

Per discussion on #259: the SEP-2243 conformance-test-case table is the
approved source of truth and lists these as reject cases, so they're
FAILURE-level even though the spec body itself only says 'MUST decode them
accordingly'. SDKs whose stdlib base64 is lenient (Node, browsers) will need
to validate before decoding; if that's burdensome we'll revisit.

Removes the now-unused 'reject-info' mode and statusSeverity/INFO plumbing
introduced for these two probes.

---------

Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-05-15 13:20:43 +01:00
Paul Carleton
acc70de0f6
refactor: range-based spec version tagging (introducedIn/removedIn) (#265)
* refactor: replace specVersions list with introducedIn/removedIn range tagging

Replaces per-scenario `specVersions: SpecVersion[]` arrays with `introducedIn`
and optional `removedIn` range fields on all three scenario interfaces. Extension
scenarios get an orthogonal `extension?: boolean` flag instead of the former
`'extension'` tag in the versions list.

matchesSpecVersion() is rewritten as a range comparison
(introducedIn <= target && (!removedIn || target < removedIn)), with draft
sorting after all dated versions. getScenarioSpecVersions() reconstructs the
effective version list from the range for backward-compat with tier-check.
Closes #256.

* refactor: nest spec-version range under `source: ScenarioSource` union

The flat `introducedIn`/`removedIn`/`extension?` shape forced extension
scenarios to set a placeholder `introducedIn` that was never read. Nesting
the version-range fields inside a `source` property typed as a union lets
the compiler enforce introducedIn XOR extensionId — no runtime invariant
test needed.

  type ScenarioSource =
    | { introducedIn: SpecVersion; removedIn?: SpecVersion }
    | { extensionId: ExtensionId };

A class can't `implements` a union type directly, so the union lives inside
a property and `Scenario` stays a plain interface — `class implements
Scenario` keeps working everywhere. `EXTENSION_IDS` is a const array
mirroring the `DATED_SPEC_VERSIONS` pattern.

Also renames the cross-app-access scenario to enterprise-managed-auth to
match the extension's canonical name: file, class, slug, context schema
literal, and the everything-client runner.

* refactor: use canonical SEP-2133 extension identifiers

EXTENSION_IDS now holds the wire identifiers from the spec's extension docs
(client-matrix.mdx, docs/extensions/auth/*.mdx) so extensionId values can be
cross-referenced against capabilities.extensions keys directly:

  io.modelcontextprotocol/oauth-client-credentials
  io.modelcontextprotocol/enterprise-managed-authorization

The previous commit used a shortened 'enterprise-managed-auth' which doesn't
match the canonical '-authorization'. Re-renames the scenario file/class/slug
and downstream references to align.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-14 16:12:32 +01:00
Satoshi Ito
04dd6db7ae
feat: add new-sep scaffolding command (#272)
* feat: add new-sep scaffolding command

Related #243.

This commit adds the new-sep <NNNN> subcommand, which writes the file src/scenarios/<target>/sep-<NNNN>.yaml. This file contains the "sep", "spec_url", and "requirements" rows in the same style as sep-2164.yaml, with single quotes and two spaces. The spec source resolves in order: --spec-url → --spec-path → GitHub API against modelcontextprotocol/modelcontextprotocol (explicit --pr or title search for "SEP-NNNN").
The target directory is inferred from the spec path (`server/`, `client/`, or `basic/authorization*`); the --target flag overrides this. It refuses to overwrite without the --force flag.
Token resolution reuses the "gh auth token" fallback pattern from tier-check.

It also ships the .claude/skills/new-sep directory, which drives the CLI. It fetches the spec diff via "gh api" and extracts RFC 2119 sentences. There is a warning against regex-only matching. Bullets inherit keywords from their lead-in sentence. It rewrites the placeholder rows per the severity rules in AGENTS.md. MUST/SHALL/REQUIRED are checked for FAILURE. SHOULD is checked for WARNING. MAY/OPTIONAL are excluded.

Signed-off-by: Satoshi Ito <satoshi.ito.tf@hitachi.com>

* dropped --pr arg, list changed files, support multi-file seps w url override

* Consolidate SEP yamls into src/seps/ and tighten yaml ordering

- All sep-NNNN.yaml files now live in src/seps/ regardless of which
  scenario suite their checks run in
- Drop --target / inferTarget; output dir is fixed
- renderYaml: check rows emit `check:` first, excluded rows grouped at
  bottom with a blank-line separator
- SKILL.md: document key/row ordering, expand exclusion-confirmation step
- Move src/scenarios/server/sep-2164.yaml -> src/seps/

---------

Signed-off-by: Satoshi Ito <satoshi.ito.tf@hitachi.com>
Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-05-13 15:53:24 +01:00
Paul Carleton
17f1f93cc0
feat: support "draft" as a first-class spec version target (#255)
* feat: support "draft" as a first-class spec version target

- Add LATEST_SPEC_VERSION and DATED_SPEC_VERSIONS constants so the next
  spec release is a one-line change in types.ts.
- Accept "draft" as a valid protocolVersion in the initialize check and
  mock-server response.
- --spec-version draft now selects latest-dated scenarios plus draft-tagged
  ones, so SEP authors can run the full suite against an SDK tracking the
  in-progress spec without retagging core scenarios.
- Forward --spec-version to the client process via
  MCP_CONFORMANCE_SPEC_VERSION so SDK examples can pick the matching
  protocolVersion.

Closes #253

* review: collapse SpecVersion to wire strings; dedup NEGOTIABLE_PROTOCOL_VERSIONS; split out 'extension'

Addresses review feedback from @felixweinberger and @mikekistler:

- SpecVersion is now always a wire protocolVersion string
  (DatedSpecVersion | typeof DRAFT_PROTOCOL_VERSION). The separate
  'draft' tag literal is gone from the type system; 'draft' survives
  only as a CLI input alias in resolveSpecVersion. Removes the
  tag-vs-wire confusion and the specVersionToProtocolVersion mapping.
- NEGOTIABLE_PROTOCOL_VERSIONS in types.ts is the single source for
  what the mock server accepts on initialize (was duplicated in
  checks/client.ts and scenarios/client/initialize.ts).
- 'extension' moved out of SpecVersion into a separate ScenarioSpecTag
  type. --spec-version extension is no longer valid; extension scenarios
  remain reachable via --suite extensions.
- Draft-tagged scenarios now use the DRAFT_PROTOCOL_VERSION constant
  so a draft revision bump is a one-line change in types.ts.
2026-04-30 11:37:32 +01:00
Paul Carleton
d944122003
chore: remove dependabot.yml — security-only via repo defaults (#254)
Conformance is a leaf CLI; scheduled version bumps are churn. Deleting
the config disables version-update PRs entirely. Security advisories
remain enabled via repo settings (Code security > Dependabot).
2026-04-24 13:01:05 +01:00
dependabot[bot]
7f6eb14835
chore(deps): bump the all-dependencies group across 1 directory with 10 updates (#252)
* chore(deps): bump the all-dependencies group across 1 directory with 10 updates

Bumps the all-dependencies group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) | `1.27.1` | `1.29.0` |
| [eventsource-parser](https://github.com/rexxars/eventsource-parser) | `3.0.6` | `3.0.8` |
| [undici](https://github.com/nodejs/undici) | `7.24.5` | `7.25.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.5.0` | `25.6.0` |
| [@typescript/native-preview](https://github.com/microsoft/typescript-go) | `7.0.0-dev.20260325.1` | `7.0.0-dev.20260424.1` |
| [lefthook](https://github.com/evilmartians/lefthook) | `2.1.4` | `2.1.6` |
| [prettier](https://github.com/prettier/prettier) | `3.8.1` | `3.8.3` |
| [tsdown](https://github.com/rolldown/tsdown) | `0.21.5` | `0.21.10` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.57.2` | `8.59.0` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.1.1` | `4.1.5` |



Updates `@modelcontextprotocol/sdk` from 1.27.1 to 1.29.0
- [Release notes](https://github.com/modelcontextprotocol/typescript-sdk/releases)
- [Commits](https://github.com/modelcontextprotocol/typescript-sdk/compare/v1.27.1...v1.29.0)

Updates `eventsource-parser` from 3.0.6 to 3.0.8
- [Release notes](https://github.com/rexxars/eventsource-parser/releases)
- [Changelog](https://github.com/rexxars/eventsource-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rexxars/eventsource-parser/compare/v3.0.6...v3.0.8)

Updates `undici` from 7.24.5 to 7.25.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.5...v7.25.0)

Updates `@types/node` from 25.5.0 to 25.6.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript/native-preview` from 7.0.0-dev.20260325.1 to 7.0.0-dev.20260424.1
- [Changelog](https://github.com/microsoft/typescript-go/blob/main/CHANGES.md)
- [Commits](https://github.com/microsoft/typescript-go/commits)

Updates `lefthook` from 2.1.4 to 2.1.6
- [Release notes](https://github.com/evilmartians/lefthook/releases)
- [Changelog](https://github.com/evilmartians/lefthook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/evilmartians/lefthook/compare/v2.1.4...v2.1.6)

Updates `prettier` from 3.8.1 to 3.8.3
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.1...3.8.3)

Updates `tsdown` from 0.21.5 to 0.21.10
- [Release notes](https://github.com/rolldown/tsdown/releases)
- [Commits](https://github.com/rolldown/tsdown/compare/v0.21.5...v0.21.10)

Updates `typescript-eslint` from 8.57.2 to 8.59.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.0/packages/typescript-eslint)

Updates `vitest` from 4.1.1 to 4.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.5/packages/vitest)

---
updated-dependencies:
- dependency-name: "@modelcontextprotocol/sdk"
  dependency-version: 1.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-dependencies
- dependency-name: eventsource-parser
  dependency-version: 3.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: undici
  dependency-version: 7.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-dependencies
- dependency-name: "@types/node"
  dependency-version: 25.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all-dependencies
- dependency-name: "@typescript/native-preview"
  dependency-version: 7.0.0-dev.20260424.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: lefthook
  dependency-version: 2.1.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: prettier
  dependency-version: 3.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: tsdown
  dependency-version: 0.21.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: typescript-eslint
  dependency-version: 8.59.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all-dependencies
- dependency-name: vitest
  dependency-version: 4.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: switch moduleResolution to bundler for newer tsgo

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-04-24 12:51:39 +01:00
Paul Carleton
825f2031c8
chore(deps): security rollup — path-to-regexp, defu, vite, hono, @hono/node-server (#251)
Supersedes #204, #209, #210, #218, #229, #230, #231, #232, #233.
Excludes #205 (failing CI; triaged separately).
2026-04-24 12:22:07 +01:00
Paul Carleton
5d8595b663
test: add server-side negative test harness (#249)
Adds src/scenarios/server/negative.test.ts with spawn helpers. Wires
two cases: the previously-orphaned no-dns-rebinding-protection.ts and
a new sep-2164-empty-contents.ts. Strengthens the AGENTS.md guidance
to point at the harness.
2026-04-24 12:09:12 +01:00
Nate Barbettini
90b2334dcc
feat: Tool name format checks (SEP-986) (#240) 2026-04-24 11:57:36 +01:00
Paul Carleton
88c087e9c4
docs: add SEP scenario review guidance to AGENTS.md (#247) 2026-04-24 11:51:24 +01:00
Nate Barbettini
22b4dce608
doc: Add example of testing against TS SDK (#237) 2026-04-24 11:45:09 +01:00
Peter Alexander
7ee58ef780
feat: add conformance scenario for SEP-2164 resource-not-found error code (#200)
* feat: add conformance scenario for SEP-2164 resource-not-found error code

Adds a draft-scoped scenario verifying servers return -32602 (Invalid
Params) for non-existent resources instead of the legacy -32002 or an
empty contents array. Includes a sep-2164.yaml traceability file mapping
each MUST/MUST NOT/SHOULD to its check per the proposed SEP-2484 process.

* fix: align SEP-2164 check severities with spec text (#246)

Splits sep-2164-error-code into:
- sep-2164-no-empty-contents (MUST NOT -> FAILURE)
- sep-2164-error-code (SHOULD -> WARNING)

Updates sep-2164.yaml to quote the spec text verbatim and adds an
excluded row for the client-side -32002 backcompat SHOULD.

See #245 for the SHOULD/WARNING tier-scoring policy discussion.

---------

Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com>
2026-04-24 11:42:51 +01:00
Anubhav Dhawan
64e6c7c0dd
fix(tier-check): add missing markdown table headers for repository health (#239)
Fixes a bug where the Markdown output format for the Repository Health section lacked a table header, causing it to render as raw text instead of a table on GitHub.
2026-04-23 16:36:41 +00:00
Takashi Norimatsu
70cc5efbad
feat: check for PKCE of authorization server metadata (#212) 2026-04-13 17:56:48 +01:00
Nate Barbettini
8d9f80a258
feat: Session ID ASCII validation check (#206)
* Checks for session ASCII correctness

* tests: Session ID ASCII checks
2026-04-13 17:39:39 +01:00
Michito-Okai
050d9cf93a
feat: add conformance test for authorization server metadata (#170) 2026-04-01 08:42:23 -04:00
Paul Carleton
cb0f4c3601
docs: add MAINTAINERS.md and remove experimental warning (#199)
* docs: add MAINTAINERS.md and remove experimental warning from README

* docs: flatten MAINTAINERS.md to single list
2026-03-27 19:25:07 +00:00
Paul Carleton
21a9a2febd
chore: bump version to 0.1.16 (#198) v0.1.16 2026-03-27 11:29:13 +00:00
Anthony
1c48a30ff6
feat: add --spec-version option to tier-check (#176)
* feat: add --spec-version option to tier-check

* refactor: share resolveSpecVersion between CLI and tier-check

Move resolveSpecVersion to src/scenarios/index.ts so tier-check can
reuse it instead of duplicating the validation logic.

---------

Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
2026-03-25 14:53:26 +00:00
Paul Carleton
fe16e381c7
fix: don't leak escalated scopes in PRM scopes_supported for step-up test (#154) 2026-03-25 12:19:11 +00:00
Jeff Handley
a2ec2d44ad
Fix Windows compatibility in tier-check client conformance (#168)
* Fix Windows compatibility in tier-check client conformance

Two issues prevented client conformance tests from running on Windows:

1. Single-quote quoting in execSync: The --command argument was wrapped in single quotes, which cmd.exe treats as literal characters rather than string delimiters. This caused the CLI to receive only the first word of the command. Switched to execFileSync with an args array to bypass shell quoting entirely.

2. Backslash path separators in parseOutputDir: dirname() on Windows returns auth\scenario-name but reconcileWithExpected compares against auth/scenario-name, causing auth scenarios to be double-counted. Normalize backslashes to forward slashes in parsed scenario names.

* fix: use process.argv[1] for CLI path in subprocess calls

Combines the npx-compatibility fix from #175 with this PR's execFileSync
approach. process.argv[1] resolves to the absolute path of the running CLI
regardless of working directory, so tier-check works when invoked via npx
or from any cwd.

---------

Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-03-25 12:03:34 +00:00
Anthony
e702a253ba
fix: resolve CLI path for tier-check conformance subprocess (#175)
Use process.argv[1] instead of relative dist/index.js so tier-check
works when invoked via npx or from outside the package directory.
2026-03-25 12:01:08 +00:00
dependabot[bot]
7b5865a874
chore(deps-dev): bump the all-dependencies group with 2 updates (#196)
Bumps the all-dependencies group with 2 updates: [@typescript/native-preview](https://github.com/microsoft/typescript-go) and [tsdown](https://github.com/rolldown/tsdown).


Updates `@typescript/native-preview` from 7.0.0-dev.20260323.1 to 7.0.0-dev.20260325.1
- [Changelog](https://github.com/microsoft/typescript-go/blob/main/CHANGES.md)
- [Commits](https://github.com/microsoft/typescript-go/commits)

Updates `tsdown` from 0.21.4 to 0.21.5
- [Release notes](https://github.com/rolldown/tsdown/releases)
- [Commits](https://github.com/rolldown/tsdown/compare/v0.21.4...v0.21.5)

---
updated-dependencies:
- dependency-name: "@typescript/native-preview"
  dependency-version: 7.0.0-dev.20260325.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
- dependency-name: tsdown
  dependency-version: 0.21.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 11:49:15 +00:00
Paul Carleton
687d5b4035
chore(deps): ignore major version bumps in dependabot (#195)
Major bumps of devDeps (eslint, typescript, prettier) need manual config
migration and provide no value for conformance testing. Security updates
still come through regardless; scheduled updates are now minor/patch only.
2026-03-25 11:42:31 +00:00
Paul Carleton
4859a81547
docs: add AGENTS.md and CONTRIBUTING.md (#194)
* docs: add AGENTS.md and CONTRIBUTING.md

Codifies scenario design guidelines from past PR reviews:
- fewer scenarios with more checks (CI cost multiplies per-SDK)
- same check id for SUCCESS and FAIL, optimize for Ctrl+F
- extend the everything-client/server rather than adding new example files
- prove it passes and fails
- reuse the CLI runner, don't add parallel entry points

Also asks contributors to open an issue for discussion before a PR, and
to target specific spec MUSTs or open issues rather than running generic
AI bug-hunts against the harness.

* docs: broaden issue-first guidance to cover bugs, not just scenarios
2026-03-25 11:42:06 +00:00
Paul Carleton
8f3994c75f
chore(deps): consolidate dependabot updates (#192)
* chore(deps): consolidate dependabot updates

Bumps all pending dependency updates into one commit:

Root package:
- zod 3.25.76 → 4.3.6 (major)
- @types/node 22 → 25 (major)
- @modelcontextprotocol/sdk 1.26.0 → 1.27.1
- tsdown 0.15.12 → 0.21.4
- prettier 3.6.2 → 3.8.1
- typescript-eslint 8.48.0 → 8.57.1
- lefthook 2.0.2 → 2.1.4
- eslint/@eslint/js → 9.39.4 (kept at v9, typescript-eslint lacks v10 support)
- Regenerated lockfile to pick up transitive security fixes
  (hono, @hono/node-server, express-rate-limit, flatted, rollup,
  minimatch, ajv, qs, undici)

examples/servers/typescript:
- @modelcontextprotocol/sdk → 1.27.1
- Removed zod-to-json-schema (broken with zod v4)
- Added zod ^4 as direct dep
- Regenerated lockfile

GitHub Actions:
- actions/setup-node v4 → v6 in action.yml

Code changes for zod v4:
- ZodError.errors → ZodError.issues (src/index.ts)
- .refine() callback signature updated (src/schemas.ts)
- everything-server: replaced zodToJsonSchema with SDK's
  toJsonSchemaCompat helper (handles zod v3/v4/v4-mini)

Build fix for tsdown 0.21:
- Added --no-fixed-extension to preserve dist/index.js output
  (tsdown 0.21 defaults to .mjs for type:module packages)

* fix: include all platform binaries in lockfile

The lockfile was generated on macOS which caused npm to only resolve
darwin-arm64 entries for platform-specific optional dependencies
(esbuild, rolldown bindings). This broke npm ci on Linux CI runners.

Regenerated from a clean state to include all 26 esbuild platforms
and all 15 rolldown platform bindings.
2026-03-24 16:18:54 +00:00
Wils Dawson
02a5f1c41d
feat (auth): add sep-2207 client checks (#166)
* feat: add sep-2207 client checks

* Update description for the offline access test

Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com>

---------

Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com>
2026-03-18 08:34:17 +00:00
Maciej Kisiel
22f5c8bb1c
chore: update Node.js version in the conformance action to 22 (#162)
With Node.js 20 the action fails with:

```
SyntaxError: The requested module 'fs' does not provide an export named 'globSync'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:213:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:320:5)
    at async ModuleLoader.import (node:internal/modules/esm/loader:606:24)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5)
```

`fs.globSync` was added in Node.js 22.
2026-03-02 10:03:15 +00:00
Paul Carleton
a2855b0358
0.1.15 (#156) v0.1.15 2026-02-20 14:41:15 +00:00
Daniel Garnier-Moiroux
50c3cf1a43
fix: include tenant path in auth server issuer claim (#152)
- Fixes gh-140

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2026-02-20 14:32:19 +00:00
Felix Weinberger
066b2d7080
fix: tier-check branch support and draft/extension scoring (#153)
* fix: pass --branch to tier-check CLI in tier-audit skill

The skill was not forwarding the --branch argument to the tier-check
CLI, causing policy signal checks to always run against the repo's
default branch. Files on feature branches showed as 'Not found.'

Now derives the branch from the local checkout if not explicitly
provided, and always passes it to the CLI.

* fix: exclude draft/extension scenarios from tier-scoring conformance rates

SEP-1730 says date-versioned scenarios count toward tier scoring while
draft and extension scenarios are informational. The CLI was including
all scenarios in pass_rate, causing extension-only failures to block
Tier 1.

Changes:
- pass_rate now only counts scenarios with at least one date-versioned
  spec version
- Terminal and markdown output split into a tier-scoring matrix
  (date-versioned + All*) and an informational section (draft/extension)
  that only renders when there are draft/extension scenarios
2026-02-17 13:09:31 +00:00
Paul Carleton
8ab0831130
0.1.14 (#149) 2026-02-13 19:13:12 +00:00
Felix Weinberger
3f9048a019
feat: add specVersion classification to conformance scenarios (#147)
* feat: add specVersions classification to conformance scenarios

Each scenario declares which spec versions it applies to as a list.
Scenarios that carry forward (e.g. initialize) list all applicable versions
['2025-06-18', '2025-11-25']. Scenarios removed from newer specs (e.g.
backcompat auth) only list their original version ['2025-03-26'].

- specVersions list on Scenario and ClientScenario interfaces
- --spec-version CLI filter uses simple .includes()
- Tier-check conformance matrix (Server / Client: Core / Client: Auth)
  with per-version columns and unique All* count
- 7 unit tests for specVersions helpers
- Updated tier-audit skill docs with matrix format

* fix: fix console output template for tier audit skill

The template had an orphan table header (Check | Value | T2 | T1)
with no rows above the conformance matrix, causing an empty table
to render. The scorecard rows below the matrix also lacked their
own header.

Fix: two self-contained tables with clear labels — 'Conformance:'
for the per-version matrix, 'Scorecard:' for the check rows.

* fix: align skill console template with tier-check script output

Add asterisk footnote ('unique scenarios — a scenario may apply to
multiple spec versions') and rename 'Scorecard' to 'Repository Health'
to match the labels used by the tier-check CLI output.

* fix: add specVersions to CrossAppAccessCompleteFlowScenario

Added in 83c446d on main after this branch diverged.
2026-02-13 18:08:15 +00:00
jd
dd14862ee4
fix: use InvalidTokenError instead of generic Error in MockTokenVerifier (#138)
The SDK's `requireBearerAuth` middleware only converts `InvalidTokenError`
instances to HTTP 401 responses. Generic `Error` instances fall through
as HTTP 500, which prevents clients from detecting authentication failures
and initiating the OAuth refresh/re-auth flow.

This was discovered while building token refresh conformance scenarios —
the mock server was returning 500 for expired/invalid tokens instead of
the expected 401.

Co-authored-by: JD Maturen <70791+jdmaturen@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-13 17:59:48 +00:00
sagar-okta
83c446ddf5
feat: add conformance tests for SEP-990 (#110)
* feat: add conformance tests for SEP-990

* Resolving review changes: Removed redundant tests, updated audience params

* fix: unused serverUrl parameter in runCrossAppAccessTokenExchange

* chore: apply prettier formatting

* fix: address PR review comments for SEP-990 conformance tests

- Delete unused separate token-exchange and jwt-bearer scenarios,
  keeping only the complete e2e flow (review comment)
- Add missing required token exchange params per SEP-990 spec:
  requested_token_type, audience, resource (review comment)
- Use ctx.idp_client_id for token exchange client_id instead of
  AS client_id (review comment)
- Client discovers resource and auth server via PRM metadata
  instead of receiving auth_server_url via context (review comment)
- Server IdP handler verifies all required token exchange params
  with detailed error messages (review comment)
- Add resource, client_id, jti claims to ID-JAG per SEP-990 spec
- Verify ID-JAG typ header (oauth-id-jag+jwt) in JWT bearer handler
- Remove auth_server_url from context schema

* feat: add client auth and ID-JAG validation to XAA conformance test

Server-side (AS) now verifies:
- client_secret_basic authentication on JWT bearer grant
- ID-JAG typ header is oauth-id-jag+jwt
- ID-JAG client_id claim matches the authenticating client (Section 5.1)
- ID-JAG resource claim matches the MCP server resource identifier
- Client credentials provided via context (client_secret)

Server-side (IdP) now:
- Sets ID-JAG client_id to the MCP Client's AS client_id (not the
  IdP client_id), per Section 6.1

Example client now:
- Authenticates to AS via client_secret_basic (Authorization: Basic)
  instead of sending client_id in body
- Checks AS metadata grant_types_supported includes jwt-bearer
  before attempting the flow

* fix: share MockTokenVerifier and remove unadvertised auth method

- Add shared MockTokenVerifier between AS and MCP server so the MCP
  server only accepts tokens actually issued by the auth server,
  matching the pattern used by all other auth scenarios
- Remove private_key_jwt from tokenEndpointAuthMethodsSupported since
  the handler only implements client_secret_basic

---------

Co-authored-by: Paul Carleton <paulc@anthropic.com>
2026-02-13 17:47:54 +00:00
Felix Weinberger
c82fd65cfa
fix: recurse into subdirectories when parsing conformance output (#148)
parseOutputDir only read one level deep, so scenarios with '/' in their
name (e.g. auth/metadata-default) were stored in nested subdirectories
and never found. This caused tier-check to report 4/23 client conformance
when the actual pass rate was 23/23.

Also removes accidentally committed pnpm-lock.yaml.
2026-02-13 16:13:48 +00:00
Felix Weinberger
3b4a92baad
feat: SDK tier assessment CLI and skill (#142)
* feat: add tier-check CLI for SDK tier assessment

Adds a 'tier-check' subcommand to the conformance tool that automates
SDK tier assessment against SEP-1730 criteria.

Checks performed:
- Conformance test pass rate (via everything-server)
- GitHub label taxonomy (priority/status/area labels)
- Issue triage SLA compliance
- P0 bug resolution tracking
- Stable release detection
- Required file existence (CHANGELOG, SECURITY, etc.)
- Spec tracking (SDK release within 30d of spec release)

Also includes a Claude Code skill (skills/mcp-sdk-tier-audit/) for
judgment-based checks that require codebase analysis (feature coverage,
docs quality, policy evaluation).

Usage:
  npx tsx src/index.ts tier-check --repo modelcontextprotocol/typescript-sdk
  npx tsx src/index.ts tier-check --repo ... --conformance-server-cmd '...' \
    --conformance-server-cwd ... --conformance-server-url ... --output json

* refactor: revise tier-check CLI and skill based on review feedback

- Move skill to .claude/skills/ so it's auto-available in Claude Code
- Remove feature-coverage subagent (redundant with conformance tests)
- Remove hardcoded ~/src/mcp paths from all skill files
- Trim conformance server table to TS + Python only
- Rename file_existence check to policy_signals (informational, not blocking)
- Add GitHub native issue types detection to labels check
- Add missing features to docs-coverage checklist (tasks, elicitation URL mode, JSON Schema 2020-12)
- Add README with CLI quick start and escape hatch for non-Claude-Code users
- Use --limit 500 instead of --limit 100 for gh issue list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback on skill and README

- Use npx @modelcontextprotocol/conformance instead of node dist/index.js
- Add full GitHub auth instructions (gh auth login, GITHUB_TOKEN, --token)
- Point TS SDK conformance server to typescript-sdk/test/conformance/
- Fix Python SDK URL to localhost:3001/mcp (not TBD)
- Remove manual gh issue list / gh release list from SKILL.md (CLI handles it)
- Remove Claude Code-specific subagent_type references
- Assume user is already in conformance repo
- Clean up policy-evaluation-prompt.md: remove redundant grep commands,
  focus on content evaluation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve lint errors in conformance.ts

Remove unused variable assignments flagged by eslint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: apply prettier formatting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add npm run tier-check script, update docs with examples

- Add "tier-check" npm script so users can run `npm run tier-check --`
  instead of `node dist/index.js tier-check`
- Update SKILL.md, README, and skill README to use npm run tier-check
- Add full conformance examples with --conformance-server-cmd/cwd/url
  flags and realistic paths (~/src/mcp/typescript-sdk)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: fix prettier formatting in SKILL.md

* fix: add per-scenario timeout, support url-only conformance, fix stdout pollution

- Add 30s per-scenario timeout to prevent tier-check from hanging
- Allow --conformance-server-url without --conformance-server-cmd (server already running)
- Move runner status logs to stderr so --output json produces clean JSON
- Update SKILL.md and README with --silent flag and pre-start server workflow

* refactor: skill takes local path + server URL instead of repo name

The skill now requires two arguments:
1. Local path to the SDK checkout (for direct file inspection)
2. URL where the everything server is already running

The GitHub owner/repo is derived from git remote. This eliminates
cloning, server startup complexity, and branch confusion (v1.x vs main).

* refactor: write detailed reports to files, show concise summary

Reports go to results/tier-audits/<sdk>-<date>/ (already gitignored).
Claude's console output is now just the tier classification,
pass/fail summary line, top 3 actions, and file paths.

* docs: update READMEs for new skill interface and pre-start workflow

* simplify: flat file output instead of nested directory

* fix: remediation always shows path to Tier 2 and Tier 1

* feat: add client conformance testing to tier-check CLI and skill

- Add checkClientConformance() that runs core client scenarios
  (initialize, tools_call, elicitation-defaults, sse-retry, auth)
  by spawning the SDK's conformance client via --client-cmd
- Add client_conformance to TierScorecard type
- Wire --client-cmd option into the CLI
- Update tier logic: both server + client conformance feed into
  Tier 1 (100%) and Tier 2 (>=80%) requirements
- Update terminal and markdown output to show both conformance types
- Update skill to auto-detect conformance client or accept explicit
  client-cmd argument
- Update README with new option and examples

* improve: table summary output, write reports via subagents

- Change executive summary from pipe-delimited line to a readable
  table with T2/T1 columns
- Move assessment and remediation file writing into parallel
  subagents to keep the main conversation thread clean

* improve: list tier gaps as numbered items instead of one-line blob

* improve: finalize summary format with separator, high-priority fixes, numbered gaps

* improve: add pre-flight checks for gh auth and server reachability

Fail fast with clear error messages if GitHub CLI is not authenticated
or if the conformance server URL is not reachable, rather than failing
deep into the scorecard run.

* docs: improve README and fix skill auto-detection paths

- Claude Code section: explain client-cmd auto-detection for TS/Python,
  show explicit 3-arg form for other SDKs, add examples for all three
- Fix TypeScript build command (npm run build, not pnpm build:all)
- Fix Python server command (add --port, use uv sync --package)
- Fix Python client path (.github/actions/conformance/client.py)
- Expand 'Other SDKs' section with guidance on everything server
- Add gh auth login prerequisite to Claude Code steps

* simplify: remove client-cmd auto-detection, require explicit argument

Client command is now always passed as the third argument. If omitted,
client conformance is skipped and noted as a gap. No more magic path
detection — clearer and more predictable.

* fix: align docs table with canonical list (48 features), simplify policy eval

Docs coverage:
- Table now has numbered rows matching all 48 non-experimental features
  from the canonical list (was missing 7: tools text/image/audio/embedded/
  error/notifications, protocol version negotiation)
- Hardcode total as 48 in summary so agents don't miscount

Policy evaluation:
- Simplified from deep content analysis to file-existence checks
- Dependency policy: DEPENDENCY_POLICY.md, dependabot.yml, or CONTRIBUTING.md section
- Roadmap: ROADMAP.md must exist (GitHub milestones alone not sufficient)
- Versioning: VERSIONING.md or CONTRIBUTING.md section
- Removed GitHub API calls for milestones and releases from policy eval

* refactor: extract canonical feature list into single source of truth

Create references/feature-list.md with all 48 non-experimental + 5
experimental features. The docs-coverage prompt now references this
file instead of duplicating the list. One place to update when
features change.

* fix: separate deterministic file checks from AI content evaluation

CLI (files.ts): now checks all policy files deterministically —
DEPENDENCY_POLICY.md, docs/dependency-policy.md, dependabot.yml,
renovate.json, ROADMAP.md, docs/roadmap.md, VERSIONING.md,
docs/versioning.md, BREAKING_CHANGES.md (in addition to existing
CHANGELOG.md, SECURITY.md, CONTRIBUTING.md).

AI policy eval: receives CLI output showing which files exist,
then reads ONLY those files to judge content quality. No longer
searches the repo for files — clean separation of concerns.

* style: apply prettier formatting

* revert: undo unrelated console.log change in runner/server.ts

* refactor: shell out to conformance CLI instead of reimplementing runner

Address PR feedback: conformance.ts was duplicating the normal conformance
running code. Now shells out to 'node dist/index.js server/client' with
-o to save results to a temp dir, then parses the checks.json files.

Also removes --conformance-server-cmd and --conformance-server-cwd options
since the server must be pre-started.

* docs: add Go and C# SDK examples to README and SKILL.md

* fix: add --framework net9.0 to C# server command

* rename: conformance.ts -> test-conformance-results.ts

Avoids confusion with src/runner/ (the actual conformance runner).
This file just invokes the CLI and parses output.

* style: prettier formatting

* fix: reconcile conformance results against full scenario list

The tier-check CLI was only counting scenarios that produced a
checks.json file. Scenarios that crashed or failed to run (e.g., auth
scenarios when OAuth is not implemented) were invisible, making the
denominator artificially small (e.g., 4/4 instead of 4/23).

Now both checkConformance and checkClientConformance reconcile their
parsed results against the known scenario lists, adding failure entries
for any expected scenario that didn't produce results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: tighten documentation evaluation criteria

Clarify what counts as documented vs just having code:
- Conformance test servers don't count as docs or examples
- Examples without prose = PARTIAL, not PASS
- Go Example* test functions explicitly allowed
- Clear PASS/PARTIAL/FAIL verdict definitions

* docs: add Labels and Spec Tracking rows to audit report templates

The executive summary and assessment report were missing two SEP-1730
requirements: label taxonomy compliance and spec tracking (new protocol
features timeline).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: reuse ConformanceCheck type from src/types.ts instead of redefining

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:59:06 +00:00
Felix Weinberger
37225cef7d
fix: create fresh Server per request in auth test helpers (#141)
The auth test server helper and no-dns-rebinding-protection example
reused a single Server instance across requests, calling connect()
on each new transport. SDK v1.26.0's security fix (GHSA-345p-7cg4-v4c7)
now throws "Already connected to a transport" in this case.

Fix by wrapping Server creation in a factory function called per
request, matching the pattern already used by tools_call.ts and
everything-server.ts.

Also updates no-dns-rebinding-protection.ts to use registerTool()
instead of the deprecated tool() API.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:22:16 +00:00
Paul Carleton
a1b8aaae5e
0.1.13 (#136) v0.1.13 2026-02-05 16:10:50 +00:00
Paul Carleton
22196ca809
fix: bump SDK to 1.26.0, add session management to tools_call scenario (#134)
* fix: bump SDK to 1.26.0, add session management to tools_call scenario

SDK 1.26.0 made Protocol.connect() throw if already connected to a
transport. The tools_call scenario was calling server.connect(transport)
on every request with the same Server instance, which now throws.

Fixed by adding proper session management: each initialize request
creates a new Server + Transport pair, and subsequent requests are
routed to the correct transport via the mcp-session-id header.

* fix: return 404 for invalid session IDs in tools_call POST handler

The else branch was returning 400 for both missing-session and
invalid/stale-session cases. The MCP spec requires 404 for invalid
session IDs and 400 only for non-initialization requests without
any session ID.

* refactor: keep tools_call stateless, create fresh server per request

Instead of adding session management, simply create a new Server
instance per request. This preserves the original stateless design
while fixing the SDK 1.26.0 Protocol.connect() restriction.
2026-02-05 15:43:21 +00:00
dependabot[bot]
189a31dc47
Bump hono from 4.11.4 to 4.11.7 (#124)
Bumps [hono](https://github.com/honojs/hono) from 4.11.4 to 4.11.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.11.4...v4.11.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.11.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-30 09:59:34 +00:00
Paul Carleton
4bfafd5e31
chore: 0.1.12 (#128) v0.1.12
* chore: bump version to 0.1.12-alpha.0 for OIDC trusted publishing test

* ci: rename prerelease checkbox to publish_alpha, clarify no-publish default

* 0.1.12
2026-01-29 18:19:35 +00:00