From 65b34e510e3c2e8956ba021c6be9cedfe8375d0f Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 16:54:14 +0000 Subject: [PATCH 01/34] 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 --- package-lock.json | 1936 +++++++---------- package.json | 3 +- skills/mcp-sdk-tier-audit/SKILL.md | 232 ++ .../references/docs-coverage-prompt.md | 211 ++ .../references/feature-coverage-prompt.md | 251 +++ .../references/feature-list.md | 156 ++ .../references/policy-evaluation-prompt.md | 212 ++ .../references/report-template.md | 139 ++ .../references/tier-requirements.md | 97 + src/index.ts | 4 + src/tier-check/checks/conformance.ts | 112 + src/tier-check/checks/files.ts | 38 + src/tier-check/checks/labels.ts | 49 + src/tier-check/checks/p0.ts | 89 + src/tier-check/checks/release.ts | 59 + src/tier-check/checks/spec-tracking.ts | 79 + src/tier-check/checks/triage.ts | 110 + src/tier-check/index.ts | 179 ++ src/tier-check/output.ts | 141 ++ src/tier-check/tier-logic.ts | 61 + src/tier-check/types.ts | 85 + 21 files changed, 3104 insertions(+), 1139 deletions(-) create mode 100644 skills/mcp-sdk-tier-audit/SKILL.md create mode 100644 skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md create mode 100644 skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md create mode 100644 skills/mcp-sdk-tier-audit/references/feature-list.md create mode 100644 skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md create mode 100644 skills/mcp-sdk-tier-audit/references/report-template.md create mode 100644 skills/mcp-sdk-tier-audit/references/tier-requirements.md create mode 100644 src/tier-check/checks/conformance.ts create mode 100644 src/tier-check/checks/files.ts create mode 100644 src/tier-check/checks/labels.ts create mode 100644 src/tier-check/checks/p0.ts create mode 100644 src/tier-check/checks/release.ts create mode 100644 src/tier-check/checks/spec-tracking.ts create mode 100644 src/tier-check/checks/triage.ts create mode 100644 src/tier-check/index.ts create mode 100644 src/tier-check/output.ts create mode 100644 src/tier-check/tier-logic.ts create mode 100644 src/tier-check/types.ts diff --git a/package-lock.json b/package-lock.json index 936103b..250c002 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.26.0", + "@octokit/rest": "^22.0.0", "commander": "^14.0.2", "eventsource-parser": "^3.0.6", "express": "^5.1.0", @@ -39,14 +40,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -76,13 +77,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -92,9 +93,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -106,9 +107,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.6.0.tgz", - "integrity": "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", "dev": true, "license": "MIT", "optional": true, @@ -118,9 +119,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", - "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "dev": true, "license": "MIT", "optional": true, @@ -140,9 +141,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", - "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ "ppc64" ], @@ -157,9 +158,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz", - "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "cpu": [ "arm" ], @@ -174,9 +175,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz", - "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "cpu": [ "arm64" ], @@ -191,9 +192,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz", - "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "cpu": [ "x64" ], @@ -208,9 +209,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz", - "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "cpu": [ "arm64" ], @@ -225,9 +226,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz", - "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "cpu": [ "x64" ], @@ -242,9 +243,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz", - "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "cpu": [ "arm64" ], @@ -259,9 +260,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz", - "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "cpu": [ "x64" ], @@ -276,9 +277,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz", - "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "cpu": [ "arm" ], @@ -293,9 +294,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz", - "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ "arm64" ], @@ -310,9 +311,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz", - "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "cpu": [ "ia32" ], @@ -327,9 +328,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz", - "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "cpu": [ "loong64" ], @@ -344,9 +345,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz", - "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "cpu": [ "mips64el" ], @@ -361,9 +362,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz", - "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "cpu": [ "ppc64" ], @@ -378,9 +379,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz", - "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "cpu": [ "riscv64" ], @@ -395,9 +396,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz", - "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "cpu": [ "s390x" ], @@ -412,9 +413,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", - "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "cpu": [ "x64" ], @@ -429,9 +430,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz", - "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "cpu": [ "arm64" ], @@ -446,9 +447,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz", - "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "cpu": [ "x64" ], @@ -463,9 +464,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz", - "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "cpu": [ "arm64" ], @@ -480,9 +481,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz", - "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "cpu": [ "x64" ], @@ -497,9 +498,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz", - "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "cpu": [ "arm64" ], @@ -514,9 +515,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz", - "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "cpu": [ "x64" ], @@ -531,9 +532,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz", - "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "cpu": [ "arm64" ], @@ -548,9 +549,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz", - "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "cpu": [ "ia32" ], @@ -565,9 +566,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz", - "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "cpu": [ "x64" ], @@ -582,9 +583,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -651,7 +652,7 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-helpers/node_modules/@eslint/core": { + "node_modules/@eslint/core": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", @@ -664,23 +665,10 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/core": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", - "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -690,7 +678,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -701,10 +689,34 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -738,19 +750,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@hono/node-server": { "version": "1.19.9", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", @@ -894,39 +893,175 @@ } } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/Brooooooklyn" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz", + "integrity": "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", "license": "MIT" }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", - "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", - "dev": true, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", "license": "MIT", - "optional": true, "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@tybys/wasm-util": "^0.10.1" + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz", + "integrity": "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.2", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/request-error": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", + "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest": { + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.1.tgz", + "integrity": "sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^27.0.0" } }, "node_modules/@oxc-project/types": { @@ -940,13 +1075,13 @@ } }, "node_modules/@quansync/fs": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-0.1.5.tgz", - "integrity": "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", "dev": true, "license": "MIT", "dependencies": { - "quansync": "^0.2.11" + "quansync": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" @@ -1198,9 +1333,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", "cpu": [ "arm" ], @@ -1212,9 +1347,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", "cpu": [ "arm64" ], @@ -1226,9 +1361,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", "cpu": [ "arm64" ], @@ -1240,9 +1375,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", "cpu": [ "x64" ], @@ -1254,9 +1389,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", "cpu": [ "arm64" ], @@ -1268,9 +1403,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", "cpu": [ "x64" ], @@ -1282,9 +1417,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", "cpu": [ "arm" ], @@ -1296,9 +1431,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", "cpu": [ "arm" ], @@ -1310,9 +1445,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", "cpu": [ "arm64" ], @@ -1324,9 +1459,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", "cpu": [ "arm64" ], @@ -1338,9 +1473,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", "cpu": [ "loong64" ], @@ -1352,9 +1487,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", "cpu": [ "loong64" ], @@ -1366,9 +1501,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", "cpu": [ "ppc64" ], @@ -1380,9 +1515,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", "cpu": [ "ppc64" ], @@ -1394,9 +1529,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", "cpu": [ "riscv64" ], @@ -1408,9 +1543,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", "cpu": [ "riscv64" ], @@ -1422,9 +1557,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", "cpu": [ "s390x" ], @@ -1436,9 +1571,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", "cpu": [ "x64" ], @@ -1450,9 +1585,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", "cpu": [ "x64" ], @@ -1464,9 +1599,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", "cpu": [ "x64" ], @@ -1478,9 +1613,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", "cpu": [ "arm64" ], @@ -1492,9 +1627,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", "cpu": [ "arm64" ], @@ -1506,9 +1641,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", "cpu": [ "ia32" ], @@ -1520,9 +1655,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", "cpu": [ "x64" ], @@ -1534,9 +1669,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", "cpu": [ "x64" ], @@ -1612,21 +1747,21 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" + "@types/serve-static": "^2" } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", "dev": true, "license": "MIT", "dependencies": { @@ -1647,13 +1782,15 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "22.18.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.12.tgz", - "integrity": "sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog==", + "version": "22.19.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz", + "integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } @@ -1673,9 +1810,9 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.0.tgz", - "integrity": "sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1951,28 +2088,28 @@ } }, "node_modules/@typescript/native-preview": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-EiPEgGwNa2uHyyKgeoWTL6wWHKUBmF3xsfZ3OHofk7TxUuxb2mpLG5igEuaBe8iUwkCUl9uZgJvOu6o0wE5NSA==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-vy52DLNMYVTizp02/Uu8TrHQrt3BU0b7foE7qqxPAZF63zXpwvGg1g4EAgFtu7ZDJlYrAlUqSdZg6INb/3iY6w==", "dev": true, "license": "Apache-2.0", "bin": { "tsgo": "bin/tsgo.js" }, "optionalDependencies": { - "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20251201.1", - "@typescript/native-preview-darwin-x64": "7.0.0-dev.20251201.1", - "@typescript/native-preview-linux-arm": "7.0.0-dev.20251201.1", - "@typescript/native-preview-linux-arm64": "7.0.0-dev.20251201.1", - "@typescript/native-preview-linux-x64": "7.0.0-dev.20251201.1", - "@typescript/native-preview-win32-arm64": "7.0.0-dev.20251201.1", - "@typescript/native-preview-win32-x64": "7.0.0-dev.20251201.1" + "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260210.1", + "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260210.1", + "@typescript/native-preview-linux-arm": "7.0.0-dev.20260210.1", + "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260210.1", + "@typescript/native-preview-linux-x64": "7.0.0-dev.20260210.1", + "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260210.1", + "@typescript/native-preview-win32-x64": "7.0.0-dev.20260210.1" } }, "node_modules/@typescript/native-preview-darwin-arm64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-PY0BrlRF3YCZEMxzuk79IFSgpGqUErkdrW7Aq+/mF8DEET5uaDypTMb8Vz4CLYJ7Xvvxz8eZsLimPbv6hYDIvA==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-taEYpsrCbdcyHkqNMBiVcqKR7ZHMC1jwTBM9kn3eUgOjXn68ASRrmyzYBdrujluBJMO7rl+Gm5QRT68onYt53A==", "cpu": [ "arm64" ], @@ -1984,9 +2121,9 @@ ] }, "node_modules/@typescript/native-preview-darwin-x64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-YeDrjnsvXwm/MNG8aURT3J+cmHQIhpiElBKOVOy/H6ky4S2Ro9ufG+Bj9CqS3etbTCLhV5btk+QNh86DZ4VDkQ==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-TSgIk2osa3UpivKybsyglBx7KBL+vTNayagmpzYvxBXbPvBnbgGOgzE/5iHkzFJYVUFxqmuj1gopmDT9X/obaQ==", "cpu": [ "x64" ], @@ -1998,9 +2135,9 @@ ] }, "node_modules/@typescript/native-preview-linux-arm": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-gr2EQYK888YdGROMc7l3N3MeKY1V3QVImKIQZNgqprV+N2rXaFnxGAZ+gql3LqZgRGel4a12vCUJeP7Pjl2gww==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-2matUA2ZU/1Zdv/pWLsdNwdzkOxBPeLa1581wgnaANrzZD3IJm4eCMfidRFTh9fVPN/eMsthYOeSnuVJa/mPmg==", "cpu": [ "arm" ], @@ -2012,9 +2149,9 @@ ] }, "node_modules/@typescript/native-preview-linux-arm64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-HbEn+SBTDZEtwN/VUxA2To+6vEr7x++SCRc6yGp5y4onpBL2xnH17UoxWiqN9J4Bu1DbQ9jZv3D5CzwBlofPQA==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-aSdY/1Uh+4hOpQT1jHvM16cNqXv6lihe3oZmGTV6DmgkeH9soGXRumbu+oA73E3w0Hm6PjD/aIzbvK53yjvN1Q==", "cpu": [ "arm64" ], @@ -2026,9 +2163,9 @@ ] }, "node_modules/@typescript/native-preview-linux-x64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-q94K/LZ3Ab/SbUBMBsf37VdsumeZ1dZmymJYlhGBqk/fdXBayL0diLR3RdzyeQWbCXAxWL5KFKLIiIc3cI/fcA==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-7C5mhiOFzWB+hdoCuog9roQuNFFHALw1jz0zrA9ikH18DOgnnGJpGLuekQJdXG1yQSdrALZROXLidTmVxFYSgg==", "cpu": [ "x64" ], @@ -2040,9 +2177,9 @@ ] }, "node_modules/@typescript/native-preview-win32-arm64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-/AFwpsX/G05bBsfVURfg4+/JC6gfvqj9jfFe/7oe1Y1J42koN5C8TH+eSmMOOEcPYpFjR1e+NWckqBJKaCXJ4A==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-n8/tI1rOrqy+kFqrNc4xBYaVc1eGn5SYS9HHDZOPZ8E2b3Oq7RAPSZdNi+YYwMcOx3MFon0Iu6mZ1N6lqer9Dw==", "cpu": [ "arm64" ], @@ -2054,9 +2191,9 @@ ] }, "node_modules/@typescript/native-preview-win32-x64": { - "version": "7.0.0-dev.20251201.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20251201.1.tgz", - "integrity": "sha512-vTUCDEuSP4ifLHqb8aljuj44v6+M1HDKo1WLnboTDpwU7IIrTux/0jzkPfEHd9xd5FU4EhSA8ZrYDwKI0BcRcg==", + "version": "7.0.0-dev.20260210.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20260210.1.tgz", + "integrity": "sha512-wC/Aoxf/5/m/7alzb7RxLivGuYwZw3/Iq7RO73egG70LL2RLUuP306MDg1sj2TyeAe+S3zZX3rU1L6qMOW439A==", "cpu": [ "x64" ], @@ -2068,16 +2205,16 @@ ] }, "node_modules/@vitest/expect": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.16.tgz", - "integrity": "sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.16", - "@vitest/utils": "4.0.16", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" }, @@ -2086,13 +2223,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.16.tgz", - "integrity": "sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.16", + "@vitest/spy": "4.0.18", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -2113,9 +2250,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.16.tgz", - "integrity": "sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", "dev": true, "license": "MIT", "dependencies": { @@ -2126,13 +2263,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.16.tgz", - "integrity": "sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.16", + "@vitest/utils": "4.0.18", "pathe": "^2.0.3" }, "funding": { @@ -2140,13 +2277,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.16.tgz", - "integrity": "sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.16", + "@vitest/pretty-format": "4.0.18", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2155,9 +2292,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.16.tgz", - "integrity": "sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", "dev": true, "license": "MIT", "funding": { @@ -2165,13 +2302,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.16.tgz", - "integrity": "sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.16", + "@vitest/pretty-format": "4.0.18", "tinyrainbow": "^3.0.3" }, "funding": { @@ -2209,21 +2346,21 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -2247,28 +2384,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2313,13 +2428,13 @@ } }, "node_modules/ast-kit": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.1.3.tgz", - "integrity": "sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.4", + "@babel/parser": "^7.28.5", "pathe": "^2.0.3" }, "engines": { @@ -2329,24 +2444,6 @@ "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/async-generator-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-generator-function/-/async-generator-function-1.0.0.tgz", - "integrity": "sha512-+NAXNqgCrB95ya4Sr66i1CL2hqLVckAk7xwRYWdcm39/ELQ6YNn1aw5r0bdQtqNZgQpEWzc5yc/igXc7aL5SLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2354,10 +2451,16 @@ "dev": true, "license": "MIT" }, + "node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "license": "Apache-2.0" + }, "node_modules/birpc": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz", - "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", "dev": true, "license": "MIT", "funding": { @@ -2365,9 +2468,9 @@ } }, "node_modules/body-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", - "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -2376,7 +2479,7 @@ "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.14.0", + "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" }, @@ -2521,9 +2624,9 @@ "license": "MIT" }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "license": "MIT", "engines": { "node": ">=20" @@ -2537,15 +2640,16 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -2576,9 +2680,9 @@ } }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -2586,6 +2690,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cross-spawn": { @@ -2653,13 +2761,13 @@ } }, "node_modules/dts-resolver": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.2.tgz", - "integrity": "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" @@ -2750,9 +2858,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", - "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2763,32 +2871,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.11", - "@esbuild/android-arm": "0.25.11", - "@esbuild/android-arm64": "0.25.11", - "@esbuild/android-x64": "0.25.11", - "@esbuild/darwin-arm64": "0.25.11", - "@esbuild/darwin-x64": "0.25.11", - "@esbuild/freebsd-arm64": "0.25.11", - "@esbuild/freebsd-x64": "0.25.11", - "@esbuild/linux-arm": "0.25.11", - "@esbuild/linux-arm64": "0.25.11", - "@esbuild/linux-ia32": "0.25.11", - "@esbuild/linux-loong64": "0.25.11", - "@esbuild/linux-mips64el": "0.25.11", - "@esbuild/linux-ppc64": "0.25.11", - "@esbuild/linux-riscv64": "0.25.11", - "@esbuild/linux-s390x": "0.25.11", - "@esbuild/linux-x64": "0.25.11", - "@esbuild/netbsd-arm64": "0.25.11", - "@esbuild/netbsd-x64": "0.25.11", - "@esbuild/openbsd-arm64": "0.25.11", - "@esbuild/openbsd-x64": "0.25.11", - "@esbuild/openharmony-arm64": "0.25.11", - "@esbuild/sunos-x64": "0.25.11", - "@esbuild/win32-arm64": "0.25.11", - "@esbuild/win32-ia32": "0.25.11", - "@esbuild/win32-x64": "0.25.11" + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, "node_modules/escape-html": { @@ -2811,19 +2919,20 @@ } }, "node_modules/eslint": { - "version": "9.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", - "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.1", - "@eslint/core": "^0.16.0", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.38.0", - "@eslint/plugin-kit": "^0.4.0", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -2915,19 +3024,30 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "9.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", - "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://eslint.org/donate" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -2947,9 +3067,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3033,9 +3153,9 @@ } }, "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3103,18 +3223,34 @@ "express": ">= 4.11" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -3162,6 +3298,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -3170,9 +3307,9 @@ } }, "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -3183,7 +3320,11 @@ "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/find-up": { @@ -3247,6 +3388,7 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -3265,29 +3407,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-intrinsic": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.1.tgz", - "integrity": "sha512-fk1ZVEeOX9hVZ6QzoBNEC55+Ucqg4sTVwrVuigZhuRPESVFpMyXnd3sbXvPOwp7Y9riVyANiqhEuRF0G1aVSeQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "async-function": "^1.0.0", - "async-generator-function": "^1.0.0", "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "generator-function": "^2.0.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", @@ -3315,9 +3445,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -3407,9 +3537,9 @@ } }, "node_modules/hono": { - "version": "4.11.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", - "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz", + "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", "license": "MIT", "engines": { "node": ">=16.9.0" @@ -3423,34 +3553,29 @@ "license": "MIT" }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -3612,10 +3737,9 @@ "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, "node_modules/json-schema-typed": { @@ -3642,31 +3766,32 @@ } }, "node_modules/lefthook": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.0.2.tgz", - "integrity": "sha512-2lrSva53G604ZWjK5kHYvDdwb5GzbhciIPWhebv0A8ceveqSsnG2JgVEt+DnhOPZ4VfNcXvt3/ohFBPNpuAlVw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.1.0.tgz", + "integrity": "sha512-+vS+yywGQW6CN1J1hbGkez//6ixGHIQqfxDN/d3JDm531w9GfGt2lAWTDfZTw/CEl80XsN0raFcnEraR3ldw9g==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "lefthook": "bin/index.js" }, "optionalDependencies": { - "lefthook-darwin-arm64": "2.0.2", - "lefthook-darwin-x64": "2.0.2", - "lefthook-freebsd-arm64": "2.0.2", - "lefthook-freebsd-x64": "2.0.2", - "lefthook-linux-arm64": "2.0.2", - "lefthook-linux-x64": "2.0.2", - "lefthook-openbsd-arm64": "2.0.2", - "lefthook-openbsd-x64": "2.0.2", - "lefthook-windows-arm64": "2.0.2", - "lefthook-windows-x64": "2.0.2" + "lefthook-darwin-arm64": "2.1.0", + "lefthook-darwin-x64": "2.1.0", + "lefthook-freebsd-arm64": "2.1.0", + "lefthook-freebsd-x64": "2.1.0", + "lefthook-linux-arm64": "2.1.0", + "lefthook-linux-x64": "2.1.0", + "lefthook-openbsd-arm64": "2.1.0", + "lefthook-openbsd-x64": "2.1.0", + "lefthook-windows-arm64": "2.1.0", + "lefthook-windows-x64": "2.1.0" } }, "node_modules/lefthook-darwin-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.0.2.tgz", - "integrity": "sha512-x/4AOinpMS2abZyA/krDd50cRPZit/6P670Z1mJjfS0+fPZkFw7AXpjxroiN0rgglg78vD7BwcA5331z4YZa5g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.1.0.tgz", + "integrity": "sha512-u2hjHLQXWSFfzO7ln2n/uEydSzfC9sc5cDC7tvKSuOdhvBwaJ0AQ7ZeuqqCQ4YfVIJfYOom1SVE9CBd10FVyig==", "cpu": [ "arm64" ], @@ -3678,9 +3803,9 @@ ] }, "node_modules/lefthook-darwin-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.0.2.tgz", - "integrity": "sha512-MSb8XZBfmlNvCpuLiQqrJS+sPiSEAyuoHOMZOHjlceYqO0leVVw9YfePVcb4Vi/PqOYngTdJk83MmYvqhsSNTQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.1.0.tgz", + "integrity": "sha512-zz5rcyrtOZpxon7uE+c0KC/o2ypJeLZql5CL0Y9oaTuECbmhfokm8glsGnyWstW/++PuMpZYYr/qsCJA5elxkQ==", "cpu": [ "x64" ], @@ -3692,9 +3817,9 @@ ] }, "node_modules/lefthook-freebsd-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.0.2.tgz", - "integrity": "sha512-gewPsUPc3J/n2/RrhHLS9jtL3qK4HcTED25vfExhvFRW3eT1SDYaBbXnUUmB8SE0zE8Bl6AfEdT2zzZcPbOFuA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.1.0.tgz", + "integrity": "sha512-+mXNCNuFHNGYLrDqYWDeHH7kWCLCJFPpspx5PAAm+PD37PRMZJrTqDbaNK9qCghC1tdmT4/Lvilf/ewXHPlaKw==", "cpu": [ "arm64" ], @@ -3706,9 +3831,9 @@ ] }, "node_modules/lefthook-freebsd-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.0.2.tgz", - "integrity": "sha512-fsLlaChiKAWiSavQO2LXPR8Z9OcBnyMDvmkIlXC0lG3SjBb9xbVdBdDVlcrsUyDCs5YstmGYHuzw6DfJYpAE1g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.1.0.tgz", + "integrity": "sha512-+AU2HD7szuDsUdHue/E3OnF84B2ae/h7CGKpuIUHJntgoJ4kxf89oDvq2/xl8kDCn9cT76UUjgeZUgFYLRj+6Q==", "cpu": [ "x64" ], @@ -3720,9 +3845,9 @@ ] }, "node_modules/lefthook-linux-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.0.2.tgz", - "integrity": "sha512-vNl3HiZud9T2nGHMngvLw3hSJgutjlN/Lzf5/5jKt/2IIuyd9L3UYktWC9HLUb03Zukr7jeaxG3+VxdAohQwAw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.1.0.tgz", + "integrity": "sha512-KM70eV1tsEib1/tk+3TFxIdH84EaYlIg5KTQWAg+LB1N23nTQ7lL4Dnh1je6f6KW4tf21nmoMUqsh0xvMkQk8Q==", "cpu": [ "arm64" ], @@ -3734,9 +3859,9 @@ ] }, "node_modules/lefthook-linux-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.0.2.tgz", - "integrity": "sha512-0ghHMPu4fixIieS8V2k2yZHvcFd9pP0q+sIAIaWo8x7ce/AOQIXFCPHGPAOc8/wi5uVtfyEvCnhxIDKf+lHA2A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.1.0.tgz", + "integrity": "sha512-6Bxmv+l7LiYq9W0IE6v2lmlRtBp6pisnlzhcouMGvH3rDwEGw11NAyRJZA3IPGEMAkIuhnlnVTUwAUzKomfJLg==", "cpu": [ "x64" ], @@ -3748,9 +3873,9 @@ ] }, "node_modules/lefthook-openbsd-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.0.2.tgz", - "integrity": "sha512-qfXnDM8jffut9rylvi3T+HOqlNRkFYqIDUXeVXlY7dmwCW4u2K46p0W4M3BmAVUeL/MRxBRnjze//Yy6aCbGQw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.1.0.tgz", + "integrity": "sha512-ppJNK0bBSPLC8gqksRw5zI/0uLeMA5cK+hmZ4ofcuGNmdrN1dfl2Tx84fdeef0NcQY0ii9Y3j3icIKngIoid/g==", "cpu": [ "arm64" ], @@ -3762,9 +3887,9 @@ ] }, "node_modules/lefthook-openbsd-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.0.2.tgz", - "integrity": "sha512-RXqR0FiDTwsQv1X3QVsuBFneWeNXS+tmPFIX8F6Wz9yDPHF8+vBnkWCju6HdkTVTY71Ba5HbYGKEVDvscJkU7Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.1.0.tgz", + "integrity": "sha512-8k9lQsMYqQGu4spaQ8RNSOJidxIcOyfaoF2FPZhthtBfRV3cgVFGrsQ0hbIi5pvQRGUlCqYuCN79qauXHmnL3Q==", "cpu": [ "x64" ], @@ -3776,9 +3901,9 @@ ] }, "node_modules/lefthook-windows-arm64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.0.2.tgz", - "integrity": "sha512-KfLKhiUPHP9Aea+9D7or2hgL9wtKEV+GHpx7LBg82ZhCXkAml6rop7mWsBgL80xPYLqMahKolZGO+8z5H6W4HQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.1.0.tgz", + "integrity": "sha512-0WN+grrxt9zP9NGRcztoPXcz25tteem91rfLWgQFab+50csJ47zldlsB7/eOS/eHG5mUg5g5NPR4XefnXtjOcQ==", "cpu": [ "arm64" ], @@ -3790,9 +3915,9 @@ ] }, "node_modules/lefthook-windows-x64": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.0.2.tgz", - "integrity": "sha512-TdysWxGRNtuRg5bN6Uj00tZJIsHTrF/7FavoR5rp1sq21QJhJi36M4I3UVlmOKAUCKhibAIAauZWmX7yaW3eHA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.1.0.tgz", + "integrity": "sha512-XbO/5nAZQLpUn0tPpgCYfFBFJHnymSglQ73jD6wymNrR1j8I5EcXGlP6YcLhnZ83yzsdLC+gup+N6IqUeiyRdw==", "cpu": [ "x64" ], @@ -3837,7 +3962,8 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/magic-string": { "version": "0.30.21", @@ -3889,15 +4015,19 @@ } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/minimatch": { @@ -4188,6 +4318,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -4237,9 +4368,9 @@ } }, "node_modules/quansync": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", - "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", "dev": true, "funding": [ { @@ -4263,15 +4394,15 @@ } }, "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" @@ -4325,6 +4456,7 @@ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.45.tgz", "integrity": "sha512-iMmuD72XXLf26Tqrv1cryNYLX6NNPLhZ3AmNkSf8+xda0H+yijjGJ+wVT9UdBUHOpKzq9RjKtQKRCWoEKQQBZQ==", "dev": true, + "license": "MIT", "dependencies": { "@oxc-project/types": "=0.95.0", "@rolldown/pluginutils": "1.0.0-beta.45" @@ -4353,24 +4485,24 @@ } }, "node_modules/rolldown-plugin-dts": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.3.tgz", - "integrity": "sha512-8mGnNUVNrqEdTnrlcaDxs4sAZg0No6njO+FuhQd4L56nUbJO1tHxOoKDH3mmMJg7f/BhEj/1KjU5W9kZ9zM/kQ==", + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.17.8.tgz", + "integrity": "sha512-76EEBlhF00yeY6M7VpMkWKI4r9WjuoMiOGey7j4D6zf3m0BR+ZrrY9hvSXdueJ3ljxSLq4DJBKFpX/X9+L7EKw==", "dev": true, "license": "MIT", "dependencies": { "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", - "ast-kit": "^2.1.3", - "birpc": "^2.6.1", - "debug": "^4.4.3", - "dts-resolver": "^2.1.2", + "ast-kit": "^2.2.0", + "birpc": "^2.8.0", + "dts-resolver": "^2.1.3", "get-tsconfig": "^4.13.0", - "magic-string": "^0.30.21" + "magic-string": "^0.30.21", + "obug": "^2.0.0" }, "engines": { - "node": ">=20.18.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" @@ -4398,9 +4530,9 @@ } }, "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, "license": "MIT", "dependencies": { @@ -4414,31 +4546,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" } }, @@ -4458,26 +4590,6 @@ "node": ">= 18" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -4485,9 +4597,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -4498,31 +4610,35 @@ } }, "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "license": "MIT", "dependencies": { - "debug": "^4.3.5", + "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", - "statuses": "^2.0.1" + "statuses": "^2.0.2" }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -4532,6 +4648,10 @@ }, "engines": { "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/setprototypeof": { @@ -4544,6 +4664,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4762,9 +4883,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -4843,13 +4964,13 @@ "optional": true }, "node_modules/tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.25.0", + "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -4894,6 +5015,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4927,24 +5049,40 @@ } }, "node_modules/unconfig": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.3.3.tgz", - "integrity": "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.4.2.tgz", + "integrity": "sha512-nrMlWRQ1xdTjSnSUqvYqJzbTBFugoqHobQj58B2bc8qxHKBBHMNNsWQFP3Cd3/JZK907voM2geYPWqD4VK3MPQ==", "dev": true, + "license": "MIT", "dependencies": { - "@quansync/fs": "^0.1.5", + "@quansync/fs": "^1.0.0", "defu": "^6.1.4", - "jiti": "^2.5.1", - "quansync": "^0.2.11" + "jiti": "^2.6.1", + "quansync": "^1.0.0", + "unconfig-core": "7.4.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.2.tgz", + "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/undici": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.0.tgz", - "integrity": "sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.21.0.tgz", + "integrity": "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -4957,6 +5095,12 @@ "dev": true, "license": "MIT" }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4986,9 +5130,9 @@ } }, "node_modules/vite": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", - "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", "dependencies": { @@ -5060,504 +5204,20 @@ } } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" - } - }, "node_modules/vitest": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.16.tgz", - "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.16", - "@vitest/mocker": "4.0.16", - "@vitest/pretty-format": "4.0.16", - "@vitest/runner": "4.0.16", - "@vitest/snapshot": "4.0.16", - "@vitest/spy": "4.0.16", - "@vitest/utils": "4.0.16", + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", @@ -5585,10 +5245,10 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.16", - "@vitest/browser-preview": "4.0.16", - "@vitest/browser-webdriverio": "4.0.16", - "@vitest/ui": "4.0.16", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, @@ -5667,7 +5327,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/yaml": { diff --git a/package.json b/package.json index 09ff1d0..6143e39 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "jose": "^6.1.2", "undici": "^7.19.0", "yaml": "^2.8.2", - "zod": "^3.25.76" + "zod": "^3.25.76", + "@octokit/rest": "^22.0.0" } } diff --git a/skills/mcp-sdk-tier-audit/SKILL.md b/skills/mcp-sdk-tier-audit/SKILL.md new file mode 100644 index 0000000..b3dee23 --- /dev/null +++ b/skills/mcp-sdk-tier-audit/SKILL.md @@ -0,0 +1,232 @@ +--- +name: mcp-sdk-tier-audit +description: >- + Comprehensive tier assessment for an MCP SDK repository against SEP-1730. + Produces tier classification (1/2/3) with evidence table, gap list, and + remediation guide. Works for any official MCP SDK (TypeScript, Python, Go, + C#, Java, Kotlin, PHP, Swift, Rust, Ruby). +argument-hint: "[repo] [--branch ]" +--- + +# MCP SDK Tier Audit + +You are performing a comprehensive tier assessment for an MCP SDK repository against SEP-1730 (the SDK Tiering System). Your goal is to produce a definitive tier classification (Tier 1, 2, or 3) backed by evidence. + +## Step 1: Parse Arguments + +Extract the target SDK from the user's input: + +- **repo**: e.g. `modelcontextprotocol/typescript-sdk`, `modelcontextprotocol/python-sdk` +- **--branch**: optional branch name (defaults to the repo's default branch) + +If the user did not specify a repo, check if the current working directory is inside a known SDK repo and auto-detect. The known SDK repos under `~/src/mcp/` are: +- `typescript-sdk` -> `modelcontextprotocol/typescript-sdk` +- `python-sdk` -> `modelcontextprotocol/python-sdk` + +If you still cannot determine the repo, ask the user. + +## Step 2: Run Deterministic Conformance Checks + +Look up the SDK in the conformance server table below. If the SDK has a known conformance server, run the full conformance suite. If not, use `--skip-conformance` and note this as a gap. + +### Conformance Server Lookup Table + +| SDK | Org/Repo | Server Location | Start Command | Default URL | +|-----|----------|----------------|---------------|-------------| +| TypeScript | `modelcontextprotocol/typescript-sdk` | `~/src/mcp/conformance/examples/servers/typescript/` | `npx tsx everything-server.ts` | `http://localhost:3000/mcp` | +| Python | `modelcontextprotocol/python-sdk` | SDK repo `examples/servers/everything-server/` | `python main.py` | TBD - check server source | +| Go | `modelcontextprotocol/go-sdk` | SDK repo `conformance/everything-server/` | `go run ./everything-server` | TBD - check server source | +| C# | `modelcontextprotocol/csharp-sdk` | SDK repo `samples/EverythingServer/` | `dotnet run` | TBD - check server source | +| Java | `modelcontextprotocol/java-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| Kotlin | `modelcontextprotocol/kotlin-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| PHP | `modelcontextprotocol/php-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| Swift | `modelcontextprotocol/swift-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| Rust | `modelcontextprotocol/rust-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| Ruby | `modelcontextprotocol/ruby-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | + +### Running Conformance Tests + +For SDKs with a known server, run conformance tests: + +```bash +cd ~/src/mcp/conformance + +# First, start the SDK's everything server (in background) +# Then run the conformance suite against it: +npx tsx src/index.ts server --url --suite active --verbose +``` + +Parse the output to extract: +- Total tests passed / failed / warnings +- Per-scenario pass/fail status +- Calculate conformance percentage: `passed / (passed + failed) * 100` + +For SDKs **without** a known conformance server, note conformance as "Not testable - no conformance server available" and recommend the maintainers set one up. + +### GitHub Issue Metrics + +Use the GitHub CLI to gather issue triage and resolution metrics: + +```bash +# Get recent issues with labels and timestamps +gh issue list --repo --state all --limit 100 --json number,title,labels,createdAt,closedAt,state + +# Check for P0 issues specifically +gh issue list --repo --label P0 --state all --json number,title,createdAt,closedAt,state + +# Check label usage +gh label list --repo --json name +``` + +Calculate: +- **Triage compliance**: percentage of issues that received a label within the required timeframe +- **P0 resolution time**: time from P0 label to issue close + +### Release Information + +```bash +# Get latest releases +gh release list --repo --limit 10 +``` + +Check if there is a stable release >= 1.0.0 with no pre-release suffix (`-alpha`, `-beta`, `-rc`). + +## Step 3: Launch Parallel Subagent Evaluations + +Launch exactly 3 subagents in parallel using the Task tool with `subagent_type="general-purpose"`. Each subagent should clone or read the SDK repo and evaluate its assigned area. + +**IMPORTANT**: Launch all 3 subagents at the same time (in the same response) so they run in parallel. + +### Subagent 1: Documentation Coverage + +Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name, branch, and the feature list from `references/feature-list.md`. + +The subagent evaluates: +- Whether all non-experimental features are documented with examples (Tier 1 requirement) +- Whether core features are documented (Tier 2 requirement) +- Produces an evidence table with file:line references + +### Subagent 2: Policy Evaluation + +Use the prompt from `references/policy-evaluation-prompt.md`. Pass the repo name and branch. + +The subagent evaluates: +- Dependency update policy (required for Tier 1 and Tier 2) +- Published roadmap (required for Tier 1; plan-toward-Tier-1 for Tier 2) +- Clear versioning with documented breaking change policy (required for Tier 1) +- Produces evidence tables for each policy area + +### Subagent 3: Feature Coverage + +Use the prompt from `references/feature-coverage-prompt.md`. Pass the repo name, branch, and the feature list from `references/feature-list.md`. + +The subagent evaluates: +- API surface completeness against MCP spec schema +- Protocol version tracking +- Produces an evidence table with source file:line references + +## Step 4: Compute Final Tier + +Combine the deterministic scorecard (conformance %, issue metrics, release info) with the subagent judgment results (docs, policies, features). Apply the tier logic: + +### Tier 1 requires ALL of: +- Conformance test pass rate == 100% +- Issue triage compliance >= 90% within 2 business days +- All P0 bugs resolved within 7 days +- Stable release >= 1.0.0 with no pre-release suffix +- Clear versioning with documented breaking change policy (subagent-evaluated) +- All non-experimental features documented with examples (subagent-evaluated) +- Published dependency update policy (subagent-evaluated) +- Published roadmap with concrete steps tracking spec components (subagent-evaluated) + +### Tier 2 requires ALL of: +- Conformance test pass rate >= 80% +- Issue triage compliance >= 80% within 1 month +- P0 bugs resolved within 2 weeks +- At least one stable release >= 1.0.0 +- Basic docs covering core features (subagent-evaluated) +- Published dependency update policy (subagent-evaluated) +- Published plan toward Tier 1 or explanation for remaining Tier 2 (subagent-evaluated) + +### Otherwise: Tier 3 + +If any Tier 2 requirement is not met, the SDK is Tier 3. + +**Important edge cases:** +- If conformance tests could not be run (no server), this counts as a FAIL for both Tier 1 and Tier 2 conformance requirements unless the SDK has a documented reason and plan. +- If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. + +## Step 5: Generate Output + +Use the template from `references/report-template.md` to produce the final report. + +### Part 1: Audit Report + +Output the tier summary table showing every requirement, the Tier 1 standard, the Tier 2 standard, the current value, whether it passes for T1 and T2, and any gap detail. + +### Part 2: Remediation Guide + +Produce a prioritized list of action items for SDK maintainers. Order by impact -- items that would advance the SDK to a higher tier come first. Group by: + +1. **Blocking for next tier** -- requirements that must be met to advance +2. **Quick wins** -- low-effort improvements +3. **Longer-term** -- structural work needed + +Each item should include: +- What needs to change +- Where in the repo to make the change (file paths if possible) +- Estimated effort (small/medium/large) +- Which tier requirement it satisfies + +## Reference Files + +The following reference files are available in the `references/` directory alongside this skill: + +- `references/tier-requirements.md` -- Full SEP-1730 requirements table with exact thresholds +- `references/feature-list.md` -- Canonical MCP feature list for coverage evaluation +- `references/report-template.md` -- Output format template for the audit report +- `references/docs-coverage-prompt.md` -- Subagent prompt for documentation evaluation +- `references/policy-evaluation-prompt.md` -- Subagent prompt for policy evaluation +- `references/feature-coverage-prompt.md` -- Subagent prompt for feature/spec coverage + +Read these reference files when you need the detailed content for subagent prompts or report formatting. + +## Usage Examples + +``` +# TypeScript SDK (default branch) +/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk + +# TypeScript SDK on specific branch +/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk --branch v1.x + +# Python SDK +/mcp-sdk-tier-audit modelcontextprotocol/python-sdk + +# Go SDK +/mcp-sdk-tier-audit modelcontextprotocol/go-sdk + +# C# SDK +/mcp-sdk-tier-audit modelcontextprotocol/csharp-sdk + +# Java SDK +/mcp-sdk-tier-audit modelcontextprotocol/java-sdk + +# Kotlin SDK +/mcp-sdk-tier-audit modelcontextprotocol/kotlin-sdk + +# PHP SDK +/mcp-sdk-tier-audit modelcontextprotocol/php-sdk + +# Swift SDK +/mcp-sdk-tier-audit modelcontextprotocol/swift-sdk + +# Rust SDK +/mcp-sdk-tier-audit modelcontextprotocol/rust-sdk + +# Ruby SDK +/mcp-sdk-tier-audit modelcontextprotocol/ruby-sdk + +# Auto-detect from current directory +/mcp-sdk-tier-audit +``` diff --git a/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md new file mode 100644 index 0000000..1da56ed --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -0,0 +1,211 @@ +# Documentation Coverage Subagent Prompt + +You are evaluating the documentation coverage of an MCP SDK repository for the SEP-1730 tier assessment. + +## Input + +- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) +- **Branch**: {branch} (default branch if not specified) + +## Your Task + +Evaluate the documentation quality and coverage of this MCP SDK against the canonical feature list. You need to determine: + +1. **Tier 1 compliance**: Are ALL non-experimental features documented with examples? +2. **Tier 2 compliance**: Are core features documented (basic docs)? + +## Steps + +### 1. Clone or access the repository + +```bash +# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there +# Otherwise clone it: +gh repo clone {repo} /tmp/sdk-audit-docs -- --branch {branch} --depth 1 +``` + +### 2. Find all documentation sources + +Search for documentation in these locations: +- `README.md` (root and any subdirectory READMEs) +- `docs/` directory +- `documentation/` directory +- `examples/` directory +- API documentation (generated or hand-written) +- `CONTRIBUTING.md` +- Inline code comments and docstrings on public API surfaces +- Any `*.md` files in the repo + +```bash +# Find all markdown files +find /path/to/repo -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" + +# Find example files +find /path/to/repo -path "*/examples/*" -not -path "*/node_modules/*" + +# Find API docs +find /path/to/repo -path "*/docs/*" -not -path "*/node_modules/*" +``` + +### 3. Evaluate each feature + +For each feature in the canonical list below, determine: +- **Documented?**: Is there documentation explaining this feature? (Yes/No) +- **Where**: File path and line numbers where documentation exists +- **Has Examples?**: Are there code examples showing how to use this feature? (Yes/No/N/A) +- **Verdict**: PASS (documented with examples), PARTIAL (documented but no examples), or FAIL (not documented) + +## Canonical Feature List to Check + +### Core Features + +**Tools:** +- Tools - listing (`tools/list`) +- Tools - calling (`tools/call`) +- Tools - text results +- Tools - image results +- Tools - audio results +- Tools - embedded resources +- Tools - error handling +- Tools - change notifications + +**Resources:** +- Resources - listing (`resources/list`) +- Resources - reading text +- Resources - reading binary +- Resources - templates (`resources/templates/list`) +- Resources - template reading +- Resources - subscribing (`resources/subscribe`) +- Resources - unsubscribing (`resources/unsubscribe`) +- Resources - change notifications + +**Prompts:** +- Prompts - listing (`prompts/list`) +- Prompts - getting simple +- Prompts - getting with arguments +- Prompts - embedded resources +- Prompts - image content +- Prompts - change notifications + +**Sampling:** +- Sampling - creating messages (`sampling/createMessage`) + +**Elicitation:** +- Elicitation - requesting input (`elicitation/create`) +- Elicitation - schema validation +- Elicitation - default values +- Elicitation - enum values + +**Roots:** +- Roots - listing (`roots/list`) +- Roots - change notifications + +**Logging:** +- Logging - sending log messages +- Logging - setting level (`logging/setLevel`) + +**Completions:** +- Completions - resource argument completion +- Completions - prompt argument completion + +**Ping:** +- Ping (`ping`) + +### Transport Features +- Streamable HTTP transport (client) +- Streamable HTTP transport (server) +- SSE transport - legacy (client) +- SSE transport - legacy (server) +- stdio transport (client) +- stdio transport (server) + +### Protocol Features +- Progress notifications +- Cancellation +- Pagination +- Capability negotiation (initialize/initialized) +- Protocol version negotiation + +## Required Output Format + +Produce your assessment in this exact format: + +```markdown +### Documentation Coverage Assessment + +**Repository**: {repo} +**Branch**: {branch} +**Documentation locations found**: +- {path1}: {description} +- {path2}: {description} +- ... + +#### Feature Documentation Table + +| Feature | Documented? | Where | Has Examples? | Verdict | +|---------|-------------|-------|---------------|---------| +| Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - requesting input | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | + +#### Summary + +**Total features**: {N} +**PASS (documented with examples)**: {N} +**PARTIAL (documented, no examples)**: {N} +**FAIL (not documented)**: {N} + +**Core features documented**: {N}/{total core} ({percentage}%) +**All features documented with examples**: {N}/{total non-experimental} ({percentage}%) + +#### Tier Verdicts + +**Tier 1** (all non-experimental features documented with examples): **PASS/FAIL** +- {If FAIL: list the features missing documentation or examples} + +**Tier 2** (basic docs covering core features): **PASS/FAIL** +- {If FAIL: list the core features missing documentation} +``` + +## Important Notes + +- A feature is "documented" if there is prose or API reference explaining what it does and how to use it. Mere existence of source code does not count as documentation. +- "Has examples" means there is runnable or near-runnable code showing the feature in use. This can be in docs, README, or an examples/ directory. +- Examples in test files count only if they are clearly labeled as examples or referenced from documentation. +- If the SDK does not implement a feature at all, mark it as "FAIL" for documentation but note "Not implemented" in the Where column. +- Be thorough: check README, docs/, examples/, API references, and inline docstrings. diff --git a/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md b/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md new file mode 100644 index 0000000..ae87072 --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md @@ -0,0 +1,251 @@ +# Feature Coverage Subagent Prompt + +You are evaluating the feature/spec coverage of an MCP SDK repository for the SEP-1730 tier assessment. + +## Input + +- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) +- **Branch**: {branch} (default branch if not specified) + +## Your Task + +Evaluate the SDK's implementation completeness against the MCP specification. Determine which spec features are implemented, partially implemented, or missing. + +## Steps + +### 1. Clone or access the repository + +```bash +# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there +# Otherwise clone it: +gh repo clone {repo} /tmp/sdk-audit-features -- --branch {branch} --depth 1 +``` + +### 2. Identify the SDK's architecture + +Determine the SDK's structure: +- Where are client implementations? (e.g., `src/client/`, `client.ts`, `mcp/client/`) +- Where are server implementations? (e.g., `src/server/`, `server.ts`, `mcp/server/`) +- Where are transport implementations? (e.g., `src/transport/`, `transports/`) +- Where are type definitions? (e.g., `src/types/`, `types.ts`, `schema/`) +- What protocol version does the SDK target? + +```bash +# Identify key source files +find /path/to/repo/src -name "*.ts" -o -name "*.py" -o -name "*.go" -o -name "*.cs" -o -name "*.java" -o -name "*.kt" -o -name "*.swift" -o -name "*.rs" -o -name "*.rb" -o -name "*.php" | head -50 + +# Look for protocol version references +grep -rn "protocolVersion\|protocol_version\|PROTOCOL_VERSION\|LATEST_PROTOCOL_VERSION" /path/to/repo/src/ +``` + +### 3. Check each spec feature + +For each feature in the canonical list, search the source code to determine if it is implemented. + +**How to verify implementation:** +- Look for method/function definitions that handle the spec method (e.g., `tools/list`, `resources/read`) +- Check for request/response type definitions +- Verify handler registration or routing for each method +- Check both client-side and server-side implementations + +```bash +# Example searches for TypeScript SDK +grep -rn "tools/list\|toolsList\|tools_list\|listTools\|list_tools" /path/to/repo/src/ +grep -rn "resources/read\|resourcesRead\|resources_read\|readResource\|read_resource" /path/to/repo/src/ +grep -rn "sampling/createMessage\|samplingCreateMessage\|createMessage\|create_message" /path/to/repo/src/ +grep -rn "elicitation/create\|elicitationCreate\|createElicitation\|create_elicitation" /path/to/repo/src/ +``` + +### 4. Check protocol version tracking + +Determine: +- Which MCP spec version(s) does the SDK support? +- Is there a version constant or configuration? +- Does the SDK handle version negotiation during initialization? + +```bash +grep -rn "2025-06-18\|2024-11-05\|draft" /path/to/repo/src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.cs" --include="*.java" +``` + +### 5. Cross-reference with MCP spec schema + +The MCP specification defines these methods. Check each one: + +**Lifecycle:** +- `initialize` / `initialized` +- `ping` + +**Tools:** +- `tools/list` +- `tools/call` +- `notifications/tools/list_changed` + +**Resources:** +- `resources/list` +- `resources/read` +- `resources/templates/list` +- `resources/subscribe` +- `resources/unsubscribe` +- `notifications/resources/list_changed` +- `notifications/resources/updated` + +**Prompts:** +- `prompts/list` +- `prompts/get` +- `notifications/prompts/list_changed` + +**Sampling:** +- `sampling/createMessage` + +**Elicitation:** +- `elicitation/create` + +**Roots:** +- `roots/list` +- `notifications/roots/list_changed` + +**Logging:** +- `logging/setLevel` +- `notifications/message` (log messages) + +**Completions:** +- `completion/complete` + +**Progress:** +- `notifications/progress` + +**Cancellation:** +- `notifications/cancelled` + +**Transports:** +- Streamable HTTP (client and server) +- SSE (legacy, client and server) +- stdio (client and server) + +## Canonical Feature List + +### Core Protocol Methods + +| Spec Method | Category | Required Side(s) | Description | +|---|---|---|---| +| `initialize` | Lifecycle | Client + Server | Capability negotiation handshake | +| `initialized` | Lifecycle | Client + Server | Post-handshake notification | +| `ping` | Utility | Client + Server | Keepalive check | +| `tools/list` | Tools | Server (handler) + Client (caller) | List available tools | +| `tools/call` | Tools | Server (handler) + Client (caller) | Invoke a tool | +| `notifications/tools/list_changed` | Tools | Server (sender) + Client (receiver) | Tool list change notification | +| `resources/list` | Resources | Server (handler) + Client (caller) | List resources | +| `resources/read` | Resources | Server (handler) + Client (caller) | Read a resource | +| `resources/templates/list` | Resources | Server (handler) + Client (caller) | List URI templates | +| `resources/subscribe` | Resources | Server (handler) + Client (caller) | Subscribe to resource updates | +| `resources/unsubscribe` | Resources | Server (handler) + Client (caller) | Unsubscribe from updates | +| `notifications/resources/list_changed` | Resources | Server (sender) + Client (receiver) | Resource list change notification | +| `notifications/resources/updated` | Resources | Server (sender) + Client (receiver) | Resource content update notification | +| `prompts/list` | Prompts | Server (handler) + Client (caller) | List prompts | +| `prompts/get` | Prompts | Server (handler) + Client (caller) | Get a prompt | +| `notifications/prompts/list_changed` | Prompts | Server (sender) + Client (receiver) | Prompt list change notification | +| `sampling/createMessage` | Sampling | Client (handler) + Server (caller) | Request LLM sampling | +| `elicitation/create` | Elicitation | Client (handler) + Server (caller) | Request user input | +| `roots/list` | Roots | Client (handler) + Server (caller) | List client roots | +| `notifications/roots/list_changed` | Roots | Client (sender) + Server (receiver) | Root list change notification | +| `logging/setLevel` | Logging | Server (handler) + Client (caller) | Set log level | +| `notifications/message` | Logging | Server (sender) + Client (receiver) | Log message | +| `completion/complete` | Completions | Server (handler) + Client (caller) | Auto-complete arguments | +| `notifications/progress` | Progress | Both (sender + receiver) | Progress reporting | +| `notifications/cancelled` | Cancellation | Both (sender + receiver) | Request cancellation | + +### Transport Implementations + +| Transport | Client Implementation | Server Implementation | +|---|---|---| +| Streamable HTTP | HTTP client with SSE support | HTTP server with SSE streaming | +| SSE (legacy) | EventSource-based client | SSE endpoint server | +| stdio | Process stdin/stdout client | Process stdin/stdout server | + +## Required Output Format + +Produce your assessment in this exact format: + +```markdown +### Feature Coverage Assessment + +**Repository**: {repo} +**Branch**: {branch} +**Protocol version(s) supported**: {version(s) found in source} +**SDK architecture**: {brief description of client/server/transport structure} + +#### Spec Method Implementation Table + +| Spec Method | Category | Client Support | Server Support | Evidence | Notes | +|---|---|---|---|---|---| +| `initialize` | Lifecycle | Implemented | Implemented | {file}:{line} | {notes} | +| `initialized` | Lifecycle | Implemented | Implemented | {file}:{line} | {notes} | +| `ping` | Utility | Implemented | Implemented | {file}:{line} | {notes} | +| `tools/list` | Tools | Implemented | Implemented | {file}:{line} | {notes} | +| `tools/call` | Tools | Implemented | Implemented | {file}:{line} | {notes} | +| `notifications/tools/list_changed` | Tools | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `resources/list` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `resources/read` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `resources/templates/list` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `resources/subscribe` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `resources/unsubscribe` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/resources/list_changed` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/resources/updated` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `prompts/list` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `prompts/get` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/prompts/list_changed` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `sampling/createMessage` | Sampling | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `elicitation/create` | Elicitation | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `roots/list` | Roots | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/roots/list_changed` | Roots | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `logging/setLevel` | Logging | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/message` | Logging | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `completion/complete` | Completions | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/progress` | Progress | {status} | {status} | {file}:{line} or "Not found" | {notes} | +| `notifications/cancelled` | Cancellation | {status} | {status} | {file}:{line} or "Not found" | {notes} | + +Status values: `Implemented`, `Partial`, `Not implemented`, `N/A` + +#### Transport Implementation Table + +| Transport | Client | Server | Evidence | Notes | +|---|---|---|---|---| +| Streamable HTTP | {status} | {status} | {file}:{line} | {notes} | +| SSE (legacy) | {status} | {status} | {file}:{line} | {notes} | +| stdio | {status} | {status} | {file}:{line} | {notes} | + +#### Content Type Support + +| Content Type | Supported? | Evidence | Notes | +|---|---|---|---| +| Text content | {Yes/No} | {file}:{line} | {notes} | +| Image content | {Yes/No} | {file}:{line} | {notes} | +| Audio content | {Yes/No} | {file}:{line} | {notes} | +| Embedded resources | {Yes/No} | {file}:{line} | {notes} | + +#### Summary + +**Total spec methods**: 25 +**Fully implemented (both sides)**: {N} +**Partially implemented**: {N} +**Not implemented**: {N} + +**Implementation coverage**: {N}/25 ({percentage}%) + +**Missing features**: +- {feature 1}: {brief explanation of what is missing} +- {feature 2}: {brief explanation} +- ... + +**Protocol version**: {version} -- {Is this the latest spec version? If not, what is missing?} +``` + +## Important Notes + +- "Implemented" means both the type definitions AND the handler/caller logic exist. Having only types is "Partial". +- Check BOTH client and server sides. An SDK may implement the server handler for `tools/list` but not the client caller, or vice versa. +- For notifications, check that both sending and receiving are implemented. +- For transports, check that there is actual transport implementation code, not just type stubs. +- Include file:line references for every piece of evidence so reviewers can verify findings. +- If the SDK uses a different naming convention (e.g., snake_case vs camelCase), search for both patterns. +- Experimental features (like Tasks) should be noted if present but do NOT count toward tier requirements. diff --git a/skills/mcp-sdk-tier-audit/references/feature-list.md b/skills/mcp-sdk-tier-audit/references/feature-list.md new file mode 100644 index 0000000..537acdc --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/feature-list.md @@ -0,0 +1,156 @@ +# Canonical MCP Feature List + +This is the canonical list of MCP features used for SDK coverage evaluation. Features are organized by category and tagged with whether they are required for tier assessment. + +Source: MCP specification schema and conformance test scenarios. + +## Core Features (required for tier documentation assessment) + +These features are part of the core MCP protocol. Documentation coverage for these is required for Tier 2 (basic docs) and Tier 1 (comprehensive with examples). + +### Tools +| Feature | Spec Method | Description | +|---|---|---| +| Tools - listing | `tools/list` | List available tools from the server | +| Tools - calling | `tools/call` | Invoke a tool on the server | +| Tools - text results | `tools/call` response | Handle text content in tool results | +| Tools - image results | `tools/call` response | Handle image content in tool results | +| Tools - audio results | `tools/call` response | Handle audio content in tool results | +| Tools - embedded resources | `tools/call` response | Handle embedded resource content in tool results | +| Tools - error handling | `tools/call` response | Handle isError flag in tool results | +| Tools - change notifications | `notifications/tools/list_changed` | React to tool list changes | + +### Resources +| Feature | Spec Method | Description | +|---|---|---| +| Resources - listing | `resources/list` | List available resources | +| Resources - reading text | `resources/read` | Read text resource content | +| Resources - reading binary | `resources/read` | Read binary/blob resource content | +| Resources - templates | `resources/templates/list` | List and use URI templates | +| Resources - template reading | `resources/read` (with template URI) | Read resources via URI templates | +| Resources - subscribing | `resources/subscribe` | Subscribe to resource change notifications | +| Resources - unsubscribing | `resources/unsubscribe` | Unsubscribe from resource notifications | +| Resources - change notifications | `notifications/resources/list_changed` | React to resource list changes | + +### Prompts +| Feature | Spec Method | Description | +|---|---|---| +| Prompts - listing | `prompts/list` | List available prompts | +| Prompts - getting (simple) | `prompts/get` | Get a prompt with no arguments | +| Prompts - getting (with args) | `prompts/get` | Get a prompt with arguments | +| Prompts - embedded resources | `prompts/get` response | Handle embedded resources in prompt messages | +| Prompts - image content | `prompts/get` response | Handle image content in prompt messages | +| Prompts - change notifications | `notifications/prompts/list_changed` | React to prompt list changes | + +### Sampling +| Feature | Spec Method | Description | +|---|---|---| +| Sampling - creating messages | `sampling/createMessage` | Server requests LLM sampling from client | + +### Elicitation +| Feature | Spec Method | Description | +|---|---|---| +| Elicitation - requesting input | `elicitation/create` | Server requests structured user input from client | +| Elicitation - schema validation | `elicitation/create` | Validate elicitation responses against JSON schema | +| Elicitation - default values | `elicitation/create` | Support default values in elicitation schemas | +| Elicitation - enum values | `elicitation/create` | Support enum constraints in elicitation schemas | + +### Roots +| Feature | Spec Method | Description | +|---|---|---| +| Roots - listing | `roots/list` | Server requests list of client roots | +| Roots - change notifications | `notifications/roots/list_changed` | Client notifies server of root changes | + +### Logging +| Feature | Spec Method | Description | +|---|---|---| +| Logging - sending log messages | `notifications/message` | Server sends log messages to client | +| Logging - setting level | `logging/setLevel` | Client sets minimum log level | + +### Completions +| Feature | Spec Method | Description | +|---|---|---| +| Completions - resource argument | `completion/complete` | Auto-complete resource URI arguments | +| Completions - prompt argument | `completion/complete` | Auto-complete prompt arguments | + +### Ping +| Feature | Spec Method | Description | +|---|---|---| +| Ping | `ping` | Keepalive / connectivity check | + +## Transport Features + +### Streamable HTTP Transport +| Feature | Description | +|---|---| +| Streamable HTTP - client | Client-side streamable HTTP transport implementation | +| Streamable HTTP - server | Server-side streamable HTTP transport implementation | +| Streamable HTTP - SSE streaming | Server-sent events for streaming responses | +| Streamable HTTP - session management | Session ID tracking and management | + +### SSE Transport (Legacy) +| Feature | Description | +|---|---| +| SSE transport - client | Legacy SSE transport client (backward compatibility) | +| SSE transport - server | Legacy SSE transport server (backward compatibility) | + +### stdio Transport +| Feature | Description | +|---|---| +| stdio transport - client | stdio-based transport client | +| stdio transport - server | stdio-based transport server | + +## Protocol Features + +| Feature | Spec Method | Description | +|---|---|---| +| Progress notifications | `notifications/progress` | Report progress during long-running operations | +| Cancellation | `notifications/cancelled` | Cancel in-progress requests | +| Pagination | `cursor` parameter | Paginated listing of tools, resources, prompts | +| Capability negotiation | `initialize` / `initialized` | Client-server capability handshake | +| Protocol version negotiation | `initialize` | Negotiate supported protocol version | +| DNS rebinding protection | N/A (transport-level) | Validate Origin/Host headers to prevent DNS rebinding | + +## Experimental Features (NOT required for any tier) + +| Feature | Description | +|---|---| +| Tasks | Task tracking and management (experimental) | + +## Conformance Test Scenario Mapping + +The following maps conformance test scenarios to the features above: + +| Conformance Scenario | Feature(s) Tested | +|---|---| +| `lifecycle` | Capability negotiation, Protocol version negotiation | +| `tools-list` | Tools - listing | +| `tools-call-simple-text` | Tools - calling, Tools - text results | +| `tools-call-image` | Tools - image results | +| `tools-call-audio` | Tools - audio results | +| `tools-call-embedded-resource` | Tools - embedded resources | +| `tools-call-multiple-content-types` | Tools - text/image/audio results | +| `tools-call-with-logging` | Tools - calling, Logging - sending log messages | +| `tools-call-error` | Tools - error handling | +| `tools-call-with-progress` | Progress notifications | +| `tools-call-sampling` | Sampling - creating messages | +| `tools-call-elicitation` | Elicitation - requesting input | +| `elicitation-defaults` | Elicitation - default values | +| `elicitation-enums` | Elicitation - enum values | +| `resources-list` | Resources - listing | +| `resources-read-text` | Resources - reading text | +| `resources-read-binary` | Resources - reading binary | +| `resources-template-read` | Resources - templates, Resources - template reading | +| `resources-subscribe` | Resources - subscribing | +| `resources-unsubscribe` | Resources - unsubscribing | +| `prompts-list` | Prompts - listing | +| `prompts-get-simple` | Prompts - getting (simple) | +| `prompts-get-with-args` | Prompts - getting (with args) | +| `prompts-get-embedded-resource` | Prompts - embedded resources | +| `prompts-get-with-image` | Prompts - image content | +| `ping` | Ping | +| `logging-set-level` | Logging - setting level | +| `completion-complete` | Completions - resource/prompt argument | +| `dns-rebinding-protection` | DNS rebinding protection | +| `sse-polling` | Streamable HTTP - SSE streaming | +| `sse-multiple-streams` | Streamable HTTP - SSE streaming, session management | diff --git a/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md new file mode 100644 index 0000000..d2d46f3 --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -0,0 +1,212 @@ +# Policy Evaluation Subagent Prompt + +You are evaluating the governance and policy documentation of an MCP SDK repository for the SEP-1730 tier assessment. + +## Input + +- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) +- **Branch**: {branch} (default branch if not specified) + +## Your Task + +Evaluate three policy areas required by SEP-1730: +1. **Dependency update policy** (required for Tier 1 and Tier 2) +2. **Roadmap** (Tier 1: published roadmap; Tier 2: published plan toward Tier 1) +3. **Versioning policy** (Tier 1: clear versioning with documented breaking change policy) + +## Steps + +### 1. Clone or access the repository + +```bash +# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there +# Otherwise clone it: +gh repo clone {repo} /tmp/sdk-audit-policy -- --branch {branch} --depth 1 +``` + +### 2. Search for policy documents + +Check these files and locations for each policy area: + +**Dependency Policy:** +- `CONTRIBUTING.md` (look for dependency/update sections) +- `SECURITY.md` (may reference dependency updates) +- `.github/dependabot.yml` or `.github/dependabot.yaml` +- `.github/renovate.json` or `renovate.json` +- `docs/` directory (any policy documents) +- `README.md` (may reference update policy) +- `DEPENDENCIES.md` or similar +- Any CI workflow files that run dependency updates + +**Roadmap:** +- `ROADMAP.md` +- `docs/roadmap.md` or `docs/ROADMAP.md` +- `README.md` (roadmap section) +- GitHub Projects or Milestones (check via `gh` CLI) +- `CHANGELOG.md` (for evidence of planned work) +- Any file mentioning "roadmap" or "planned features" + +**Versioning Policy:** +- `CONTRIBUTING.md` (versioning/release sections) +- `README.md` (versioning section) +- `CHANGELOG.md` (evidence of versioning practice) +- `docs/versioning.md` or similar +- `RELEASE.md` or `docs/releasing.md` +- Any documentation mentioning "breaking changes", "semver", "versioning" + +```bash +# Search for policy-related content +grep -rli "dependency\|dependencies\|update policy\|dependabot\|renovate" /path/to/repo --include="*.md" --include="*.yml" --include="*.yaml" --include="*.json" +grep -rli "roadmap\|planned\|upcoming\|milestone" /path/to/repo --include="*.md" +grep -rli "breaking change\|semver\|versioning\|version policy\|release policy" /path/to/repo --include="*.md" +``` + +Also check GitHub-level resources: + +```bash +# Check for GitHub milestones +gh api repos/{repo}/milestones --jq '.[].title' + +# Check for GitHub projects +gh api repos/{repo}/projects --jq '.[].name' 2>/dev/null || echo "No classic projects" + +# Check for releases and versioning pattern +gh release list --repo {repo} --limit 20 +``` + +### 3. Evaluate each policy area + +For each area, determine: +- Is there a published policy/document? +- What does it commit to? (specific commitments vs vague statements) +- Does it meet Tier 1 standards? Tier 2 standards? + +## Evaluation Criteria + +### Dependency Update Policy + +**PASS for Tier 1 and Tier 2** requires: +- A published, findable policy describing how dependencies are updated +- The policy must include actual commitments (e.g., "updated monthly", "security patches within 48h") +- Automated tooling (Dependabot, Renovate) configured counts as evidence of policy in practice +- Simply having a lockfile or running `npm install` does NOT count + +**Tier 1 additional**: Policy should be comprehensive -- covering frequency, security updates, major version handling + +**FAIL** if: +- No dependency update policy found anywhere in the repo +- Only vague references like "we try to keep dependencies up to date" + +### Roadmap + +**PASS for Tier 1** requires: +- A published roadmap document with concrete steps and work items +- Must track implementation of MCP specification components (non-experimental features and optional capabilities) +- Must give users visibility into upcoming feature support +- Can be a ROADMAP.md, GitHub milestones/projects, or a section in docs + +**PASS for Tier 2** requires: +- A published plan toward Tier 1 (what the SDK intends to implement to reach full support) +- OR an explanation of why the SDK will remain at Tier 2 (intentionally scoped) +- Can be simpler than a full roadmap + +**FAIL** if: +- No roadmap or plan found +- Only a CHANGELOG showing past work (not forward-looking) + +### Versioning Policy + +**PASS for Tier 1** requires: +- Documented breaking change policy (what constitutes a breaking change, how they are communicated) +- Clear versioning pattern (SemVer or language-idiomatic equivalent) +- Users can understand compatibility expectations when upgrading + +**Not required for Tier 2** (only needs a stable release >= 1.0.0) + +**FAIL** if: +- No versioning documentation found +- No breaking change policy documented + +## Required Output Format + +Produce your assessment in this exact format: + +```markdown +### Policy Evaluation Assessment + +**Repository**: {repo} +**Branch**: {branch} + +--- + +#### 1. Dependency Update Policy: {PASS/FAIL} + +| What Was Checked | Where | Content Found | Verdict | +|---|---|---|---| +| CONTRIBUTING.md dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No dependency section" | {Found/Not found} | +| Dependabot/Renovate config | {path} or "Not found" | "{config summary}" or "Not configured" | {Found/Not found} | +| README dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | +| SECURITY.md dependency references | {path}:{lines} or "Not found" | "{relevant quote}" or "No references" | {Found/Not found} | +| CI dependency update workflows | {path} or "Not found" | "{workflow description}" or "None" | {Found/Not found} | +| Other policy documents | {path}:{lines} or "Not found" | "{relevant quote}" or "None" | {Found/Not found} | + +**Policy content summary**: {Brief description of what the policy says, or "No dependency update policy found"} + +**Tier 1 verdict**: **PASS/FAIL** -- {explanation} +**Tier 2 verdict**: **PASS/FAIL** -- {explanation} + +--- + +#### 2. Roadmap: {PASS/FAIL} + +| What Was Checked | Where | Content Found | Verdict | +|---|---|---|---| +| ROADMAP.md | {path} or "Not found" | "{summary}" or "File does not exist" | {Found/Not found} | +| README roadmap section | {path}:{lines} or "Not found" | "{summary}" or "No roadmap section" | {Found/Not found} | +| GitHub Milestones | {URL or count} | "{milestone names}" or "None" | {Found/Not found} | +| GitHub Projects | {URL or count} | "{project names}" or "None" | {Found/Not found} | +| docs/ roadmap documents | {path} or "Not found" | "{summary}" or "None" | {Found/Not found} | +| Other forward-looking docs | {path}:{lines} or "Not found" | "{summary}" or "None" | {Found/Not found} | + +**Roadmap content summary**: {Brief description of the roadmap contents, or "No roadmap found"} + +**Tier 1 verdict**: **PASS/FAIL** -- {explanation: does it track concrete spec component implementation?} +**Tier 2 verdict**: **PASS/FAIL** -- {explanation: is there a plan toward Tier 1?} + +--- + +#### 3. Versioning Policy: {PASS/FAIL} + +| What Was Checked | Where | Content Found | Verdict | +|---|---|---|---| +| CONTRIBUTING.md versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No versioning section" | {Found/Not found} | +| README versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | +| CHANGELOG.md versioning evidence | {path} or "Not found" | "{pattern observed}" or "Not found" | {Found/Not found} | +| Release docs | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | +| Breaking change documentation | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | +| Version pattern analysis | Release history | "{pattern}" (e.g., "Follows SemVer, X.Y.Z pattern") | {Consistent/Inconsistent} | + +**Versioning content summary**: {Brief description of the versioning approach and breaking change policy, or "No versioning policy found"} + +**Tier 1 verdict**: **PASS/FAIL** -- {explanation: is there a documented breaking change policy with clear versioning?} +**Tier 2 verdict**: **N/A** -- Tier 2 only requires at least one stable release (checked separately) + +--- + +#### Overall Policy Summary + +| Policy Area | Tier 1 | Tier 2 | +|---|---|---| +| Dependency Update Policy | PASS/FAIL | PASS/FAIL | +| Roadmap | PASS/FAIL | PASS/FAIL | +| Versioning Policy | PASS/FAIL | N/A | +``` + +## Important Notes + +- Be factual and evidence-based. Quote actual content found in files. +- If a policy exists but is vague or insufficient, explain WHY it does not meet the standard. +- Automated dependency tooling (Dependabot, Renovate) configured and active counts as a published policy in practice, even without a separate written policy document. +- GitHub Milestones and Projects with concrete work items count as a roadmap. +- For versioning, look at both documentation AND practice (release history pattern). +- Include file:line references for every piece of evidence so reviewers can verify. diff --git a/skills/mcp-sdk-tier-audit/references/report-template.md b/skills/mcp-sdk-tier-audit/references/report-template.md new file mode 100644 index 0000000..c4e363d --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/report-template.md @@ -0,0 +1,139 @@ +# Audit Report Template + +Use this exact format when generating the final tier audit report. + +## Part 1: Tier Assessment + +```markdown +# MCP SDK Tier Audit: {repo} + +**Date**: {date} +**Branch**: {branch} +**Auditor**: mcp-sdk-tier-audit skill (automated + subagent evaluation) + +--- + +## Tier Assessment: Tier {X} + +{Brief 1-2 sentence summary of the overall assessment and key factors.} + +### Requirements Summary + +| # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | +|---|---|---|---|---|---|---|---| +| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 2 | Issue Triage | Within 2 business days | Within 1 month | {median triage time} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 3 | Critical Bug Resolution | Within 7 days | Within 2 weeks | {P0 resolution stats} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 4 | Stable Release | Required + clear versioning | At least one stable release | {latest version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 5 | Documentation | Comprehensive w/ examples for all features | Basic docs covering core features | {X}/{Y} features documented | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 8 | Versioning Policy | Documented breaking change policy | N/A | {Found/Not found} | {PASS/FAIL} | {N/A} | {detail or "None"} | + +**Legend**: PASS = meets requirement, FAIL = does not meet requirement, N/A = not applicable at this tier + +### Tier Determination Logic + +- Tier 1: {PASS/FAIL} -- {count} of 8 requirements met ({list failing requirements if any}) +- Tier 2: {PASS/FAIL} -- {count} of 7 requirements met ({list failing requirements if any}) +- **Final Tier: {X}** + +--- + +### Conformance Test Details + +**Suite**: {active/all} +**Total scenarios**: {N} +**Passed**: {N} | **Failed**: {N} | **Warnings**: {N} +**Pass rate**: {X}% + +{If tests were run, include per-scenario breakdown:} + +| Scenario | Status | Notes | +|---|---|---| +| lifecycle | PASS/FAIL | {detail} | +| tools-list | PASS/FAIL | {detail} | +| ... | ... | ... | + +{If tests were NOT run:} +> Conformance tests could not be run: {reason}. This is recorded as a gap. + +--- + +### Issue Triage Metrics + +**Analysis period**: Last {N} issues +**Labels configured**: {Yes/No -- list which SEP-1730 labels are present} + +| Metric | Value | Tier 1 Requirement | Tier 2 Requirement | Verdict | +|---|---|---|---|---| +| Median triage time | {value} | <= 2 business days | <= 1 month | {T1: PASS/FAIL, T2: PASS/FAIL} | +| Triage compliance rate | {X}% | >= 90% | >= 80% | {T1: PASS/FAIL, T2: PASS/FAIL} | +| P0 issues found | {N} | -- | -- | -- | +| P0 median resolution time | {value} | <= 7 days | <= 14 days | {T1: PASS/FAIL, T2: PASS/FAIL} | + +{If labels are not set up:} +> SEP-1730 labels are not configured in this repository. Issue triage metrics cannot be computed. This is a blocking gap for Tier 1 and Tier 2. + +--- + +### Documentation Coverage (Subagent 1) + +{Paste the subagent's evidence table here} + +--- + +### Policy Evaluation (Subagent 2) + +{Paste the subagent's evidence tables here} + +--- + +### Feature Coverage (Subagent 3) + +{Paste the subagent's evidence table here} +``` + +## Part 2: Remediation Guide + +```markdown +--- + +## Remediation Guide + +### Blocking for Tier {next tier} (must fix) + +| # | Action Item | Requirement | Effort | Where to Change | +|---|---|---|---|---| +| 1 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | +| 2 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | +| ... | ... | ... | ... | ... | + +### Quick Wins (low effort, high impact) + +| # | Action Item | Requirement | Effort | Where to Change | +|---|---|---|---|---| +| 1 | {description} | {requirement name} | Small | {file path(s)} | +| ... | ... | ... | ... | ... | + +### Longer-Term Improvements + +| # | Action Item | Requirement | Effort | Where to Change | +|---|---|---|---|---| +| 1 | {description} | {requirement name} | {Medium/Large} | {file path(s)} | +| ... | ... | ... | ... | ... | + +### Recommended Next Steps + +1. {First priority action with brief rationale} +2. {Second priority action} +3. {Third priority action} +``` + +## Formatting Rules + +1. Every PASS/FAIL cell must be based on evidence, not assumption. +2. If data is unavailable (e.g., conformance tests not runnable), mark as "N/A - {reason}" rather than FAIL, but note it as a gap in the remediation guide. +3. All file references from subagents must include file path and line numbers where possible. +4. The remediation guide must be ordered by impact: items that would advance the SDK to the next tier come first. +5. Effort estimates should be realistic: Small (< 1 day), Medium (1-3 days), Large (> 3 days). diff --git a/skills/mcp-sdk-tier-audit/references/tier-requirements.md b/skills/mcp-sdk-tier-audit/references/tier-requirements.md new file mode 100644 index 0000000..cc033aa --- /dev/null +++ b/skills/mcp-sdk-tier-audit/references/tier-requirements.md @@ -0,0 +1,97 @@ +# SEP-1730: SDK Tier Requirements Reference + +This is the authoritative reference table for MCP SDK tiering requirements, extracted from SEP-1730. + +Source: `~/src/mcp/modelcontextprotocol/docs/community/sdk-tiers.mdx` + +## Full Requirements Table + +| Requirement | Tier 1: Fully Supported | Tier 2: Commitment to Full Support | Tier 3: Experimental | +|---|---|---|---| +| **Conformance Tests** | 100% pass rate | >= 80% pass rate | No minimum | +| **New Protocol Features** | Before new spec version release, timeline agreed per release based on feature complexity | Within 6 months | No timeline commitment | +| **Issue Triage** | Within 2 business days | Within a month | No requirement | +| **Critical Bug Resolution** | Within 7 days | Within two weeks | No requirement | +| **Stable Release** | Required with clear versioning | At least one stable release | Not required | +| **Documentation** | Comprehensive with examples for all features | Basic documentation covering core features | No minimum | +| **Dependency Policy** | Published update policy | Published update policy | Not required | +| **Roadmap** | Published roadmap | Published plan toward Tier 1 or explanation for remaining Tier 2 | Not required | + +## Exact Thresholds for Automated Checking + +| Metric | Tier 1 Threshold | Tier 2 Threshold | How to Measure | +|---|---|---|---| +| Conformance pass rate | == 100% | >= 80% | `passed / (passed + failed) * 100` from conformance suite | +| Issue triage time | <= 2 business days | <= 1 month (30 calendar days) | Time from issue creation to first label application | +| P0 resolution time | <= 7 calendar days | <= 14 calendar days | Time from P0 label application to issue close | +| Stable release version | >= 1.0.0, no pre-release suffix | >= 1.0.0 (at least one) | Check `gh release list` for version matching `^[0-9]+\.[0-9]+\.[0-9]+$` where major >= 1 | +| Documentation coverage | All non-experimental features documented with examples | Core features documented | Subagent evaluation | +| Dependency policy | Published and findable in repo | Published and findable in repo | Subagent evaluation | +| Roadmap | Published with concrete steps tracking spec components | Published plan toward Tier 1 | Subagent evaluation | +| Versioning policy | Documented breaking change policy | N/A (just needs stable release) | Subagent evaluation | + +## Conformance Score Calculation + +Conformance scores are calculated against **applicable required tests** only: +- Tests for the specification version the SDK targets +- Excluding tests marked as pending or skipped +- Excluding tests for experimental features +- Excluding legacy backward-compatibility tests (unless the SDK claims legacy support) + +## Tier Relegation Rules + +- **Tier 1 to Tier 2**: Any conformance test fails continuously for 4 weeks +- **Tier 2 to Tier 3**: More than 20% of conformance tests fail continuously for 4 weeks + +## Issue Triage Label Taxonomy + +SDK repositories must use these consistent labels to enable automated reporting. + +### Type Labels (pick one) + +| Label | Description | +|---|---| +| `bug` | Something isn't working | +| `enhancement` | Request for new feature | +| `question` | Further information requested | + +Note: Repositories using GitHub's native issue types satisfy this requirement without needing type labels. + +### Status Labels (pick one) + +| Label | Description | +|---|---| +| `needs confirmation` | Unclear if still relevant | +| `needs repro` | Insufficient information to reproduce | +| `ready for work` | Has enough information to start | +| `good first issue` | Good for newcomers | +| `help wanted` | Contributions welcome from those familiar with codebase | + +### Priority Labels (only if actionable) + +| Label | Description | +|---|---| +| `P0` | Critical: core functionality failures or high-severity security | +| `P1` | Significant bug affecting many users | +| `P2` | Moderate issues, valuable feature requests | +| `P3` | Nice to haves, rare edge cases | + +**Total: 12 labels** (3 type + 5 status + 4 priority) + +## Key Definitions + +### Issue Triage +Labeling and determining whether an issue is valid. This is NOT the same as resolving the issue. An issue is considered triaged when it receives its first label. + +### Critical Bug (P0) +- **Security vulnerabilities** with CVSS score >= 7.0 (High or Critical severity) +- **Core functionality failures** that prevent basic MCP operations: connection establishment, message exchange, or use of core primitives (tools, resources, prompts) + +### Stable Release +A published version explicitly marked as production-ready. Specifically: version `1.0.0` or higher without pre-release identifiers like `-alpha`, `-beta`, or `-rc`. + +### Clear Versioning +Following idiomatic versioning patterns with documented breaking change policies, so users can understand compatibility expectations when upgrading. + +### Roadmap +Outlines concrete steps and work items that track implementation of required MCP specification components (non-experimental features and optional capabilities), giving users visibility into upcoming feature support. diff --git a/src/index.ts b/src/index.ts index 7be7ed0..d51eb0d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,7 @@ import { evaluateBaseline, printBaselineResults } from './expected-failures'; +import { createTierCheckCommand } from './tier-check'; import packageJson from '../package.json'; const program = new Command(); @@ -383,6 +384,9 @@ program } }); +// Tier check command +program.addCommand(createTierCheckCommand()); + // List scenarios command program .command('list') diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts new file mode 100644 index 0000000..c475871 --- /dev/null +++ b/src/tier-check/checks/conformance.ts @@ -0,0 +1,112 @@ +import { spawn, ChildProcess } from 'child_process'; +import { listActiveClientScenarios } from '../../scenarios'; +import { runServerConformanceTest } from '../../runner'; +import { ConformanceResult } from '../types'; + +async function waitForServer( + url: string, + timeoutMs: number = 30000 +): Promise { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + try { + const resp = await fetch(url, { method: 'GET' }); + // Any HTTP response means the server is listening (400, 405, etc. are all valid) + return; + } catch { + // server not ready yet + } + await new Promise((r) => setTimeout(r, 1000)); + } + throw new Error( + `Server at ${url} did not become ready within ${timeoutMs}ms` + ); +} + +export async function checkConformance(options: { + serverCmd?: string; + serverCwd?: string; + serverUrl?: string; + skip?: boolean; +}): Promise { + if (options.skip || !options.serverCmd || !options.serverUrl) { + return { + status: 'skipped', + pass_rate: 0, + passed: 0, + failed: 0, + total: 0, + details: [] + }; + } + + let serverProcess: ChildProcess | undefined; + try { + // Spawn server + const [cmd, ...args] = options.serverCmd.split(' '); + serverProcess = spawn(cmd, args, { + cwd: options.serverCwd || process.cwd(), + stdio: 'pipe', + shell: true + }); + + // Wait for server to be ready + await waitForServer(options.serverUrl); + + // Run all active scenarios + const scenarios = listActiveClientScenarios(); + const details: ConformanceResult['details'] = []; + let totalPassed = 0; + let totalFailed = 0; + + for (const scenarioName of scenarios) { + try { + const result = await runServerConformanceTest( + options.serverUrl, + scenarioName + ); + const passed = result.checks.filter( + (c) => c.status === 'SUCCESS' + ).length; + const failed = result.checks.filter( + (c) => c.status === 'FAILURE' + ).length; + totalPassed += passed > 0 && failed === 0 ? 1 : 0; + totalFailed += failed > 0 ? 1 : 0; + details.push({ + scenario: scenarioName, + passed: failed === 0, + checks_passed: passed, + checks_failed: failed + }); + } catch (error) { + totalFailed++; + details.push({ + scenario: scenarioName, + passed: false, + checks_passed: 0, + checks_failed: 1 + }); + } + } + + const total = totalPassed + totalFailed; + const pass_rate = total > 0 ? totalPassed / total : 0; + + return { + status: + pass_rate >= 1.0 ? 'pass' : pass_rate >= 0.8 ? 'partial' : 'fail', + pass_rate, + passed: totalPassed, + failed: totalFailed, + total, + details + }; + } finally { + if (serverProcess) { + serverProcess.kill('SIGTERM'); + // Give it a moment, then force kill + setTimeout(() => serverProcess?.kill('SIGKILL'), 5000); + } + } +} diff --git a/src/tier-check/checks/files.ts b/src/tier-check/checks/files.ts new file mode 100644 index 0000000..05e4c44 --- /dev/null +++ b/src/tier-check/checks/files.ts @@ -0,0 +1,38 @@ +import { Octokit } from '@octokit/rest'; +import { FilesResult } from '../types'; + +const REQUIRED_FILES = [ + 'CHANGELOG.md', + 'SECURITY.md', + 'CONTRIBUTING.md', + '.github/dependabot.yml', + 'ROADMAP.md' +]; + +export async function checkFiles( + octokit: Octokit, + owner: string, + repo: string, + branch?: string +): Promise { + const files: Record = {}; + + for (const filePath of REQUIRED_FILES) { + try { + await octokit.repos.getContent({ + owner, + repo, + path: filePath, + ...(branch ? { ref: branch } : {}) + }); + files[filePath] = true; + } catch { + files[filePath] = false; + } + } + + return { + status: Object.values(files).every((v) => v) ? 'pass' : 'fail', + files + }; +} diff --git a/src/tier-check/checks/labels.ts b/src/tier-check/checks/labels.ts new file mode 100644 index 0000000..b099e1b --- /dev/null +++ b/src/tier-check/checks/labels.ts @@ -0,0 +1,49 @@ +import { Octokit } from '@octokit/rest'; +import { LabelsResult } from '../types'; + +const REQUIRED_LABELS = [ + 'bug', + 'enhancement', + 'question', + 'needs confirmation', + 'needs repro', + 'ready for work', + 'good first issue', + 'help wanted', + 'P0', + 'P1', + 'P2', + 'P3' +]; + +export async function checkLabels( + octokit: Octokit, + owner: string, + repo: string +): Promise { + const labels: string[] = []; + let page = 1; + while (true) { + const { data } = await octokit.issues.listLabelsForRepo({ + owner, + repo, + per_page: 100, + page + }); + labels.push(...data.map((l) => l.name)); + if (data.length < 100) break; + page++; + } + + const labelSet = new Set(labels.map((l) => l.toLowerCase())); + const missing = REQUIRED_LABELS.filter((l) => !labelSet.has(l.toLowerCase())); + const found = REQUIRED_LABELS.filter((l) => labelSet.has(l.toLowerCase())); + + return { + status: missing.length === 0 ? 'pass' : 'fail', + present: found.length, + required: REQUIRED_LABELS.length, + missing, + found + }; +} diff --git a/src/tier-check/checks/p0.ts b/src/tier-check/checks/p0.ts new file mode 100644 index 0000000..599cdc1 --- /dev/null +++ b/src/tier-check/checks/p0.ts @@ -0,0 +1,89 @@ +import { Octokit } from '@octokit/rest'; +import { P0Result } from '../types'; + +export async function checkP0Resolution( + octokit: Octokit, + owner: string, + repo: string +): Promise { + // Fetch all issues with P0 label + const p0Issues: Array<{ + number: number; + title: string; + state: string; + created_at: string; + closed_at: string | null; + labels: Array<{ name: string }>; + }> = []; + + let page = 1; + while (true) { + const { data } = await octokit.issues.listForRepo({ + owner, + repo, + labels: 'P0', + state: 'all', + per_page: 100, + page + }); + for (const issue of data) { + if (issue.pull_request) continue; + p0Issues.push({ + number: issue.number, + title: issue.title, + state: issue.state, + created_at: issue.created_at, + closed_at: issue.closed_at ?? null, + labels: issue.labels.filter( + (l): l is { name: string } => + typeof l === 'object' && l !== null && 'name' in l + ) + }); + } + if (data.length < 100) break; + page++; + } + + const openP0s = p0Issues.filter((i) => i.state === 'open'); + const closedP0s = p0Issues.filter( + (i) => i.state === 'closed' && i.closed_at + ); + + let closedWithin7d = 0; + let closedWithin14d = 0; + + for (const issue of closedP0s) { + const daysToClose = + (new Date(issue.closed_at!).getTime() - + new Date(issue.created_at).getTime()) / + (1000 * 60 * 60 * 24); + if (daysToClose <= 7) closedWithin7d++; + if (daysToClose <= 14) closedWithin14d++; + } + + const openP0Details = openP0s.map((i) => ({ + number: i.number, + title: i.title, + age_days: Math.round( + (Date.now() - new Date(i.created_at).getTime()) / (1000 * 60 * 60 * 24) + ) + })); + + const allResolved7d = + openP0s.length === 0 && + (closedP0s.length === 0 || closedWithin7d === closedP0s.length); + const allResolved14d = + openP0s.length === 0 && + (closedP0s.length === 0 || closedWithin14d === closedP0s.length); + + return { + status: allResolved7d ? 'pass' : allResolved14d ? 'partial' : 'fail', + open_p0s: openP0s.length, + open_p0_details: openP0Details, + closed_within_7d: closedWithin7d, + closed_within_14d: closedWithin14d, + closed_total: closedP0s.length, + all_p0s_resolved_within_7d: allResolved7d, + all_p0s_resolved_within_14d: allResolved14d + }; +} diff --git a/src/tier-check/checks/release.ts b/src/tier-check/checks/release.ts new file mode 100644 index 0000000..3eb53f1 --- /dev/null +++ b/src/tier-check/checks/release.ts @@ -0,0 +1,59 @@ +import { Octokit } from '@octokit/rest'; +import { ReleaseResult } from '../types'; + +export async function checkStableRelease( + octokit: Octokit, + owner: string, + repo: string +): Promise { + try { + const { data: releases } = await octokit.repos.listReleases({ + owner, + repo, + per_page: 20 + }); + + if (releases.length === 0) { + return { + status: 'fail', + version: null, + is_stable: false, + is_prerelease: false + }; + } + + // Find latest non-draft release + const latest = releases.find((r) => !r.draft); + if (!latest) { + return { + status: 'fail', + version: null, + is_stable: false, + is_prerelease: false + }; + } + + const version = latest.tag_name.replace(/^v/, ''); + const isPrerelease = + latest.prerelease || + /-(alpha|beta|rc|dev|preview|snapshot)/i.test(version); + + // Check if version is >= 1.0.0 + const parts = version.split('.').map((p) => parseInt(p, 10)); + const isStable = !isPrerelease && parts.length >= 2 && parts[0] >= 1; + + return { + status: isStable ? 'pass' : 'fail', + version, + is_stable: isStable, + is_prerelease: isPrerelease + }; + } catch { + return { + status: 'fail', + version: null, + is_stable: false, + is_prerelease: false + }; + } +} diff --git a/src/tier-check/checks/spec-tracking.ts b/src/tier-check/checks/spec-tracking.ts new file mode 100644 index 0000000..ce4c101 --- /dev/null +++ b/src/tier-check/checks/spec-tracking.ts @@ -0,0 +1,79 @@ +import { Octokit } from '@octokit/rest'; +import { SpecTrackingResult } from '../types'; + +export async function checkSpecTracking( + octokit: Octokit, + owner: string, + repo: string +): Promise { + try { + // Get latest spec release from modelcontextprotocol/modelcontextprotocol + const { data: specReleases } = await octokit.repos.listReleases({ + owner: 'modelcontextprotocol', + repo: 'modelcontextprotocol', + per_page: 5 + }); + const latestSpec = specReleases.find((r) => !r.draft && !r.prerelease); + + // Get SDK releases (API returns newest-first) + const { data: sdkReleases } = await octokit.repos.listReleases({ + owner, + repo, + per_page: 50 + }); + const nonDraftSdkReleases = sdkReleases.filter((r) => !r.draft); + + if (!latestSpec || nonDraftSdkReleases.length === 0) { + return { + status: 'skipped', + latest_spec_release: latestSpec?.published_at || null, + latest_sdk_release: nonDraftSdkReleases[0]?.published_at || null, + sdk_release_within_30d: null, + days_gap: null + }; + } + + const specDate = new Date(latestSpec.published_at!); + + // Reverse so oldest-first, then find the FIRST SDK release after the spec + const oldestFirst = [...nonDraftSdkReleases].reverse(); + const firstSdkAfterSpec = oldestFirst.find( + (r) => new Date(r.published_at!) >= specDate + ); + + if (!firstSdkAfterSpec) { + // No SDK release after the latest spec release + const daysSinceSpec = Math.round( + (Date.now() - specDate.getTime()) / (1000 * 60 * 60 * 24) + ); + return { + status: daysSinceSpec <= 30 ? 'pass' : 'fail', + latest_spec_release: latestSpec.published_at, + latest_sdk_release: nonDraftSdkReleases[0]?.published_at || null, + sdk_release_within_30d: daysSinceSpec <= 30, + days_gap: daysSinceSpec + }; + } + + const sdkDate = new Date(firstSdkAfterSpec.published_at!); + const daysGap = Math.round( + (sdkDate.getTime() - specDate.getTime()) / (1000 * 60 * 60 * 24) + ); + + return { + status: daysGap <= 30 ? 'pass' : 'fail', + latest_spec_release: latestSpec.published_at, + latest_sdk_release: firstSdkAfterSpec.published_at, + sdk_release_within_30d: daysGap <= 30, + days_gap: daysGap + }; + } catch { + return { + status: 'skipped', + latest_spec_release: null, + latest_sdk_release: null, + sdk_release_within_30d: null, + days_gap: null + }; + } +} diff --git a/src/tier-check/checks/triage.ts b/src/tier-check/checks/triage.ts new file mode 100644 index 0000000..7feac1f --- /dev/null +++ b/src/tier-check/checks/triage.ts @@ -0,0 +1,110 @@ +import { Octokit } from '@octokit/rest'; +import { TriageResult } from '../types'; + +export async function checkTriage( + octokit: Octokit, + owner: string, + repo: string, + days?: number +): Promise { + const since = days + ? new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString() + : undefined; + + // Fetch issues (not PRs) — the API returns labels inline + const issues: Array<{ + number: number; + created_at: string; + labels: string[]; + }> = []; + + let page = 1; + while (true) { + const { data } = await octokit.issues.listForRepo({ + owner, + repo, + state: 'open', + ...(since ? { since } : {}), + per_page: 100, + page, + sort: 'created', + direction: 'desc' + }); + if (data.length === 0) break; + for (const issue of data) { + if (issue.pull_request) continue; + if (since && new Date(issue.created_at) < new Date(since)) continue; + issues.push({ + number: issue.number, + created_at: issue.created_at, + labels: issue.labels + .filter( + (l): l is { name: string } => + typeof l === 'object' && l !== null && 'name' in l + ) + .map((l) => l.name) + }); + } + if (data.length < 100) break; + page++; + } + + if (issues.length === 0) { + return { + status: 'pass', + compliance_rate: 1, + total_issues: 0, + triaged_within_sla: 0, + exceeding_sla: 0, + median_hours: 0, + p95_hours: 0, + days_analyzed: days + }; + } + + // An issue is "triaged" if it has at least one label + const triaged = issues.filter((i) => i.labels.length > 0); + const untriaged = issues.filter((i) => i.labels.length === 0); + + // For untriaged issues, compute how long they've been open without a label + const untriagedAgeHours = untriaged.map( + (i) => + (Date.now() - new Date(i.created_at).getTime()) / (1000 * 60 * 60) + ); + untriagedAgeHours.sort((a, b) => a - b); + + const total = issues.length; + const triagedRate = total > 0 ? triaged.length / total : 1; + + // For SLA: issues without labels that are older than 2BD are SLA violations + const TWO_BUSINESS_DAYS_HOURS = 2 * 24; + const exceeding = untriagedAgeHours.filter( + (h) => h > TWO_BUSINESS_DAYS_HOURS + ).length; + + // Median/p95 of untriaged issue ages (0 if all triaged) + const median = + untriagedAgeHours.length > 0 + ? untriagedAgeHours[Math.floor(untriagedAgeHours.length / 2)] + : 0; + const p95 = + untriagedAgeHours.length > 0 + ? untriagedAgeHours[Math.floor(untriagedAgeHours.length * 0.95)] + : 0; + + let status: 'pass' | 'partial' | 'fail'; + if (triagedRate >= 0.9) status = 'pass'; + else if (triagedRate >= 0.8) status = 'partial'; + else status = 'fail'; + + return { + status, + compliance_rate: triagedRate, + total_issues: total, + triaged_within_sla: triaged.length, + exceeding_sla: exceeding, + median_hours: Math.round(median * 10) / 10, + p95_hours: Math.round(p95 * 10) / 10, + days_analyzed: days + }; +} diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts new file mode 100644 index 0000000..194b45e --- /dev/null +++ b/src/tier-check/index.ts @@ -0,0 +1,179 @@ +import { Command } from 'commander'; +import { Octokit } from '@octokit/rest'; +import { checkConformance } from './checks/conformance'; +import { checkLabels } from './checks/labels'; +import { checkTriage } from './checks/triage'; +import { checkP0Resolution } from './checks/p0'; +import { checkStableRelease } from './checks/release'; +import { checkFiles } from './checks/files'; +import { checkSpecTracking } from './checks/spec-tracking'; +import { computeTier } from './tier-logic'; +import { formatJson, formatMarkdown, formatTerminal } from './output'; +import { TierScorecard } from './types'; + +function parseRepo(repo: string): { owner: string; repo: string } { + const parts = repo.split('/'); + if (parts.length !== 2) + throw new Error(`Invalid repo format: ${repo}. Expected owner/repo`); + return { owner: parts[0], repo: parts[1] }; +} + +export function createTierCheckCommand(): Command { + const tierCheck = new Command('tier-check') + .description( + 'Run SDK tier assessment checks against a GitHub repository' + ) + .requiredOption( + '--repo ', + 'GitHub repository (e.g., modelcontextprotocol/typescript-sdk)' + ) + .option('--branch ', 'Branch to check') + .option( + '--conformance-server-cmd ', + 'Command to start the conformance server' + ) + .option( + '--conformance-server-cwd ', + 'Working directory for the conformance server' + ) + .option( + '--conformance-server-url ', + 'URL of the conformance server' + ) + .option('--skip-conformance', 'Skip conformance tests') + .option('--days ', 'Limit triage check to issues created in last N days') + .option( + '--output ', + 'Output format: json, markdown, terminal', + 'terminal' + ) + .option( + '--token ', + 'GitHub token (defaults to GITHUB_TOKEN env var)' + ) + .action(async (options) => { + const { owner, repo } = parseRepo(options.repo); + const token = options.token || process.env.GITHUB_TOKEN; + + if (!token) { + console.error( + 'GitHub token required. Either:\n' + + ' export GITHUB_TOKEN=$(gh auth token)\n' + + ' or pass --token ' + ); + process.exit(1); + } + + const octokit = new Octokit({ auth: token }); + const days = options.days ? parseInt(options.days, 10) : undefined; + + console.error('Running tier assessment checks...\n'); + + // Run all checks + const [conformance, labels, triage, p0, release, files, specTracking] = + await Promise.all([ + checkConformance({ + serverCmd: options.conformanceServerCmd, + serverCwd: options.conformanceServerCwd, + serverUrl: options.conformanceServerUrl, + skip: options.skipConformance + }).then((r) => { + console.error(' ✓ Conformance'); + return r; + }), + checkLabels(octokit, owner, repo).then((r) => { + console.error(' ✓ Labels'); + return r; + }), + checkTriage(octokit, owner, repo, days).then((r) => { + console.error(' \u2713 Triage'); + return r; + }), + checkP0Resolution(octokit, owner, repo).then((r) => { + console.error(' \u2713 P0 Resolution'); + return r; + }), + checkStableRelease(octokit, owner, repo).then((r) => { + console.error(' \u2713 Stable Release'); + return r; + }), + checkFiles(octokit, owner, repo, options.branch).then((r) => { + console.error(' \u2713 File Existence'); + return r; + }), + checkSpecTracking(octokit, owner, repo).then((r) => { + console.error(' \u2713 Spec Tracking'); + return r; + }) + ]); + + const checks = { + conformance, + labels, + triage, + p0_resolution: p0, + stable_release: release, + file_existence: files, + spec_tracking: specTracking + }; + + const implied_tier = computeTier(checks); + + const scorecard: TierScorecard = { + repo: options.repo, + branch: options.branch || null, + timestamp: new Date().toISOString(), + version: release.version, + checks, + implied_tier + }; + + switch (options.output) { + case 'json': + console.log(formatJson(scorecard)); + break; + case 'markdown': + console.log(formatMarkdown(scorecard)); + break; + default: + formatTerminal(scorecard); + } + }); + + // Subcommands for individual checks + tierCheck + .command('labels') + .description('Check label taxonomy') + .requiredOption('--repo ', 'GitHub repository') + .option('--token ', 'GitHub token') + .action(async (options) => { + const { owner, repo } = parseRepo(options.repo); + const octokit = new Octokit({ + auth: options.token || process.env.GITHUB_TOKEN + }); + const result = await checkLabels(octokit, owner, repo); + console.log(JSON.stringify(result, null, 2)); + }); + + tierCheck + .command('triage') + .description('Check issue triage speed') + .requiredOption('--repo ', 'GitHub repository') + .option('--days ', 'Limit triage check to issues created in last N days') + .option('--token ', 'GitHub token') + .action(async (options) => { + const { owner, repo } = parseRepo(options.repo); + const octokit = new Octokit({ + auth: options.token || process.env.GITHUB_TOKEN + }); + const result = await checkTriage( + octokit, + owner, + repo, + options.days ? parseInt(options.days, 10) : undefined + ); + console.log(JSON.stringify(result, null, 2)); + }); + + return tierCheck; +} diff --git a/src/tier-check/output.ts b/src/tier-check/output.ts new file mode 100644 index 0000000..c4733cd --- /dev/null +++ b/src/tier-check/output.ts @@ -0,0 +1,141 @@ +import { TierScorecard, CheckStatus } from './types'; + +const COLORS = { + RESET: '\x1b[0m', + GREEN: '\x1b[32m', + YELLOW: '\x1b[33m', + RED: '\x1b[31m', + BLUE: '\x1b[36m', + BOLD: '\x1b[1m', + DIM: '\x1b[2m' +}; + +function statusIcon(status: CheckStatus): string { + switch (status) { + case 'pass': + return `${COLORS.GREEN}\u2713${COLORS.RESET}`; + case 'fail': + return `${COLORS.RED}\u2717${COLORS.RESET}`; + case 'partial': + return `${COLORS.YELLOW}~${COLORS.RESET}`; + case 'skipped': + return `${COLORS.DIM}-${COLORS.RESET}`; + } +} + +export function formatJson(scorecard: TierScorecard): string { + return JSON.stringify(scorecard, null, 2); +} + +export function formatMarkdown(scorecard: TierScorecard): string { + const lines: string[] = []; + const c = scorecard.checks; + + lines.push(`# Tier Assessment: Tier ${scorecard.implied_tier.tier}`); + lines.push(''); + lines.push(`**Repo**: ${scorecard.repo}`); + if (scorecard.branch) lines.push(`**Branch**: ${scorecard.branch}`); + if (scorecard.version) lines.push(`**Version**: ${scorecard.version}`); + lines.push(`**Timestamp**: ${scorecard.timestamp}`); + lines.push(''); + lines.push('## Check Results'); + lines.push(''); + lines.push('| Check | Status | Detail |'); + lines.push('|-------|--------|--------|'); + lines.push( + `| Conformance | ${c.conformance.status} | ${c.conformance.passed}/${c.conformance.total} scenarios pass (${Math.round(c.conformance.pass_rate * 100)}%) |` + ); + lines.push( + `| Labels | ${c.labels.status} | ${c.labels.present}/${c.labels.required} required labels${c.labels.missing.length > 0 ? ` (missing: ${c.labels.missing.join(', ')})` : ''} |` + ); + lines.push( + `| Triage | ${c.triage.status} | ${Math.round(c.triage.compliance_rate * 100)}% within 2BD, median ${c.triage.median_hours}h, p95 ${c.triage.p95_hours}h |` + ); + lines.push( + `| P0 Resolution | ${c.p0_resolution.status} | ${c.p0_resolution.open_p0s} open, ${c.p0_resolution.closed_within_7d}/${c.p0_resolution.closed_total} closed within 7d |` + ); + lines.push( + `| Stable Release | ${c.stable_release.status} | ${c.stable_release.version || 'none'} (stable: ${c.stable_release.is_stable}) |` + ); + lines.push( + `| Files | ${c.file_existence.status} | ${Object.entries(c.file_existence.files).map(([f, e]) => `${f}: ${e ? '\u2713' : '\u2717'}`).join(', ')} |` + ); + lines.push( + `| Spec Tracking | ${c.spec_tracking.status} | ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'} |` + ); + lines.push(''); + + if (scorecard.implied_tier.tier1_blockers.length > 0) { + lines.push('## Tier 1 Blockers'); + lines.push(''); + for (const blocker of scorecard.implied_tier.tier1_blockers) { + lines.push(`- ${blocker}`); + } + lines.push(''); + } + + lines.push(`> ${scorecard.implied_tier.note}`); + + return lines.join('\n'); +} + +export function formatTerminal(scorecard: TierScorecard): void { + const c = scorecard.checks; + const tier = scorecard.implied_tier.tier; + const tierColor = + tier === 1 ? COLORS.GREEN : tier === 2 ? COLORS.YELLOW : COLORS.RED; + + console.log( + `\n${COLORS.BOLD}Tier Assessment: ${tierColor}Tier ${tier}${COLORS.RESET}\n` + ); + console.log(`Repo: ${scorecard.repo}`); + if (scorecard.branch) console.log(`Branch: ${scorecard.branch}`); + if (scorecard.version) console.log(`Version: ${scorecard.version}`); + console.log(`Timestamp: ${scorecard.timestamp}\n`); + + console.log(`${COLORS.BOLD}Check Results:${COLORS.RESET}\n`); + + console.log( + ` ${statusIcon(c.conformance.status)} Conformance ${c.conformance.passed}/${c.conformance.total} (${Math.round(c.conformance.pass_rate * 100)}%)` + ); + console.log( + ` ${statusIcon(c.labels.status)} Labels ${c.labels.present}/${c.labels.required} required labels` + ); + if (c.labels.missing.length > 0) + console.log( + ` ${COLORS.DIM}Missing: ${c.labels.missing.join(', ')}${COLORS.RESET}` + ); + console.log( + ` ${statusIcon(c.triage.status)} Triage ${Math.round(c.triage.compliance_rate * 100)}% within 2BD (${c.triage.total_issues} issues, median ${c.triage.median_hours}h)` + ); + console.log( + ` ${statusIcon(c.p0_resolution.status)} P0 Resolution ${c.p0_resolution.open_p0s} open, ${c.p0_resolution.closed_within_7d}/${c.p0_resolution.closed_total} closed within 7d` + ); + if (c.p0_resolution.open_p0_details.length > 0) { + for (const p0 of c.p0_resolution.open_p0_details) { + console.log( + ` ${COLORS.RED}#${p0.number} (${p0.age_days}d old): ${p0.title}${COLORS.RESET}` + ); + } + } + console.log( + ` ${statusIcon(c.stable_release.status)} Stable Release ${c.stable_release.version || 'none'}` + ); + console.log( + ` ${statusIcon(c.file_existence.status)} Files ${Object.entries(c.file_existence.files).map(([f, e]) => `${e ? '\u2713' : '\u2717'} ${f}`).join(', ')}` + ); + console.log( + ` ${statusIcon(c.spec_tracking.status)} Spec Tracking ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'}` + ); + + if (scorecard.implied_tier.tier1_blockers.length > 0) { + console.log(`\n${COLORS.BOLD}Tier 1 Blockers:${COLORS.RESET}`); + for (const blocker of scorecard.implied_tier.tier1_blockers) { + console.log(` ${COLORS.RED}\u2022${COLORS.RESET} ${blocker}`); + } + } + + console.log( + `\n${COLORS.DIM}${scorecard.implied_tier.note}${COLORS.RESET}\n` + ); +} diff --git a/src/tier-check/tier-logic.ts b/src/tier-check/tier-logic.ts new file mode 100644 index 0000000..a8146fa --- /dev/null +++ b/src/tier-check/tier-logic.ts @@ -0,0 +1,61 @@ +import { TierScorecard } from './types'; + +export function computeTier( + checks: TierScorecard['checks'] +): TierScorecard['implied_tier'] { + const tier1Blockers: string[] = []; + + // Check Tier 1 requirements + if (checks.conformance.status === 'skipped') { + tier1Blockers.push('conformance (skipped)'); + } else if (checks.conformance.pass_rate < 1.0) { + tier1Blockers.push('conformance'); + } + + if (checks.triage.compliance_rate < 0.9) { + tier1Blockers.push('triage'); + } + + if (!checks.p0_resolution.all_p0s_resolved_within_7d) { + tier1Blockers.push('p0_resolution'); + } + + if (!checks.stable_release.is_stable) { + tier1Blockers.push('stable_release'); + } + + // File checks - needed for T1 + const missingFiles = Object.entries(checks.file_existence.files) + .filter(([, exists]) => !exists) + .map(([file]) => file); + if (missingFiles.length > 0) { + tier1Blockers.push('file_existence'); + } + + if (checks.spec_tracking.status === 'fail') { + tier1Blockers.push('spec_tracking'); + } + + if (checks.labels.missing.length > 0) { + tier1Blockers.push('labels'); + } + + // Check Tier 2 requirements + const tier2Met = + (checks.conformance.status === 'skipped' || + checks.conformance.pass_rate >= 0.8) && + checks.p0_resolution.all_p0s_resolved_within_14d && + checks.stable_release.is_stable; + + const tier = tier1Blockers.length === 0 ? 1 : tier2Met ? 2 : 3; + + return { + tier, + tier1_blockers: tier1Blockers, + tier2_met: tier2Met, + note: + tier === 1 + ? 'All deterministic checks pass. Judgment-based checks (docs, policy, roadmap) require /mcp-sdk-tier-audit skill.' + : 'Partial assessment — judgment-based checks require /mcp-sdk-tier-audit skill' + }; +} diff --git a/src/tier-check/types.ts b/src/tier-check/types.ts new file mode 100644 index 0000000..8f4d589 --- /dev/null +++ b/src/tier-check/types.ts @@ -0,0 +1,85 @@ +export type CheckStatus = 'pass' | 'fail' | 'partial' | 'skipped'; + +export interface CheckResult { + status: CheckStatus; + [key: string]: unknown; +} + +export interface ConformanceResult extends CheckResult { + pass_rate: number; + passed: number; + failed: number; + total: number; + details: Array<{ + scenario: string; + passed: boolean; + checks_passed: number; + checks_failed: number; + }>; +} + +export interface LabelsResult extends CheckResult { + present: number; + required: number; + missing: string[]; + found: string[]; +} + +export interface TriageResult extends CheckResult { + compliance_rate: number; + total_issues: number; + triaged_within_sla: number; + exceeding_sla: number; + median_hours: number; + p95_hours: number; + days_analyzed: number | undefined; +} + +export interface P0Result extends CheckResult { + open_p0s: number; + open_p0_details: Array<{ number: number; title: string; age_days: number }>; + closed_within_7d: number; + closed_within_14d: number; + closed_total: number; + all_p0s_resolved_within_7d: boolean; + all_p0s_resolved_within_14d: boolean; +} + +export interface ReleaseResult extends CheckResult { + version: string | null; + is_stable: boolean; + is_prerelease: boolean; +} + +export interface FilesResult extends CheckResult { + files: Record; +} + +export interface SpecTrackingResult extends CheckResult { + latest_spec_release: string | null; + latest_sdk_release: string | null; + sdk_release_within_30d: boolean | null; + days_gap: number | null; +} + +export interface TierScorecard { + repo: string; + branch: string | null; + timestamp: string; + version: string | null; + checks: { + conformance: ConformanceResult; + labels: LabelsResult; + triage: TriageResult; + p0_resolution: P0Result; + stable_release: ReleaseResult; + file_existence: FilesResult; + spec_tracking: SpecTrackingResult; + }; + implied_tier: { + tier: 1 | 2 | 3; + tier1_blockers: string[]; + tier2_met: boolean; + note: string; + }; +} From c4f1c591a7034056c4dbfedc462f87a7cea09349 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 17:41:40 +0000 Subject: [PATCH 02/34] 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 --- .claude/skills/mcp-sdk-tier-audit/README.md | 158 +++++++++++ .../skills}/mcp-sdk-tier-audit/SKILL.md | 85 ++---- .../references/docs-coverage-prompt.md | 24 +- .../references/policy-evaluation-prompt.md | 2 +- .../references/report-template.md | 6 - .../references/tier-requirements.md | 2 +- README.md | 12 + .../references/feature-coverage-prompt.md | 251 ------------------ .../references/feature-list.md | 156 ----------- src/tier-check/checks/files.ts | 19 +- src/tier-check/checks/labels.ts | 51 +++- src/tier-check/index.ts | 8 +- src/tier-check/output.ts | 4 +- src/tier-check/tier-logic.ts | 10 +- src/tier-check/types.ts | 5 +- 15 files changed, 284 insertions(+), 509 deletions(-) create mode 100644 .claude/skills/mcp-sdk-tier-audit/README.md rename {skills => .claude/skills}/mcp-sdk-tier-audit/SKILL.md (70%) rename {skills => .claude/skills}/mcp-sdk-tier-audit/references/docs-coverage-prompt.md (86%) rename {skills => .claude/skills}/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md (99%) rename {skills => .claude/skills}/mcp-sdk-tier-audit/references/report-template.md (98%) rename {skills => .claude/skills}/mcp-sdk-tier-audit/references/tier-requirements.md (98%) delete mode 100644 skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md delete mode 100644 skills/mcp-sdk-tier-audit/references/feature-list.md diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md new file mode 100644 index 0000000..4e3f1e5 --- /dev/null +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -0,0 +1,158 @@ +# MCP SDK Tier Audit + +Assess any MCP SDK repository against [SEP-1730](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1730) (the SDK Tiering System). Produces a tier classification (1/2/3) with an evidence-backed scorecard. + +Two components work together: + +- **`tier-check` CLI** — runs deterministic checks (conformance pass rate, issue triage speed, P0 resolution, labels, releases, policy signals). Works standalone, no AI needed. +- **AI-assisted assessment** — an agent uses the CLI scorecard plus judgment-based evaluation (documentation coverage, dependency policy, roadmap) to produce a full tier report with remediation guide. + +## Quick Start: CLI + +The CLI is a subcommand of the [MCP Conformance](https://github.com/modelcontextprotocol/conformance) tool. + +```bash +# Clone and build +git clone https://github.com/modelcontextprotocol/conformance.git +cd conformance +npm install +npm run build + +# Run against any MCP SDK repo +node dist/index.js tier-check --repo modelcontextprotocol/typescript-sdk +``` + +Requires a `GITHUB_TOKEN` environment variable (or pass `--token`). + +### CLI Options + +``` +--repo GitHub repository (required) +--branch Branch to check +--skip-conformance Skip conformance tests +--conformance-server-cmd Command to start the conformance server +--conformance-server-cwd Working directory for the conformance server +--conformance-server-url URL of the running conformance server +--days Limit triage analysis to last N days +--output json | markdown | terminal (default: terminal) +``` + +### What the CLI Checks + +| Check | What it measures | +|-------|-----------------| +| Conformance | Pass rate against the conformance test suite | +| Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | +| Triage | How quickly issues get labeled after creation | +| P0 Resolution | Whether critical bugs are resolved within SLA | +| Stable Release | Whether a stable release >= 1.0.0 exists | +| Policy Signals | Presence of CHANGELOG, SECURITY, CONTRIBUTING, dependabot, ROADMAP | +| Spec Tracking | Gap between latest spec release and SDK release | + +### Example Output + +``` +Tier Assessment: Tier 2 + +Repo: modelcontextprotocol/typescript-sdk +Timestamp: 2026-02-10T12:00:00Z + +Check Results: + + ✓ Conformance 45/45 (100%) + ✗ Labels 9/12 required labels + Missing: needs confirmation, needs repro, ready for work + ✓ Triage 92% within 2BD (150 issues, median 8h) + ✓ P0 Resolution 0 open, 3/3 closed within 7d + ✓ Stable Release 2.3.1 + ~ Policy Signals ✓ CHANGELOG.md, ✗ SECURITY.md, ✓ CONTRIBUTING.md, ✓ .github/dependabot.yml, ✗ ROADMAP.md + ✓ Spec Tracking 2d gap +``` + +Use `--output json` to get machine-readable results, or `--output markdown` for a report you can paste into an issue. + +## Full AI-Assisted Assessment + +The CLI produces a deterministic scorecard, but some SEP-1730 requirements need judgment: documentation quality, dependency policy, roadmap substance. An AI agent can evaluate these by reading the repo. + +### Claude Code + +The skill lives in `.claude/skills/` in this repo, so if you open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) in the conformance repo it's already available — just run: + +``` +/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk +``` + +It runs the CLI, launches parallel evaluations for docs and policy, and produces a full report with remediation guide. + +### Any Other AI Coding Agent + +If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it these instructions: + +1. **Run the CLI** to get the deterministic scorecard: + ```bash + node dist/index.js tier-check --repo --output json + ``` + +2. **Evaluate documentation coverage** — check whether MCP features (tools, resources, prompts, sampling, transports, etc.) are documented with examples. See [`references/docs-coverage-prompt.md`](references/docs-coverage-prompt.md) for the full checklist. + +3. **Evaluate policies** — check for dependency update policy, roadmap, and versioning/breaking-change policy. See [`references/policy-evaluation-prompt.md`](references/policy-evaluation-prompt.md) for criteria. + +4. **Apply tier logic** — combine scorecard + evaluations against the thresholds in [`references/tier-requirements.md`](references/tier-requirements.md). + +5. **Generate report** — use [`references/report-template.md`](references/report-template.md) for the output format. + +### Manual Review + +Run the CLI for the scorecard, then review docs and policies yourself using the tier requirements as a checklist: + +| Requirement | Tier 1 | Tier 2 | +|---|---|---| +| Conformance | 100% pass | >= 80% pass | +| Issue triage | Within 2 business days | Within 1 month | +| P0 resolution | Within 7 days | Within 2 weeks | +| Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | +| Documentation | All features with examples | Core features documented | +| Dependency policy | Published | Published | +| Roadmap | Published with spec tracking | Plan toward Tier 1 | + +## Running Conformance Tests + +To include conformance test results in the scorecard, start a conformance server for the SDK under test, then point the CLI at it. + +**TypeScript SDK:** +```bash +# In the conformance repo +cd examples/servers/typescript +npx tsx everything-server.ts & + +# Run tier-check with conformance +node dist/index.js tier-check \ + --repo modelcontextprotocol/typescript-sdk \ + --conformance-server-url http://localhost:3000/mcp +``` + +**Python SDK:** +```bash +# In the python-sdk repo +cd examples/servers/everything-server +uv run mcp-everything-server & + +# Run tier-check with conformance +node dist/index.js tier-check \ + --repo modelcontextprotocol/python-sdk \ + --conformance-server-url http://localhost:8000/mcp +``` + +**Other SDKs:** Start your conformance server however it works, then pass `--conformance-server-url`. If no conformance server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. + +## Reference Files + +These files in [`references/`](references/) contain the detailed criteria and prompts: + +| File | Purpose | +|------|---------| +| `tier-requirements.md` | Full SEP-1730 requirements with exact thresholds | +| `docs-coverage-prompt.md` | Feature checklist for documentation evaluation | +| `policy-evaluation-prompt.md` | Criteria for dependency, roadmap, and versioning policy | +| `report-template.md` | Output format for the full audit report | diff --git a/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md similarity index 70% rename from skills/mcp-sdk-tier-audit/SKILL.md rename to .claude/skills/mcp-sdk-tier-audit/SKILL.md index b3dee23..ac44296 100644 --- a/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -19,11 +19,7 @@ Extract the target SDK from the user's input: - **repo**: e.g. `modelcontextprotocol/typescript-sdk`, `modelcontextprotocol/python-sdk` - **--branch**: optional branch name (defaults to the repo's default branch) -If the user did not specify a repo, check if the current working directory is inside a known SDK repo and auto-detect. The known SDK repos under `~/src/mcp/` are: -- `typescript-sdk` -> `modelcontextprotocol/typescript-sdk` -- `python-sdk` -> `modelcontextprotocol/python-sdk` - -If you still cannot determine the repo, ask the user. +If the user did not specify a repo, check if the current working directory is inside a known SDK repo (look for a `package.json` or `pyproject.toml` with MCP-related metadata) and auto-detect. If you still cannot determine the repo, ask the user. ## Step 2: Run Deterministic Conformance Checks @@ -33,23 +29,17 @@ Look up the SDK in the conformance server table below. If the SDK has a known co | SDK | Org/Repo | Server Location | Start Command | Default URL | |-----|----------|----------------|---------------|-------------| -| TypeScript | `modelcontextprotocol/typescript-sdk` | `~/src/mcp/conformance/examples/servers/typescript/` | `npx tsx everything-server.ts` | `http://localhost:3000/mcp` | -| Python | `modelcontextprotocol/python-sdk` | SDK repo `examples/servers/everything-server/` | `python main.py` | TBD - check server source | -| Go | `modelcontextprotocol/go-sdk` | SDK repo `conformance/everything-server/` | `go run ./everything-server` | TBD - check server source | -| C# | `modelcontextprotocol/csharp-sdk` | SDK repo `samples/EverythingServer/` | `dotnet run` | TBD - check server source | -| Java | `modelcontextprotocol/java-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | -| Kotlin | `modelcontextprotocol/kotlin-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | -| PHP | `modelcontextprotocol/php-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | -| Swift | `modelcontextprotocol/swift-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | -| Rust | `modelcontextprotocol/rust-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | -| Ruby | `modelcontextprotocol/ruby-sdk` | Check SDK repo for conformance/everything server | Varies | TBD | +| TypeScript | `modelcontextprotocol/typescript-sdk` | Conformance repo `examples/servers/typescript/` | `npx tsx everything-server.ts` | `http://localhost:3000/mcp` | +| Python | `modelcontextprotocol/python-sdk` | SDK repo `examples/servers/everything-server/` | `uv run mcp-everything-server` | TBD - check server source | + +For other SDKs, ask the user how to start the conformance server, or check for a `scripts/run-server-conformance.sh` or entry points in `pyproject.toml` / `package.json`. If no conformance server is available, skip conformance and note the gap. ### Running Conformance Tests -For SDKs with a known server, run conformance tests: +Ask the user where the conformance repo checkout is, or look for it as a sibling directory. Then: ```bash -cd ~/src/mcp/conformance +cd # First, start the SDK's everything server (in background) # Then run the conformance suite against it: @@ -69,7 +59,7 @@ Use the GitHub CLI to gather issue triage and resolution metrics: ```bash # Get recent issues with labels and timestamps -gh issue list --repo --state all --limit 100 --json number,title,labels,createdAt,closedAt,state +gh issue list --repo --state all --limit 500 --json number,title,labels,createdAt,closedAt,state # Check for P0 issues specifically gh issue list --repo --label P0 --state all --json number,title,createdAt,closedAt,state @@ -93,13 +83,13 @@ Check if there is a stable release >= 1.0.0 with no pre-release suffix (`-alpha` ## Step 3: Launch Parallel Subagent Evaluations -Launch exactly 3 subagents in parallel using the Task tool with `subagent_type="general-purpose"`. Each subagent should clone or read the SDK repo and evaluate its assigned area. +Launch exactly 2 subagents in parallel using the Task tool with `subagent_type="general-purpose"`. Each subagent should clone or read the SDK repo and evaluate its assigned area. -**IMPORTANT**: Launch all 3 subagents at the same time (in the same response) so they run in parallel. +**IMPORTANT**: Launch both subagents at the same time (in the same response) so they run in parallel. ### Subagent 1: Documentation Coverage -Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name, branch, and the feature list from `references/feature-list.md`. +Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name, branch, and the feature list embedded in that prompt. The subagent evaluates: - Whether all non-experimental features are documented with examples (Tier 1 requirement) @@ -116,18 +106,9 @@ The subagent evaluates: - Clear versioning with documented breaking change policy (required for Tier 1) - Produces evidence tables for each policy area -### Subagent 3: Feature Coverage - -Use the prompt from `references/feature-coverage-prompt.md`. Pass the repo name, branch, and the feature list from `references/feature-list.md`. - -The subagent evaluates: -- API surface completeness against MCP spec schema -- Protocol version tracking -- Produces an evidence table with source file:line references - ## Step 4: Compute Final Tier -Combine the deterministic scorecard (conformance %, issue metrics, release info) with the subagent judgment results (docs, policies, features). Apply the tier logic: +Combine the deterministic scorecard (conformance %, issue metrics, release info) with the subagent judgment results (docs, policies). Apply the tier logic: ### Tier 1 requires ALL of: - Conformance test pass rate == 100% @@ -154,7 +135,7 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. **Important edge cases:** - If conformance tests could not be run (no server), this counts as a FAIL for both Tier 1 and Tier 2 conformance requirements unless the SDK has a documented reason and plan. -- If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. +- If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — check for both. ## Step 5: Generate Output @@ -183,11 +164,9 @@ Each item should include: The following reference files are available in the `references/` directory alongside this skill: - `references/tier-requirements.md` -- Full SEP-1730 requirements table with exact thresholds -- `references/feature-list.md` -- Canonical MCP feature list for coverage evaluation - `references/report-template.md` -- Output format template for the audit report - `references/docs-coverage-prompt.md` -- Subagent prompt for documentation evaluation - `references/policy-evaluation-prompt.md` -- Subagent prompt for policy evaluation -- `references/feature-coverage-prompt.md` -- Subagent prompt for feature/spec coverage Read these reference files when you need the detailed content for subagent prompts or report formatting. @@ -203,30 +182,22 @@ Read these reference files when you need the detailed content for subagent promp # Python SDK /mcp-sdk-tier-audit modelcontextprotocol/python-sdk -# Go SDK -/mcp-sdk-tier-audit modelcontextprotocol/go-sdk - -# C# SDK -/mcp-sdk-tier-audit modelcontextprotocol/csharp-sdk - -# Java SDK -/mcp-sdk-tier-audit modelcontextprotocol/java-sdk - -# Kotlin SDK -/mcp-sdk-tier-audit modelcontextprotocol/kotlin-sdk - -# PHP SDK -/mcp-sdk-tier-audit modelcontextprotocol/php-sdk - -# Swift SDK -/mcp-sdk-tier-audit modelcontextprotocol/swift-sdk +# Auto-detect from current directory +/mcp-sdk-tier-audit +``` -# Rust SDK -/mcp-sdk-tier-audit modelcontextprotocol/rust-sdk +For other SDKs, specify the repo and tell Claude how to start the conformance server: +``` +/mcp-sdk-tier-audit modelcontextprotocol/go-sdk +# Claude will ask how to start the conformance server if it can't find one +``` -# Ruby SDK -/mcp-sdk-tier-audit modelcontextprotocol/ruby-sdk +### Directory Layout -# Auto-detect from current directory -/mcp-sdk-tier-audit +For best results, have the conformance repo and SDK repos checked out as siblings: +``` +some-dir/ + conformance/ # modelcontextprotocol/conformance + typescript-sdk/ # modelcontextprotocol/typescript-sdk + python-sdk/ # modelcontextprotocol/python-sdk ``` diff --git a/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md similarity index 86% rename from skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md rename to .claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 1da56ed..9c17048 100644 --- a/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -19,7 +19,7 @@ Evaluate the documentation quality and coverage of this MCP SDK against the cano ### 1. Clone or access the repository ```bash -# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there +# If the repo is available locally, read from there # Otherwise clone it: gh repo clone {repo} /tmp/sdk-audit-docs -- --branch {branch} --depth 1 ``` @@ -91,10 +91,12 @@ For each feature in the canonical list below, determine: - Sampling - creating messages (`sampling/createMessage`) **Elicitation:** -- Elicitation - requesting input (`elicitation/create`) +- Elicitation - requesting input (`elicitation/create`) — form mode +- Elicitation - URL mode (`elicitation/create` with `mode: "url"`) - Elicitation - schema validation - Elicitation - default values - Elicitation - enum values +- Elicitation - complete notification (`notifications/elicitation/complete`) **Roots:** - Roots - listing (`roots/list`) @@ -125,6 +127,14 @@ For each feature in the canonical list below, determine: - Pagination - Capability negotiation (initialize/initialized) - Protocol version negotiation +- JSON Schema 2020-12 support + +### Experimental Features (does not count toward tier score) +- Tasks - get (`tasks/get`) +- Tasks - result (`tasks/result`) +- Tasks - cancel (`tasks/cancel`) +- Tasks - list (`tasks/list`) +- Tasks - status notifications (`notifications/tasks/status`) ## Required Output Format @@ -161,10 +171,12 @@ Produce your assessment in this exact format: | Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - requesting input | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | @@ -182,6 +194,12 @@ Produce your assessment in this exact format: | Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | | Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - status notifications (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | #### Summary diff --git a/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md similarity index 99% rename from skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md rename to .claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index d2d46f3..dab0b1a 100644 --- a/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -19,7 +19,7 @@ Evaluate three policy areas required by SEP-1730: ### 1. Clone or access the repository ```bash -# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there +# If the repo is available locally, read from there # Otherwise clone it: gh repo clone {repo} /tmp/sdk-audit-policy -- --branch {branch} --depth 1 ``` diff --git a/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md similarity index 98% rename from skills/mcp-sdk-tier-audit/references/report-template.md rename to .claude/skills/mcp-sdk-tier-audit/references/report-template.md index c4e363d..de46e6b 100644 --- a/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -86,12 +86,6 @@ Use this exact format when generating the final tier audit report. ### Policy Evaluation (Subagent 2) {Paste the subagent's evidence tables here} - ---- - -### Feature Coverage (Subagent 3) - -{Paste the subagent's evidence table here} ``` ## Part 2: Remediation Guide diff --git a/skills/mcp-sdk-tier-audit/references/tier-requirements.md b/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md similarity index 98% rename from skills/mcp-sdk-tier-audit/references/tier-requirements.md rename to .claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md index cc033aa..ea64f41 100644 --- a/skills/mcp-sdk-tier-audit/references/tier-requirements.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md @@ -2,7 +2,7 @@ This is the authoritative reference table for MCP SDK tiering requirements, extracted from SEP-1730. -Source: `~/src/mcp/modelcontextprotocol/docs/community/sdk-tiers.mdx` +Source: `modelcontextprotocol/docs/community/sdk-tiers.mdx` in the spec repository ## Full Requirements Table diff --git a/README.md b/README.md index da649d5..47f80df 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,18 @@ Run `npx @modelcontextprotocol/conformance list --server` to see all available s - **resources-\*** - Resource management scenarios - **prompts-\*** - Prompt management scenarios +## SDK Tier Assessment + +The `tier-check` subcommand evaluates an MCP SDK repository against [SEP-1730](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1730) (the SDK Tiering System): + +```bash +npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typescript-sdk +``` + +If you use Claude Code, open it in this repo and run `/mcp-sdk-tier-audit` for a full AI-assisted assessment with remediation guide. + +See [`.claude/skills/mcp-sdk-tier-audit/README.md`](.claude/skills/mcp-sdk-tier-audit/README.md) for full documentation. + ## Architecture See `src/runner/DESIGN.md` for detailed architecture documentation. diff --git a/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md b/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md deleted file mode 100644 index ae87072..0000000 --- a/skills/mcp-sdk-tier-audit/references/feature-coverage-prompt.md +++ /dev/null @@ -1,251 +0,0 @@ -# Feature Coverage Subagent Prompt - -You are evaluating the feature/spec coverage of an MCP SDK repository for the SEP-1730 tier assessment. - -## Input - -- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) -- **Branch**: {branch} (default branch if not specified) - -## Your Task - -Evaluate the SDK's implementation completeness against the MCP specification. Determine which spec features are implemented, partially implemented, or missing. - -## Steps - -### 1. Clone or access the repository - -```bash -# If the repo is available locally at ~/src/mcp/{sdk-name}, read from there -# Otherwise clone it: -gh repo clone {repo} /tmp/sdk-audit-features -- --branch {branch} --depth 1 -``` - -### 2. Identify the SDK's architecture - -Determine the SDK's structure: -- Where are client implementations? (e.g., `src/client/`, `client.ts`, `mcp/client/`) -- Where are server implementations? (e.g., `src/server/`, `server.ts`, `mcp/server/`) -- Where are transport implementations? (e.g., `src/transport/`, `transports/`) -- Where are type definitions? (e.g., `src/types/`, `types.ts`, `schema/`) -- What protocol version does the SDK target? - -```bash -# Identify key source files -find /path/to/repo/src -name "*.ts" -o -name "*.py" -o -name "*.go" -o -name "*.cs" -o -name "*.java" -o -name "*.kt" -o -name "*.swift" -o -name "*.rs" -o -name "*.rb" -o -name "*.php" | head -50 - -# Look for protocol version references -grep -rn "protocolVersion\|protocol_version\|PROTOCOL_VERSION\|LATEST_PROTOCOL_VERSION" /path/to/repo/src/ -``` - -### 3. Check each spec feature - -For each feature in the canonical list, search the source code to determine if it is implemented. - -**How to verify implementation:** -- Look for method/function definitions that handle the spec method (e.g., `tools/list`, `resources/read`) -- Check for request/response type definitions -- Verify handler registration or routing for each method -- Check both client-side and server-side implementations - -```bash -# Example searches for TypeScript SDK -grep -rn "tools/list\|toolsList\|tools_list\|listTools\|list_tools" /path/to/repo/src/ -grep -rn "resources/read\|resourcesRead\|resources_read\|readResource\|read_resource" /path/to/repo/src/ -grep -rn "sampling/createMessage\|samplingCreateMessage\|createMessage\|create_message" /path/to/repo/src/ -grep -rn "elicitation/create\|elicitationCreate\|createElicitation\|create_elicitation" /path/to/repo/src/ -``` - -### 4. Check protocol version tracking - -Determine: -- Which MCP spec version(s) does the SDK support? -- Is there a version constant or configuration? -- Does the SDK handle version negotiation during initialization? - -```bash -grep -rn "2025-06-18\|2024-11-05\|draft" /path/to/repo/src/ --include="*.ts" --include="*.py" --include="*.go" --include="*.cs" --include="*.java" -``` - -### 5. Cross-reference with MCP spec schema - -The MCP specification defines these methods. Check each one: - -**Lifecycle:** -- `initialize` / `initialized` -- `ping` - -**Tools:** -- `tools/list` -- `tools/call` -- `notifications/tools/list_changed` - -**Resources:** -- `resources/list` -- `resources/read` -- `resources/templates/list` -- `resources/subscribe` -- `resources/unsubscribe` -- `notifications/resources/list_changed` -- `notifications/resources/updated` - -**Prompts:** -- `prompts/list` -- `prompts/get` -- `notifications/prompts/list_changed` - -**Sampling:** -- `sampling/createMessage` - -**Elicitation:** -- `elicitation/create` - -**Roots:** -- `roots/list` -- `notifications/roots/list_changed` - -**Logging:** -- `logging/setLevel` -- `notifications/message` (log messages) - -**Completions:** -- `completion/complete` - -**Progress:** -- `notifications/progress` - -**Cancellation:** -- `notifications/cancelled` - -**Transports:** -- Streamable HTTP (client and server) -- SSE (legacy, client and server) -- stdio (client and server) - -## Canonical Feature List - -### Core Protocol Methods - -| Spec Method | Category | Required Side(s) | Description | -|---|---|---|---| -| `initialize` | Lifecycle | Client + Server | Capability negotiation handshake | -| `initialized` | Lifecycle | Client + Server | Post-handshake notification | -| `ping` | Utility | Client + Server | Keepalive check | -| `tools/list` | Tools | Server (handler) + Client (caller) | List available tools | -| `tools/call` | Tools | Server (handler) + Client (caller) | Invoke a tool | -| `notifications/tools/list_changed` | Tools | Server (sender) + Client (receiver) | Tool list change notification | -| `resources/list` | Resources | Server (handler) + Client (caller) | List resources | -| `resources/read` | Resources | Server (handler) + Client (caller) | Read a resource | -| `resources/templates/list` | Resources | Server (handler) + Client (caller) | List URI templates | -| `resources/subscribe` | Resources | Server (handler) + Client (caller) | Subscribe to resource updates | -| `resources/unsubscribe` | Resources | Server (handler) + Client (caller) | Unsubscribe from updates | -| `notifications/resources/list_changed` | Resources | Server (sender) + Client (receiver) | Resource list change notification | -| `notifications/resources/updated` | Resources | Server (sender) + Client (receiver) | Resource content update notification | -| `prompts/list` | Prompts | Server (handler) + Client (caller) | List prompts | -| `prompts/get` | Prompts | Server (handler) + Client (caller) | Get a prompt | -| `notifications/prompts/list_changed` | Prompts | Server (sender) + Client (receiver) | Prompt list change notification | -| `sampling/createMessage` | Sampling | Client (handler) + Server (caller) | Request LLM sampling | -| `elicitation/create` | Elicitation | Client (handler) + Server (caller) | Request user input | -| `roots/list` | Roots | Client (handler) + Server (caller) | List client roots | -| `notifications/roots/list_changed` | Roots | Client (sender) + Server (receiver) | Root list change notification | -| `logging/setLevel` | Logging | Server (handler) + Client (caller) | Set log level | -| `notifications/message` | Logging | Server (sender) + Client (receiver) | Log message | -| `completion/complete` | Completions | Server (handler) + Client (caller) | Auto-complete arguments | -| `notifications/progress` | Progress | Both (sender + receiver) | Progress reporting | -| `notifications/cancelled` | Cancellation | Both (sender + receiver) | Request cancellation | - -### Transport Implementations - -| Transport | Client Implementation | Server Implementation | -|---|---|---| -| Streamable HTTP | HTTP client with SSE support | HTTP server with SSE streaming | -| SSE (legacy) | EventSource-based client | SSE endpoint server | -| stdio | Process stdin/stdout client | Process stdin/stdout server | - -## Required Output Format - -Produce your assessment in this exact format: - -```markdown -### Feature Coverage Assessment - -**Repository**: {repo} -**Branch**: {branch} -**Protocol version(s) supported**: {version(s) found in source} -**SDK architecture**: {brief description of client/server/transport structure} - -#### Spec Method Implementation Table - -| Spec Method | Category | Client Support | Server Support | Evidence | Notes | -|---|---|---|---|---|---| -| `initialize` | Lifecycle | Implemented | Implemented | {file}:{line} | {notes} | -| `initialized` | Lifecycle | Implemented | Implemented | {file}:{line} | {notes} | -| `ping` | Utility | Implemented | Implemented | {file}:{line} | {notes} | -| `tools/list` | Tools | Implemented | Implemented | {file}:{line} | {notes} | -| `tools/call` | Tools | Implemented | Implemented | {file}:{line} | {notes} | -| `notifications/tools/list_changed` | Tools | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `resources/list` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `resources/read` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `resources/templates/list` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `resources/subscribe` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `resources/unsubscribe` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/resources/list_changed` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/resources/updated` | Resources | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `prompts/list` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `prompts/get` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/prompts/list_changed` | Prompts | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `sampling/createMessage` | Sampling | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `elicitation/create` | Elicitation | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `roots/list` | Roots | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/roots/list_changed` | Roots | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `logging/setLevel` | Logging | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/message` | Logging | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `completion/complete` | Completions | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/progress` | Progress | {status} | {status} | {file}:{line} or "Not found" | {notes} | -| `notifications/cancelled` | Cancellation | {status} | {status} | {file}:{line} or "Not found" | {notes} | - -Status values: `Implemented`, `Partial`, `Not implemented`, `N/A` - -#### Transport Implementation Table - -| Transport | Client | Server | Evidence | Notes | -|---|---|---|---|---| -| Streamable HTTP | {status} | {status} | {file}:{line} | {notes} | -| SSE (legacy) | {status} | {status} | {file}:{line} | {notes} | -| stdio | {status} | {status} | {file}:{line} | {notes} | - -#### Content Type Support - -| Content Type | Supported? | Evidence | Notes | -|---|---|---|---| -| Text content | {Yes/No} | {file}:{line} | {notes} | -| Image content | {Yes/No} | {file}:{line} | {notes} | -| Audio content | {Yes/No} | {file}:{line} | {notes} | -| Embedded resources | {Yes/No} | {file}:{line} | {notes} | - -#### Summary - -**Total spec methods**: 25 -**Fully implemented (both sides)**: {N} -**Partially implemented**: {N} -**Not implemented**: {N} - -**Implementation coverage**: {N}/25 ({percentage}%) - -**Missing features**: -- {feature 1}: {brief explanation of what is missing} -- {feature 2}: {brief explanation} -- ... - -**Protocol version**: {version} -- {Is this the latest spec version? If not, what is missing?} -``` - -## Important Notes - -- "Implemented" means both the type definitions AND the handler/caller logic exist. Having only types is "Partial". -- Check BOTH client and server sides. An SDK may implement the server handler for `tools/list` but not the client caller, or vice versa. -- For notifications, check that both sending and receiving are implemented. -- For transports, check that there is actual transport implementation code, not just type stubs. -- Include file:line references for every piece of evidence so reviewers can verify findings. -- If the SDK uses a different naming convention (e.g., snake_case vs camelCase), search for both patterns. -- Experimental features (like Tasks) should be noted if present but do NOT count toward tier requirements. diff --git a/skills/mcp-sdk-tier-audit/references/feature-list.md b/skills/mcp-sdk-tier-audit/references/feature-list.md deleted file mode 100644 index 537acdc..0000000 --- a/skills/mcp-sdk-tier-audit/references/feature-list.md +++ /dev/null @@ -1,156 +0,0 @@ -# Canonical MCP Feature List - -This is the canonical list of MCP features used for SDK coverage evaluation. Features are organized by category and tagged with whether they are required for tier assessment. - -Source: MCP specification schema and conformance test scenarios. - -## Core Features (required for tier documentation assessment) - -These features are part of the core MCP protocol. Documentation coverage for these is required for Tier 2 (basic docs) and Tier 1 (comprehensive with examples). - -### Tools -| Feature | Spec Method | Description | -|---|---|---| -| Tools - listing | `tools/list` | List available tools from the server | -| Tools - calling | `tools/call` | Invoke a tool on the server | -| Tools - text results | `tools/call` response | Handle text content in tool results | -| Tools - image results | `tools/call` response | Handle image content in tool results | -| Tools - audio results | `tools/call` response | Handle audio content in tool results | -| Tools - embedded resources | `tools/call` response | Handle embedded resource content in tool results | -| Tools - error handling | `tools/call` response | Handle isError flag in tool results | -| Tools - change notifications | `notifications/tools/list_changed` | React to tool list changes | - -### Resources -| Feature | Spec Method | Description | -|---|---|---| -| Resources - listing | `resources/list` | List available resources | -| Resources - reading text | `resources/read` | Read text resource content | -| Resources - reading binary | `resources/read` | Read binary/blob resource content | -| Resources - templates | `resources/templates/list` | List and use URI templates | -| Resources - template reading | `resources/read` (with template URI) | Read resources via URI templates | -| Resources - subscribing | `resources/subscribe` | Subscribe to resource change notifications | -| Resources - unsubscribing | `resources/unsubscribe` | Unsubscribe from resource notifications | -| Resources - change notifications | `notifications/resources/list_changed` | React to resource list changes | - -### Prompts -| Feature | Spec Method | Description | -|---|---|---| -| Prompts - listing | `prompts/list` | List available prompts | -| Prompts - getting (simple) | `prompts/get` | Get a prompt with no arguments | -| Prompts - getting (with args) | `prompts/get` | Get a prompt with arguments | -| Prompts - embedded resources | `prompts/get` response | Handle embedded resources in prompt messages | -| Prompts - image content | `prompts/get` response | Handle image content in prompt messages | -| Prompts - change notifications | `notifications/prompts/list_changed` | React to prompt list changes | - -### Sampling -| Feature | Spec Method | Description | -|---|---|---| -| Sampling - creating messages | `sampling/createMessage` | Server requests LLM sampling from client | - -### Elicitation -| Feature | Spec Method | Description | -|---|---|---| -| Elicitation - requesting input | `elicitation/create` | Server requests structured user input from client | -| Elicitation - schema validation | `elicitation/create` | Validate elicitation responses against JSON schema | -| Elicitation - default values | `elicitation/create` | Support default values in elicitation schemas | -| Elicitation - enum values | `elicitation/create` | Support enum constraints in elicitation schemas | - -### Roots -| Feature | Spec Method | Description | -|---|---|---| -| Roots - listing | `roots/list` | Server requests list of client roots | -| Roots - change notifications | `notifications/roots/list_changed` | Client notifies server of root changes | - -### Logging -| Feature | Spec Method | Description | -|---|---|---| -| Logging - sending log messages | `notifications/message` | Server sends log messages to client | -| Logging - setting level | `logging/setLevel` | Client sets minimum log level | - -### Completions -| Feature | Spec Method | Description | -|---|---|---| -| Completions - resource argument | `completion/complete` | Auto-complete resource URI arguments | -| Completions - prompt argument | `completion/complete` | Auto-complete prompt arguments | - -### Ping -| Feature | Spec Method | Description | -|---|---|---| -| Ping | `ping` | Keepalive / connectivity check | - -## Transport Features - -### Streamable HTTP Transport -| Feature | Description | -|---|---| -| Streamable HTTP - client | Client-side streamable HTTP transport implementation | -| Streamable HTTP - server | Server-side streamable HTTP transport implementation | -| Streamable HTTP - SSE streaming | Server-sent events for streaming responses | -| Streamable HTTP - session management | Session ID tracking and management | - -### SSE Transport (Legacy) -| Feature | Description | -|---|---| -| SSE transport - client | Legacy SSE transport client (backward compatibility) | -| SSE transport - server | Legacy SSE transport server (backward compatibility) | - -### stdio Transport -| Feature | Description | -|---|---| -| stdio transport - client | stdio-based transport client | -| stdio transport - server | stdio-based transport server | - -## Protocol Features - -| Feature | Spec Method | Description | -|---|---|---| -| Progress notifications | `notifications/progress` | Report progress during long-running operations | -| Cancellation | `notifications/cancelled` | Cancel in-progress requests | -| Pagination | `cursor` parameter | Paginated listing of tools, resources, prompts | -| Capability negotiation | `initialize` / `initialized` | Client-server capability handshake | -| Protocol version negotiation | `initialize` | Negotiate supported protocol version | -| DNS rebinding protection | N/A (transport-level) | Validate Origin/Host headers to prevent DNS rebinding | - -## Experimental Features (NOT required for any tier) - -| Feature | Description | -|---|---| -| Tasks | Task tracking and management (experimental) | - -## Conformance Test Scenario Mapping - -The following maps conformance test scenarios to the features above: - -| Conformance Scenario | Feature(s) Tested | -|---|---| -| `lifecycle` | Capability negotiation, Protocol version negotiation | -| `tools-list` | Tools - listing | -| `tools-call-simple-text` | Tools - calling, Tools - text results | -| `tools-call-image` | Tools - image results | -| `tools-call-audio` | Tools - audio results | -| `tools-call-embedded-resource` | Tools - embedded resources | -| `tools-call-multiple-content-types` | Tools - text/image/audio results | -| `tools-call-with-logging` | Tools - calling, Logging - sending log messages | -| `tools-call-error` | Tools - error handling | -| `tools-call-with-progress` | Progress notifications | -| `tools-call-sampling` | Sampling - creating messages | -| `tools-call-elicitation` | Elicitation - requesting input | -| `elicitation-defaults` | Elicitation - default values | -| `elicitation-enums` | Elicitation - enum values | -| `resources-list` | Resources - listing | -| `resources-read-text` | Resources - reading text | -| `resources-read-binary` | Resources - reading binary | -| `resources-template-read` | Resources - templates, Resources - template reading | -| `resources-subscribe` | Resources - subscribing | -| `resources-unsubscribe` | Resources - unsubscribing | -| `prompts-list` | Prompts - listing | -| `prompts-get-simple` | Prompts - getting (simple) | -| `prompts-get-with-args` | Prompts - getting (with args) | -| `prompts-get-embedded-resource` | Prompts - embedded resources | -| `prompts-get-with-image` | Prompts - image content | -| `ping` | Ping | -| `logging-set-level` | Logging - setting level | -| `completion-complete` | Completions - resource/prompt argument | -| `dns-rebinding-protection` | DNS rebinding protection | -| `sse-polling` | Streamable HTTP - SSE streaming | -| `sse-multiple-streams` | Streamable HTTP - SSE streaming, session management | diff --git a/src/tier-check/checks/files.ts b/src/tier-check/checks/files.ts index 05e4c44..4cd7bd4 100644 --- a/src/tier-check/checks/files.ts +++ b/src/tier-check/checks/files.ts @@ -1,7 +1,10 @@ import { Octokit } from '@octokit/rest'; -import { FilesResult } from '../types'; +import { PolicySignalsResult } from '../types'; -const REQUIRED_FILES = [ +// These files are evidence for policy evaluation, not hard tier requirements. +// Their presence/absence feeds into the overall assessment but does not +// independently block tier advancement. +const POLICY_SIGNAL_FILES = [ 'CHANGELOG.md', 'SECURITY.md', 'CONTRIBUTING.md', @@ -9,15 +12,15 @@ const REQUIRED_FILES = [ 'ROADMAP.md' ]; -export async function checkFiles( +export async function checkPolicySignals( octokit: Octokit, owner: string, repo: string, branch?: string -): Promise { +): Promise { const files: Record = {}; - for (const filePath of REQUIRED_FILES) { + for (const filePath of POLICY_SIGNAL_FILES) { try { await octokit.repos.getContent({ owner, @@ -32,7 +35,11 @@ export async function checkFiles( } return { - status: Object.values(files).every((v) => v) ? 'pass' : 'fail', + status: Object.values(files).every((v) => v) + ? 'pass' + : Object.values(files).some((v) => v) + ? 'partial' + : 'fail', files }; } diff --git a/src/tier-check/checks/labels.ts b/src/tier-check/checks/labels.ts index b099e1b..93b7f96 100644 --- a/src/tier-check/checks/labels.ts +++ b/src/tier-check/checks/labels.ts @@ -1,21 +1,19 @@ import { Octokit } from '@octokit/rest'; import { LabelsResult } from '../types'; -const REQUIRED_LABELS = [ - 'bug', - 'enhancement', - 'question', +// Type labels can be satisfied by GitHub's native issue types (Bug, Enhancement, Question) +const TYPE_LABELS = ['bug', 'enhancement', 'question']; + +const STATUS_LABELS = [ 'needs confirmation', 'needs repro', 'ready for work', 'good first issue', - 'help wanted', - 'P0', - 'P1', - 'P2', - 'P3' + 'help wanted' ]; +const PRIORITY_LABELS = ['P0', 'P1', 'P2', 'P3']; + export async function checkLabels( octokit: Octokit, owner: string, @@ -35,15 +33,42 @@ export async function checkLabels( page++; } + // Check if the repo uses GitHub's native issue types + // If so, type labels (bug/enhancement/question) are satisfied + let usesIssueTypes = false; + try { + const { data: repoData } = await octokit.request( + 'GET /repos/{owner}/{repo}', + { owner, repo } + ); + // Repos with issue types enabled have them configured at the org or repo level. + // We detect this by checking for the presence of issue type configuration. + // As a heuristic: if the repo has no type labels but has issues, it likely uses types. + usesIssueTypes = !!(repoData as Record).issue_types; + } catch { + // If we can't determine, assume labels are needed + } + const labelSet = new Set(labels.map((l) => l.toLowerCase())); - const missing = REQUIRED_LABELS.filter((l) => !labelSet.has(l.toLowerCase())); - const found = REQUIRED_LABELS.filter((l) => labelSet.has(l.toLowerCase())); + + // Build required labels list, excluding type labels if issue types are used + const requiredLabels = [ + ...(usesIssueTypes ? [] : TYPE_LABELS), + ...STATUS_LABELS, + ...PRIORITY_LABELS + ]; + + const missing = requiredLabels.filter( + (l) => !labelSet.has(l.toLowerCase()) + ); + const found = requiredLabels.filter((l) => labelSet.has(l.toLowerCase())); return { status: missing.length === 0 ? 'pass' : 'fail', present: found.length, - required: REQUIRED_LABELS.length, + required: requiredLabels.length, missing, - found + found, + uses_issue_types: usesIssueTypes }; } diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index 194b45e..5aa8dff 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -5,7 +5,7 @@ import { checkLabels } from './checks/labels'; import { checkTriage } from './checks/triage'; import { checkP0Resolution } from './checks/p0'; import { checkStableRelease } from './checks/release'; -import { checkFiles } from './checks/files'; +import { checkPolicySignals } from './checks/files'; import { checkSpecTracking } from './checks/spec-tracking'; import { computeTier } from './tier-logic'; import { formatJson, formatMarkdown, formatTerminal } from './output'; @@ -97,8 +97,8 @@ export function createTierCheckCommand(): Command { console.error(' \u2713 Stable Release'); return r; }), - checkFiles(octokit, owner, repo, options.branch).then((r) => { - console.error(' \u2713 File Existence'); + checkPolicySignals(octokit, owner, repo, options.branch).then((r) => { + console.error(' \u2713 Policy Signals'); return r; }), checkSpecTracking(octokit, owner, repo).then((r) => { @@ -113,7 +113,7 @@ export function createTierCheckCommand(): Command { triage, p0_resolution: p0, stable_release: release, - file_existence: files, + policy_signals: files, spec_tracking: specTracking }; diff --git a/src/tier-check/output.ts b/src/tier-check/output.ts index c4733cd..a787d01 100644 --- a/src/tier-check/output.ts +++ b/src/tier-check/output.ts @@ -58,7 +58,7 @@ export function formatMarkdown(scorecard: TierScorecard): string { `| Stable Release | ${c.stable_release.status} | ${c.stable_release.version || 'none'} (stable: ${c.stable_release.is_stable}) |` ); lines.push( - `| Files | ${c.file_existence.status} | ${Object.entries(c.file_existence.files).map(([f, e]) => `${f}: ${e ? '\u2713' : '\u2717'}`).join(', ')} |` + `| Policy Signals | ${c.policy_signals.status} | ${Object.entries(c.policy_signals.files).map(([f, e]) => `${f}: ${e ? '\u2713' : '\u2717'}`).join(', ')} |` ); lines.push( `| Spec Tracking | ${c.spec_tracking.status} | ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'} |` @@ -122,7 +122,7 @@ export function formatTerminal(scorecard: TierScorecard): void { ` ${statusIcon(c.stable_release.status)} Stable Release ${c.stable_release.version || 'none'}` ); console.log( - ` ${statusIcon(c.file_existence.status)} Files ${Object.entries(c.file_existence.files).map(([f, e]) => `${e ? '\u2713' : '\u2717'} ${f}`).join(', ')}` + ` ${statusIcon(c.policy_signals.status)} Policy Signals ${Object.entries(c.policy_signals.files).map(([f, e]) => `${e ? '\u2713' : '\u2717'} ${f}`).join(', ')}` ); console.log( ` ${statusIcon(c.spec_tracking.status)} Spec Tracking ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'}` diff --git a/src/tier-check/tier-logic.ts b/src/tier-check/tier-logic.ts index a8146fa..e93b645 100644 --- a/src/tier-check/tier-logic.ts +++ b/src/tier-check/tier-logic.ts @@ -24,13 +24,9 @@ export function computeTier( tier1Blockers.push('stable_release'); } - // File checks - needed for T1 - const missingFiles = Object.entries(checks.file_existence.files) - .filter(([, exists]) => !exists) - .map(([file]) => file); - if (missingFiles.length > 0) { - tier1Blockers.push('file_existence'); - } + // Policy signals (CHANGELOG, SECURITY, etc.) are informational evidence — + // they feed into the skill's judgment-based evaluation but don't independently + // block tier advancement since SEP-1730 doesn't list specific files. if (checks.spec_tracking.status === 'fail') { tier1Blockers.push('spec_tracking'); diff --git a/src/tier-check/types.ts b/src/tier-check/types.ts index 8f4d589..ae0960a 100644 --- a/src/tier-check/types.ts +++ b/src/tier-check/types.ts @@ -23,6 +23,7 @@ export interface LabelsResult extends CheckResult { required: number; missing: string[]; found: string[]; + uses_issue_types: boolean; } export interface TriageResult extends CheckResult { @@ -51,7 +52,7 @@ export interface ReleaseResult extends CheckResult { is_prerelease: boolean; } -export interface FilesResult extends CheckResult { +export interface PolicySignalsResult extends CheckResult { files: Record; } @@ -73,7 +74,7 @@ export interface TierScorecard { triage: TriageResult; p0_resolution: P0Result; stable_release: ReleaseResult; - file_existence: FilesResult; + policy_signals: PolicySignalsResult; spec_tracking: SpecTrackingResult; }; implied_tier: { From f0849b95ae304cc8a6ecb4b766f058fb32544200 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 18:04:26 +0000 Subject: [PATCH 03/34] 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 --- .claude/skills/mcp-sdk-tier-audit/README.md | 36 +++--- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 122 ++++++------------ .../references/policy-evaluation-prompt.md | 53 +++----- README.md | 2 + 4 files changed, 80 insertions(+), 133 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 4e3f1e5..e24fde1 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -18,11 +18,17 @@ cd conformance npm install npm run build +# Authenticate with GitHub (needed for API access) +gh auth login + # Run against any MCP SDK repo -node dist/index.js tier-check --repo modelcontextprotocol/typescript-sdk +npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typescript-sdk ``` -Requires a `GITHUB_TOKEN` environment variable (or pass `--token`). +The CLI uses the GitHub API for issue metrics, labels, and release checks. Authenticate via one of: +- **GitHub CLI** (recommended): `gh auth login` — the CLI picks up your token automatically +- **Environment variable**: `export GITHUB_TOKEN=ghp_...` (create a read-only token at [github.com/settings/tokens](https://github.com/settings/tokens) with `repo:read` and `issues:read` scopes) +- **Flag**: `--token ghp_...` ### CLI Options @@ -35,6 +41,7 @@ Requires a `GITHUB_TOKEN` environment variable (or pass `--token`). --conformance-server-url URL of the running conformance server --days Limit triage analysis to last N days --output json | markdown | terminal (default: terminal) +--token GitHub token (defaults to GITHUB_TOKEN or gh auth token) ``` ### What the CLI Checks @@ -91,7 +98,7 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the 1. **Run the CLI** to get the deterministic scorecard: ```bash - node dist/index.js tier-check --repo --output json + npx @modelcontextprotocol/conformance tier-check --repo --output json ``` 2. **Evaluate documentation coverage** — check whether MCP features (tools, resources, prompts, sampling, transports, etc.) are documented with examples. See [`references/docs-coverage-prompt.md`](references/docs-coverage-prompt.md) for the full checklist. @@ -118,33 +125,32 @@ Run the CLI for the scorecard, then review docs and policies yourself using the ## Running Conformance Tests -To include conformance test results in the scorecard, start a conformance server for the SDK under test, then point the CLI at it. +To include conformance test results in the scorecard, you need to start the SDK's everything server, then run tier-check against it. **TypeScript SDK:** ```bash -# In the conformance repo -cd examples/servers/typescript -npx tsx everything-server.ts & +# Clone the TypeScript SDK and start its conformance server +cd /path/to/typescript-sdk/test/conformance +npx tsx src/everythingServer.ts & -# Run tier-check with conformance -node dist/index.js tier-check \ +# Back in the conformance repo, run tier-check +npx @modelcontextprotocol/conformance tier-check \ --repo modelcontextprotocol/typescript-sdk \ --conformance-server-url http://localhost:3000/mcp ``` **Python SDK:** ```bash -# In the python-sdk repo -cd examples/servers/everything-server +# In the python-sdk repo, start the everything server uv run mcp-everything-server & -# Run tier-check with conformance -node dist/index.js tier-check \ +# Back in the conformance repo, run tier-check +npx @modelcontextprotocol/conformance tier-check \ --repo modelcontextprotocol/python-sdk \ - --conformance-server-url http://localhost:8000/mcp + --conformance-server-url http://localhost:3001/mcp ``` -**Other SDKs:** Start your conformance server however it works, then pass `--conformance-server-url`. If no conformance server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. +**Other SDKs:** Start your SDK's everything server, then pass `--conformance-server-url`. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. ## Reference Files diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index ac44296..e26ffe9 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -19,88 +19,60 @@ Extract the target SDK from the user's input: - **repo**: e.g. `modelcontextprotocol/typescript-sdk`, `modelcontextprotocol/python-sdk` - **--branch**: optional branch name (defaults to the repo's default branch) -If the user did not specify a repo, check if the current working directory is inside a known SDK repo (look for a `package.json` or `pyproject.toml` with MCP-related metadata) and auto-detect. If you still cannot determine the repo, ask the user. +If the user did not specify a repo, ask them which SDK to audit. -## Step 2: Run Deterministic Conformance Checks +## Step 2: Run the Deterministic Scorecard -Look up the SDK in the conformance server table below. If the SDK has a known conformance server, run the full conformance suite. If not, use `--skip-conformance` and note this as a gap. +The `tier-check` CLI handles all deterministic checks — conformance, labels, triage, P0 resolution, releases, policy signals, and spec tracking. You are already in the conformance repo, so run it directly. -### Conformance Server Lookup Table - -| SDK | Org/Repo | Server Location | Start Command | Default URL | -|-----|----------|----------------|---------------|-------------| -| TypeScript | `modelcontextprotocol/typescript-sdk` | Conformance repo `examples/servers/typescript/` | `npx tsx everything-server.ts` | `http://localhost:3000/mcp` | -| Python | `modelcontextprotocol/python-sdk` | SDK repo `examples/servers/everything-server/` | `uv run mcp-everything-server` | TBD - check server source | - -For other SDKs, ask the user how to start the conformance server, or check for a `scripts/run-server-conformance.sh` or entry points in `pyproject.toml` / `package.json`. If no conformance server is available, skip conformance and note the gap. - -### Running Conformance Tests - -Ask the user where the conformance repo checkout is, or look for it as a sibling directory. Then: +### Without conformance tests (fastest) ```bash -cd - -# First, start the SDK's everything server (in background) -# Then run the conformance suite against it: -npx tsx src/index.ts server --url --suite active --verbose +npx @modelcontextprotocol/conformance tier-check --repo --skip-conformance --output json ``` -Parse the output to extract: -- Total tests passed / failed / warnings -- Per-scenario pass/fail status -- Calculate conformance percentage: `passed / (passed + failed) * 100` - -For SDKs **without** a known conformance server, note conformance as "Not testable - no conformance server available" and recommend the maintainers set one up. - -### GitHub Issue Metrics - -Use the GitHub CLI to gather issue triage and resolution metrics: - -```bash -# Get recent issues with labels and timestamps -gh issue list --repo --state all --limit 500 --json number,title,labels,createdAt,closedAt,state +### With conformance tests -# Check for P0 issues specifically -gh issue list --repo --label P0 --state all --json number,title,createdAt,closedAt,state +To include conformance results, you need to start the SDK's everything server first. Look up the SDK below: -# Check label usage -gh label list --repo --json name -``` +| SDK | Everything Server Location | Start Command | URL | +|-----|---------------------------|---------------|-----| +| TypeScript | `typescript-sdk/test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | +| Python | `python-sdk/examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | -Calculate: -- **Triage compliance**: percentage of issues that received a label within the required timeframe -- **P0 resolution time**: time from P0 label to issue close +For other SDKs, ask the user how to start their everything server. -### Release Information +Start the server, then run: ```bash -# Get latest releases -gh release list --repo --limit 10 +npx @modelcontextprotocol/conformance tier-check \ + --repo \ + --conformance-server-url \ + --output json ``` -Check if there is a stable release >= 1.0.0 with no pre-release suffix (`-alpha`, `-beta`, `-rc`). +The CLI output includes conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. -## Step 3: Launch Parallel Subagent Evaluations +## Step 3: Launch Parallel Evaluations -Launch exactly 2 subagents in parallel using the Task tool with `subagent_type="general-purpose"`. Each subagent should clone or read the SDK repo and evaluate its assigned area. +Launch 2 evaluations in parallel. Each should clone or read the SDK repo and evaluate its assigned area. -**IMPORTANT**: Launch both subagents at the same time (in the same response) so they run in parallel. +**IMPORTANT**: Launch both evaluations at the same time (in the same response) so they run in parallel. -### Subagent 1: Documentation Coverage +### Evaluation 1: Documentation Coverage -Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name, branch, and the feature list embedded in that prompt. +Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name and branch. -The subagent evaluates: +This evaluation checks: - Whether all non-experimental features are documented with examples (Tier 1 requirement) - Whether core features are documented (Tier 2 requirement) - Produces an evidence table with file:line references -### Subagent 2: Policy Evaluation +### Evaluation 2: Policy Evaluation Use the prompt from `references/policy-evaluation-prompt.md`. Pass the repo name and branch. -The subagent evaluates: +This evaluation checks: - Dependency update policy (required for Tier 1 and Tier 2) - Published roadmap (required for Tier 1; plan-toward-Tier-1 for Tier 2) - Clear versioning with documented breaking change policy (required for Tier 1) @@ -108,26 +80,26 @@ The subagent evaluates: ## Step 4: Compute Final Tier -Combine the deterministic scorecard (conformance %, issue metrics, release info) with the subagent judgment results (docs, policies). Apply the tier logic: +Combine the deterministic scorecard (from the CLI) with the evaluation results (docs, policies). Apply the tier logic: ### Tier 1 requires ALL of: - Conformance test pass rate == 100% - Issue triage compliance >= 90% within 2 business days - All P0 bugs resolved within 7 days - Stable release >= 1.0.0 with no pre-release suffix -- Clear versioning with documented breaking change policy (subagent-evaluated) -- All non-experimental features documented with examples (subagent-evaluated) -- Published dependency update policy (subagent-evaluated) -- Published roadmap with concrete steps tracking spec components (subagent-evaluated) +- Clear versioning with documented breaking change policy (evaluation) +- All non-experimental features documented with examples (evaluation) +- Published dependency update policy (evaluation) +- Published roadmap with concrete steps tracking spec components (evaluation) ### Tier 2 requires ALL of: - Conformance test pass rate >= 80% - Issue triage compliance >= 80% within 1 month - P0 bugs resolved within 2 weeks - At least one stable release >= 1.0.0 -- Basic docs covering core features (subagent-evaluated) -- Published dependency update policy (subagent-evaluated) -- Published plan toward Tier 1 or explanation for remaining Tier 2 (subagent-evaluated) +- Basic docs covering core features (evaluation) +- Published dependency update policy (evaluation) +- Published plan toward Tier 1 or explanation for remaining Tier 2 (evaluation) ### Otherwise: Tier 3 @@ -135,7 +107,7 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. **Important edge cases:** - If conformance tests could not be run (no server), this counts as a FAIL for both Tier 1 and Tier 2 conformance requirements unless the SDK has a documented reason and plan. -- If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — check for both. +- If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. ## Step 5: Generate Output @@ -165,10 +137,10 @@ The following reference files are available in the `references/` directory along - `references/tier-requirements.md` -- Full SEP-1730 requirements table with exact thresholds - `references/report-template.md` -- Output format template for the audit report -- `references/docs-coverage-prompt.md` -- Subagent prompt for documentation evaluation -- `references/policy-evaluation-prompt.md` -- Subagent prompt for policy evaluation +- `references/docs-coverage-prompt.md` -- Evaluation prompt for documentation coverage +- `references/policy-evaluation-prompt.md` -- Evaluation prompt for policy review -Read these reference files when you need the detailed content for subagent prompts or report formatting. +Read these reference files when you need the detailed content for evaluation prompts or report formatting. ## Usage Examples @@ -182,22 +154,6 @@ Read these reference files when you need the detailed content for subagent promp # Python SDK /mcp-sdk-tier-audit modelcontextprotocol/python-sdk -# Auto-detect from current directory -/mcp-sdk-tier-audit -``` - -For other SDKs, specify the repo and tell Claude how to start the conformance server: -``` +# Any other SDK /mcp-sdk-tier-audit modelcontextprotocol/go-sdk -# Claude will ask how to start the conformance server if it can't find one -``` - -### Directory Layout - -For best results, have the conformance repo and SDK repos checked out as siblings: -``` -some-dir/ - conformance/ # modelcontextprotocol/conformance - typescript-sdk/ # modelcontextprotocol/typescript-sdk - python-sdk/ # modelcontextprotocol/python-sdk ``` diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index dab0b1a..8d9f0ce 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -1,4 +1,4 @@ -# Policy Evaluation Subagent Prompt +# Policy Evaluation Prompt You are evaluating the governance and policy documentation of an MCP SDK repository for the SEP-1730 tier assessment. @@ -24,56 +24,40 @@ Evaluate three policy areas required by SEP-1730: gh repo clone {repo} /tmp/sdk-audit-policy -- --branch {branch} --depth 1 ``` -### 2. Search for policy documents +### 2. Read and evaluate policy documents -Check these files and locations for each policy area: +Check these files for each policy area. Read the actual content — you're evaluating the substance of what's written, not just whether the file exists. -**Dependency Policy:** -- `CONTRIBUTING.md` (look for dependency/update sections) -- `SECURITY.md` (may reference dependency updates) -- `.github/dependabot.yml` or `.github/dependabot.yaml` -- `.github/renovate.json` or `renovate.json` +**Dependency Policy** — check these files: +- `CONTRIBUTING.md` (dependency/update sections) +- `SECURITY.md` (dependency update references) +- `.github/dependabot.yml` or `.github/renovate.json` - `docs/` directory (any policy documents) -- `README.md` (may reference update policy) -- `DEPENDENCIES.md` or similar -- Any CI workflow files that run dependency updates +- `README.md` (dependency update references) +- CI workflow files that run dependency updates -**Roadmap:** +**Roadmap** — check these files: - `ROADMAP.md` -- `docs/roadmap.md` or `docs/ROADMAP.md` +- `docs/roadmap.md` - `README.md` (roadmap section) -- GitHub Projects or Milestones (check via `gh` CLI) - `CHANGELOG.md` (for evidence of planned work) -- Any file mentioning "roadmap" or "planned features" - -**Versioning Policy:** -- `CONTRIBUTING.md` (versioning/release sections) -- `README.md` (versioning section) -- `CHANGELOG.md` (evidence of versioning practice) -- `docs/versioning.md` or similar -- `RELEASE.md` or `docs/releasing.md` -- Any documentation mentioning "breaking changes", "semver", "versioning" - -```bash -# Search for policy-related content -grep -rli "dependency\|dependencies\|update policy\|dependabot\|renovate" /path/to/repo --include="*.md" --include="*.yml" --include="*.yaml" --include="*.json" -grep -rli "roadmap\|planned\|upcoming\|milestone" /path/to/repo --include="*.md" -grep -rli "breaking change\|semver\|versioning\|version policy\|release policy" /path/to/repo --include="*.md" -``` Also check GitHub-level resources: - ```bash # Check for GitHub milestones gh api repos/{repo}/milestones --jq '.[].title' -# Check for GitHub projects -gh api repos/{repo}/projects --jq '.[].name' 2>/dev/null || echo "No classic projects" - # Check for releases and versioning pattern gh release list --repo {repo} --limit 20 ``` +**Versioning Policy** — check these files: +- `CONTRIBUTING.md` (versioning/release sections) +- `README.md` (versioning section) +- `CHANGELOG.md` (evidence of versioning practice) +- `RELEASE.md` or `docs/releasing.md` +- Any documentation mentioning "breaking changes", "semver", "versioning" + ### 3. Evaluate each policy area For each area, determine: @@ -164,7 +148,6 @@ Produce your assessment in this exact format: | ROADMAP.md | {path} or "Not found" | "{summary}" or "File does not exist" | {Found/Not found} | | README roadmap section | {path}:{lines} or "Not found" | "{summary}" or "No roadmap section" | {Found/Not found} | | GitHub Milestones | {URL or count} | "{milestone names}" or "None" | {Found/Not found} | -| GitHub Projects | {URL or count} | "{project names}" or "None" | {Found/Not found} | | docs/ roadmap documents | {path} or "Not found" | "{summary}" or "None" | {Found/Not found} | | Other forward-looking docs | {path}:{lines} or "Not found" | "{summary}" or "None" | {Found/Not found} | diff --git a/README.md b/README.md index 47f80df..2b0583a 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,8 @@ Run `npx @modelcontextprotocol/conformance list --server` to see all available s The `tier-check` subcommand evaluates an MCP SDK repository against [SEP-1730](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1730) (the SDK Tiering System): ```bash +# Authenticate with GitHub, then run +gh auth login npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typescript-sdk ``` From cdc740270b0fd314b867b3de402982592d04e394 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 19:04:08 +0000 Subject: [PATCH 04/34] fix: resolve lint errors in conformance.ts Remove unused variable assignments flagged by eslint. Co-Authored-By: Claude Opus 4.6 --- src/tier-check/checks/conformance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index c475871..cfcb4db 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -10,7 +10,7 @@ async function waitForServer( const start = Date.now(); while (Date.now() - start < timeoutMs) { try { - const resp = await fetch(url, { method: 'GET' }); + await fetch(url, { method: 'GET' }); // Any HTTP response means the server is listening (400, 405, etc. are all valid) return; } catch { @@ -79,7 +79,7 @@ export async function checkConformance(options: { checks_passed: passed, checks_failed: failed }); - } catch (error) { + } catch { totalFailed++; details.push({ scenario: scenarioName, From 5e62b5fd5ad0347ce3baaa2f9e9369dd61e2a2aa Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 19:04:33 +0000 Subject: [PATCH 05/34] style: apply prettier formatting Co-Authored-By: Claude Opus 4.6 --- .claude/skills/mcp-sdk-tier-audit/README.md | 50 ++++---- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 16 ++- .../references/docs-coverage-prompt.md | 113 ++++++++++-------- .../references/policy-evaluation-prompt.md | 65 ++++++---- .../references/report-template.md | 68 ++++++----- .../references/tier-requirements.md | 82 +++++++------ src/tier-check/checks/conformance.ts | 3 +- src/tier-check/checks/labels.ts | 4 +- src/tier-check/checks/p0.ts | 4 +- src/tier-check/checks/triage.ts | 3 +- src/tier-check/index.ts | 13 +- src/tier-check/output.ts | 16 ++- 12 files changed, 240 insertions(+), 197 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index e24fde1..922caf6 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -26,6 +26,7 @@ npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typ ``` The CLI uses the GitHub API for issue metrics, labels, and release checks. Authenticate via one of: + - **GitHub CLI** (recommended): `gh auth login` — the CLI picks up your token automatically - **Environment variable**: `export GITHUB_TOKEN=ghp_...` (create a read-only token at [github.com/settings/tokens](https://github.com/settings/tokens) with `repo:read` and `issues:read` scopes) - **Flag**: `--token ghp_...` @@ -46,15 +47,15 @@ The CLI uses the GitHub API for issue metrics, labels, and release checks. Authe ### What the CLI Checks -| Check | What it measures | -|-------|-----------------| -| Conformance | Pass rate against the conformance test suite | -| Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | -| Triage | How quickly issues get labeled after creation | -| P0 Resolution | Whether critical bugs are resolved within SLA | -| Stable Release | Whether a stable release >= 1.0.0 exists | -| Policy Signals | Presence of CHANGELOG, SECURITY, CONTRIBUTING, dependabot, ROADMAP | -| Spec Tracking | Gap between latest spec release and SDK release | +| Check | What it measures | +| -------------- | ------------------------------------------------------------------------------ | +| Conformance | Pass rate against the conformance test suite | +| Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | +| Triage | How quickly issues get labeled after creation | +| P0 Resolution | Whether critical bugs are resolved within SLA | +| Stable Release | Whether a stable release >= 1.0.0 exists | +| Policy Signals | Presence of CHANGELOG, SECURITY, CONTRIBUTING, dependabot, ROADMAP | +| Spec Tracking | Gap between latest spec release and SDK release | ### Example Output @@ -97,6 +98,7 @@ It runs the CLI, launches parallel evaluations for docs and policy, and produces If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it these instructions: 1. **Run the CLI** to get the deterministic scorecard: + ```bash npx @modelcontextprotocol/conformance tier-check --repo --output json ``` @@ -113,21 +115,22 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the Run the CLI for the scorecard, then review docs and policies yourself using the tier requirements as a checklist: -| Requirement | Tier 1 | Tier 2 | -|---|---|---| -| Conformance | 100% pass | >= 80% pass | -| Issue triage | Within 2 business days | Within 1 month | -| P0 resolution | Within 7 days | Within 2 weeks | -| Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | -| Documentation | All features with examples | Core features documented | -| Dependency policy | Published | Published | -| Roadmap | Published with spec tracking | Plan toward Tier 1 | +| Requirement | Tier 1 | Tier 2 | +| ----------------- | ------------------------------ | ------------------------ | +| Conformance | 100% pass | >= 80% pass | +| Issue triage | Within 2 business days | Within 1 month | +| P0 resolution | Within 7 days | Within 2 weeks | +| Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | +| Documentation | All features with examples | Core features documented | +| Dependency policy | Published | Published | +| Roadmap | Published with spec tracking | Plan toward Tier 1 | ## Running Conformance Tests To include conformance test results in the scorecard, you need to start the SDK's everything server, then run tier-check against it. **TypeScript SDK:** + ```bash # Clone the TypeScript SDK and start its conformance server cd /path/to/typescript-sdk/test/conformance @@ -140,6 +143,7 @@ npx @modelcontextprotocol/conformance tier-check \ ``` **Python SDK:** + ```bash # In the python-sdk repo, start the everything server uv run mcp-everything-server & @@ -156,9 +160,9 @@ npx @modelcontextprotocol/conformance tier-check \ These files in [`references/`](references/) contain the detailed criteria and prompts: -| File | Purpose | -|------|---------| -| `tier-requirements.md` | Full SEP-1730 requirements with exact thresholds | -| `docs-coverage-prompt.md` | Feature checklist for documentation evaluation | +| File | Purpose | +| ----------------------------- | ------------------------------------------------------- | +| `tier-requirements.md` | Full SEP-1730 requirements with exact thresholds | +| `docs-coverage-prompt.md` | Feature checklist for documentation evaluation | | `policy-evaluation-prompt.md` | Criteria for dependency, roadmap, and versioning policy | -| `report-template.md` | Output format for the full audit report | +| `report-template.md` | Output format for the full audit report | diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index e26ffe9..986300f 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -5,7 +5,7 @@ description: >- Produces tier classification (1/2/3) with evidence table, gap list, and remediation guide. Works for any official MCP SDK (TypeScript, Python, Go, C#, Java, Kotlin, PHP, Swift, Rust, Ruby). -argument-hint: "[repo] [--branch ]" +argument-hint: '[repo] [--branch ]' --- # MCP SDK Tier Audit @@ -35,10 +35,10 @@ npx @modelcontextprotocol/conformance tier-check --repo --skip-conformanc To include conformance results, you need to start the SDK's everything server first. Look up the SDK below: -| SDK | Everything Server Location | Start Command | URL | -|-----|---------------------------|---------------|-----| -| TypeScript | `typescript-sdk/test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | -| Python | `python-sdk/examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | +| SDK | Everything Server Location | Start Command | URL | +| ---------- | ------------------------------------------------ | --------------------------------- | --------------------------- | +| TypeScript | `typescript-sdk/test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | +| Python | `python-sdk/examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | For other SDKs, ask the user how to start their everything server. @@ -64,6 +64,7 @@ Launch 2 evaluations in parallel. Each should clone or read the SDK repo and eva Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name and branch. This evaluation checks: + - Whether all non-experimental features are documented with examples (Tier 1 requirement) - Whether core features are documented (Tier 2 requirement) - Produces an evidence table with file:line references @@ -73,6 +74,7 @@ This evaluation checks: Use the prompt from `references/policy-evaluation-prompt.md`. Pass the repo name and branch. This evaluation checks: + - Dependency update policy (required for Tier 1 and Tier 2) - Published roadmap (required for Tier 1; plan-toward-Tier-1 for Tier 2) - Clear versioning with documented breaking change policy (required for Tier 1) @@ -83,6 +85,7 @@ This evaluation checks: Combine the deterministic scorecard (from the CLI) with the evaluation results (docs, policies). Apply the tier logic: ### Tier 1 requires ALL of: + - Conformance test pass rate == 100% - Issue triage compliance >= 90% within 2 business days - All P0 bugs resolved within 7 days @@ -93,6 +96,7 @@ Combine the deterministic scorecard (from the CLI) with the evaluation results ( - Published roadmap with concrete steps tracking spec components (evaluation) ### Tier 2 requires ALL of: + - Conformance test pass rate >= 80% - Issue triage compliance >= 80% within 1 month - P0 bugs resolved within 2 weeks @@ -106,6 +110,7 @@ Combine the deterministic scorecard (from the CLI) with the evaluation results ( If any Tier 2 requirement is not met, the SDK is Tier 3. **Important edge cases:** + - If conformance tests could not be run (no server), this counts as a FAIL for both Tier 1 and Tier 2 conformance requirements unless the SDK has a documented reason and plan. - If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. @@ -126,6 +131,7 @@ Produce a prioritized list of action items for SDK maintainers. Order by impact 3. **Longer-term** -- structural work needed Each item should include: + - What needs to change - Where in the repo to make the change (file paths if possible) - Estimated effort (small/medium/large) diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 9c17048..2ce9145 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -27,6 +27,7 @@ gh repo clone {repo} /tmp/sdk-audit-docs -- --branch {branch} --depth 1 ### 2. Find all documentation sources Search for documentation in these locations: + - `README.md` (root and any subdirectory READMEs) - `docs/` directory - `documentation/` directory @@ -50,6 +51,7 @@ find /path/to/repo -path "*/docs/*" -not -path "*/node_modules/*" ### 3. Evaluate each feature For each feature in the canonical list below, determine: + - **Documented?**: Is there documentation explaining this feature? (Yes/No) - **Where**: File path and line numbers where documentation exists - **Has Examples?**: Are there code examples showing how to use this feature? (Yes/No/N/A) @@ -60,6 +62,7 @@ For each feature in the canonical list below, determine: ### Core Features **Tools:** + - Tools - listing (`tools/list`) - Tools - calling (`tools/call`) - Tools - text results @@ -70,6 +73,7 @@ For each feature in the canonical list below, determine: - Tools - change notifications **Resources:** + - Resources - listing (`resources/list`) - Resources - reading text - Resources - reading binary @@ -80,6 +84,7 @@ For each feature in the canonical list below, determine: - Resources - change notifications **Prompts:** + - Prompts - listing (`prompts/list`) - Prompts - getting simple - Prompts - getting with arguments @@ -88,9 +93,11 @@ For each feature in the canonical list below, determine: - Prompts - change notifications **Sampling:** + - Sampling - creating messages (`sampling/createMessage`) **Elicitation:** + - Elicitation - requesting input (`elicitation/create`) — form mode - Elicitation - URL mode (`elicitation/create` with `mode: "url"`) - Elicitation - schema validation @@ -99,21 +106,26 @@ For each feature in the canonical list below, determine: - Elicitation - complete notification (`notifications/elicitation/complete`) **Roots:** + - Roots - listing (`roots/list`) - Roots - change notifications **Logging:** + - Logging - sending log messages - Logging - setting level (`logging/setLevel`) **Completions:** + - Completions - resource argument completion - Completions - prompt argument completion **Ping:** + - Ping (`ping`) ### Transport Features + - Streamable HTTP transport (client) - Streamable HTTP transport (server) - SSE transport - legacy (client) @@ -122,6 +134,7 @@ For each feature in the canonical list below, determine: - stdio transport (server) ### Protocol Features + - Progress notifications - Cancellation - Pagination @@ -130,6 +143,7 @@ For each feature in the canonical list below, determine: - JSON Schema 2020-12 support ### Experimental Features (does not count toward tier score) + - Tasks - get (`tasks/get`) - Tasks - result (`tasks/result`) - Tasks - cancel (`tasks/cancel`) @@ -146,60 +160,61 @@ Produce your assessment in this exact format: **Repository**: {repo} **Branch**: {branch} **Documentation locations found**: + - {path1}: {description} - {path2}: {description} - ... #### Feature Documentation Table -| Feature | Documented? | Where | Has Examples? | Verdict | -|---------|-------------|-------|---------------|---------| -| Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - status notifications (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Feature | Documented? | Where | Has Examples? | Verdict | +| ------------------------------------------- | ----------- | -------------- | ----------------------- | ----------------- | +| Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| Tasks - status notifications (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | #### Summary @@ -214,9 +229,11 @@ Produce your assessment in this exact format: #### Tier Verdicts **Tier 1** (all non-experimental features documented with examples): **PASS/FAIL** + - {If FAIL: list the features missing documentation or examples} **Tier 2** (basic docs covering core features): **PASS/FAIL** + - {If FAIL: list the core features missing documentation} ``` diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index 8d9f0ce..18d072b 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -10,6 +10,7 @@ You are evaluating the governance and policy documentation of an MCP SDK reposit ## Your Task Evaluate three policy areas required by SEP-1730: + 1. **Dependency update policy** (required for Tier 1 and Tier 2) 2. **Roadmap** (Tier 1: published roadmap; Tier 2: published plan toward Tier 1) 3. **Versioning policy** (Tier 1: clear versioning with documented breaking change policy) @@ -29,6 +30,7 @@ gh repo clone {repo} /tmp/sdk-audit-policy -- --branch {branch} --depth 1 Check these files for each policy area. Read the actual content — you're evaluating the substance of what's written, not just whether the file exists. **Dependency Policy** — check these files: + - `CONTRIBUTING.md` (dependency/update sections) - `SECURITY.md` (dependency update references) - `.github/dependabot.yml` or `.github/renovate.json` @@ -37,12 +39,14 @@ Check these files for each policy area. Read the actual content — you're evalu - CI workflow files that run dependency updates **Roadmap** — check these files: + - `ROADMAP.md` - `docs/roadmap.md` - `README.md` (roadmap section) - `CHANGELOG.md` (for evidence of planned work) Also check GitHub-level resources: + ```bash # Check for GitHub milestones gh api repos/{repo}/milestones --jq '.[].title' @@ -52,6 +56,7 @@ gh release list --repo {repo} --limit 20 ``` **Versioning Policy** — check these files: + - `CONTRIBUTING.md` (versioning/release sections) - `README.md` (versioning section) - `CHANGELOG.md` (evidence of versioning practice) @@ -61,6 +66,7 @@ gh release list --repo {repo} --limit 20 ### 3. Evaluate each policy area For each area, determine: + - Is there a published policy/document? - What does it commit to? (specific commitments vs vague statements) - Does it meet Tier 1 standards? Tier 2 standards? @@ -70,6 +76,7 @@ For each area, determine: ### Dependency Update Policy **PASS for Tier 1 and Tier 2** requires: + - A published, findable policy describing how dependencies are updated - The policy must include actual commitments (e.g., "updated monthly", "security patches within 48h") - Automated tooling (Dependabot, Renovate) configured counts as evidence of policy in practice @@ -78,29 +85,34 @@ For each area, determine: **Tier 1 additional**: Policy should be comprehensive -- covering frequency, security updates, major version handling **FAIL** if: + - No dependency update policy found anywhere in the repo - Only vague references like "we try to keep dependencies up to date" ### Roadmap **PASS for Tier 1** requires: + - A published roadmap document with concrete steps and work items - Must track implementation of MCP specification components (non-experimental features and optional capabilities) - Must give users visibility into upcoming feature support - Can be a ROADMAP.md, GitHub milestones/projects, or a section in docs **PASS for Tier 2** requires: + - A published plan toward Tier 1 (what the SDK intends to implement to reach full support) - OR an explanation of why the SDK will remain at Tier 2 (intentionally scoped) - Can be simpler than a full roadmap **FAIL** if: + - No roadmap or plan found - Only a CHANGELOG showing past work (not forward-looking) ### Versioning Policy **PASS for Tier 1** requires: + - Documented breaking change policy (what constitutes a breaking change, how they are communicated) - Clear versioning pattern (SemVer or language-idiomatic equivalent) - Users can understand compatibility expectations when upgrading @@ -108,6 +120,7 @@ For each area, determine: **Not required for Tier 2** (only needs a stable release >= 1.0.0) **FAIL** if: + - No versioning documentation found - No breaking change policy documented @@ -125,14 +138,14 @@ Produce your assessment in this exact format: #### 1. Dependency Update Policy: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -|---|---|---|---| +| What Was Checked | Where | Content Found | Verdict | +| ---------------------------------- | ----------------------------- | --------------------------------------------- | ----------------- | | CONTRIBUTING.md dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No dependency section" | {Found/Not found} | -| Dependabot/Renovate config | {path} or "Not found" | "{config summary}" or "Not configured" | {Found/Not found} | -| README dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | -| SECURITY.md dependency references | {path}:{lines} or "Not found" | "{relevant quote}" or "No references" | {Found/Not found} | -| CI dependency update workflows | {path} or "Not found" | "{workflow description}" or "None" | {Found/Not found} | -| Other policy documents | {path}:{lines} or "Not found" | "{relevant quote}" or "None" | {Found/Not found} | +| Dependabot/Renovate config | {path} or "Not found" | "{config summary}" or "Not configured" | {Found/Not found} | +| README dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | +| SECURITY.md dependency references | {path}:{lines} or "Not found" | "{relevant quote}" or "No references" | {Found/Not found} | +| CI dependency update workflows | {path} or "Not found" | "{workflow description}" or "None" | {Found/Not found} | +| Other policy documents | {path}:{lines} or "Not found" | "{relevant quote}" or "None" | {Found/Not found} | **Policy content summary**: {Brief description of what the policy says, or "No dependency update policy found"} @@ -143,13 +156,13 @@ Produce your assessment in this exact format: #### 2. Roadmap: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -|---|---|---|---| -| ROADMAP.md | {path} or "Not found" | "{summary}" or "File does not exist" | {Found/Not found} | -| README roadmap section | {path}:{lines} or "Not found" | "{summary}" or "No roadmap section" | {Found/Not found} | -| GitHub Milestones | {URL or count} | "{milestone names}" or "None" | {Found/Not found} | -| docs/ roadmap documents | {path} or "Not found" | "{summary}" or "None" | {Found/Not found} | -| Other forward-looking docs | {path}:{lines} or "Not found" | "{summary}" or "None" | {Found/Not found} | +| What Was Checked | Where | Content Found | Verdict | +| -------------------------- | ----------------------------- | ------------------------------------ | ----------------- | +| ROADMAP.md | {path} or "Not found" | "{summary}" or "File does not exist" | {Found/Not found} | +| README roadmap section | {path}:{lines} or "Not found" | "{summary}" or "No roadmap section" | {Found/Not found} | +| GitHub Milestones | {URL or count} | "{milestone names}" or "None" | {Found/Not found} | +| docs/ roadmap documents | {path} or "Not found" | "{summary}" or "None" | {Found/Not found} | +| Other forward-looking docs | {path}:{lines} or "Not found" | "{summary}" or "None" | {Found/Not found} | **Roadmap content summary**: {Brief description of the roadmap contents, or "No roadmap found"} @@ -160,14 +173,14 @@ Produce your assessment in this exact format: #### 3. Versioning Policy: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -|---|---|---|---| -| CONTRIBUTING.md versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No versioning section" | {Found/Not found} | -| README versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | -| CHANGELOG.md versioning evidence | {path} or "Not found" | "{pattern observed}" or "Not found" | {Found/Not found} | -| Release docs | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | -| Breaking change documentation | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | -| Version pattern analysis | Release history | "{pattern}" (e.g., "Follows SemVer, X.Y.Z pattern") | {Consistent/Inconsistent} | +| What Was Checked | Where | Content Found | Verdict | +| ---------------------------------- | ----------------------------- | --------------------------------------------------- | ------------------------- | +| CONTRIBUTING.md versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No versioning section" | {Found/Not found} | +| README versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | +| CHANGELOG.md versioning evidence | {path} or "Not found" | "{pattern observed}" or "Not found" | {Found/Not found} | +| Release docs | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | +| Breaking change documentation | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | +| Version pattern analysis | Release history | "{pattern}" (e.g., "Follows SemVer, X.Y.Z pattern") | {Consistent/Inconsistent} | **Versioning content summary**: {Brief description of the versioning approach and breaking change policy, or "No versioning policy found"} @@ -178,11 +191,11 @@ Produce your assessment in this exact format: #### Overall Policy Summary -| Policy Area | Tier 1 | Tier 2 | -|---|---|---| +| Policy Area | Tier 1 | Tier 2 | +| ------------------------ | --------- | --------- | | Dependency Update Policy | PASS/FAIL | PASS/FAIL | -| Roadmap | PASS/FAIL | PASS/FAIL | -| Versioning Policy | PASS/FAIL | N/A | +| Roadmap | PASS/FAIL | PASS/FAIL | +| Versioning Policy | PASS/FAIL | N/A | ``` ## Important Notes diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index de46e6b..abb2104 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -19,16 +19,16 @@ Use this exact format when generating the final tier audit report. ### Requirements Summary -| # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | -|---|---|---|---|---|---|---|---| -| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 2 | Issue Triage | Within 2 business days | Within 1 month | {median triage time} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 3 | Critical Bug Resolution | Within 7 days | Within 2 weeks | {P0 resolution stats} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 4 | Stable Release | Required + clear versioning | At least one stable release | {latest version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 5 | Documentation | Comprehensive w/ examples for all features | Basic docs covering core features | {X}/{Y} features documented | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 8 | Versioning Policy | Documented breaking change policy | N/A | {Found/Not found} | {PASS/FAIL} | {N/A} | {detail or "None"} | +| # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | +| --- | ----------------------- | ------------------------------------------ | --------------------------------- | --------------------------- | ----------- | ----------- | ------------------ | +| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 2 | Issue Triage | Within 2 business days | Within 1 month | {median triage time} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 3 | Critical Bug Resolution | Within 7 days | Within 2 weeks | {P0 resolution stats} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 4 | Stable Release | Required + clear versioning | At least one stable release | {latest version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 5 | Documentation | Comprehensive w/ examples for all features | Basic docs covering core features | {X}/{Y} features documented | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 8 | Versioning Policy | Documented breaking change policy | N/A | {Found/Not found} | {PASS/FAIL} | {N/A} | {detail or "None"} | **Legend**: PASS = meets requirement, FAIL = does not meet requirement, N/A = not applicable at this tier @@ -49,13 +49,14 @@ Use this exact format when generating the final tier audit report. {If tests were run, include per-scenario breakdown:} -| Scenario | Status | Notes | -|---|---|---| -| lifecycle | PASS/FAIL | {detail} | +| Scenario | Status | Notes | +| ---------- | --------- | -------- | +| lifecycle | PASS/FAIL | {detail} | | tools-list | PASS/FAIL | {detail} | -| ... | ... | ... | +| ... | ... | ... | {If tests were NOT run:} + > Conformance tests could not be run: {reason}. This is recorded as a gap. --- @@ -65,14 +66,15 @@ Use this exact format when generating the final tier audit report. **Analysis period**: Last {N} issues **Labels configured**: {Yes/No -- list which SEP-1730 labels are present} -| Metric | Value | Tier 1 Requirement | Tier 2 Requirement | Verdict | -|---|---|---|---|---| -| Median triage time | {value} | <= 2 business days | <= 1 month | {T1: PASS/FAIL, T2: PASS/FAIL} | -| Triage compliance rate | {X}% | >= 90% | >= 80% | {T1: PASS/FAIL, T2: PASS/FAIL} | -| P0 issues found | {N} | -- | -- | -- | -| P0 median resolution time | {value} | <= 7 days | <= 14 days | {T1: PASS/FAIL, T2: PASS/FAIL} | +| Metric | Value | Tier 1 Requirement | Tier 2 Requirement | Verdict | +| ------------------------- | ------- | ------------------ | ------------------ | ------------------------------ | +| Median triage time | {value} | <= 2 business days | <= 1 month | {T1: PASS/FAIL, T2: PASS/FAIL} | +| Triage compliance rate | {X}% | >= 90% | >= 80% | {T1: PASS/FAIL, T2: PASS/FAIL} | +| P0 issues found | {N} | -- | -- | -- | +| P0 median resolution time | {value} | <= 7 days | <= 14 days | {T1: PASS/FAIL, T2: PASS/FAIL} | {If labels are not set up:} + > SEP-1730 labels are not configured in this repository. Issue triage metrics cannot be computed. This is a blocking gap for Tier 1 and Tier 2. --- @@ -97,25 +99,25 @@ Use this exact format when generating the final tier audit report. ### Blocking for Tier {next tier} (must fix) -| # | Action Item | Requirement | Effort | Where to Change | -|---|---|---|---|---| -| 1 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | -| 2 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action Item | Requirement | Effort | Where to Change | +| --- | ------------- | ------------------ | -------------------- | --------------- | +| 1 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | +| 2 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | +| ... | ... | ... | ... | ... | ### Quick Wins (low effort, high impact) -| # | Action Item | Requirement | Effort | Where to Change | -|---|---|---|---|---| -| 1 | {description} | {requirement name} | Small | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action Item | Requirement | Effort | Where to Change | +| --- | ------------- | ------------------ | ------ | --------------- | +| 1 | {description} | {requirement name} | Small | {file path(s)} | +| ... | ... | ... | ... | ... | ### Longer-Term Improvements -| # | Action Item | Requirement | Effort | Where to Change | -|---|---|---|---|---| -| 1 | {description} | {requirement name} | {Medium/Large} | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action Item | Requirement | Effort | Where to Change | +| --- | ------------- | ------------------ | -------------- | --------------- | +| 1 | {description} | {requirement name} | {Medium/Large} | {file path(s)} | +| ... | ... | ... | ... | ... | ### Recommended Next Steps diff --git a/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md b/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md index ea64f41..b36a2d2 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/tier-requirements.md @@ -6,33 +6,34 @@ Source: `modelcontextprotocol/docs/community/sdk-tiers.mdx` in the spec reposito ## Full Requirements Table -| Requirement | Tier 1: Fully Supported | Tier 2: Commitment to Full Support | Tier 3: Experimental | -|---|---|---|---| -| **Conformance Tests** | 100% pass rate | >= 80% pass rate | No minimum | -| **New Protocol Features** | Before new spec version release, timeline agreed per release based on feature complexity | Within 6 months | No timeline commitment | -| **Issue Triage** | Within 2 business days | Within a month | No requirement | -| **Critical Bug Resolution** | Within 7 days | Within two weeks | No requirement | -| **Stable Release** | Required with clear versioning | At least one stable release | Not required | -| **Documentation** | Comprehensive with examples for all features | Basic documentation covering core features | No minimum | -| **Dependency Policy** | Published update policy | Published update policy | Not required | -| **Roadmap** | Published roadmap | Published plan toward Tier 1 or explanation for remaining Tier 2 | Not required | +| Requirement | Tier 1: Fully Supported | Tier 2: Commitment to Full Support | Tier 3: Experimental | +| --------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------- | +| **Conformance Tests** | 100% pass rate | >= 80% pass rate | No minimum | +| **New Protocol Features** | Before new spec version release, timeline agreed per release based on feature complexity | Within 6 months | No timeline commitment | +| **Issue Triage** | Within 2 business days | Within a month | No requirement | +| **Critical Bug Resolution** | Within 7 days | Within two weeks | No requirement | +| **Stable Release** | Required with clear versioning | At least one stable release | Not required | +| **Documentation** | Comprehensive with examples for all features | Basic documentation covering core features | No minimum | +| **Dependency Policy** | Published update policy | Published update policy | Not required | +| **Roadmap** | Published roadmap | Published plan toward Tier 1 or explanation for remaining Tier 2 | Not required | ## Exact Thresholds for Automated Checking -| Metric | Tier 1 Threshold | Tier 2 Threshold | How to Measure | -|---|---|---|---| -| Conformance pass rate | == 100% | >= 80% | `passed / (passed + failed) * 100` from conformance suite | -| Issue triage time | <= 2 business days | <= 1 month (30 calendar days) | Time from issue creation to first label application | -| P0 resolution time | <= 7 calendar days | <= 14 calendar days | Time from P0 label application to issue close | -| Stable release version | >= 1.0.0, no pre-release suffix | >= 1.0.0 (at least one) | Check `gh release list` for version matching `^[0-9]+\.[0-9]+\.[0-9]+$` where major >= 1 | -| Documentation coverage | All non-experimental features documented with examples | Core features documented | Subagent evaluation | -| Dependency policy | Published and findable in repo | Published and findable in repo | Subagent evaluation | -| Roadmap | Published with concrete steps tracking spec components | Published plan toward Tier 1 | Subagent evaluation | -| Versioning policy | Documented breaking change policy | N/A (just needs stable release) | Subagent evaluation | +| Metric | Tier 1 Threshold | Tier 2 Threshold | How to Measure | +| ---------------------- | ------------------------------------------------------ | ------------------------------- | ---------------------------------------------------------------------------------------- | +| Conformance pass rate | == 100% | >= 80% | `passed / (passed + failed) * 100` from conformance suite | +| Issue triage time | <= 2 business days | <= 1 month (30 calendar days) | Time from issue creation to first label application | +| P0 resolution time | <= 7 calendar days | <= 14 calendar days | Time from P0 label application to issue close | +| Stable release version | >= 1.0.0, no pre-release suffix | >= 1.0.0 (at least one) | Check `gh release list` for version matching `^[0-9]+\.[0-9]+\.[0-9]+$` where major >= 1 | +| Documentation coverage | All non-experimental features documented with examples | Core features documented | Subagent evaluation | +| Dependency policy | Published and findable in repo | Published and findable in repo | Subagent evaluation | +| Roadmap | Published with concrete steps tracking spec components | Published plan toward Tier 1 | Subagent evaluation | +| Versioning policy | Documented breaking change policy | N/A (just needs stable release) | Subagent evaluation | ## Conformance Score Calculation Conformance scores are calculated against **applicable required tests** only: + - Tests for the specification version the SDK targets - Excluding tests marked as pending or skipped - Excluding tests for experimental features @@ -49,49 +50,54 @@ SDK repositories must use these consistent labels to enable automated reporting. ### Type Labels (pick one) -| Label | Description | -|---|---| -| `bug` | Something isn't working | -| `enhancement` | Request for new feature | -| `question` | Further information requested | +| Label | Description | +| ------------- | ----------------------------- | +| `bug` | Something isn't working | +| `enhancement` | Request for new feature | +| `question` | Further information requested | Note: Repositories using GitHub's native issue types satisfy this requirement without needing type labels. ### Status Labels (pick one) -| Label | Description | -|---|---| -| `needs confirmation` | Unclear if still relevant | -| `needs repro` | Insufficient information to reproduce | -| `ready for work` | Has enough information to start | -| `good first issue` | Good for newcomers | -| `help wanted` | Contributions welcome from those familiar with codebase | +| Label | Description | +| -------------------- | ------------------------------------------------------- | +| `needs confirmation` | Unclear if still relevant | +| `needs repro` | Insufficient information to reproduce | +| `ready for work` | Has enough information to start | +| `good first issue` | Good for newcomers | +| `help wanted` | Contributions welcome from those familiar with codebase | ### Priority Labels (only if actionable) -| Label | Description | -|---|---| -| `P0` | Critical: core functionality failures or high-severity security | -| `P1` | Significant bug affecting many users | -| `P2` | Moderate issues, valuable feature requests | -| `P3` | Nice to haves, rare edge cases | +| Label | Description | +| ----- | --------------------------------------------------------------- | +| `P0` | Critical: core functionality failures or high-severity security | +| `P1` | Significant bug affecting many users | +| `P2` | Moderate issues, valuable feature requests | +| `P3` | Nice to haves, rare edge cases | **Total: 12 labels** (3 type + 5 status + 4 priority) ## Key Definitions ### Issue Triage + Labeling and determining whether an issue is valid. This is NOT the same as resolving the issue. An issue is considered triaged when it receives its first label. ### Critical Bug (P0) + - **Security vulnerabilities** with CVSS score >= 7.0 (High or Critical severity) - **Core functionality failures** that prevent basic MCP operations: connection establishment, message exchange, or use of core primitives (tools, resources, prompts) ### Stable Release + A published version explicitly marked as production-ready. Specifically: version `1.0.0` or higher without pre-release identifiers like `-alpha`, `-beta`, or `-rc`. ### Clear Versioning + Following idiomatic versioning patterns with documented breaking change policies, so users can understand compatibility expectations when upgrading. ### Roadmap + Outlines concrete steps and work items that track implementation of required MCP specification components (non-experimental features and optional capabilities), giving users visibility into upcoming feature support. diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index cfcb4db..604d7f7 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -94,8 +94,7 @@ export async function checkConformance(options: { const pass_rate = total > 0 ? totalPassed / total : 0; return { - status: - pass_rate >= 1.0 ? 'pass' : pass_rate >= 0.8 ? 'partial' : 'fail', + status: pass_rate >= 1.0 ? 'pass' : pass_rate >= 0.8 ? 'partial' : 'fail', pass_rate, passed: totalPassed, failed: totalFailed, diff --git a/src/tier-check/checks/labels.ts b/src/tier-check/checks/labels.ts index 93b7f96..a2b37b7 100644 --- a/src/tier-check/checks/labels.ts +++ b/src/tier-check/checks/labels.ts @@ -58,9 +58,7 @@ export async function checkLabels( ...PRIORITY_LABELS ]; - const missing = requiredLabels.filter( - (l) => !labelSet.has(l.toLowerCase()) - ); + const missing = requiredLabels.filter((l) => !labelSet.has(l.toLowerCase())); const found = requiredLabels.filter((l) => labelSet.has(l.toLowerCase())); return { diff --git a/src/tier-check/checks/p0.ts b/src/tier-check/checks/p0.ts index 599cdc1..25fad15 100644 --- a/src/tier-check/checks/p0.ts +++ b/src/tier-check/checks/p0.ts @@ -45,9 +45,7 @@ export async function checkP0Resolution( } const openP0s = p0Issues.filter((i) => i.state === 'open'); - const closedP0s = p0Issues.filter( - (i) => i.state === 'closed' && i.closed_at - ); + const closedP0s = p0Issues.filter((i) => i.state === 'closed' && i.closed_at); let closedWithin7d = 0; let closedWithin14d = 0; diff --git a/src/tier-check/checks/triage.ts b/src/tier-check/checks/triage.ts index 7feac1f..523f4ec 100644 --- a/src/tier-check/checks/triage.ts +++ b/src/tier-check/checks/triage.ts @@ -68,8 +68,7 @@ export async function checkTriage( // For untriaged issues, compute how long they've been open without a label const untriagedAgeHours = untriaged.map( - (i) => - (Date.now() - new Date(i.created_at).getTime()) / (1000 * 60 * 60) + (i) => (Date.now() - new Date(i.created_at).getTime()) / (1000 * 60 * 60) ); untriagedAgeHours.sort((a, b) => a - b); diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index 5aa8dff..9817ba6 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -20,9 +20,7 @@ function parseRepo(repo: string): { owner: string; repo: string } { export function createTierCheckCommand(): Command { const tierCheck = new Command('tier-check') - .description( - 'Run SDK tier assessment checks against a GitHub repository' - ) + .description('Run SDK tier assessment checks against a GitHub repository') .requiredOption( '--repo ', 'GitHub repository (e.g., modelcontextprotocol/typescript-sdk)' @@ -36,10 +34,7 @@ export function createTierCheckCommand(): Command { '--conformance-server-cwd ', 'Working directory for the conformance server' ) - .option( - '--conformance-server-url ', - 'URL of the conformance server' - ) + .option('--conformance-server-url ', 'URL of the conformance server') .option('--skip-conformance', 'Skip conformance tests') .option('--days ', 'Limit triage check to issues created in last N days') .option( @@ -58,8 +53,8 @@ export function createTierCheckCommand(): Command { if (!token) { console.error( 'GitHub token required. Either:\n' + - ' export GITHUB_TOKEN=$(gh auth token)\n' + - ' or pass --token ' + ' export GITHUB_TOKEN=$(gh auth token)\n' + + ' or pass --token ' ); process.exit(1); } diff --git a/src/tier-check/output.ts b/src/tier-check/output.ts index a787d01..94f9dda 100644 --- a/src/tier-check/output.ts +++ b/src/tier-check/output.ts @@ -58,7 +58,11 @@ export function formatMarkdown(scorecard: TierScorecard): string { `| Stable Release | ${c.stable_release.status} | ${c.stable_release.version || 'none'} (stable: ${c.stable_release.is_stable}) |` ); lines.push( - `| Policy Signals | ${c.policy_signals.status} | ${Object.entries(c.policy_signals.files).map(([f, e]) => `${f}: ${e ? '\u2713' : '\u2717'}`).join(', ')} |` + `| Policy Signals | ${c.policy_signals.status} | ${Object.entries( + c.policy_signals.files + ) + .map(([f, e]) => `${f}: ${e ? '\u2713' : '\u2717'}`) + .join(', ')} |` ); lines.push( `| Spec Tracking | ${c.spec_tracking.status} | ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'} |` @@ -122,7 +126,11 @@ export function formatTerminal(scorecard: TierScorecard): void { ` ${statusIcon(c.stable_release.status)} Stable Release ${c.stable_release.version || 'none'}` ); console.log( - ` ${statusIcon(c.policy_signals.status)} Policy Signals ${Object.entries(c.policy_signals.files).map(([f, e]) => `${e ? '\u2713' : '\u2717'} ${f}`).join(', ')}` + ` ${statusIcon(c.policy_signals.status)} Policy Signals ${Object.entries( + c.policy_signals.files + ) + .map(([f, e]) => `${e ? '\u2713' : '\u2717'} ${f}`) + .join(', ')}` ); console.log( ` ${statusIcon(c.spec_tracking.status)} Spec Tracking ${c.spec_tracking.days_gap !== null ? `${c.spec_tracking.days_gap}d gap` : 'N/A'}` @@ -135,7 +143,5 @@ export function formatTerminal(scorecard: TierScorecard): void { } } - console.log( - `\n${COLORS.DIM}${scorecard.implied_tier.note}${COLORS.RESET}\n` - ); + console.log(`\n${COLORS.DIM}${scorecard.implied_tier.note}${COLORS.RESET}\n`); } From 9a1018c2108eea4732b834eba49b97179b2a927e Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:11:24 +0000 Subject: [PATCH 06/34] 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 --- .claude/skills/mcp-sdk-tier-audit/README.md | 36 ++++++++++----------- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 22 +++++++------ README.md | 2 +- package.json | 1 + src/tier-check/index.ts | 13 +++++++- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 922caf6..f4c17b2 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -21,16 +21,18 @@ npm run build # Authenticate with GitHub (needed for API access) gh auth login -# Run against any MCP SDK repo -npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typescript-sdk +# Run against any MCP SDK repo (without conformance tests) +npm run tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance ``` -The CLI uses the GitHub API for issue metrics, labels, and release checks. Authenticate via one of: +The CLI uses the GitHub API (read-only) for issue metrics, labels, and release checks. Authenticate via one of: - **GitHub CLI** (recommended): `gh auth login` — the CLI picks up your token automatically -- **Environment variable**: `export GITHUB_TOKEN=ghp_...` (create a read-only token at [github.com/settings/tokens](https://github.com/settings/tokens) with `repo:read` and `issues:read` scopes) +- **Environment variable**: `export GITHUB_TOKEN=ghp_...` - **Flag**: `--token ghp_...` +For public repos, any authenticated token works (no special scopes needed — authentication just avoids rate limits). For a [fine-grained personal access token](https://github.com/settings/personal-access-tokens/new), select **Public Repositories (read-only)** with no additional permissions. + ### CLI Options ``` @@ -100,7 +102,7 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the 1. **Run the CLI** to get the deterministic scorecard: ```bash - npx @modelcontextprotocol/conformance tier-check --repo --output json + npm run tier-check -- --repo --skip-conformance --output json ``` 2. **Evaluate documentation coverage** — check whether MCP features (tools, resources, prompts, sampling, transports, etc.) are documented with examples. See [`references/docs-coverage-prompt.md`](references/docs-coverage-prompt.md) for the full checklist. @@ -129,32 +131,28 @@ Run the CLI for the scorecard, then review docs and policies yourself using the To include conformance test results in the scorecard, you need to start the SDK's everything server, then run tier-check against it. -**TypeScript SDK:** +**TypeScript SDK** (assuming checkout at `~/src/mcp/typescript-sdk`): ```bash -# Clone the TypeScript SDK and start its conformance server -cd /path/to/typescript-sdk/test/conformance -npx tsx src/everythingServer.ts & - -# Back in the conformance repo, run tier-check -npx @modelcontextprotocol/conformance tier-check \ +# The CLI starts the server, runs conformance, and cleans up automatically +npm run tier-check -- \ --repo modelcontextprotocol/typescript-sdk \ + --conformance-server-cmd 'npx tsx src/everythingServer.ts' \ + --conformance-server-cwd ~/src/mcp/typescript-sdk/test/conformance \ --conformance-server-url http://localhost:3000/mcp ``` -**Python SDK:** +**Python SDK** (assuming checkout at `~/src/mcp/python-sdk`): ```bash -# In the python-sdk repo, start the everything server -uv run mcp-everything-server & - -# Back in the conformance repo, run tier-check -npx @modelcontextprotocol/conformance tier-check \ +npm run tier-check -- \ --repo modelcontextprotocol/python-sdk \ + --conformance-server-cmd 'uv run mcp-everything-server' \ + --conformance-server-cwd ~/src/mcp/python-sdk/examples/servers/everything-server \ --conformance-server-url http://localhost:3001/mcp ``` -**Other SDKs:** Start your SDK's everything server, then pass `--conformance-server-url`. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. +**Other SDKs:** Pass `--conformance-server-cmd`, `--conformance-server-cwd`, and `--conformance-server-url` pointing to your SDK's everything server. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. ## Reference Files diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 986300f..6e79bfe 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -28,26 +28,28 @@ The `tier-check` CLI handles all deterministic checks — conformance, labels, t ### Without conformance tests (fastest) ```bash -npx @modelcontextprotocol/conformance tier-check --repo --skip-conformance --output json +npm run tier-check -- --repo --skip-conformance --output json ``` ### With conformance tests -To include conformance results, you need to start the SDK's everything server first. Look up the SDK below: +To include conformance results, the CLI can start the SDK's everything server automatically. Look up the SDK below: -| SDK | Everything Server Location | Start Command | URL | -| ---------- | ------------------------------------------------ | --------------------------------- | --------------------------- | -| TypeScript | `typescript-sdk/test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | -| Python | `python-sdk/examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | +| SDK | Everything Server Location (relative to SDK repo) | Start Command | URL | +| ---------- | ------------------------------------------------- | --------------------------------- | --------------------------- | +| TypeScript | `test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | +| Python | `examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | For other SDKs, ask the user how to start their everything server. -Start the server, then run: +Example (assuming TypeScript SDK checked out at `~/src/mcp/typescript-sdk`): ```bash -npx @modelcontextprotocol/conformance tier-check \ - --repo \ - --conformance-server-url \ +npm run tier-check -- \ + --repo modelcontextprotocol/typescript-sdk \ + --conformance-server-cmd 'npx tsx src/everythingServer.ts' \ + --conformance-server-cwd ~/src/mcp/typescript-sdk/test/conformance \ + --conformance-server-url http://localhost:3000/mcp \ --output json ``` diff --git a/README.md b/README.md index 2b0583a..4be710e 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ The `tier-check` subcommand evaluates an MCP SDK repository against [SEP-1730](h ```bash # Authenticate with GitHub, then run gh auth login -npx @modelcontextprotocol/conformance tier-check --repo modelcontextprotocol/typescript-sdk +npm run tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance ``` If you use Claude Code, open it in this repo and run `/mcp-sdk-tier-audit` for a full AI-assisted assessment with remediation guide. diff --git a/package.json b/package.json index 6143e39..a9f1e8f 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "lint": "eslint src/ examples/ && prettier --check .", "lint:fix": "eslint src/ examples/ --fix && prettier --write .", "lint:fix_check": "npm run lint:fix && git diff --exit-code --quiet", + "tier-check": "node dist/index.js tier-check", "check": "npm run typecheck && npm run lint", "typecheck": "tsgo --noEmit", "prepack": "npm run build" diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index 9817ba6..fa9f316 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -48,11 +48,22 @@ export function createTierCheckCommand(): Command { ) .action(async (options) => { const { owner, repo } = parseRepo(options.repo); - const token = options.token || process.env.GITHUB_TOKEN; + let token = options.token || process.env.GITHUB_TOKEN; + + if (!token) { + // Try to get token from GitHub CLI + try { + const { execSync } = await import('child_process'); + token = execSync('gh auth token', { encoding: 'utf-8' }).trim(); + } catch { + // gh not installed or not authenticated + } + } if (!token) { console.error( 'GitHub token required. Either:\n' + + ' gh auth login\n' + ' export GITHUB_TOKEN=$(gh auth token)\n' + ' or pass --token ' ); From 0a916729c4bce119f9c29b5de12f1375703549c4 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:28:08 +0000 Subject: [PATCH 07/34] style: fix prettier formatting in SKILL.md --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 6e79bfe..2e67e2c 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -38,7 +38,7 @@ To include conformance results, the CLI can start the SDK's everything server au | SDK | Everything Server Location (relative to SDK repo) | Start Command | URL | | ---------- | ------------------------------------------------- | --------------------------------- | --------------------------- | | TypeScript | `test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | -| Python | `examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | +| Python | `examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | For other SDKs, ask the user how to start their everything server. From 12c50a7dc2b58b70f777174f27a542bd0f6b184f Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:36:38 +0000 Subject: [PATCH 08/34] 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 --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 21 ++++++++--- README.md | 2 +- src/runner/server.ts | 2 +- src/tier-check/checks/conformance.ts | 44 +++++++++++++++++----- 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 2e67e2c..917a96c 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -28,12 +28,12 @@ The `tier-check` CLI handles all deterministic checks — conformance, labels, t ### Without conformance tests (fastest) ```bash -npm run tier-check -- --repo --skip-conformance --output json +npm run --silent tier-check -- --repo --skip-conformance --output json ``` ### With conformance tests -To include conformance results, the CLI can start the SDK's everything server automatically. Look up the SDK below: +Start the SDK's everything server first, then pass `--conformance-server-url`. Look up the SDK below: | SDK | Everything Server Location (relative to SDK repo) | Start Command | URL | | ---------- | ------------------------------------------------- | --------------------------------- | --------------------------- | @@ -42,17 +42,26 @@ To include conformance results, the CLI can start the SDK's everything server au For other SDKs, ask the user how to start their everything server. -Example (assuming TypeScript SDK checked out at `~/src/mcp/typescript-sdk`): +**Important**: The SDK must be built first (e.g. `pnpm build:all` for TypeScript). Start the server in the background, verify it's listening, then run the tier-check. + +Example (TypeScript SDK): ```bash -npm run tier-check -- \ +# 1. Build the SDK and start the everything server +cd ~/src/mcp/typescript-sdk && pnpm build:all +cd test/conformance && npx tsx src/everythingServer.ts & +sleep 3 + +# 2. Run the tier-check (from the conformance repo) +cd ~/src/mcp/worktrees/conformance-tier-check +npm run --silent tier-check -- \ --repo modelcontextprotocol/typescript-sdk \ - --conformance-server-cmd 'npx tsx src/everythingServer.ts' \ - --conformance-server-cwd ~/src/mcp/typescript-sdk/test/conformance \ --conformance-server-url http://localhost:3000/mcp \ --output json ``` +You can also have the CLI spawn the server automatically using `--conformance-server-cmd` and `--conformance-server-cwd`, but pre-starting it is more reliable. + The CLI output includes conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. ## Step 3: Launch Parallel Evaluations diff --git a/README.md b/README.md index 4be710e..09d11e2 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ The `tier-check` subcommand evaluates an MCP SDK repository against [SEP-1730](h ```bash # Authenticate with GitHub, then run gh auth login -npm run tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance +npm run --silent tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance ``` If you use Claude Code, open it in this repo and run `/mcp-sdk-tier-audit` for a full AI-assisted assessment with remediation guide. diff --git a/src/runner/server.ts b/src/runner/server.ts index a7d8449..9e67d16 100644 --- a/src/runner/server.ts +++ b/src/runner/server.ts @@ -36,7 +36,7 @@ export async function runServerConformanceTest( // Scenario is guaranteed to exist by CLI validation const scenario = getClientScenario(scenarioName)!; - console.log( + console.error( `Running client scenario '${scenarioName}' against server: ${serverUrl}` ); diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index 604d7f7..a4de237 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -23,13 +23,34 @@ async function waitForServer( ); } +const SCENARIO_TIMEOUT_MS = 30_000; + +async function withTimeout( + promise: Promise, + ms: number, + label: string +): Promise { + let timer: ReturnType; + const timeout = new Promise((_, reject) => { + timer = setTimeout( + () => reject(new Error(`${label}: timed out after ${ms}ms`)), + ms + ); + }); + try { + return await Promise.race([promise, timeout]); + } finally { + clearTimeout(timer!); + } +} + export async function checkConformance(options: { serverCmd?: string; serverCwd?: string; serverUrl?: string; skip?: boolean; }): Promise { - if (options.skip || !options.serverCmd || !options.serverUrl) { + if (options.skip || !options.serverUrl) { return { status: 'skipped', pass_rate: 0, @@ -42,13 +63,15 @@ export async function checkConformance(options: { let serverProcess: ChildProcess | undefined; try { - // Spawn server - const [cmd, ...args] = options.serverCmd.split(' '); - serverProcess = spawn(cmd, args, { - cwd: options.serverCwd || process.cwd(), - stdio: 'pipe', - shell: true - }); + // Spawn server if a command was provided; otherwise assume it's already running + if (options.serverCmd) { + const [cmd, ...args] = options.serverCmd.split(' '); + serverProcess = spawn(cmd, args, { + cwd: options.serverCwd || process.cwd(), + stdio: 'pipe', + shell: true + }); + } // Wait for server to be ready await waitForServer(options.serverUrl); @@ -61,8 +84,9 @@ export async function checkConformance(options: { for (const scenarioName of scenarios) { try { - const result = await runServerConformanceTest( - options.serverUrl, + const result = await withTimeout( + runServerConformanceTest(options.serverUrl, scenarioName), + SCENARIO_TIMEOUT_MS, scenarioName ); const passed = result.checks.filter( From 1bf90c895a6c6a8bf401ee68257f43d48d07df21 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:44:50 +0000 Subject: [PATCH 09/34] 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). --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 67 +++++-------------- .../references/docs-coverage-prompt.md | 24 ++----- .../references/policy-evaluation-prompt.md | 16 ++--- 3 files changed, 30 insertions(+), 77 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 917a96c..4e585fc 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -5,7 +5,7 @@ description: >- Produces tier classification (1/2/3) with evidence table, gap list, and remediation guide. Works for any official MCP SDK (TypeScript, Python, Go, C#, Java, Kotlin, PHP, Swift, Rust, Ruby). -argument-hint: '[repo] [--branch ]' +argument-hint: ' ' --- # MCP SDK Tier Audit @@ -14,65 +14,41 @@ You are performing a comprehensive tier assessment for an MCP SDK repository aga ## Step 1: Parse Arguments -Extract the target SDK from the user's input: +Extract from the user's input: -- **repo**: e.g. `modelcontextprotocol/typescript-sdk`, `modelcontextprotocol/python-sdk` -- **--branch**: optional branch name (defaults to the repo's default branch) +- **local-path**: absolute path to the SDK checkout (e.g. `~/src/mcp/typescript-sdk`) +- **conformance-server-url**: URL where the SDK's everything server is already running (e.g. `http://localhost:3000/mcp`) -If the user did not specify a repo, ask them which SDK to audit. +Both arguments are required. If either is missing, ask the user to provide it. -## Step 2: Run the Deterministic Scorecard - -The `tier-check` CLI handles all deterministic checks — conformance, labels, triage, P0 resolution, releases, policy signals, and spec tracking. You are already in the conformance repo, so run it directly. - -### Without conformance tests (fastest) +Derive the GitHub `owner/repo` from the local checkout: ```bash -npm run --silent tier-check -- --repo --skip-conformance --output json +cd && git remote get-url origin | sed 's#.*github.com[:/]##; s#\.git$##' ``` -### With conformance tests - -Start the SDK's everything server first, then pass `--conformance-server-url`. Look up the SDK below: - -| SDK | Everything Server Location (relative to SDK repo) | Start Command | URL | -| ---------- | ------------------------------------------------- | --------------------------------- | --------------------------- | -| TypeScript | `test/conformance/` | `npx tsx src/everythingServer.ts` | `http://localhost:3000/mcp` | -| Python | `examples/servers/everything-server/` | `uv run mcp-everything-server` | `http://localhost:3001/mcp` | - -For other SDKs, ask the user how to start their everything server. - -**Important**: The SDK must be built first (e.g. `pnpm build:all` for TypeScript). Start the server in the background, verify it's listening, then run the tier-check. +## Step 2: Run the Deterministic Scorecard -Example (TypeScript SDK): +The `tier-check` CLI handles all deterministic checks — conformance, labels, triage, P0 resolution, releases, policy signals, and spec tracking. You are already in the conformance repo, so run it directly. ```bash -# 1. Build the SDK and start the everything server -cd ~/src/mcp/typescript-sdk && pnpm build:all -cd test/conformance && npx tsx src/everythingServer.ts & -sleep 3 - -# 2. Run the tier-check (from the conformance repo) -cd ~/src/mcp/worktrees/conformance-tier-check npm run --silent tier-check -- \ - --repo modelcontextprotocol/typescript-sdk \ - --conformance-server-url http://localhost:3000/mcp \ + --repo \ + --conformance-server-url \ --output json ``` -You can also have the CLI spawn the server automatically using `--conformance-server-cmd` and `--conformance-server-cwd`, but pre-starting it is more reliable. - The CLI output includes conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. ## Step 3: Launch Parallel Evaluations -Launch 2 evaluations in parallel. Each should clone or read the SDK repo and evaluate its assigned area. +Launch 2 evaluations in parallel. Each reads the SDK from the local checkout path. **IMPORTANT**: Launch both evaluations at the same time (in the same response) so they run in parallel. ### Evaluation 1: Documentation Coverage -Use the prompt from `references/docs-coverage-prompt.md`. Pass the repo name and branch. +Use the prompt from `references/docs-coverage-prompt.md`. Pass the local path. This evaluation checks: @@ -82,7 +58,7 @@ This evaluation checks: ### Evaluation 2: Policy Evaluation -Use the prompt from `references/policy-evaluation-prompt.md`. Pass the repo name and branch. +Use the prompt from `references/policy-evaluation-prompt.md`. Pass the local path and the derived `owner/repo`. This evaluation checks: @@ -122,7 +98,6 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. **Important edge cases:** -- If conformance tests could not be run (no server), this counts as a FAIL for both Tier 1 and Tier 2 conformance requirements unless the SDK has a documented reason and plan. - If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. ## Step 5: Generate Output @@ -162,15 +137,9 @@ Read these reference files when you need the detailed content for evaluation pro ## Usage Examples ``` -# TypeScript SDK (default branch) -/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk - -# TypeScript SDK on specific branch -/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk --branch v1.x - -# Python SDK -/mcp-sdk-tier-audit modelcontextprotocol/python-sdk +# TypeScript SDK on v1.x with everything server running on port 3000 +/mcp-sdk-tier-audit ~/src/mcp/worktrees/typescript-sdk-v1x http://localhost:3000/mcp -# Any other SDK -/mcp-sdk-tier-audit modelcontextprotocol/go-sdk +# Python SDK with everything server running on port 3001 +/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp ``` diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 2ce9145..1bbc793 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -4,8 +4,7 @@ You are evaluating the documentation coverage of an MCP SDK repository for the S ## Input -- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) -- **Branch**: {branch} (default branch if not specified) +- **SDK path**: {local-path} (absolute path to local SDK checkout) ## Your Task @@ -16,17 +15,9 @@ Evaluate the documentation quality and coverage of this MCP SDK against the cano ## Steps -### 1. Clone or access the repository +### 1. Find all documentation sources -```bash -# If the repo is available locally, read from there -# Otherwise clone it: -gh repo clone {repo} /tmp/sdk-audit-docs -- --branch {branch} --depth 1 -``` - -### 2. Find all documentation sources - -Search for documentation in these locations: +The SDK is available at `{local-path}`. Search for documentation in these locations: - `README.md` (root and any subdirectory READMEs) - `docs/` directory @@ -39,13 +30,13 @@ Search for documentation in these locations: ```bash # Find all markdown files -find /path/to/repo -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" +find {local-path} -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" # Find example files -find /path/to/repo -path "*/examples/*" -not -path "*/node_modules/*" +find {local-path} -path "*/examples/*" -not -path "*/node_modules/*" # Find API docs -find /path/to/repo -path "*/docs/*" -not -path "*/node_modules/*" +find {local-path} -path "*/docs/*" -not -path "*/node_modules/*" ``` ### 3. Evaluate each feature @@ -157,8 +148,7 @@ Produce your assessment in this exact format: ```markdown ### Documentation Coverage Assessment -**Repository**: {repo} -**Branch**: {branch} +**SDK path**: {local-path} **Documentation locations found**: - {path1}: {description} diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index 18d072b..a1a6a52 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -4,8 +4,8 @@ You are evaluating the governance and policy documentation of an MCP SDK reposit ## Input -- **Repository**: {repo} (e.g., `modelcontextprotocol/typescript-sdk`) -- **Branch**: {branch} (default branch if not specified) +- **SDK path**: {local-path} (absolute path to local SDK checkout) +- **Repository**: {repo} (GitHub `owner/repo`, derived from git remote — used for GitHub API queries) ## Your Task @@ -17,15 +17,9 @@ Evaluate three policy areas required by SEP-1730: ## Steps -### 1. Clone or access the repository +### 1. Read and evaluate policy documents -```bash -# If the repo is available locally, read from there -# Otherwise clone it: -gh repo clone {repo} /tmp/sdk-audit-policy -- --branch {branch} --depth 1 -``` - -### 2. Read and evaluate policy documents +The SDK is available at `{local-path}`. Check these files for each policy area. Read the actual content — you're evaluating the substance of what's written, not just whether the file exists. @@ -131,8 +125,8 @@ Produce your assessment in this exact format: ```markdown ### Policy Evaluation Assessment +**SDK path**: {local-path} **Repository**: {repo} -**Branch**: {branch} --- From 394b6f4f339306c4d5b305162274fbcc979f9b81 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:56:11 +0000 Subject: [PATCH 10/34] refactor: write detailed reports to files, show concise summary Reports go to results/tier-audits/-/ (already gitignored). Claude's console output is now just the tier classification, pass/fail summary line, top 3 actions, and file paths. --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 44 ++++-- .../references/report-template.md | 142 ++++++++---------- 2 files changed, 97 insertions(+), 89 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 4e585fc..0fe56cd 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -102,26 +102,50 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. ## Step 5: Generate Output -Use the template from `references/report-template.md` to produce the final report. +Write detailed reports to files and show a concise summary to the user. -### Part 1: Audit Report +### Output directory -Output the tier summary table showing every requirement, the Tier 1 standard, the Tier 2 standard, the current value, whether it passes for T1 and T2, and any gap detail. +Create a directory under `results/tier-audits/` in the conformance repo: -### Part 2: Remediation Guide +``` +results/tier-audits/-/ +``` + +For example: `results/tier-audits/typescript-sdk-2026-02-10/` + +### File 1: `assessment.md` -Produce a prioritized list of action items for SDK maintainers. Order by impact -- items that would advance the SDK to a higher tier come first. Group by: +Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details, triage metrics, documentation coverage table, and policy evaluation evidence. + +### File 2: `remediation.md` + +Use the remediation template from `references/report-template.md`. This file contains prioritized action items grouped by: 1. **Blocking for next tier** -- requirements that must be met to advance 2. **Quick wins** -- low-effort improvements 3. **Longer-term** -- structural work needed -Each item should include: +### Console output (shown to the user) + +After writing the files, output a short executive summary directly to the user: + +``` +## — Tier + +Conformance: / () | Triage: % () | P0s: open () | Docs: / () | Policies: () + +Top actions for Tier : +1. +2. +3. + +Reports: +- results/tier-audits/-/assessment.md +- results/tier-audits/-/remediation.md +``` -- What needs to change -- Where in the repo to make the change (file paths if possible) -- Estimated effort (small/medium/large) -- Which tier requirement it satisfies +Use checkmarks/crosses for status: ✓ for pass, ✗ for fail. ## Reference Files diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index abb2104..d36520b 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -1,8 +1,8 @@ -# Audit Report Template +# Report Templates -Use this exact format when generating the final tier audit report. +Write two files to `results/tier-audits/-/`. -## Part 1: Tier Assessment +## File 1: assessment.md ```markdown # MCP SDK Tier Audit: {repo} @@ -11,115 +11,99 @@ Use this exact format when generating the final tier audit report. **Branch**: {branch} **Auditor**: mcp-sdk-tier-audit skill (automated + subagent evaluation) ---- - ## Tier Assessment: Tier {X} {Brief 1-2 sentence summary of the overall assessment and key factors.} ### Requirements Summary -| # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | -| --- | ----------------------- | ------------------------------------------ | --------------------------------- | --------------------------- | ----------- | ----------- | ------------------ | -| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 2 | Issue Triage | Within 2 business days | Within 1 month | {median triage time} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 3 | Critical Bug Resolution | Within 7 days | Within 2 weeks | {P0 resolution stats} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 4 | Stable Release | Required + clear versioning | At least one stable release | {latest version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 5 | Documentation | Comprehensive w/ examples for all features | Basic docs covering core features | {X}/{Y} features documented | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | -| 8 | Versioning Policy | Documented breaking change policy | N/A | {Found/Not found} | {PASS/FAIL} | {N/A} | {detail or "None"} | - -**Legend**: PASS = meets requirement, FAIL = does not meet requirement, N/A = not applicable at this tier - -### Tier Determination Logic - -- Tier 1: {PASS/FAIL} -- {count} of 8 requirements met ({list failing requirements if any}) -- Tier 2: {PASS/FAIL} -- {count} of 7 requirements met ({list failing requirements if any}) +| # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | +| --- | ----------------------- | --------------------------------- | ---------------------------- | --------------------------------- | ----------- | ----------- | ------------------ | +| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 2 | Issue Triage | >= 90% within 2 biz days | >= 80% within 1 month | {compliance}% ({triaged}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 3 | Critical Bug Resolution | All P0s within 7 days | All P0s within 2 weeks | {open P0 count} open | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 4 | Stable Release | Required + clear versioning | At least one stable release | {version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 5 | Documentation | Comprehensive w/ examples | Basic docs for core features | {pass}/{total} features | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 8 | Versioning Policy | Documented breaking change policy | N/A | {Found/Not found} | {PASS/FAIL} | N/A | {detail or "None"} | + +### Tier Determination + +- Tier 1: {PASS/FAIL} -- {count}/8 requirements met (failing: {list}) +- Tier 2: {PASS/FAIL} -- {count}/7 requirements met (failing: {list}) - **Final Tier: {X}** --- -### Conformance Test Details - -**Suite**: {active/all} -**Total scenarios**: {N} -**Passed**: {N} | **Failed**: {N} | **Warnings**: {N} -**Pass rate**: {X}% +## Conformance Details -{If tests were run, include per-scenario breakdown:} +Pass rate: {X}% ({passed}/{total}) -| Scenario | Status | Notes | -| ---------- | --------- | -------- | -| lifecycle | PASS/FAIL | {detail} | -| tools-list | PASS/FAIL | {detail} | -| ... | ... | ... | - -{If tests were NOT run:} - -> Conformance tests could not be run: {reason}. This is recorded as a gap. +| Scenario | Status | Checks | +| -------- | ----------- | ---------------- | +| {name} | {PASS/FAIL} | {passed}/{total} | +| ... | ... | ... | --- -### Issue Triage Metrics - -**Analysis period**: Last {N} issues -**Labels configured**: {Yes/No -- list which SEP-1730 labels are present} +## Issue Triage Details -| Metric | Value | Tier 1 Requirement | Tier 2 Requirement | Verdict | -| ------------------------- | ------- | ------------------ | ------------------ | ------------------------------ | -| Median triage time | {value} | <= 2 business days | <= 1 month | {T1: PASS/FAIL, T2: PASS/FAIL} | -| Triage compliance rate | {X}% | >= 90% | >= 80% | {T1: PASS/FAIL, T2: PASS/FAIL} | -| P0 issues found | {N} | -- | -- | -- | -| P0 median resolution time | {value} | <= 7 days | <= 14 days | {T1: PASS/FAIL, T2: PASS/FAIL} | +Analysis period: Last {N} issues +Labels: {present/missing list} -{If labels are not set up:} +| Metric | Value | T1 Req | T2 Req | Verdict | +| --------------- | ----- | ------ | ------ | --------- | +| Compliance rate | {X}% | >= 90% | >= 80% | {verdict} | +| Exceeding SLA | {N} | -- | -- | -- | +| Open P0s | {N} | 0 | 0 | {verdict} | -> SEP-1730 labels are not configured in this repository. Issue triage metrics cannot be computed. This is a blocking gap for Tier 1 and Tier 2. +{If open P0s, list them with issue number, title, age} --- -### Documentation Coverage (Subagent 1) +## Documentation Coverage -{Paste the subagent's evidence table here} +{Paste subagent 1 output: feature table with Documented/Where/Examples/Verdict columns} --- -### Policy Evaluation (Subagent 2) +## Policy Evaluation -{Paste the subagent's evidence tables here} +{Paste subagent 2 output: dependency policy, roadmap, versioning policy sections with evidence tables} ``` -## Part 2: Remediation Guide +## File 2: remediation.md ```markdown ---- +# Remediation Guide: {repo} -## Remediation Guide +**Date**: {date} +**Current Tier**: {X} +**Target**: Tier {next} -### Blocking for Tier {next tier} (must fix) +## Blocking for Tier {next} -| # | Action Item | Requirement | Effort | Where to Change | -| --- | ------------- | ------------------ | -------------------- | --------------- | -| 1 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | -| 2 | {description} | {requirement name} | {Small/Medium/Large} | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action | Requirement | Effort | Where | +| --- | ------------- | ------------- | -------------------- | ------------ | +| 1 | {description} | {requirement} | {Small/Medium/Large} | {file paths} | +| ... | ... | ... | ... | ... | -### Quick Wins (low effort, high impact) +## Quick Wins -| # | Action Item | Requirement | Effort | Where to Change | -| --- | ------------- | ------------------ | ------ | --------------- | -| 1 | {description} | {requirement name} | Small | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action | Requirement | Effort | Where | +| --- | ------------- | ------------- | ------ | ------------ | +| 1 | {description} | {requirement} | Small | {file paths} | +| ... | ... | ... | ... | ... | -### Longer-Term Improvements +## Longer-Term -| # | Action Item | Requirement | Effort | Where to Change | -| --- | ------------- | ------------------ | -------------- | --------------- | -| 1 | {description} | {requirement name} | {Medium/Large} | {file path(s)} | -| ... | ... | ... | ... | ... | +| # | Action | Requirement | Effort | Where | +| --- | ------------- | ------------- | -------------- | ------------ | +| 1 | {description} | {requirement} | {Medium/Large} | {file paths} | +| ... | ... | ... | ... | ... | -### Recommended Next Steps +## Recommended Next Steps 1. {First priority action with brief rationale} 2. {Second priority action} @@ -128,8 +112,8 @@ Use this exact format when generating the final tier audit report. ## Formatting Rules -1. Every PASS/FAIL cell must be based on evidence, not assumption. -2. If data is unavailable (e.g., conformance tests not runnable), mark as "N/A - {reason}" rather than FAIL, but note it as a gap in the remediation guide. -3. All file references from subagents must include file path and line numbers where possible. -4. The remediation guide must be ordered by impact: items that would advance the SDK to the next tier come first. -5. Effort estimates should be realistic: Small (< 1 day), Medium (1-3 days), Large (> 3 days). +1. Every PASS/FAIL must be based on evidence, not assumption. +2. If data is unavailable, mark as "N/A - {reason}" and note in remediation. +3. All file references must include file path and line numbers where possible. +4. Remediation items ordered by impact: tier-advancing items first. +5. Effort estimates: Small (< 1 day), Medium (1-3 days), Large (> 3 days). From b6672f0a08268cdfcd8dcc60ba657cc56c506a7a Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 22:58:25 +0000 Subject: [PATCH 11/34] docs: update READMEs for new skill interface and pre-start workflow --- .claude/skills/mcp-sdk-tier-audit/README.md | 54 ++++++++++++++------- README.md | 13 ++++- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index f4c17b2..383599c 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -22,7 +22,7 @@ npm run build gh auth login # Run against any MCP SDK repo (without conformance tests) -npm run tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance +npm run --silent tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance ``` The CLI uses the GitHub API (read-only) for issue metrics, labels, and release checks. Authenticate via one of: @@ -39,9 +39,9 @@ For public repos, any authenticated token works (no special scopes needed — au --repo GitHub repository (required) --branch Branch to check --skip-conformance Skip conformance tests ---conformance-server-cmd Command to start the conformance server ---conformance-server-cwd Working directory for the conformance server --conformance-server-url URL of the running conformance server +--conformance-server-cmd Command to start the conformance server (optional, prefer pre-starting) +--conformance-server-cwd Working directory for the conformance server command --days Limit triage analysis to last N days --output json | markdown | terminal (default: terminal) --token GitHub token (defaults to GITHUB_TOKEN or gh auth token) @@ -87,13 +87,26 @@ The CLI produces a deterministic scorecard, but some SEP-1730 requirements need ### Claude Code -The skill lives in `.claude/skills/` in this repo, so if you open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) in the conformance repo it's already available — just run: +The skill lives in `.claude/skills/` in this repo, so if you open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) in the conformance repo it's already available. +1. Start the SDK's everything server in a separate terminal +2. Run the skill: + +``` +/mcp-sdk-tier-audit ``` -/mcp-sdk-tier-audit modelcontextprotocol/typescript-sdk + +Example: + +```bash +# Terminal 1: start the everything server +cd ~/src/mcp/typescript-sdk/test/conformance && npx tsx src/everythingServer.ts + +# Terminal 2: run the audit (from the conformance repo) +/mcp-sdk-tier-audit ~/src/mcp/typescript-sdk http://localhost:3000/mcp ``` -It runs the CLI, launches parallel evaluations for docs and policy, and produces a full report with remediation guide. +The skill derives `owner/repo` from git remote, runs the CLI, launches parallel evaluations for docs and policy, and writes detailed reports to `results/tier-audits/`. ### Any Other AI Coding Agent @@ -102,7 +115,7 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the 1. **Run the CLI** to get the deterministic scorecard: ```bash - npm run tier-check -- --repo --skip-conformance --output json + node dist/index.js tier-check --repo --conformance-server-url --output json ``` 2. **Evaluate documentation coverage** — check whether MCP features (tools, resources, prompts, sampling, transports, etc.) are documented with examples. See [`references/docs-coverage-prompt.md`](references/docs-coverage-prompt.md) for the full checklist. @@ -129,30 +142,35 @@ Run the CLI for the scorecard, then review docs and policies yourself using the ## Running Conformance Tests -To include conformance test results in the scorecard, you need to start the SDK's everything server, then run tier-check against it. +To include conformance test results, start the SDK's everything server first, then pass the URL to the CLI. -**TypeScript SDK** (assuming checkout at `~/src/mcp/typescript-sdk`): +**TypeScript SDK**: ```bash -# The CLI starts the server, runs conformance, and cleans up automatically -npm run tier-check -- \ +# Terminal 1: start the server (SDK must be built first) +cd ~/src/mcp/typescript-sdk && pnpm build:all +cd test/conformance && npx tsx src/everythingServer.ts + +# Terminal 2: run tier-check +npm run --silent tier-check -- \ --repo modelcontextprotocol/typescript-sdk \ - --conformance-server-cmd 'npx tsx src/everythingServer.ts' \ - --conformance-server-cwd ~/src/mcp/typescript-sdk/test/conformance \ --conformance-server-url http://localhost:3000/mcp ``` -**Python SDK** (assuming checkout at `~/src/mcp/python-sdk`): +**Python SDK**: ```bash -npm run tier-check -- \ +# Terminal 1 +cd ~/src/mcp/python-sdk/examples/servers/everything-server +uv run mcp-everything-server + +# Terminal 2 +npm run --silent tier-check -- \ --repo modelcontextprotocol/python-sdk \ - --conformance-server-cmd 'uv run mcp-everything-server' \ - --conformance-server-cwd ~/src/mcp/python-sdk/examples/servers/everything-server \ --conformance-server-url http://localhost:3001/mcp ``` -**Other SDKs:** Pass `--conformance-server-cmd`, `--conformance-server-cwd`, and `--conformance-server-url` pointing to your SDK's everything server. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. +**Other SDKs:** Start your everything server, then pass `--conformance-server-url`. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. ## Reference Files diff --git a/README.md b/README.md index 09d11e2..8096214 100644 --- a/README.md +++ b/README.md @@ -217,12 +217,21 @@ Run `npx @modelcontextprotocol/conformance list --server` to see all available s The `tier-check` subcommand evaluates an MCP SDK repository against [SEP-1730](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1730) (the SDK Tiering System): ```bash -# Authenticate with GitHub, then run +# Without conformance tests (fastest) gh auth login npm run --silent tier-check -- --repo modelcontextprotocol/typescript-sdk --skip-conformance + +# With conformance tests (start the everything server first) +npm run --silent tier-check -- \ + --repo modelcontextprotocol/typescript-sdk \ + --conformance-server-url http://localhost:3000/mcp ``` -If you use Claude Code, open it in this repo and run `/mcp-sdk-tier-audit` for a full AI-assisted assessment with remediation guide. +For a full AI-assisted assessment with remediation guide, use Claude Code: + +``` +/mcp-sdk-tier-audit +``` See [`.claude/skills/mcp-sdk-tier-audit/README.md`](.claude/skills/mcp-sdk-tier-audit/README.md) for full documentation. From c035764d18ee31123e18705abbe01e958c9aba4c Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 23:01:59 +0000 Subject: [PATCH 12/34] simplify: flat file output instead of nested directory --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 21 +++++++------------ .../references/report-template.md | 9 +++++--- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 0fe56cd..f2f0065 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -104,21 +104,16 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. Write detailed reports to files and show a concise summary to the user. -### Output directory +### Output files -Create a directory under `results/tier-audits/` in the conformance repo: +Write two files to `results/` in the conformance repo: -``` -results/tier-audits/-/ -``` - -For example: `results/tier-audits/typescript-sdk-2026-02-10/` - -### File 1: `assessment.md` +- `results/--assessment.md` +- `results/--remediation.md` -Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details, triage metrics, documentation coverage table, and policy evaluation evidence. +For example: `results/2026-02-10-typescript-sdk-assessment.md` -### File 2: `remediation.md` +### Assessment file Use the remediation template from `references/report-template.md`. This file contains prioritized action items grouped by: @@ -141,8 +136,8 @@ Top actions for Tier : 3. Reports: -- results/tier-audits/-/assessment.md -- results/tier-audits/-/remediation.md +- results/--assessment.md +- results/--remediation.md ``` Use checkmarks/crosses for status: ✓ for pass, ✗ for fail. diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index d36520b..53d8244 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -1,8 +1,11 @@ # Report Templates -Write two files to `results/tier-audits/-/`. +Write two files to `results/` in the conformance repo: -## File 1: assessment.md +- `results/--assessment.md` +- `results/--remediation.md` + +## assessment.md ```markdown # MCP SDK Tier Audit: {repo} @@ -73,7 +76,7 @@ Labels: {present/missing list} {Paste subagent 2 output: dependency policy, roadmap, versioning policy sections with evidence tables} ``` -## File 2: remediation.md +## remediation.md ```markdown # Remediation Guide: {repo} From efae4157e25bb4a7509dff184d4499d0c9d2b0ce Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 10 Feb 2026 23:03:35 +0000 Subject: [PATCH 13/34] fix: remediation always shows path to Tier 2 and Tier 1 --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 36 ++++++++++++++----- .../references/report-template.md | 22 +++++------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index f2f0065..71d8fd5 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -100,6 +100,15 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. - If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. +**P0 Label Audit Guidance:** + +When evaluating P0 metrics, flag potentially mislabeled P0 issues: + +- If P0 count is high (>2) but other Tier 2 metrics (conformance, triage compliance, docs) are strong, this may indicate P0 labels are being used for enhancements, lower-priority work, or feature requests rather than actual critical bugs. +- In such cases, recommend a P0 label audit as a remediation action. Review open P0 issues to verify they represent genuine blocking defects vs. misclassified work. +- Document this finding in the remediation output with specific issue numbers and suggested re-triage actions. +- Do not treat high P0 count as an automatic hard blocker if the audit reveals mislabeling; instead, note it as a process improvement opportunity. + ## Step 5: Generate Output Write detailed reports to files and show a concise summary to the user. @@ -115,11 +124,14 @@ For example: `results/2026-02-10-typescript-sdk-assessment.md` ### Assessment file -Use the remediation template from `references/report-template.md`. This file contains prioritized action items grouped by: +Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details, triage metrics, documentation coverage table, and policy evaluation evidence. -1. **Blocking for next tier** -- requirements that must be met to advance -2. **Quick wins** -- low-effort improvements -3. **Longer-term** -- structural work needed +### Remediation file + +Use the remediation template from `references/report-template.md`. This file always includes both: + +- **Path to Tier 2** (if current tier is 3) -- what's needed to reach Tier 2 +- **Path to Tier 1** (always) -- what's needed to reach Tier 1 ### Console output (shown to the user) @@ -130,10 +142,8 @@ After writing the files, output a short executive summary directly to the user: Conformance: / () | Triage: % () | P0s: open () | Docs: / () | Policies: () -Top actions for Tier : -1. -2. -3. +For Tier 2: +For Tier 1: Reports: - results/--assessment.md @@ -142,6 +152,16 @@ Reports: Use checkmarks/crosses for status: ✓ for pass, ✗ for fail. +**Special note for high P0 count with strong other metrics:** + +If P0 count is >2 but other Tier 2 metrics pass, add this note to the executive summary: + +``` +⚠️ P0 Label Audit Recommended: open P0 issues detected. Review these issues to verify they represent critical bugs vs. misclassified enhancements or lower-priority work. See remediation report for specific issues and re-triage guidance. +``` + +This ensures the audit context is clear: the high P0 count may be a labeling process issue rather than a product quality issue. + ## Reference Files The following reference files are available in the `references/` directory alongside this skill: diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index 53d8244..fcd346a 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -83,28 +83,24 @@ Labels: {present/missing list} **Date**: {date} **Current Tier**: {X} -**Target**: Tier {next} -## Blocking for Tier {next} +## Path to Tier 2 + +{Only include this section if current tier is 3. List every requirement not met for Tier 2.} | # | Action | Requirement | Effort | Where | | --- | ------------- | ------------- | -------------------- | ------------ | | 1 | {description} | {requirement} | {Small/Medium/Large} | {file paths} | | ... | ... | ... | ... | ... | -## Quick Wins - -| # | Action | Requirement | Effort | Where | -| --- | ------------- | ------------- | ------ | ------------ | -| 1 | {description} | {requirement} | Small | {file paths} | -| ... | ... | ... | ... | ... | +## Path to Tier 1 -## Longer-Term +{Always include this section. List every requirement not met for Tier 1 (including any Tier 2 gaps).} -| # | Action | Requirement | Effort | Where | -| --- | ------------- | ------------- | -------------- | ------------ | -| 1 | {description} | {requirement} | {Medium/Large} | {file paths} | -| ... | ... | ... | ... | ... | +| # | Action | Requirement | Effort | Where | +| --- | ------------- | ------------- | -------------------- | ------------ | +| 1 | {description} | {requirement} | {Small/Medium/Large} | {file paths} | +| ... | ... | ... | ... | ... | ## Recommended Next Steps From 0e1099dbd193fa624372f9dca4fc249304bfd6d7 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 09:14:44 +0000 Subject: [PATCH 14/34] 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 --- .claude/skills/mcp-sdk-tier-audit/README.md | 32 +++++---- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 49 ++++++++++--- src/tier-check/checks/conformance.ts | 80 ++++++++++++++++++++- src/tier-check/index.ts | 18 ++++- src/tier-check/output.ts | 10 ++- src/tier-check/tier-logic.ts | 15 +++- src/tier-check/types.ts | 1 + 7 files changed, 174 insertions(+), 31 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 383599c..d316469 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -4,7 +4,7 @@ Assess any MCP SDK repository against [SEP-1730](https://github.com/modelcontext Two components work together: -- **`tier-check` CLI** — runs deterministic checks (conformance pass rate, issue triage speed, P0 resolution, labels, releases, policy signals). Works standalone, no AI needed. +- **`tier-check` CLI** — runs deterministic checks (server + client conformance pass rate, issue triage speed, P0 resolution, labels, releases, policy signals). Works standalone, no AI needed. - **AI-assisted assessment** — an agent uses the CLI scorecard plus judgment-based evaluation (documentation coverage, dependency policy, roadmap) to produce a full tier report with remediation guide. ## Quick Start: CLI @@ -42,6 +42,7 @@ For public repos, any authenticated token works (no special scopes needed — au --conformance-server-url URL of the running conformance server --conformance-server-cmd Command to start the conformance server (optional, prefer pre-starting) --conformance-server-cwd Working directory for the conformance server command +--client-cmd Command to run the SDK conformance client (for client conformance tests) --days Limit triage analysis to last N days --output json | markdown | terminal (default: terminal) --token GitHub token (defaults to GITHUB_TOKEN or gh auth token) @@ -49,9 +50,10 @@ For public repos, any authenticated token works (no special scopes needed — au ### What the CLI Checks -| Check | What it measures | -| -------------- | ------------------------------------------------------------------------------ | -| Conformance | Pass rate against the conformance test suite | +| Check | What it measures | +| ------------------- | ------------------------------------------------------------------------------ | +| Server Conformance | Pass rate of server implementation against the conformance test suite | +| Client Conformance | Pass rate of client implementation against the conformance test suite | | Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | | Triage | How quickly issues get labeled after creation | | P0 Resolution | Whether critical bugs are resolved within SLA | @@ -69,7 +71,8 @@ Timestamp: 2026-02-10T12:00:00Z Check Results: - ✓ Conformance 45/45 (100%) + ✓ Server Conformance 45/45 (100%) + ✓ Client Conformance 4/4 (100%) ✗ Labels 9/12 required labels Missing: needs confirmation, needs repro, ready for work ✓ Triage 92% within 2BD (150 issues, median 8h) @@ -130,9 +133,10 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the Run the CLI for the scorecard, then review docs and policies yourself using the tier requirements as a checklist: -| Requirement | Tier 1 | Tier 2 | -| ----------------- | ------------------------------ | ------------------------ | -| Conformance | 100% pass | >= 80% pass | +| Requirement | Tier 1 | Tier 2 | +| ---------------------- | ------------------------------ | ------------------------ | +| Server Conformance | 100% pass | >= 80% pass | +| Client Conformance | 100% pass | >= 80% pass | | Issue triage | Within 2 business days | Within 1 month | | P0 resolution | Within 7 days | Within 2 weeks | | Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | @@ -142,7 +146,7 @@ Run the CLI for the scorecard, then review docs and policies yourself using the ## Running Conformance Tests -To include conformance test results, start the SDK's everything server first, then pass the URL to the CLI. +To include conformance test results, start the SDK's everything server first, then pass the URL to the CLI. To also run client conformance tests, pass `--client-cmd` with the command to launch the SDK's conformance client. **TypeScript SDK**: @@ -151,10 +155,11 @@ To include conformance test results, start the SDK's everything server first, th cd ~/src/mcp/typescript-sdk && pnpm build:all cd test/conformance && npx tsx src/everythingServer.ts -# Terminal 2: run tier-check +# Terminal 2: run tier-check (server + client conformance) npm run --silent tier-check -- \ --repo modelcontextprotocol/typescript-sdk \ - --conformance-server-url http://localhost:3000/mcp + --conformance-server-url http://localhost:3000/mcp \ + --client-cmd 'npx tsx ~/src/mcp/typescript-sdk/test/conformance/src/everythingClient.ts' ``` **Python SDK**: @@ -167,10 +172,11 @@ uv run mcp-everything-server # Terminal 2 npm run --silent tier-check -- \ --repo modelcontextprotocol/python-sdk \ - --conformance-server-url http://localhost:3001/mcp + --conformance-server-url http://localhost:3001/mcp \ + --client-cmd 'uv run python ~/src/mcp/python-sdk/tests/conformance/client.py' ``` -**Other SDKs:** Start your everything server, then pass `--conformance-server-url`. If no everything server exists yet, use `--skip-conformance` — the scorecard will note this as a gap. +**Other SDKs:** Start your everything server, then pass `--conformance-server-url`. Pass `--client-cmd` if the SDK has a conformance client. If neither exists yet, use `--skip-conformance` — the scorecard will note this as a gap. ## Reference Files diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 71d8fd5..3e26220 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -5,7 +5,7 @@ description: >- Produces tier classification (1/2/3) with evidence table, gap list, and remediation guide. Works for any official MCP SDK (TypeScript, Python, Go, C#, Java, Kotlin, PHP, Swift, Rust, Ruby). -argument-hint: ' ' +argument-hint: ' [client-cmd]' --- # MCP SDK Tier Audit @@ -18,8 +18,31 @@ Extract from the user's input: - **local-path**: absolute path to the SDK checkout (e.g. `~/src/mcp/typescript-sdk`) - **conformance-server-url**: URL where the SDK's everything server is already running (e.g. `http://localhost:3000/mcp`) +- **client-cmd** (optional): command to run the SDK's conformance client (e.g. `npx tsx test/conformance/src/everythingClient.ts`). If not provided, try to auto-detect it (see below). -Both arguments are required. If either is missing, ask the user to provide it. +The first two arguments are required. If either is missing, ask the user to provide it. + +### Auto-detecting the conformance client command + +If client-cmd is not provided, look for a conformance client in the local checkout: + +```bash +# Check common locations for a conformance/everything client +ls /test/conformance/src/everythingClient.ts 2>/dev/null +ls /tests/conformance/client.py 2>/dev/null +``` + +For TypeScript SDKs, the client command is typically: +``` +npx tsx /test/conformance/src/everythingClient.ts +``` + +For Python SDKs, the client command is typically: +``` +uv run python /tests/conformance/client.py +``` + +If no conformance client is found, proceed without client conformance tests (they will be skipped and noted in the report). Derive the GitHub `owner/repo` from the local checkout: @@ -29,16 +52,19 @@ cd && git remote get-url origin | sed 's#.*github.com[:/]##; s#\.gi ## Step 2: Run the Deterministic Scorecard -The `tier-check` CLI handles all deterministic checks — conformance, labels, triage, P0 resolution, releases, policy signals, and spec tracking. You are already in the conformance repo, so run it directly. +The `tier-check` CLI handles all deterministic checks — server conformance, client conformance, labels, triage, P0 resolution, releases, policy signals, and spec tracking. You are already in the conformance repo, so run it directly. ```bash npm run --silent tier-check -- \ --repo \ --conformance-server-url \ + --client-cmd '' \ --output json ``` -The CLI output includes conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. +If no client-cmd was detected, omit the `--client-cmd` flag (client conformance will be skipped). + +The CLI output includes server conformance pass rate, client conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. ## Step 3: Launch Parallel Evaluations @@ -73,7 +99,8 @@ Combine the deterministic scorecard (from the CLI) with the evaluation results ( ### Tier 1 requires ALL of: -- Conformance test pass rate == 100% +- Server conformance test pass rate == 100% +- Client conformance test pass rate == 100% - Issue triage compliance >= 90% within 2 business days - All P0 bugs resolved within 7 days - Stable release >= 1.0.0 with no pre-release suffix @@ -84,7 +111,8 @@ Combine the deterministic scorecard (from the CLI) with the evaluation results ( ### Tier 2 requires ALL of: -- Conformance test pass rate >= 80% +- Server conformance test pass rate >= 80% +- Client conformance test pass rate >= 80% - Issue triage compliance >= 80% within 1 month - P0 bugs resolved within 2 weeks - At least one stable release >= 1.0.0 @@ -99,6 +127,7 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. **Important edge cases:** - If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. +- If client conformance was skipped (no client command found), note this as a gap but do not block tier advancement based on it alone. **P0 Label Audit Guidance:** @@ -124,7 +153,7 @@ For example: `results/2026-02-10-typescript-sdk-assessment.md` ### Assessment file -Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details, triage metrics, documentation coverage table, and policy evaluation evidence. +Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details (both server and client), triage metrics, documentation coverage table, and policy evaluation evidence. ### Remediation file @@ -140,7 +169,7 @@ After writing the files, output a short executive summary directly to the user: ``` ## — Tier -Conformance: / () | Triage: % () | P0s: open () | Docs: / () | Policies: () +Server Conformance: / () | Client Conformance: / () | Triage: % () | P0s: open () | Docs: / () | Policies: () For Tier 2: For Tier 1: @@ -177,8 +206,12 @@ Read these reference files when you need the detailed content for evaluation pro ``` # TypeScript SDK on v1.x with everything server running on port 3000 +# (client command auto-detected from test/conformance/src/everythingClient.ts) /mcp-sdk-tier-audit ~/src/mcp/worktrees/typescript-sdk-v1x http://localhost:3000/mcp +# Explicit client command +/mcp-sdk-tier-audit ~/src/mcp/worktrees/typescript-sdk-v1x http://localhost:3000/mcp "npx tsx ~/src/mcp/worktrees/typescript-sdk-v1x/test/conformance/src/everythingClient.ts" + # Python SDK with everything server running on port 3001 /mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp ``` diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index a4de237..bf4599e 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -1,6 +1,6 @@ import { spawn, ChildProcess } from 'child_process'; -import { listActiveClientScenarios } from '../../scenarios'; -import { runServerConformanceTest } from '../../runner'; +import { listActiveClientScenarios, listCoreScenarios } from '../../scenarios'; +import { runServerConformanceTest, runConformanceTest } from '../../runner'; import { ConformanceResult } from '../types'; async function waitForServer( @@ -133,3 +133,79 @@ export async function checkConformance(options: { } } } + +/** + * Run client conformance tests — the conformance tool acts as a server and + * spawns the SDK's conformance client to validate client-side behaviour. + */ +export async function checkClientConformance(options: { + clientCmd?: string; + skip?: boolean; +}): Promise { + if (options.skip || !options.clientCmd) { + return { + status: 'skipped', + pass_rate: 0, + passed: 0, + failed: 0, + total: 0, + details: [] + }; + } + + const scenarios = listCoreScenarios(); + const details: ConformanceResult['details'] = []; + let totalPassed = 0; + let totalFailed = 0; + + for (const scenarioName of scenarios) { + try { + const result = await withTimeout( + runConformanceTest(options.clientCmd, scenarioName, SCENARIO_TIMEOUT_MS), + SCENARIO_TIMEOUT_MS + 5_000, // extra buffer beyond the inner timeout + scenarioName + ); + const passed = result.checks.filter( + (c) => c.status === 'SUCCESS' + ).length; + const failed = result.checks.filter( + (c) => c.status === 'FAILURE' + ).length; + + // A non-zero exit code counts as a failure unless the scenario expects it + const clientFailed = + !result.allowClientError && + result.clientOutput.exitCode !== 0; + + const scenarioPassed = failed === 0 && passed > 0 && !clientFailed; + totalPassed += scenarioPassed ? 1 : 0; + totalFailed += scenarioPassed ? 0 : 1; + details.push({ + scenario: scenarioName, + passed: scenarioPassed, + checks_passed: passed, + checks_failed: failed + }); + } catch { + totalFailed++; + details.push({ + scenario: scenarioName, + passed: false, + checks_passed: 0, + checks_failed: 1 + }); + } + } + + const total = totalPassed + totalFailed; + const pass_rate = total > 0 ? totalPassed / total : 0; + + return { + status: pass_rate >= 1.0 ? 'pass' : pass_rate >= 0.8 ? 'partial' : 'fail', + pass_rate, + passed: totalPassed, + failed: totalFailed, + total, + details + }; +} diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index fa9f316..b9b155a 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -1,6 +1,6 @@ import { Command } from 'commander'; import { Octokit } from '@octokit/rest'; -import { checkConformance } from './checks/conformance'; +import { checkConformance, checkClientConformance } from './checks/conformance'; import { checkLabels } from './checks/labels'; import { checkTriage } from './checks/triage'; import { checkP0Resolution } from './checks/p0'; @@ -35,6 +35,10 @@ export function createTierCheckCommand(): Command { 'Working directory for the conformance server' ) .option('--conformance-server-url ', 'URL of the conformance server') + .option( + '--client-cmd ', + 'Command to run the SDK conformance client (for client conformance tests)' + ) .option('--skip-conformance', 'Skip conformance tests') .option('--days ', 'Limit triage check to issues created in last N days') .option( @@ -76,7 +80,7 @@ export function createTierCheckCommand(): Command { console.error('Running tier assessment checks...\n'); // Run all checks - const [conformance, labels, triage, p0, release, files, specTracking] = + const [conformance, clientConformance, labels, triage, p0, release, files, specTracking] = await Promise.all([ checkConformance({ serverCmd: options.conformanceServerCmd, @@ -84,7 +88,14 @@ export function createTierCheckCommand(): Command { serverUrl: options.conformanceServerUrl, skip: options.skipConformance }).then((r) => { - console.error(' ✓ Conformance'); + console.error(' ✓ Server Conformance'); + return r; + }), + checkClientConformance({ + clientCmd: options.clientCmd, + skip: options.skipConformance || !options.clientCmd + }).then((r) => { + console.error(' ✓ Client Conformance'); return r; }), checkLabels(octokit, owner, repo).then((r) => { @@ -115,6 +126,7 @@ export function createTierCheckCommand(): Command { const checks = { conformance, + client_conformance: clientConformance, labels, triage, p0_resolution: p0, diff --git a/src/tier-check/output.ts b/src/tier-check/output.ts index 94f9dda..d7e9fc8 100644 --- a/src/tier-check/output.ts +++ b/src/tier-check/output.ts @@ -43,7 +43,10 @@ export function formatMarkdown(scorecard: TierScorecard): string { lines.push('| Check | Status | Detail |'); lines.push('|-------|--------|--------|'); lines.push( - `| Conformance | ${c.conformance.status} | ${c.conformance.passed}/${c.conformance.total} scenarios pass (${Math.round(c.conformance.pass_rate * 100)}%) |` + `| Server Conformance | ${c.conformance.status} | ${c.conformance.passed}/${c.conformance.total} scenarios pass (${Math.round(c.conformance.pass_rate * 100)}%) |` + ); + lines.push( + `| Client Conformance | ${c.client_conformance.status} | ${c.client_conformance.passed}/${c.client_conformance.total} scenarios pass (${Math.round(c.client_conformance.pass_rate * 100)}%) |` ); lines.push( `| Labels | ${c.labels.status} | ${c.labels.present}/${c.labels.required} required labels${c.labels.missing.length > 0 ? ` (missing: ${c.labels.missing.join(', ')})` : ''} |` @@ -100,7 +103,10 @@ export function formatTerminal(scorecard: TierScorecard): void { console.log(`${COLORS.BOLD}Check Results:${COLORS.RESET}\n`); console.log( - ` ${statusIcon(c.conformance.status)} Conformance ${c.conformance.passed}/${c.conformance.total} (${Math.round(c.conformance.pass_rate * 100)}%)` + ` ${statusIcon(c.conformance.status)} Server Conformance ${c.conformance.passed}/${c.conformance.total} (${Math.round(c.conformance.pass_rate * 100)}%)` + ); + console.log( + ` ${statusIcon(c.client_conformance.status)} Client Conformance ${c.client_conformance.passed}/${c.client_conformance.total} (${Math.round(c.client_conformance.pass_rate * 100)}%)` ); console.log( ` ${statusIcon(c.labels.status)} Labels ${c.labels.present}/${c.labels.required} required labels` diff --git a/src/tier-check/tier-logic.ts b/src/tier-check/tier-logic.ts index e93b645..cf096c9 100644 --- a/src/tier-check/tier-logic.ts +++ b/src/tier-check/tier-logic.ts @@ -5,11 +5,18 @@ export function computeTier( ): TierScorecard['implied_tier'] { const tier1Blockers: string[] = []; - // Check Tier 1 requirements + // Check Tier 1 requirements — server conformance if (checks.conformance.status === 'skipped') { - tier1Blockers.push('conformance (skipped)'); + tier1Blockers.push('server_conformance (skipped)'); } else if (checks.conformance.pass_rate < 1.0) { - tier1Blockers.push('conformance'); + tier1Blockers.push('server_conformance'); + } + + // Check Tier 1 requirements — client conformance + if (checks.client_conformance.status === 'skipped') { + tier1Blockers.push('client_conformance (skipped)'); + } else if (checks.client_conformance.pass_rate < 1.0) { + tier1Blockers.push('client_conformance'); } if (checks.triage.compliance_rate < 0.9) { @@ -40,6 +47,8 @@ export function computeTier( const tier2Met = (checks.conformance.status === 'skipped' || checks.conformance.pass_rate >= 0.8) && + (checks.client_conformance.status === 'skipped' || + checks.client_conformance.pass_rate >= 0.8) && checks.p0_resolution.all_p0s_resolved_within_14d && checks.stable_release.is_stable; diff --git a/src/tier-check/types.ts b/src/tier-check/types.ts index ae0960a..ff6be5d 100644 --- a/src/tier-check/types.ts +++ b/src/tier-check/types.ts @@ -70,6 +70,7 @@ export interface TierScorecard { version: string | null; checks: { conformance: ConformanceResult; + client_conformance: ConformanceResult; labels: LabelsResult; triage: TriageResult; p0_resolution: P0Result; From e198a24165454aba3e8244e5738912d470c8ed21 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 10:23:42 +0000 Subject: [PATCH 15/34] 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 --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 3e26220..3daabf8 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -140,36 +140,48 @@ When evaluating P0 metrics, flag potentially mislabeled P0 issues: ## Step 5: Generate Output -Write detailed reports to files and show a concise summary to the user. +Write detailed reports to files using subagents, then show a concise summary to the user. -### Output files +### Output files (write via subagents) + +**IMPORTANT**: Write both report files using parallel subagents (Task tool) so the file-writing work does not pollute the main conversation thread. Launch both subagents at the same time. Write two files to `results/` in the conformance repo: - `results/--assessment.md` - `results/--remediation.md` -For example: `results/2026-02-10-typescript-sdk-assessment.md` +For example: `results/2026-02-11-typescript-sdk-assessment.md` -### Assessment file +#### Assessment subagent -Use the assessment template from `references/report-template.md`. This file contains the full requirements table, conformance test details (both server and client), triage metrics, documentation coverage table, and policy evaluation evidence. +Pass all the gathered data (CLI scorecard JSON, docs evaluation results, policy evaluation results) to a subagent and instruct it to write the assessment file using the template from `references/report-template.md`. This file contains the full requirements table, conformance test details (both server and client), triage metrics, documentation coverage table, and policy evaluation evidence. -### Remediation file +#### Remediation subagent -Use the remediation template from `references/report-template.md`. This file always includes both: +Pass all the gathered data to a subagent and instruct it to write the remediation file using the template from `references/report-template.md`. This file always includes both: - **Path to Tier 2** (if current tier is 3) -- what's needed to reach Tier 2 - **Path to Tier 1** (always) -- what's needed to reach Tier 1 ### Console output (shown to the user) -After writing the files, output a short executive summary directly to the user: +After the subagents finish, output a short executive summary directly to the user: ``` ## — Tier -Server Conformance: / () | Client Conformance: / () | Triage: % () | P0s: open () | Docs: / () | Policies: () +| Check | Value | T2 | T1 | +|-------|-------|----|----| +| Server Conformance | / (%) | ✓/✗ | ✓/✗ | +| Client Conformance | / (%) | ✓/✗ | ✓/✗ | +| Issue Triage | % (/) | ✓/✗ | ✓/✗ | +| P0 Resolution | open | ✓/✗ | ✓/✗ | +| Documentation | / features | ✓/✗ | ✓/✗ | +| Dependency Policy | | ✓/✗ | ✓/✗ | +| Roadmap | | ✓/✗ | ✓/✗ | +| Versioning Policy | | N/A | ✓/✗ | +| Stable Release | | ✓/✗ | ✓/✗ | For Tier 2: For Tier 1: @@ -179,7 +191,7 @@ Reports: - results/--remediation.md ``` -Use checkmarks/crosses for status: ✓ for pass, ✗ for fail. +Use ✓ for pass and ✗ for fail. **Special note for high P0 count with strong other metrics:** From 53074929896427e02a1bd744dea97df22b15df06 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 10:30:43 +0000 Subject: [PATCH 16/34] improve: list tier gaps as numbered items instead of one-line blob --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 3daabf8..2596f4b 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -183,8 +183,13 @@ After the subagents finish, output a short executive summary directly to the use | Versioning Policy | | N/A | ✓/✗ | | Stable Release | | ✓/✗ | ✓/✗ | -For Tier 2: -For Tier 1: +For Tier 2: <"All requirements met" or list each gap as a numbered item, one per line> +1. +2. + +For Tier 1: <"All requirements met" or list each gap as a numbered item, one per line> +1. +2. Reports: - results/--assessment.md From ffa04c09224614044c149862695bf57cad224ea2 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 10:40:26 +0000 Subject: [PATCH 17/34] improve: finalize summary format with separator, high-priority fixes, numbered gaps --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 2596f4b..5a012e5 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -183,11 +183,16 @@ After the subagents finish, output a short executive summary directly to the use | Versioning Policy | | N/A | ✓/✗ | | Stable Release | | ✓/✗ | ✓/✗ | -For Tier 2: <"All requirements met" or list each gap as a numbered item, one per line> +--- + +**High-Priority Fixes:** +1. + +**For Tier 2:** 1. 2. -For Tier 1: <"All requirements met" or list each gap as a numbered item, one per line> +**For Tier 1:** 1. 2. @@ -198,15 +203,9 @@ Reports: Use ✓ for pass and ✗ for fail. -**Special note for high P0 count with strong other metrics:** - -If P0 count is >2 but other Tier 2 metrics pass, add this note to the executive summary: - -``` -⚠️ P0 Label Audit Recommended: open P0 issues detected. Review these issues to verify they represent critical bugs vs. misclassified enhancements or lower-priority work. See remediation report for specific issues and re-triage guidance. -``` +**High-Priority Fixes**: List any issues that need urgent attention (e.g., P0 label audit if P0 count is >2 but other metrics are strong, suggesting mislabeled issues). If none, omit this section. -This ensures the audit context is clear: the high P0 count may be a labeling process issue rather than a product quality issue. +**For Tier 2 / For Tier 1**: List each gap as a separate numbered item. Use "All requirements met" if there are no gaps for that tier. Each item should be a concise action (e.g., "Re-triage mislabeled P0s", "Document 16 undocumented core features"). ## Reference Files From 6e662a7e2ee7b8104a4b0ee3c9f40f79ce4a2bfb Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 11:35:23 +0000 Subject: [PATCH 18/34] 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. --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 5a012e5..cc695dd 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -12,6 +12,30 @@ argument-hint: ' [client-cmd]' You are performing a comprehensive tier assessment for an MCP SDK repository against SEP-1730 (the SDK Tiering System). Your goal is to produce a definitive tier classification (Tier 1, 2, or 3) backed by evidence. +## Step 0: Pre-flight Checks + +Before doing anything else, verify GitHub CLI authentication: + +```bash +gh auth status 2>&1 +``` + +If this fails (exit code non-zero or shows "not logged in"), stop immediately and tell the user: + +> GitHub authentication is required for this skill. Please run `gh auth login` first, then re-run the skill. + +Do NOT proceed to any other step if this check fails. + +After parsing arguments (Step 1), also verify the conformance server is reachable: + +```bash +curl -sf -o /dev/null -w '%{http_code}' 2>&1 || true +``` + +If the server is not reachable, stop and tell the user: + +> Conformance server at `` is not reachable. Make sure the everything server is running before invoking this skill. + ## Step 1: Parse Arguments Extract from the user's input: From b9dffd10de41b9d16422e663a4b8d88c3389fffc Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 11:58:08 +0000 Subject: [PATCH 19/34] 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 --- .claude/skills/mcp-sdk-tier-audit/README.md | 53 +++++++++++++++------ .claude/skills/mcp-sdk-tier-audit/SKILL.md | 4 +- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index d316469..74cc836 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -92,24 +92,44 @@ The CLI produces a deterministic scorecard, but some SEP-1730 requirements need The skill lives in `.claude/skills/` in this repo, so if you open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) in the conformance repo it's already available. -1. Start the SDK's everything server in a separate terminal -2. Run the skill: +1. Make sure `gh auth login` is done (the skill checks this upfront) +2. Start the SDK's everything server in a separate terminal +3. Run the skill: ``` -/mcp-sdk-tier-audit +/mcp-sdk-tier-audit [client-cmd] ``` -Example: +The skill auto-detects the conformance client for TypeScript and Python SDKs by checking known paths (`test/conformance/src/everythingClient.ts` and `tests/conformance/client.py`). For other SDKs, pass the client command as the third argument — or omit it to skip client conformance (noted as a gap in the report). + +**TypeScript SDK example:** ```bash -# Terminal 1: start the everything server -cd ~/src/mcp/typescript-sdk/test/conformance && npx tsx src/everythingServer.ts +# Terminal 1: start the everything server (build first: npm run build) +cd ~/src/mcp/typescript-sdk && npm run test:conformance:server:run # Terminal 2: run the audit (from the conformance repo) /mcp-sdk-tier-audit ~/src/mcp/typescript-sdk http://localhost:3000/mcp ``` -The skill derives `owner/repo` from git remote, runs the CLI, launches parallel evaluations for docs and policy, and writes detailed reports to `results/tier-audits/`. +**Python SDK example:** + +```bash +# Terminal 1: install and start the everything server +cd ~/src/mcp/python-sdk && uv sync --frozen --all-extras --package mcp-everything-server +uv run mcp-everything-server --port 3001 + +# Terminal 2: run the audit (from the conformance repo) +/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp +``` + +**Other SDKs** — pass the client command explicitly: + +```bash +/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002/mcp 'go run ./test/conformance/client' +``` + +The skill derives `owner/repo` from git remote, runs the CLI, launches parallel evaluations for docs and policy, and writes detailed reports to `results/`. ### Any Other AI Coding Agent @@ -152,8 +172,8 @@ To include conformance test results, start the SDK's everything server first, th ```bash # Terminal 1: start the server (SDK must be built first) -cd ~/src/mcp/typescript-sdk && pnpm build:all -cd test/conformance && npx tsx src/everythingServer.ts +cd ~/src/mcp/typescript-sdk && npm run build +npm run test:conformance:server:run # starts on port 3000 # Terminal 2: run tier-check (server + client conformance) npm run --silent tier-check -- \ @@ -165,18 +185,21 @@ npm run --silent tier-check -- \ **Python SDK**: ```bash -# Terminal 1 -cd ~/src/mcp/python-sdk/examples/servers/everything-server -uv run mcp-everything-server +# Terminal 1: install and start the server +cd ~/src/mcp/python-sdk +uv sync --frozen --all-extras --package mcp-everything-server +uv run mcp-everything-server --port 3001 # specify port to avoid conflicts -# Terminal 2 +# Terminal 2: run tier-check (server + client conformance) npm run --silent tier-check -- \ --repo modelcontextprotocol/python-sdk \ --conformance-server-url http://localhost:3001/mcp \ - --client-cmd 'uv run python ~/src/mcp/python-sdk/tests/conformance/client.py' + --client-cmd 'uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py' ``` -**Other SDKs:** Start your everything server, then pass `--conformance-server-url`. Pass `--client-cmd` if the SDK has a conformance client. If neither exists yet, use `--skip-conformance` — the scorecard will note this as a gap. +**Other SDKs:** Your SDK needs an "everything server" — an HTTP server at `/mcp` implementing the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/draft/basic/transports.md) with all MCP features (tools, resources, prompts, etc.). See the [TypeScript](https://github.com/modelcontextprotocol/typescript-sdk/tree/v1.x/test/conformance) or [Python](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x/examples/servers/everything-server) implementations as reference. + +Start your everything server, then pass `--conformance-server-url`. Pass `--client-cmd` if your SDK has a conformance client. If neither exists yet, use `--skip-conformance` — the scorecard will note this as a gap. ## Reference Files diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index cc695dd..15bd1af 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -53,7 +53,7 @@ If client-cmd is not provided, look for a conformance client in the local checko ```bash # Check common locations for a conformance/everything client ls /test/conformance/src/everythingClient.ts 2>/dev/null -ls /tests/conformance/client.py 2>/dev/null +ls /.github/actions/conformance/client.py 2>/dev/null ``` For TypeScript SDKs, the client command is typically: @@ -63,7 +63,7 @@ npx tsx /test/conformance/src/everythingClient.ts For Python SDKs, the client command is typically: ``` -uv run python /tests/conformance/client.py +uv run python /.github/actions/conformance/client.py ``` If no conformance client is found, proceed without client conformance tests (they will be skipped and noted in the report). From 12eb095cde1bd11aac2672ad5e8c8b3da062a362 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 11:58:53 +0000 Subject: [PATCH 20/34] simplify: remove client-cmd auto-detection, require explicit argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .claude/skills/mcp-sdk-tier-audit/README.md | 12 ++----- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 37 ++++----------------- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 74cc836..e770112 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -100,7 +100,7 @@ The skill lives in `.claude/skills/` in this repo, so if you open [Claude Code]( /mcp-sdk-tier-audit [client-cmd] ``` -The skill auto-detects the conformance client for TypeScript and Python SDKs by checking known paths (`test/conformance/src/everythingClient.ts` and `tests/conformance/client.py`). For other SDKs, pass the client command as the third argument — or omit it to skip client conformance (noted as a gap in the report). +Pass the client command as the third argument to include client conformance testing. If omitted, client conformance is skipped and noted as a gap in the report. **TypeScript SDK example:** @@ -109,7 +109,7 @@ The skill auto-detects the conformance client for TypeScript and Python SDKs by cd ~/src/mcp/typescript-sdk && npm run test:conformance:server:run # Terminal 2: run the audit (from the conformance repo) -/mcp-sdk-tier-audit ~/src/mcp/typescript-sdk http://localhost:3000/mcp +/mcp-sdk-tier-audit ~/src/mcp/typescript-sdk http://localhost:3000/mcp "npx tsx ~/src/mcp/typescript-sdk/test/conformance/src/everythingClient.ts" ``` **Python SDK example:** @@ -120,13 +120,7 @@ cd ~/src/mcp/python-sdk && uv sync --frozen --all-extras --package mcp-everythin uv run mcp-everything-server --port 3001 # Terminal 2: run the audit (from the conformance repo) -/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp -``` - -**Other SDKs** — pass the client command explicitly: - -```bash -/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002/mcp 'go run ./test/conformance/client' +/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp "uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py" ``` The skill derives `owner/repo` from git remote, runs the CLI, launches parallel evaluations for docs and policy, and writes detailed reports to `results/`. diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 15bd1af..b823d3d 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -42,32 +42,10 @@ Extract from the user's input: - **local-path**: absolute path to the SDK checkout (e.g. `~/src/mcp/typescript-sdk`) - **conformance-server-url**: URL where the SDK's everything server is already running (e.g. `http://localhost:3000/mcp`) -- **client-cmd** (optional): command to run the SDK's conformance client (e.g. `npx tsx test/conformance/src/everythingClient.ts`). If not provided, try to auto-detect it (see below). +- **client-cmd** (optional): command to run the SDK's conformance client (e.g. `npx tsx test/conformance/src/everythingClient.ts`). If not provided, client conformance tests are skipped and noted as a gap in the report. The first two arguments are required. If either is missing, ask the user to provide it. -### Auto-detecting the conformance client command - -If client-cmd is not provided, look for a conformance client in the local checkout: - -```bash -# Check common locations for a conformance/everything client -ls /test/conformance/src/everythingClient.ts 2>/dev/null -ls /.github/actions/conformance/client.py 2>/dev/null -``` - -For TypeScript SDKs, the client command is typically: -``` -npx tsx /test/conformance/src/everythingClient.ts -``` - -For Python SDKs, the client command is typically: -``` -uv run python /.github/actions/conformance/client.py -``` - -If no conformance client is found, proceed without client conformance tests (they will be skipped and noted in the report). - Derive the GitHub `owner/repo` from the local checkout: ```bash @@ -245,13 +223,12 @@ Read these reference files when you need the detailed content for evaluation pro ## Usage Examples ``` -# TypeScript SDK on v1.x with everything server running on port 3000 -# (client command auto-detected from test/conformance/src/everythingClient.ts) -/mcp-sdk-tier-audit ~/src/mcp/worktrees/typescript-sdk-v1x http://localhost:3000/mcp +# TypeScript SDK — server + client conformance +/mcp-sdk-tier-audit ~/src/mcp/typescript-sdk http://localhost:3000/mcp "npx tsx ~/src/mcp/typescript-sdk/test/conformance/src/everythingClient.ts" -# Explicit client command -/mcp-sdk-tier-audit ~/src/mcp/worktrees/typescript-sdk-v1x http://localhost:3000/mcp "npx tsx ~/src/mcp/worktrees/typescript-sdk-v1x/test/conformance/src/everythingClient.ts" +# Python SDK — server + client conformance +/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp "uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py" -# Python SDK with everything server running on port 3001 -/mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp +# Any SDK — server conformance only (no client) +/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002/mcp ``` From 655734fce0530a3f6ded39f58b4cfa86a3c494f4 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 12:10:08 +0000 Subject: [PATCH 21/34] 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 --- .../references/docs-coverage-prompt.md | 113 ++++++----- .../references/policy-evaluation-prompt.md | 181 ++++++------------ 2 files changed, 122 insertions(+), 172 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 1bbc793..14d5caa 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -157,64 +157,71 @@ Produce your assessment in this exact format: #### Feature Documentation Table -| Feature | Documented? | Where | Has Examples? | Verdict | -| ------------------------------------------- | ----------- | -------------- | ----------------------- | ----------------- | -| Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| Tasks - status notifications (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| # | Feature | Documented? | Where | Has Examples? | Verdict | +|---|---------------------------------------------|-------------|----------------|-------------------------| ------------------| +| 1 | Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 2 | Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 3 | Tools - text results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 4 | Tools - image results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 5 | Tools - audio results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 6 | Tools - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 7 | Tools - error handling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 8 | Tools - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 9 | Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 10 | Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 11 | Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 12 | Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 13 | Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 14 | Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 15 | Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 16 | Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 17 | Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 18 | Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 19 | Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 20 | Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 21 | Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 22 | Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 23 | Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 24 | Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 25 | Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 26 | Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 27 | Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 28 | Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 29 | Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 30 | Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 31 | Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 32 | Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 33 | Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 34 | Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 35 | Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 36 | Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 37 | Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 38 | Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 39 | SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 40 | SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 41 | stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 42 | stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 43 | Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 44 | Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 45 | Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 46 | Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 47 | Protocol version negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 48 | JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| — | Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| — | Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| — | Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| — | Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| — | Tasks - status notifications (experimental)| Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | #### Summary -**Total features**: {N} -**PASS (documented with examples)**: {N} -**PARTIAL (documented, no examples)**: {N} -**FAIL (not documented)**: {N} +**Total non-experimental features**: 48 +**PASS (documented with examples)**: {N}/48 +**PARTIAL (documented, no examples)**: {N}/48 +**FAIL (not documented)**: {N}/48 **Core features documented**: {N}/{total core} ({percentage}%) -**All features documented with examples**: {N}/{total non-experimental} ({percentage}%) +**All features documented with examples**: {N}/48 ({percentage}%) #### Tier Verdicts diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index a1a6a52..127f021 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -5,118 +5,74 @@ You are evaluating the governance and policy documentation of an MCP SDK reposit ## Input - **SDK path**: {local-path} (absolute path to local SDK checkout) -- **Repository**: {repo} (GitHub `owner/repo`, derived from git remote — used for GitHub API queries) +- **Repository**: {repo} (GitHub `owner/repo`, derived from git remote) ## Your Task -Evaluate three policy areas required by SEP-1730: +Check whether three required policy documents exist as files in the repository. This is a simple file-existence check — if the file exists and has substantive content, it passes. 1. **Dependency update policy** (required for Tier 1 and Tier 2) 2. **Roadmap** (Tier 1: published roadmap; Tier 2: published plan toward Tier 1) -3. **Versioning policy** (Tier 1: clear versioning with documented breaking change policy) +3. **Versioning policy** (Tier 1 only: documented breaking change policy) ## Steps -### 1. Read and evaluate policy documents - -The SDK is available at `{local-path}`. - -Check these files for each policy area. Read the actual content — you're evaluating the substance of what's written, not just whether the file exists. - -**Dependency Policy** — check these files: - -- `CONTRIBUTING.md` (dependency/update sections) -- `SECURITY.md` (dependency update references) -- `.github/dependabot.yml` or `.github/renovate.json` -- `docs/` directory (any policy documents) -- `README.md` (dependency update references) -- CI workflow files that run dependency updates - -**Roadmap** — check these files: - -- `ROADMAP.md` -- `docs/roadmap.md` -- `README.md` (roadmap section) -- `CHANGELOG.md` (for evidence of planned work) - -Also check GitHub-level resources: +### 1. Check for policy files ```bash -# Check for GitHub milestones -gh api repos/{repo}/milestones --jq '.[].title' +# Dependency update policy +ls {local-path}/DEPENDENCY_POLICY.md {local-path}/docs/dependency-policy.md 2>/dev/null -# Check for releases and versioning pattern -gh release list --repo {repo} --limit 20 -``` +# Also check for automated dependency tooling as evidence +ls {local-path}/.github/dependabot.yml {local-path}/.github/renovate.json {local-path}/renovate.json 2>/dev/null -**Versioning Policy** — check these files: +# Roadmap +ls {local-path}/ROADMAP.md {local-path}/docs/roadmap.md 2>/dev/null -- `CONTRIBUTING.md` (versioning/release sections) -- `README.md` (versioning section) -- `CHANGELOG.md` (evidence of versioning practice) -- `RELEASE.md` or `docs/releasing.md` -- Any documentation mentioning "breaking changes", "semver", "versioning" +# Versioning / breaking change policy +ls {local-path}/VERSIONING.md {local-path}/docs/versioning.md {local-path}/BREAKING_CHANGES.md 2>/dev/null -### 3. Evaluate each policy area +# Also check CONTRIBUTING.md and CHANGELOG.md for versioning sections +ls {local-path}/CONTRIBUTING.md {local-path}/CHANGELOG.md 2>/dev/null +``` -For each area, determine: +### 2. Evaluate each policy area -- Is there a published policy/document? -- What does it commit to? (specific commitments vs vague statements) -- Does it meet Tier 1 standards? Tier 2 standards? +For each area, check: +- Does a dedicated file exist? +- If no dedicated file, is there a clearly labeled section in CONTRIBUTING.md or README.md? +- Is the content substantive (not just a placeholder)? ## Evaluation Criteria ### Dependency Update Policy -**PASS for Tier 1 and Tier 2** requires: - -- A published, findable policy describing how dependencies are updated -- The policy must include actual commitments (e.g., "updated monthly", "security patches within 48h") -- Automated tooling (Dependabot, Renovate) configured counts as evidence of policy in practice -- Simply having a lockfile or running `npm install` does NOT count +**PASS** if any of these exist with substantive content: +- `DEPENDENCY_POLICY.md` or `docs/dependency-policy.md` +- A clearly labeled "Dependency Updates" or "Dependency Policy" section in `CONTRIBUTING.md` +- Configured Dependabot (`.github/dependabot.yml`) or Renovate (`.github/renovate.json`) — automated tooling counts as a published policy in practice -**Tier 1 additional**: Policy should be comprehensive -- covering frequency, security updates, major version handling - -**FAIL** if: - -- No dependency update policy found anywhere in the repo -- Only vague references like "we try to keep dependencies up to date" +**FAIL** if none of the above exist. ### Roadmap -**PASS for Tier 1** requires: - -- A published roadmap document with concrete steps and work items -- Must track implementation of MCP specification components (non-experimental features and optional capabilities) -- Must give users visibility into upcoming feature support -- Can be a ROADMAP.md, GitHub milestones/projects, or a section in docs - -**PASS for Tier 2** requires: - -- A published plan toward Tier 1 (what the SDK intends to implement to reach full support) -- OR an explanation of why the SDK will remain at Tier 2 (intentionally scoped) -- Can be simpler than a full roadmap +**PASS for Tier 1**: `ROADMAP.md` or `docs/roadmap.md` exists with concrete work items tracking MCP spec components. -**FAIL** if: +**PASS for Tier 2**: Same file exists with at least a plan toward Tier 1, or explanation for remaining at Tier 2. -- No roadmap or plan found -- Only a CHANGELOG showing past work (not forward-looking) +**FAIL** if no roadmap file exists. GitHub milestones alone are not sufficient — there must be a file in the repo. ### Versioning Policy -**PASS for Tier 1** requires: +**PASS for Tier 1** if any of these exist with substantive content: +- `VERSIONING.md` or `docs/versioning.md` or `BREAKING_CHANGES.md` +- A clearly labeled "Versioning" or "Breaking Changes" section in `CONTRIBUTING.md` -- Documented breaking change policy (what constitutes a breaking change, how they are communicated) -- Clear versioning pattern (SemVer or language-idiomatic equivalent) -- Users can understand compatibility expectations when upgrading +The content must describe: what constitutes a breaking change, how breaking changes are communicated, and the versioning scheme (SemVer or language-idiomatic equivalent). -**Not required for Tier 2** (only needs a stable release >= 1.0.0) +**Not required for Tier 2** (only needs a stable release >= 1.0.0, checked separately). -**FAIL** if: - -- No versioning documentation found -- No breaking change policy documented +**FAIL** if no versioning documentation found. ## Required Output Format @@ -132,54 +88,43 @@ Produce your assessment in this exact format: #### 1. Dependency Update Policy: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -| ---------------------------------- | ----------------------------- | --------------------------------------------- | ----------------- | -| CONTRIBUTING.md dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No dependency section" | {Found/Not found} | -| Dependabot/Renovate config | {path} or "Not found" | "{config summary}" or "Not configured" | {Found/Not found} | -| README dependency section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | -| SECURITY.md dependency references | {path}:{lines} or "Not found" | "{relevant quote}" or "No references" | {Found/Not found} | -| CI dependency update workflows | {path} or "Not found" | "{workflow description}" or "None" | {Found/Not found} | -| Other policy documents | {path}:{lines} or "Not found" | "{relevant quote}" or "None" | {Found/Not found} | - -**Policy content summary**: {Brief description of what the policy says, or "No dependency update policy found"} +| File Checked | Exists? | Path | +|---|---|---| +| DEPENDENCY_POLICY.md | Yes/No | {path} or N/A | +| docs/dependency-policy.md | Yes/No | {path} or N/A | +| .github/dependabot.yml | Yes/No | {path} or N/A | +| .github/renovate.json | Yes/No | {path} or N/A | +| CONTRIBUTING.md (dependency section) | Yes/No | {path}:{lines} or N/A | -**Tier 1 verdict**: **PASS/FAIL** -- {explanation} -**Tier 2 verdict**: **PASS/FAIL** -- {explanation} +**Verdict**: **PASS/FAIL** — {one-line explanation} --- #### 2. Roadmap: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -| -------------------------- | ----------------------------- | ------------------------------------ | ----------------- | -| ROADMAP.md | {path} or "Not found" | "{summary}" or "File does not exist" | {Found/Not found} | -| README roadmap section | {path}:{lines} or "Not found" | "{summary}" or "No roadmap section" | {Found/Not found} | -| GitHub Milestones | {URL or count} | "{milestone names}" or "None" | {Found/Not found} | -| docs/ roadmap documents | {path} or "Not found" | "{summary}" or "None" | {Found/Not found} | -| Other forward-looking docs | {path}:{lines} or "Not found" | "{summary}" or "None" | {Found/Not found} | +| File Checked | Exists? | Path | +|---|---|---| +| ROADMAP.md | Yes/No | {path} or N/A | +| docs/roadmap.md | Yes/No | {path} or N/A | -**Roadmap content summary**: {Brief description of the roadmap contents, or "No roadmap found"} - -**Tier 1 verdict**: **PASS/FAIL** -- {explanation: does it track concrete spec component implementation?} -**Tier 2 verdict**: **PASS/FAIL** -- {explanation: is there a plan toward Tier 1?} +**Verdict**: +- **Tier 1**: **PASS/FAIL** — {one-line explanation} +- **Tier 2**: **PASS/FAIL** — {one-line explanation} --- #### 3. Versioning Policy: {PASS/FAIL} -| What Was Checked | Where | Content Found | Verdict | -| ---------------------------------- | ----------------------------- | --------------------------------------------------- | ------------------------- | -| CONTRIBUTING.md versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No versioning section" | {Found/Not found} | -| README versioning section | {path}:{lines} or "Not found" | "{relevant quote}" or "No section" | {Found/Not found} | -| CHANGELOG.md versioning evidence | {path} or "Not found" | "{pattern observed}" or "Not found" | {Found/Not found} | -| Release docs | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | -| Breaking change documentation | {path}:{lines} or "Not found" | "{relevant quote}" or "Not found" | {Found/Not found} | -| Version pattern analysis | Release history | "{pattern}" (e.g., "Follows SemVer, X.Y.Z pattern") | {Consistent/Inconsistent} | - -**Versioning content summary**: {Brief description of the versioning approach and breaking change policy, or "No versioning policy found"} +| File Checked | Exists? | Path | +|---|---|---| +| VERSIONING.md | Yes/No | {path} or N/A | +| docs/versioning.md | Yes/No | {path} or N/A | +| BREAKING_CHANGES.md | Yes/No | {path} or N/A | +| CONTRIBUTING.md (versioning section) | Yes/No | {path}:{lines} or N/A | -**Tier 1 verdict**: **PASS/FAIL** -- {explanation: is there a documented breaking change policy with clear versioning?} -**Tier 2 verdict**: **N/A** -- Tier 2 only requires at least one stable release (checked separately) +**Verdict**: +- **Tier 1**: **PASS/FAIL** — {one-line explanation} +- **Tier 2**: **N/A** — only requires stable release --- @@ -194,9 +139,7 @@ Produce your assessment in this exact format: ## Important Notes -- Be factual and evidence-based. Quote actual content found in files. -- If a policy exists but is vague or insufficient, explain WHY it does not meet the standard. -- Automated dependency tooling (Dependabot, Renovate) configured and active counts as a published policy in practice, even without a separate written policy document. -- GitHub Milestones and Projects with concrete work items count as a roadmap. -- For versioning, look at both documentation AND practice (release history pattern). -- Include file:line references for every piece of evidence so reviewers can verify. +- This is primarily a file-existence check. If the file exists and has real content (not just a title), it passes. +- Do NOT search through the entire repo looking for scattered references. The policy must be in a dedicated file or a clearly labeled section in CONTRIBUTING.md. +- Dependabot/Renovate configuration counts as a dependency policy — it's a published, machine-readable commitment. +- CHANGELOG.md showing past releases does NOT count as a roadmap (it's backward-looking, not forward-looking). From 6f3ec840b95e501714b50a46eededafe10dd028b Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 12:10:57 +0000 Subject: [PATCH 22/34] 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. --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 1 + .../references/docs-coverage-prompt.md | 168 ++---------------- .../references/feature-list.md | 80 +++++++++ 3 files changed, 99 insertions(+), 150 deletions(-) create mode 100644 .claude/skills/mcp-sdk-tier-audit/references/feature-list.md diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index b823d3d..c9222a1 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -213,6 +213,7 @@ Use ✓ for pass and ✗ for fail. The following reference files are available in the `references/` directory alongside this skill: +- `references/feature-list.md` -- Canonical list of 48 non-experimental + 5 experimental features (single source of truth) - `references/tier-requirements.md` -- Full SEP-1730 requirements table with exact thresholds - `references/report-template.md` -- Output format template for the audit report - `references/docs-coverage-prompt.md` -- Evaluation prompt for documentation coverage diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 14d5caa..ea0901c 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -15,7 +15,11 @@ Evaluate the documentation quality and coverage of this MCP SDK against the cano ## Steps -### 1. Find all documentation sources +### 1. Read the canonical feature list + +Read `references/feature-list.md` for the definitive list of 48 non-experimental features (plus 5 experimental) to evaluate. That file is the single source of truth — use every feature listed there, in order. + +### 2. Find all documentation sources The SDK is available at `{local-path}`. Search for documentation in these locations: @@ -41,106 +45,13 @@ find {local-path} -path "*/docs/*" -not -path "*/node_modules/*" ### 3. Evaluate each feature -For each feature in the canonical list below, determine: +For each of the 48 non-experimental features in the canonical list, determine: - **Documented?**: Is there documentation explaining this feature? (Yes/No) - **Where**: File path and line numbers where documentation exists - **Has Examples?**: Are there code examples showing how to use this feature? (Yes/No/N/A) - **Verdict**: PASS (documented with examples), PARTIAL (documented but no examples), or FAIL (not documented) -## Canonical Feature List to Check - -### Core Features - -**Tools:** - -- Tools - listing (`tools/list`) -- Tools - calling (`tools/call`) -- Tools - text results -- Tools - image results -- Tools - audio results -- Tools - embedded resources -- Tools - error handling -- Tools - change notifications - -**Resources:** - -- Resources - listing (`resources/list`) -- Resources - reading text -- Resources - reading binary -- Resources - templates (`resources/templates/list`) -- Resources - template reading -- Resources - subscribing (`resources/subscribe`) -- Resources - unsubscribing (`resources/unsubscribe`) -- Resources - change notifications - -**Prompts:** - -- Prompts - listing (`prompts/list`) -- Prompts - getting simple -- Prompts - getting with arguments -- Prompts - embedded resources -- Prompts - image content -- Prompts - change notifications - -**Sampling:** - -- Sampling - creating messages (`sampling/createMessage`) - -**Elicitation:** - -- Elicitation - requesting input (`elicitation/create`) — form mode -- Elicitation - URL mode (`elicitation/create` with `mode: "url"`) -- Elicitation - schema validation -- Elicitation - default values -- Elicitation - enum values -- Elicitation - complete notification (`notifications/elicitation/complete`) - -**Roots:** - -- Roots - listing (`roots/list`) -- Roots - change notifications - -**Logging:** - -- Logging - sending log messages -- Logging - setting level (`logging/setLevel`) - -**Completions:** - -- Completions - resource argument completion -- Completions - prompt argument completion - -**Ping:** - -- Ping (`ping`) - -### Transport Features - -- Streamable HTTP transport (client) -- Streamable HTTP transport (server) -- SSE transport - legacy (client) -- SSE transport - legacy (server) -- stdio transport (client) -- stdio transport (server) - -### Protocol Features - -- Progress notifications -- Cancellation -- Pagination -- Capability negotiation (initialize/initialized) -- Protocol version negotiation -- JSON Schema 2020-12 support - -### Experimental Features (does not count toward tier score) - -- Tasks - get (`tasks/get`) -- Tasks - result (`tasks/result`) -- Tasks - cancel (`tasks/cancel`) -- Tasks - list (`tasks/list`) -- Tasks - status notifications (`notifications/tasks/status`) - ## Required Output Format Produce your assessment in this exact format: @@ -157,61 +68,18 @@ Produce your assessment in this exact format: #### Feature Documentation Table -| # | Feature | Documented? | Where | Has Examples? | Verdict | -|---|---------------------------------------------|-------------|----------------|-------------------------| ------------------| -| 1 | Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 2 | Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 3 | Tools - text results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 4 | Tools - image results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 5 | Tools - audio results | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 6 | Tools - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 7 | Tools - error handling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 8 | Tools - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 9 | Resources - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 10 | Resources - reading text | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 11 | Resources - reading binary | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 12 | Resources - templates | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 13 | Resources - template reading | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 14 | Resources - subscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 15 | Resources - unsubscribing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 16 | Resources - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 17 | Prompts - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 18 | Prompts - getting simple | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 19 | Prompts - getting with args | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 20 | Prompts - embedded resources | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 21 | Prompts - image content | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 22 | Prompts - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 23 | Sampling - creating messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 24 | Elicitation - form mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 25 | Elicitation - URL mode | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 26 | Elicitation - schema validation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 27 | Elicitation - default values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 28 | Elicitation - enum values | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 29 | Elicitation - complete notification | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 30 | Roots - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 31 | Roots - change notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 32 | Logging - sending log messages | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 33 | Logging - setting level | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 34 | Completions - resource argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 35 | Completions - prompt argument | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 36 | Ping | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 37 | Streamable HTTP - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 38 | Streamable HTTP - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 39 | SSE transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 40 | SSE transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 41 | stdio transport - client | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 42 | stdio transport - server | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 43 | Progress notifications | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 44 | Cancellation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 45 | Pagination | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 46 | Capability negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 47 | Protocol version negotiation | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 48 | JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| — | Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| — | Tasks - result (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| — | Tasks - cancel (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| — | Tasks - list (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| — | Tasks - status notifications (experimental)| Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +One row per feature from `references/feature-list.md`. Use the exact feature numbers and names from that file. + +| # | Feature | Documented? | Where | Has Examples? | Verdict | +|---|---------|-------------|-------|---------------|---------| +| 1 | Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 2 | Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| ... | ... | ... | ... | ... | ... | +| 48 | JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| — | Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| ... | ... | ... | ... | ... | ... | + +All 48 non-experimental features MUST appear in the table. Do not skip or merge rows. #### Summary diff --git a/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md b/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md new file mode 100644 index 0000000..eff6189 --- /dev/null +++ b/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md @@ -0,0 +1,80 @@ +# MCP SDK Canonical Feature List + +Single source of truth for all MCP features evaluated in the tier audit. **48 non-experimental features** plus 5 experimental (informational only). + +When updating this list, also update the total count referenced in `docs-coverage-prompt.md`. + +## Non-Experimental Features (48 total) + +### Core Features (36) + +| # | Feature | Protocol Method | +|---|---------|-----------------| +| 1 | Tools - listing | `tools/list` | +| 2 | Tools - calling | `tools/call` | +| 3 | Tools - text results | | +| 4 | Tools - image results | | +| 5 | Tools - audio results | | +| 6 | Tools - embedded resources | | +| 7 | Tools - error handling | | +| 8 | Tools - change notifications | `notifications/tools/list_changed` | +| 9 | Resources - listing | `resources/list` | +| 10 | Resources - reading text | `resources/read` | +| 11 | Resources - reading binary | `resources/read` | +| 12 | Resources - templates | `resources/templates/list` | +| 13 | Resources - template reading | | +| 14 | Resources - subscribing | `resources/subscribe` | +| 15 | Resources - unsubscribing | `resources/unsubscribe` | +| 16 | Resources - change notifications | `notifications/resources/list_changed` | +| 17 | Prompts - listing | `prompts/list` | +| 18 | Prompts - getting simple | `prompts/get` | +| 19 | Prompts - getting with arguments | `prompts/get` | +| 20 | Prompts - embedded resources | | +| 21 | Prompts - image content | | +| 22 | Prompts - change notifications | `notifications/prompts/list_changed` | +| 23 | Sampling - creating messages | `sampling/createMessage` | +| 24 | Elicitation - form mode | `elicitation/create` | +| 25 | Elicitation - URL mode | `elicitation/create` (mode: "url") | +| 26 | Elicitation - schema validation | | +| 27 | Elicitation - default values | | +| 28 | Elicitation - enum values | | +| 29 | Elicitation - complete notification | `notifications/elicitation/complete` | +| 30 | Roots - listing | `roots/list` | +| 31 | Roots - change notifications | `notifications/roots/list_changed` | +| 32 | Logging - sending log messages | `notifications/message` | +| 33 | Logging - setting level | `logging/setLevel` | +| 34 | Completions - resource argument | `completion/complete` | +| 35 | Completions - prompt argument | `completion/complete` | +| 36 | Ping | `ping` | + +### Transport Features (6) + +| # | Feature | +|---|---------| +| 37 | Streamable HTTP transport (client) | +| 38 | Streamable HTTP transport (server) | +| 39 | SSE transport - legacy (client) | +| 40 | SSE transport - legacy (server) | +| 41 | stdio transport (client) | +| 42 | stdio transport (server) | + +### Protocol Features (6) + +| # | Feature | +|---|---------| +| 43 | Progress notifications | +| 44 | Cancellation | +| 45 | Pagination | +| 46 | Capability negotiation | +| 47 | Protocol version negotiation | +| 48 | JSON Schema 2020-12 support | + +## Experimental Features (5, informational only) + +| # | Feature | Protocol Method | +|---|---------|-----------------| +| — | Tasks - get | `tasks/get` | +| — | Tasks - result | `tasks/result` | +| — | Tasks - cancel | `tasks/cancel` | +| — | Tasks - list | `tasks/list` | +| — | Tasks - status notifications | `notifications/tasks/status` | From 5b4f5e2a66ee7dcde892b278d6aff9ab5f18617e Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 12:20:19 +0000 Subject: [PATCH 23/34] fix: separate deterministic file checks from AI content evaluation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 4 +- .../references/policy-evaluation-prompt.md | 92 +++++++++---------- src/tier-check/checks/files.ts | 21 ++++- 3 files changed, 64 insertions(+), 53 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index c9222a1..5ba0342 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -86,7 +86,9 @@ This evaluation checks: ### Evaluation 2: Policy Evaluation -Use the prompt from `references/policy-evaluation-prompt.md`. Pass the local path and the derived `owner/repo`. +Use the prompt from `references/policy-evaluation-prompt.md`. Pass the local path, the derived `owner/repo`, and the `policy_signals` section from the CLI JSON output. + +The CLI has already checked which policy files exist (ROADMAP.md, DEPENDENCY_POLICY.md, dependabot.yml, VERSIONING.md, etc.). The AI evaluation reads only the files the CLI found to judge whether the content is substantive — it does NOT search for files in other locations. This evaluation checks: diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index 127f021..f7d13cb 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -6,10 +6,13 @@ You are evaluating the governance and policy documentation of an MCP SDK reposit - **SDK path**: {local-path} (absolute path to local SDK checkout) - **Repository**: {repo} (GitHub `owner/repo`, derived from git remote) +- **CLI policy_signals**: {policy_signals_json} (from the tier-check CLI output — shows which files exist) ## Your Task -Check whether three required policy documents exist as files in the repository. This is a simple file-existence check — if the file exists and has substantive content, it passes. +The CLI has already determined which policy files exist in the repository. Your job is to **read and evaluate the content** of the files that were found. Do NOT search for files in other locations — only evaluate what the CLI reported as present. + +Three policy areas to evaluate: 1. **Dependency update policy** (required for Tier 1 and Tier 2) 2. **Roadmap** (Tier 1: published roadmap; Tier 2: published plan toward Tier 1) @@ -17,42 +20,38 @@ Check whether three required policy documents exist as files in the repository. ## Steps -### 1. Check for policy files +### 1. Identify which files exist from CLI output -```bash -# Dependency update policy -ls {local-path}/DEPENDENCY_POLICY.md {local-path}/docs/dependency-policy.md 2>/dev/null +From the `policy_signals.files` object in the CLI JSON output, note which files have `true` (exist) vs `false` (missing). -# Also check for automated dependency tooling as evidence -ls {local-path}/.github/dependabot.yml {local-path}/.github/renovate.json {local-path}/renovate.json 2>/dev/null +The CLI checks these files: -# Roadmap -ls {local-path}/ROADMAP.md {local-path}/docs/roadmap.md 2>/dev/null +**Dependency policy**: `DEPENDENCY_POLICY.md`, `docs/dependency-policy.md`, `.github/dependabot.yml`, `.github/renovate.json`, `renovate.json` -# Versioning / breaking change policy -ls {local-path}/VERSIONING.md {local-path}/docs/versioning.md {local-path}/BREAKING_CHANGES.md 2>/dev/null +**Roadmap**: `ROADMAP.md`, `docs/roadmap.md` -# Also check CONTRIBUTING.md and CHANGELOG.md for versioning sections -ls {local-path}/CONTRIBUTING.md {local-path}/CHANGELOG.md 2>/dev/null -``` +**Versioning**: `VERSIONING.md`, `docs/versioning.md`, `BREAKING_CHANGES.md` + +**General** (may contain relevant sections): `CONTRIBUTING.md` -### 2. Evaluate each policy area +### 2. Read and evaluate files that exist -For each area, check: -- Does a dedicated file exist? -- If no dedicated file, is there a clearly labeled section in CONTRIBUTING.md or README.md? -- Is the content substantive (not just a placeholder)? +For each file that the CLI reported as present, read its content at `{local-path}/{file}` and evaluate: + +- Is the content substantive (not just a placeholder title)? +- Does it meet the criteria below? + +**Do NOT** search the repo for policy information in other files. If the dedicated file doesn't exist, the policy is not published. ## Evaluation Criteria ### Dependency Update Policy **PASS** if any of these exist with substantive content: -- `DEPENDENCY_POLICY.md` or `docs/dependency-policy.md` -- A clearly labeled "Dependency Updates" or "Dependency Policy" section in `CONTRIBUTING.md` -- Configured Dependabot (`.github/dependabot.yml`) or Renovate (`.github/renovate.json`) — automated tooling counts as a published policy in practice +- `DEPENDENCY_POLICY.md` or `docs/dependency-policy.md` — must describe how and when dependencies are updated +- `.github/dependabot.yml` or `.github/renovate.json` or `renovate.json` — automated tooling counts as a published policy in practice -**FAIL** if none of the above exist. +**FAIL** if none of the above exist (per CLI output). ### Roadmap @@ -60,24 +59,22 @@ For each area, check: **PASS for Tier 2**: Same file exists with at least a plan toward Tier 1, or explanation for remaining at Tier 2. -**FAIL** if no roadmap file exists. GitHub milestones alone are not sufficient — there must be a file in the repo. +**FAIL** if no roadmap file exists (per CLI output). ### Versioning Policy **PASS for Tier 1** if any of these exist with substantive content: - `VERSIONING.md` or `docs/versioning.md` or `BREAKING_CHANGES.md` -- A clearly labeled "Versioning" or "Breaking Changes" section in `CONTRIBUTING.md` +- A clearly labeled "Versioning" or "Breaking Changes" section in `CONTRIBUTING.md` (only check if CONTRIBUTING.md exists per CLI output) -The content must describe: what constitutes a breaking change, how breaking changes are communicated, and the versioning scheme (SemVer or language-idiomatic equivalent). +The content must describe: what constitutes a breaking change, how breaking changes are communicated, and the versioning scheme. -**Not required for Tier 2** (only needs a stable release >= 1.0.0, checked separately). +**Not required for Tier 2.** -**FAIL** if no versioning documentation found. +**FAIL** if no versioning documentation found in the above files. ## Required Output Format -Produce your assessment in this exact format: - ```markdown ### Policy Evaluation Assessment @@ -88,13 +85,12 @@ Produce your assessment in this exact format: #### 1. Dependency Update Policy: {PASS/FAIL} -| File Checked | Exists? | Path | +| File | Exists (CLI) | Content Verdict | |---|---|---| -| DEPENDENCY_POLICY.md | Yes/No | {path} or N/A | -| docs/dependency-policy.md | Yes/No | {path} or N/A | -| .github/dependabot.yml | Yes/No | {path} or N/A | -| .github/renovate.json | Yes/No | {path} or N/A | -| CONTRIBUTING.md (dependency section) | Yes/No | {path}:{lines} or N/A | +| DEPENDENCY_POLICY.md | Yes/No | Substantive / Placeholder / N/A | +| docs/dependency-policy.md | Yes/No | Substantive / Placeholder / N/A | +| .github/dependabot.yml | Yes/No | Configured / N/A | +| .github/renovate.json | Yes/No | Configured / N/A | **Verdict**: **PASS/FAIL** — {one-line explanation} @@ -102,10 +98,10 @@ Produce your assessment in this exact format: #### 2. Roadmap: {PASS/FAIL} -| File Checked | Exists? | Path | +| File | Exists (CLI) | Content Verdict | |---|---|---| -| ROADMAP.md | Yes/No | {path} or N/A | -| docs/roadmap.md | Yes/No | {path} or N/A | +| ROADMAP.md | Yes/No | Substantive / Placeholder / N/A | +| docs/roadmap.md | Yes/No | Substantive / Placeholder / N/A | **Verdict**: - **Tier 1**: **PASS/FAIL** — {one-line explanation} @@ -115,12 +111,12 @@ Produce your assessment in this exact format: #### 3. Versioning Policy: {PASS/FAIL} -| File Checked | Exists? | Path | +| File | Exists (CLI) | Content Verdict | |---|---|---| -| VERSIONING.md | Yes/No | {path} or N/A | -| docs/versioning.md | Yes/No | {path} or N/A | -| BREAKING_CHANGES.md | Yes/No | {path} or N/A | -| CONTRIBUTING.md (versioning section) | Yes/No | {path}:{lines} or N/A | +| VERSIONING.md | Yes/No | Substantive / Placeholder / N/A | +| docs/versioning.md | Yes/No | Substantive / Placeholder / N/A | +| BREAKING_CHANGES.md | Yes/No | Substantive / Placeholder / N/A | +| CONTRIBUTING.md (versioning section) | Yes/No | Found / Not found / N/A | **Verdict**: - **Tier 1**: **PASS/FAIL** — {one-line explanation} @@ -139,7 +135,7 @@ Produce your assessment in this exact format: ## Important Notes -- This is primarily a file-existence check. If the file exists and has real content (not just a title), it passes. -- Do NOT search through the entire repo looking for scattered references. The policy must be in a dedicated file or a clearly labeled section in CONTRIBUTING.md. -- Dependabot/Renovate configuration counts as a dependency policy — it's a published, machine-readable commitment. -- CHANGELOG.md showing past releases does NOT count as a roadmap (it's backward-looking, not forward-looking). +- Only evaluate files the CLI reported as existing. Do not search the repo for alternatives. +- If a file exists but is just a placeholder (e.g., only has a title with no content), mark it as "Placeholder" and FAIL. +- Dependabot/Renovate config files pass automatically if they exist and are properly configured. +- CHANGELOG.md showing past releases does NOT count as a roadmap. diff --git a/src/tier-check/checks/files.ts b/src/tier-check/checks/files.ts index 4cd7bd4..1fd768d 100644 --- a/src/tier-check/checks/files.ts +++ b/src/tier-check/checks/files.ts @@ -1,15 +1,28 @@ import { Octokit } from '@octokit/rest'; import { PolicySignalsResult } from '../types'; -// These files are evidence for policy evaluation, not hard tier requirements. -// Their presence/absence feeds into the overall assessment but does not -// independently block tier advancement. +// Policy files checked deterministically by the CLI. +// The AI policy evaluation then reads ONLY files that exist here +// to judge whether content is substantive — it does not search for +// files in other locations. const POLICY_SIGNAL_FILES = [ + // General project health 'CHANGELOG.md', 'SECURITY.md', 'CONTRIBUTING.md', + // Dependency update policy + 'DEPENDENCY_POLICY.md', + 'docs/dependency-policy.md', '.github/dependabot.yml', - 'ROADMAP.md' + '.github/renovate.json', + 'renovate.json', + // Roadmap + 'ROADMAP.md', + 'docs/roadmap.md', + // Versioning / breaking change policy + 'VERSIONING.md', + 'docs/versioning.md', + 'BREAKING_CHANGES.md' ]; export async function checkPolicySignals( From f5beda8aff89eac5c5a2299dfe832463b2f0af0b Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 16:23:54 +0000 Subject: [PATCH 24/34] style: apply prettier formatting --- .claude/skills/mcp-sdk-tier-audit/README.md | 40 +++--- .../references/docs-coverage-prompt.md | 16 +-- .../references/feature-list.md | 122 +++++++++--------- .../references/policy-evaluation-prompt.md | 36 +++--- src/tier-check/checks/conformance.ts | 17 ++- src/tier-check/index.ts | 94 ++++++++------ 6 files changed, 168 insertions(+), 157 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index e770112..632b385 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -50,16 +50,16 @@ For public repos, any authenticated token works (no special scopes needed — au ### What the CLI Checks -| Check | What it measures | -| ------------------- | ------------------------------------------------------------------------------ | -| Server Conformance | Pass rate of server implementation against the conformance test suite | -| Client Conformance | Pass rate of client implementation against the conformance test suite | -| Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | -| Triage | How quickly issues get labeled after creation | -| P0 Resolution | Whether critical bugs are resolved within SLA | -| Stable Release | Whether a stable release >= 1.0.0 exists | -| Policy Signals | Presence of CHANGELOG, SECURITY, CONTRIBUTING, dependabot, ROADMAP | -| Spec Tracking | Gap between latest spec release and SDK release | +| Check | What it measures | +| ------------------ | ------------------------------------------------------------------------------ | +| Server Conformance | Pass rate of server implementation against the conformance test suite | +| Client Conformance | Pass rate of client implementation against the conformance test suite | +| Labels | Whether SEP-1730 label taxonomy is set up (supports GitHub native issue types) | +| Triage | How quickly issues get labeled after creation | +| P0 Resolution | Whether critical bugs are resolved within SLA | +| Stable Release | Whether a stable release >= 1.0.0 exists | +| Policy Signals | Presence of CHANGELOG, SECURITY, CONTRIBUTING, dependabot, ROADMAP | +| Spec Tracking | Gap between latest spec release and SDK release | ### Example Output @@ -147,16 +147,16 @@ If you use a different agent (Codex, Cursor, Aider, OpenCode, etc.), give it the Run the CLI for the scorecard, then review docs and policies yourself using the tier requirements as a checklist: -| Requirement | Tier 1 | Tier 2 | -| ---------------------- | ------------------------------ | ------------------------ | -| Server Conformance | 100% pass | >= 80% pass | -| Client Conformance | 100% pass | >= 80% pass | -| Issue triage | Within 2 business days | Within 1 month | -| P0 resolution | Within 7 days | Within 2 weeks | -| Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | -| Documentation | All features with examples | Core features documented | -| Dependency policy | Published | Published | -| Roadmap | Published with spec tracking | Plan toward Tier 1 | +| Requirement | Tier 1 | Tier 2 | +| ------------------ | ------------------------------ | ------------------------ | +| Server Conformance | 100% pass | >= 80% pass | +| Client Conformance | 100% pass | >= 80% pass | +| Issue triage | Within 2 business days | Within 1 month | +| P0 resolution | Within 7 days | Within 2 weeks | +| Stable release | >= 1.0.0 with clear versioning | At least one >= 1.0.0 | +| Documentation | All features with examples | Core features documented | +| Dependency policy | Published | Published | +| Roadmap | Published with spec tracking | Plan toward Tier 1 | ## Running Conformance Tests diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index ea0901c..8e7beb8 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -70,14 +70,14 @@ Produce your assessment in this exact format: One row per feature from `references/feature-list.md`. Use the exact feature numbers and names from that file. -| # | Feature | Documented? | Where | Has Examples? | Verdict | -|---|---------|-------------|-------|---------------|---------| -| 1 | Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| 2 | Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| ... | ... | ... | ... | ... | ... | -| 48 | JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | -| — | Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | -| ... | ... | ... | ... | ... | ... | +| # | Feature | Documented? | Where | Has Examples? | Verdict | +| --- | -------------------------- | ----------- | -------------- | ----------------------- | ----------------- | +| 1 | Tools - listing | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| 2 | Tools - calling | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| ... | ... | ... | ... | ... | ... | +| 48 | JSON Schema 2020-12 | Yes/No | {file}:{lines} | Yes ({N} examples) / No | PASS/PARTIAL/FAIL | +| — | Tasks - get (experimental) | Yes/No | {file}:{lines} | Yes ({N} examples) / No | INFO | +| ... | ... | ... | ... | ... | ... | All 48 non-experimental features MUST appear in the table. Do not skip or merge rows. diff --git a/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md b/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md index eff6189..b0e019a 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/feature-list.md @@ -8,73 +8,73 @@ When updating this list, also update the total count referenced in `docs-coverag ### Core Features (36) -| # | Feature | Protocol Method | -|---|---------|-----------------| -| 1 | Tools - listing | `tools/list` | -| 2 | Tools - calling | `tools/call` | -| 3 | Tools - text results | | -| 4 | Tools - image results | | -| 5 | Tools - audio results | | -| 6 | Tools - embedded resources | | -| 7 | Tools - error handling | | -| 8 | Tools - change notifications | `notifications/tools/list_changed` | -| 9 | Resources - listing | `resources/list` | -| 10 | Resources - reading text | `resources/read` | -| 11 | Resources - reading binary | `resources/read` | -| 12 | Resources - templates | `resources/templates/list` | -| 13 | Resources - template reading | | -| 14 | Resources - subscribing | `resources/subscribe` | -| 15 | Resources - unsubscribing | `resources/unsubscribe` | -| 16 | Resources - change notifications | `notifications/resources/list_changed` | -| 17 | Prompts - listing | `prompts/list` | -| 18 | Prompts - getting simple | `prompts/get` | -| 19 | Prompts - getting with arguments | `prompts/get` | -| 20 | Prompts - embedded resources | | -| 21 | Prompts - image content | | -| 22 | Prompts - change notifications | `notifications/prompts/list_changed` | -| 23 | Sampling - creating messages | `sampling/createMessage` | -| 24 | Elicitation - form mode | `elicitation/create` | -| 25 | Elicitation - URL mode | `elicitation/create` (mode: "url") | -| 26 | Elicitation - schema validation | | -| 27 | Elicitation - default values | | -| 28 | Elicitation - enum values | | -| 29 | Elicitation - complete notification | `notifications/elicitation/complete` | -| 30 | Roots - listing | `roots/list` | -| 31 | Roots - change notifications | `notifications/roots/list_changed` | -| 32 | Logging - sending log messages | `notifications/message` | -| 33 | Logging - setting level | `logging/setLevel` | -| 34 | Completions - resource argument | `completion/complete` | -| 35 | Completions - prompt argument | `completion/complete` | -| 36 | Ping | `ping` | +| # | Feature | Protocol Method | +| --- | ----------------------------------- | -------------------------------------- | +| 1 | Tools - listing | `tools/list` | +| 2 | Tools - calling | `tools/call` | +| 3 | Tools - text results | | +| 4 | Tools - image results | | +| 5 | Tools - audio results | | +| 6 | Tools - embedded resources | | +| 7 | Tools - error handling | | +| 8 | Tools - change notifications | `notifications/tools/list_changed` | +| 9 | Resources - listing | `resources/list` | +| 10 | Resources - reading text | `resources/read` | +| 11 | Resources - reading binary | `resources/read` | +| 12 | Resources - templates | `resources/templates/list` | +| 13 | Resources - template reading | | +| 14 | Resources - subscribing | `resources/subscribe` | +| 15 | Resources - unsubscribing | `resources/unsubscribe` | +| 16 | Resources - change notifications | `notifications/resources/list_changed` | +| 17 | Prompts - listing | `prompts/list` | +| 18 | Prompts - getting simple | `prompts/get` | +| 19 | Prompts - getting with arguments | `prompts/get` | +| 20 | Prompts - embedded resources | | +| 21 | Prompts - image content | | +| 22 | Prompts - change notifications | `notifications/prompts/list_changed` | +| 23 | Sampling - creating messages | `sampling/createMessage` | +| 24 | Elicitation - form mode | `elicitation/create` | +| 25 | Elicitation - URL mode | `elicitation/create` (mode: "url") | +| 26 | Elicitation - schema validation | | +| 27 | Elicitation - default values | | +| 28 | Elicitation - enum values | | +| 29 | Elicitation - complete notification | `notifications/elicitation/complete` | +| 30 | Roots - listing | `roots/list` | +| 31 | Roots - change notifications | `notifications/roots/list_changed` | +| 32 | Logging - sending log messages | `notifications/message` | +| 33 | Logging - setting level | `logging/setLevel` | +| 34 | Completions - resource argument | `completion/complete` | +| 35 | Completions - prompt argument | `completion/complete` | +| 36 | Ping | `ping` | ### Transport Features (6) -| # | Feature | -|---|---------| -| 37 | Streamable HTTP transport (client) | -| 38 | Streamable HTTP transport (server) | -| 39 | SSE transport - legacy (client) | -| 40 | SSE transport - legacy (server) | -| 41 | stdio transport (client) | -| 42 | stdio transport (server) | +| # | Feature | +| --- | ---------------------------------- | +| 37 | Streamable HTTP transport (client) | +| 38 | Streamable HTTP transport (server) | +| 39 | SSE transport - legacy (client) | +| 40 | SSE transport - legacy (server) | +| 41 | stdio transport (client) | +| 42 | stdio transport (server) | ### Protocol Features (6) -| # | Feature | -|---|---------| -| 43 | Progress notifications | -| 44 | Cancellation | -| 45 | Pagination | -| 46 | Capability negotiation | -| 47 | Protocol version negotiation | -| 48 | JSON Schema 2020-12 support | +| # | Feature | +| --- | ---------------------------- | +| 43 | Progress notifications | +| 44 | Cancellation | +| 45 | Pagination | +| 46 | Capability negotiation | +| 47 | Protocol version negotiation | +| 48 | JSON Schema 2020-12 support | ## Experimental Features (5, informational only) -| # | Feature | Protocol Method | -|---|---------|-----------------| -| — | Tasks - get | `tasks/get` | -| — | Tasks - result | `tasks/result` | -| — | Tasks - cancel | `tasks/cancel` | -| — | Tasks - list | `tasks/list` | -| — | Tasks - status notifications | `notifications/tasks/status` | +| # | Feature | Protocol Method | +| --- | ---------------------------- | ---------------------------- | +| — | Tasks - get | `tasks/get` | +| — | Tasks - result | `tasks/result` | +| — | Tasks - cancel | `tasks/cancel` | +| — | Tasks - list | `tasks/list` | +| — | Tasks - status notifications | `notifications/tasks/status` | diff --git a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md index f7d13cb..b3960e6 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/policy-evaluation-prompt.md @@ -48,6 +48,7 @@ For each file that the CLI reported as present, read its content at `{local-path ### Dependency Update Policy **PASS** if any of these exist with substantive content: + - `DEPENDENCY_POLICY.md` or `docs/dependency-policy.md` — must describe how and when dependencies are updated - `.github/dependabot.yml` or `.github/renovate.json` or `renovate.json` — automated tooling counts as a published policy in practice @@ -64,6 +65,7 @@ For each file that the CLI reported as present, read its content at `{local-path ### Versioning Policy **PASS for Tier 1** if any of these exist with substantive content: + - `VERSIONING.md` or `docs/versioning.md` or `BREAKING_CHANGES.md` - A clearly labeled "Versioning" or "Breaking Changes" section in `CONTRIBUTING.md` (only check if CONTRIBUTING.md exists per CLI output) @@ -85,12 +87,12 @@ The content must describe: what constitutes a breaking change, how breaking chan #### 1. Dependency Update Policy: {PASS/FAIL} -| File | Exists (CLI) | Content Verdict | -|---|---|---| -| DEPENDENCY_POLICY.md | Yes/No | Substantive / Placeholder / N/A | -| docs/dependency-policy.md | Yes/No | Substantive / Placeholder / N/A | -| .github/dependabot.yml | Yes/No | Configured / N/A | -| .github/renovate.json | Yes/No | Configured / N/A | +| File | Exists (CLI) | Content Verdict | +| ------------------------- | ------------ | ------------------------------- | +| DEPENDENCY_POLICY.md | Yes/No | Substantive / Placeholder / N/A | +| docs/dependency-policy.md | Yes/No | Substantive / Placeholder / N/A | +| .github/dependabot.yml | Yes/No | Configured / N/A | +| .github/renovate.json | Yes/No | Configured / N/A | **Verdict**: **PASS/FAIL** — {one-line explanation} @@ -98,12 +100,13 @@ The content must describe: what constitutes a breaking change, how breaking chan #### 2. Roadmap: {PASS/FAIL} -| File | Exists (CLI) | Content Verdict | -|---|---|---| -| ROADMAP.md | Yes/No | Substantive / Placeholder / N/A | -| docs/roadmap.md | Yes/No | Substantive / Placeholder / N/A | +| File | Exists (CLI) | Content Verdict | +| --------------- | ------------ | ------------------------------- | +| ROADMAP.md | Yes/No | Substantive / Placeholder / N/A | +| docs/roadmap.md | Yes/No | Substantive / Placeholder / N/A | **Verdict**: + - **Tier 1**: **PASS/FAIL** — {one-line explanation} - **Tier 2**: **PASS/FAIL** — {one-line explanation} @@ -111,14 +114,15 @@ The content must describe: what constitutes a breaking change, how breaking chan #### 3. Versioning Policy: {PASS/FAIL} -| File | Exists (CLI) | Content Verdict | -|---|---|---| -| VERSIONING.md | Yes/No | Substantive / Placeholder / N/A | -| docs/versioning.md | Yes/No | Substantive / Placeholder / N/A | -| BREAKING_CHANGES.md | Yes/No | Substantive / Placeholder / N/A | -| CONTRIBUTING.md (versioning section) | Yes/No | Found / Not found / N/A | +| File | Exists (CLI) | Content Verdict | +| ------------------------------------ | ------------ | ------------------------------- | +| VERSIONING.md | Yes/No | Substantive / Placeholder / N/A | +| docs/versioning.md | Yes/No | Substantive / Placeholder / N/A | +| BREAKING_CHANGES.md | Yes/No | Substantive / Placeholder / N/A | +| CONTRIBUTING.md (versioning section) | Yes/No | Found / Not found / N/A | **Verdict**: + - **Tier 1**: **PASS/FAIL** — {one-line explanation} - **Tier 2**: **N/A** — only requires stable release diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index bf4599e..2a44382 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -161,21 +161,20 @@ export async function checkClientConformance(options: { for (const scenarioName of scenarios) { try { const result = await withTimeout( - runConformanceTest(options.clientCmd, scenarioName, SCENARIO_TIMEOUT_MS), + runConformanceTest( + options.clientCmd, + scenarioName, + SCENARIO_TIMEOUT_MS + ), SCENARIO_TIMEOUT_MS + 5_000, // extra buffer beyond the inner timeout scenarioName ); - const passed = result.checks.filter( - (c) => c.status === 'SUCCESS' - ).length; - const failed = result.checks.filter( - (c) => c.status === 'FAILURE' - ).length; + const passed = result.checks.filter((c) => c.status === 'SUCCESS').length; + const failed = result.checks.filter((c) => c.status === 'FAILURE').length; // A non-zero exit code counts as a failure unless the scenario expects it const clientFailed = - !result.allowClientError && - result.clientOutput.exitCode !== 0; + !result.allowClientError && result.clientOutput.exitCode !== 0; const scenarioPassed = failed === 0 && passed > 0 && !clientFailed; totalPassed += scenarioPassed ? 1 : 0; diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index b9b155a..ea23994 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -80,49 +80,57 @@ export function createTierCheckCommand(): Command { console.error('Running tier assessment checks...\n'); // Run all checks - const [conformance, clientConformance, labels, triage, p0, release, files, specTracking] = - await Promise.all([ - checkConformance({ - serverCmd: options.conformanceServerCmd, - serverCwd: options.conformanceServerCwd, - serverUrl: options.conformanceServerUrl, - skip: options.skipConformance - }).then((r) => { - console.error(' ✓ Server Conformance'); - return r; - }), - checkClientConformance({ - clientCmd: options.clientCmd, - skip: options.skipConformance || !options.clientCmd - }).then((r) => { - console.error(' ✓ Client Conformance'); - return r; - }), - checkLabels(octokit, owner, repo).then((r) => { - console.error(' ✓ Labels'); - return r; - }), - checkTriage(octokit, owner, repo, days).then((r) => { - console.error(' \u2713 Triage'); - return r; - }), - checkP0Resolution(octokit, owner, repo).then((r) => { - console.error(' \u2713 P0 Resolution'); - return r; - }), - checkStableRelease(octokit, owner, repo).then((r) => { - console.error(' \u2713 Stable Release'); - return r; - }), - checkPolicySignals(octokit, owner, repo, options.branch).then((r) => { - console.error(' \u2713 Policy Signals'); - return r; - }), - checkSpecTracking(octokit, owner, repo).then((r) => { - console.error(' \u2713 Spec Tracking'); - return r; - }) - ]); + const [ + conformance, + clientConformance, + labels, + triage, + p0, + release, + files, + specTracking + ] = await Promise.all([ + checkConformance({ + serverCmd: options.conformanceServerCmd, + serverCwd: options.conformanceServerCwd, + serverUrl: options.conformanceServerUrl, + skip: options.skipConformance + }).then((r) => { + console.error(' ✓ Server Conformance'); + return r; + }), + checkClientConformance({ + clientCmd: options.clientCmd, + skip: options.skipConformance || !options.clientCmd + }).then((r) => { + console.error(' ✓ Client Conformance'); + return r; + }), + checkLabels(octokit, owner, repo).then((r) => { + console.error(' ✓ Labels'); + return r; + }), + checkTriage(octokit, owner, repo, days).then((r) => { + console.error(' \u2713 Triage'); + return r; + }), + checkP0Resolution(octokit, owner, repo).then((r) => { + console.error(' \u2713 P0 Resolution'); + return r; + }), + checkStableRelease(octokit, owner, repo).then((r) => { + console.error(' \u2713 Stable Release'); + return r; + }), + checkPolicySignals(octokit, owner, repo, options.branch).then((r) => { + console.error(' \u2713 Policy Signals'); + return r; + }), + checkSpecTracking(octokit, owner, repo).then((r) => { + console.error(' \u2713 Spec Tracking'); + return r; + }) + ]); const checks = { conformance, From d55be402e7be38007e5c8e51b96f043a1881b586 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Wed, 11 Feb 2026 16:29:08 +0000 Subject: [PATCH 25/34] revert: undo unrelated console.log change in runner/server.ts --- src/runner/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/server.ts b/src/runner/server.ts index 9e67d16..a7d8449 100644 --- a/src/runner/server.ts +++ b/src/runner/server.ts @@ -36,7 +36,7 @@ export async function runServerConformanceTest( // Scenario is guaranteed to exist by CLI validation const scenario = getClientScenario(scenarioName)!; - console.error( + console.log( `Running client scenario '${scenarioName}' against server: ${serverUrl}` ); From 771adf5e6cd07116b3b2c7d96e58b806e563dcb6 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 14:48:39 +0000 Subject: [PATCH 26/34] 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. --- .claude/skills/mcp-sdk-tier-audit/README.md | 4 +- src/tier-check/checks/conformance.ts | 256 ++++++++------------ src/tier-check/index.ts | 11 +- 3 files changed, 102 insertions(+), 169 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 632b385..30ca0c9 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -39,9 +39,7 @@ For public repos, any authenticated token works (no special scopes needed — au --repo GitHub repository (required) --branch Branch to check --skip-conformance Skip conformance tests ---conformance-server-url URL of the running conformance server ---conformance-server-cmd Command to start the conformance server (optional, prefer pre-starting) ---conformance-server-cwd Working directory for the conformance server command +--conformance-server-url URL of the already-running conformance server --client-cmd Command to run the SDK conformance client (for client conformance tests) --days Limit triage analysis to last N days --output json | markdown | terminal (default: terminal) diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/conformance.ts index 2a44382..e47d567 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/conformance.ts @@ -1,150 +1,27 @@ -import { spawn, ChildProcess } from 'child_process'; -import { listActiveClientScenarios, listCoreScenarios } from '../../scenarios'; -import { runServerConformanceTest, runConformanceTest } from '../../runner'; +import { execSync } from 'child_process'; +import { mkdtempSync, readFileSync, readdirSync, existsSync } from 'fs'; +import { join } from 'path'; +import { tmpdir } from 'os'; import { ConformanceResult } from '../types'; -async function waitForServer( - url: string, - timeoutMs: number = 30000 -): Promise { - const start = Date.now(); - while (Date.now() - start < timeoutMs) { - try { - await fetch(url, { method: 'GET' }); - // Any HTTP response means the server is listening (400, 405, etc. are all valid) - return; - } catch { - // server not ready yet - } - await new Promise((r) => setTimeout(r, 1000)); - } - throw new Error( - `Server at ${url} did not become ready within ${timeoutMs}ms` - ); -} - -const SCENARIO_TIMEOUT_MS = 30_000; - -async function withTimeout( - promise: Promise, - ms: number, - label: string -): Promise { - let timer: ReturnType; - const timeout = new Promise((_, reject) => { - timer = setTimeout( - () => reject(new Error(`${label}: timed out after ${ms}ms`)), - ms - ); - }); - try { - return await Promise.race([promise, timeout]); - } finally { - clearTimeout(timer!); - } -} - -export async function checkConformance(options: { - serverCmd?: string; - serverCwd?: string; - serverUrl?: string; - skip?: boolean; -}): Promise { - if (options.skip || !options.serverUrl) { - return { - status: 'skipped', - pass_rate: 0, - passed: 0, - failed: 0, - total: 0, - details: [] - }; - } - - let serverProcess: ChildProcess | undefined; - try { - // Spawn server if a command was provided; otherwise assume it's already running - if (options.serverCmd) { - const [cmd, ...args] = options.serverCmd.split(' '); - serverProcess = spawn(cmd, args, { - cwd: options.serverCwd || process.cwd(), - stdio: 'pipe', - shell: true - }); - } - - // Wait for server to be ready - await waitForServer(options.serverUrl); - - // Run all active scenarios - const scenarios = listActiveClientScenarios(); - const details: ConformanceResult['details'] = []; - let totalPassed = 0; - let totalFailed = 0; - - for (const scenarioName of scenarios) { - try { - const result = await withTimeout( - runServerConformanceTest(options.serverUrl, scenarioName), - SCENARIO_TIMEOUT_MS, - scenarioName - ); - const passed = result.checks.filter( - (c) => c.status === 'SUCCESS' - ).length; - const failed = result.checks.filter( - (c) => c.status === 'FAILURE' - ).length; - totalPassed += passed > 0 && failed === 0 ? 1 : 0; - totalFailed += failed > 0 ? 1 : 0; - details.push({ - scenario: scenarioName, - passed: failed === 0, - checks_passed: passed, - checks_failed: failed - }); - } catch { - totalFailed++; - details.push({ - scenario: scenarioName, - passed: false, - checks_passed: 0, - checks_failed: 1 - }); - } - } - - const total = totalPassed + totalFailed; - const pass_rate = total > 0 ? totalPassed / total : 0; - - return { - status: pass_rate >= 1.0 ? 'pass' : pass_rate >= 0.8 ? 'partial' : 'fail', - pass_rate, - passed: totalPassed, - failed: totalFailed, - total, - details - }; - } finally { - if (serverProcess) { - serverProcess.kill('SIGTERM'); - // Give it a moment, then force kill - setTimeout(() => serverProcess?.kill('SIGKILL'), 5000); - } - } +interface ConformanceCheck { + name: string; + status: 'SUCCESS' | 'FAILURE' | 'WARNING'; + description?: string; + errorMessage?: string; } /** - * Run client conformance tests — the conformance tool acts as a server and - * spawns the SDK's conformance client to validate client-side behaviour. + * Parse conformance results from an output directory. + * The conformance CLI saves checks.json per scenario under outputDir//server/ or client/. */ -export async function checkClientConformance(options: { - clientCmd?: string; - skip?: boolean; -}): Promise { - if (options.skip || !options.clientCmd) { +function parseOutputDir( + outputDir: string, + mode: 'server' | 'client' +): ConformanceResult { + if (!existsSync(outputDir)) { return { - status: 'skipped', + status: 'fail', pass_rate: 0, passed: 0, failed: 0, @@ -153,30 +30,23 @@ export async function checkClientConformance(options: { }; } - const scenarios = listCoreScenarios(); const details: ConformanceResult['details'] = []; let totalPassed = 0; let totalFailed = 0; - for (const scenarioName of scenarios) { + const entries = readdirSync(outputDir); + for (const scenarioName of entries) { + const checksPath = join(outputDir, scenarioName, mode, 'checks.json'); + if (!existsSync(checksPath)) continue; + try { - const result = await withTimeout( - runConformanceTest( - options.clientCmd, - scenarioName, - SCENARIO_TIMEOUT_MS - ), - SCENARIO_TIMEOUT_MS + 5_000, // extra buffer beyond the inner timeout - scenarioName + const checks: ConformanceCheck[] = JSON.parse( + readFileSync(checksPath, 'utf-8') ); - const passed = result.checks.filter((c) => c.status === 'SUCCESS').length; - const failed = result.checks.filter((c) => c.status === 'FAILURE').length; + const passed = checks.filter((c) => c.status === 'SUCCESS').length; + const failed = checks.filter((c) => c.status === 'FAILURE').length; + const scenarioPassed = failed === 0 && passed > 0; - // A non-zero exit code counts as a failure unless the scenario expects it - const clientFailed = - !result.allowClientError && result.clientOutput.exitCode !== 0; - - const scenarioPassed = failed === 0 && passed > 0 && !clientFailed; totalPassed += scenarioPassed ? 1 : 0; totalFailed += scenarioPassed ? 0 : 1; details.push({ @@ -208,3 +78,75 @@ export async function checkClientConformance(options: { details }; } + +/** + * Run server conformance tests by shelling out to the conformance CLI. + */ +export async function checkConformance(options: { + serverUrl?: string; + skip?: boolean; +}): Promise { + if (options.skip || !options.serverUrl) { + return { + status: 'skipped', + pass_rate: 0, + passed: 0, + failed: 0, + total: 0, + details: [] + }; + } + + const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-server-')); + + try { + execSync( + `node dist/index.js server --url ${options.serverUrl} -o ${outputDir}`, + { + cwd: process.cwd(), + stdio: ['pipe', 'pipe', 'pipe'], + timeout: 120_000 + } + ); + } catch { + // Non-zero exit is expected when tests fail — results are still in outputDir + } + + return parseOutputDir(outputDir, 'server'); +} + +/** + * Run client conformance tests by shelling out to the conformance CLI. + */ +export async function checkClientConformance(options: { + clientCmd?: string; + skip?: boolean; +}): Promise { + if (options.skip || !options.clientCmd) { + return { + status: 'skipped', + pass_rate: 0, + passed: 0, + failed: 0, + total: 0, + details: [] + }; + } + + const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-client-')); + + try { + execSync( + `node dist/index.js client --command '${options.clientCmd}' --suite all -o ${outputDir}`, + { + cwd: process.cwd(), + stdio: ['pipe', 'pipe', 'pipe'], + timeout: 120_000 + } + ); + } catch { + // Non-zero exit is expected when tests fail — results are still in outputDir + } + + return parseOutputDir(outputDir, 'client'); +} diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index ea23994..7846e4c 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -27,14 +27,9 @@ export function createTierCheckCommand(): Command { ) .option('--branch ', 'Branch to check') .option( - '--conformance-server-cmd ', - 'Command to start the conformance server' + '--conformance-server-url ', + 'URL of the already-running conformance server' ) - .option( - '--conformance-server-cwd ', - 'Working directory for the conformance server' - ) - .option('--conformance-server-url ', 'URL of the conformance server') .option( '--client-cmd ', 'Command to run the SDK conformance client (for client conformance tests)' @@ -91,8 +86,6 @@ export function createTierCheckCommand(): Command { specTracking ] = await Promise.all([ checkConformance({ - serverCmd: options.conformanceServerCmd, - serverCwd: options.conformanceServerCwd, serverUrl: options.conformanceServerUrl, skip: options.skipConformance }).then((r) => { From 4606e0dc0236f91b9b2f603e49401ff4139270c1 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 15:08:42 +0000 Subject: [PATCH 27/34] docs: add Go and C# SDK examples to README and SKILL.md --- .claude/skills/mcp-sdk-tier-audit/README.md | 55 ++++++++++++++++++++- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 8 ++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index 30ca0c9..fa75c89 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -121,6 +121,29 @@ uv run mcp-everything-server --port 3001 /mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp "uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py" ``` +**Go SDK example:** + +```bash +# Terminal 1: build and start the everything server +cd ~/src/mcp/go-sdk && go build -o /tmp/go-conformance-server ./conformance/everything-server +go build -o /tmp/go-conformance-client ./conformance/everything-client +/tmp/go-conformance-server -http="localhost:3002" + +# Terminal 2: run the audit (from the conformance repo) +/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002 "/tmp/go-conformance-client" +``` + +**C# SDK example:** + +```bash +# Terminal 1: start the everything server (requires .NET SDK) +cd ~/src/mcp/csharp-sdk +dotnet run --project tests/ModelContextProtocol.ConformanceServer -- --urls http://localhost:3003 + +# Terminal 2: run the audit (from the conformance repo) +/mcp-sdk-tier-audit ~/src/mcp/csharp-sdk http://localhost:3003 "dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient" +``` + The skill derives `owner/repo` from git remote, runs the CLI, launches parallel evaluations for docs and policy, and writes detailed reports to `results/`. ### Any Other AI Coding Agent @@ -189,7 +212,37 @@ npm run --silent tier-check -- \ --client-cmd 'uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py' ``` -**Other SDKs:** Your SDK needs an "everything server" — an HTTP server at `/mcp` implementing the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/draft/basic/transports.md) with all MCP features (tools, resources, prompts, etc.). See the [TypeScript](https://github.com/modelcontextprotocol/typescript-sdk/tree/v1.x/test/conformance) or [Python](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x/examples/servers/everything-server) implementations as reference. +**Go SDK**: + +```bash +# Terminal 1: build and start the server +cd ~/src/mcp/go-sdk +go build -o /tmp/go-conformance-server ./conformance/everything-server +go build -o /tmp/go-conformance-client ./conformance/everything-client +/tmp/go-conformance-server -http="localhost:3002" + +# Terminal 2: run tier-check (server + client conformance) +npm run --silent tier-check -- \ + --repo modelcontextprotocol/go-sdk \ + --conformance-server-url http://localhost:3002 \ + --client-cmd '/tmp/go-conformance-client' +``` + +**C# SDK**: + +```bash +# Terminal 1: start the server (requires .NET SDK) +cd ~/src/mcp/csharp-sdk +dotnet run --project tests/ModelContextProtocol.ConformanceServer -- --urls http://localhost:3003 + +# Terminal 2: run tier-check (server + client conformance) +npm run --silent tier-check -- \ + --repo modelcontextprotocol/csharp-sdk \ + --conformance-server-url http://localhost:3003 \ + --client-cmd 'dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient' +``` + +**Other SDKs:** Your SDK needs an "everything server" — an HTTP server implementing the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/draft/basic/transports.md) with all MCP features (tools, resources, prompts, etc.). See the implementations above as reference. Start your everything server, then pass `--conformance-server-url`. Pass `--client-cmd` if your SDK has a conformance client. If neither exists yet, use `--skip-conformance` — the scorecard will note this as a gap. diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 5ba0342..026452e 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -232,6 +232,12 @@ Read these reference files when you need the detailed content for evaluation pro # Python SDK — server + client conformance /mcp-sdk-tier-audit ~/src/mcp/python-sdk http://localhost:3001/mcp "uv run python ~/src/mcp/python-sdk/.github/actions/conformance/client.py" +# Go SDK — server + client conformance +/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002 "/tmp/go-conformance-client" + +# C# SDK — server + client conformance +/mcp-sdk-tier-audit ~/src/mcp/csharp-sdk http://localhost:3003 "dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient" + # Any SDK — server conformance only (no client) -/mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002/mcp +/mcp-sdk-tier-audit ~/src/mcp/some-sdk http://localhost:3004 ``` From 4ac0834115525966cc2abbe5326a0ff4a3243b3b Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 15:48:17 +0000 Subject: [PATCH 28/34] fix: add --framework net9.0 to C# server command --- .claude/skills/mcp-sdk-tier-audit/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/README.md b/.claude/skills/mcp-sdk-tier-audit/README.md index fa75c89..77fc8cf 100644 --- a/.claude/skills/mcp-sdk-tier-audit/README.md +++ b/.claude/skills/mcp-sdk-tier-audit/README.md @@ -138,7 +138,7 @@ go build -o /tmp/go-conformance-client ./conformance/everything-client ```bash # Terminal 1: start the everything server (requires .NET SDK) cd ~/src/mcp/csharp-sdk -dotnet run --project tests/ModelContextProtocol.ConformanceServer -- --urls http://localhost:3003 +dotnet run --project tests/ModelContextProtocol.ConformanceServer --framework net9.0 -- --urls http://localhost:3003 # Terminal 2: run the audit (from the conformance repo) /mcp-sdk-tier-audit ~/src/mcp/csharp-sdk http://localhost:3003 "dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient" @@ -233,7 +233,7 @@ npm run --silent tier-check -- \ ```bash # Terminal 1: start the server (requires .NET SDK) cd ~/src/mcp/csharp-sdk -dotnet run --project tests/ModelContextProtocol.ConformanceServer -- --urls http://localhost:3003 +dotnet run --project tests/ModelContextProtocol.ConformanceServer --framework net9.0 -- --urls http://localhost:3003 # Terminal 2: run tier-check (server + client conformance) npm run --silent tier-check -- \ From d78d689d4b8b51e2baf4e5f27fb5b05c6c723872 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 16:02:36 +0000 Subject: [PATCH 29/34] 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. --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 35 +++++++++++++++++-- .../references/report-template.md | 28 +++++++++++++-- ...ormance.ts => test-conformance-results.ts} | 11 +++--- src/tier-check/index.ts | 5 ++- 4 files changed, 67 insertions(+), 12 deletions(-) rename src/tier-check/checks/{conformance.ts => test-conformance-results.ts} (93%) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 026452e..2954414 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -68,6 +68,16 @@ If no client-cmd was detected, omit the `--client-cmd` flag (client conformance The CLI output includes server conformance pass rate, client conformance pass rate, issue triage compliance, P0 resolution times, label taxonomy, stable release status, policy signal files, and spec tracking gap. Parse the JSON output to feed into Step 4. +### Conformance Baseline Check + +After running the CLI, check for an expected-failures baseline file in the SDK repo: + +```bash +find -name "baseline.yml" -o -name "expected-failures.yml" 2>/dev/null | head -5 +``` + +If found, read the file. It lists known/expected conformance failures. This context is essential for interpreting raw pass rates — a 20% client pass rate due entirely to unimplemented OAuth scenarios is very different from 20% due to broken core functionality. + ## Step 3: Launch Parallel Evaluations Launch 2 evaluations in parallel. Each reads the SDK from the local checkout path. @@ -133,6 +143,18 @@ If any Tier 2 requirement is not met, the SDK is Tier 3. - If GitHub issue labels are not set up per SEP-1730, triage metrics cannot be computed. Note this as a gap. However, repos may use GitHub's native issue types instead of type labels — the CLI checks for both. - If client conformance was skipped (no client command found), note this as a gap but do not block tier advancement based on it alone. +**Client Conformance Splits:** + +When reporting client conformance, always break results into three categories: + +1. **Core suite** — Non-auth scenarios (e.g. initialize, tools_call, elicitation, sse-retry) +2. **Auth suite** — OAuth/authorization scenarios (any scenario starting with `auth/`) +3. **Full suite** — All scenarios combined + +The **full suite** number is used for tier threshold checks. However, the core vs auth split provides essential context. Always present both numbers in the report. + +If the SDK has a `baseline.yml` or expected-failures file, note which failures are known/tracked vs. unexpected regressions. A low full-suite score where all failures are auth scenarios documented in the baseline is a scope gap (OAuth not yet implemented), not a quality problem — flag it accordingly in the assessment. + **P0 Label Audit Guidance:** When evaluating P0 metrics, flag potentially mislabeled P0 issues: @@ -178,7 +200,9 @@ After the subagents finish, output a short executive summary directly to the use | Check | Value | T2 | T1 | |-------|-------|----|----| | Server Conformance | / (%) | ✓/✗ | ✓/✗ | -| Client Conformance | / (%) | ✓/✗ | ✓/✗ | +| Client Conformance (full) | / (%) | ✓/✗ | ✓/✗ | +| — Core scenarios | / (%) | — | — | +| — Auth scenarios | / (%) | — | — | | Issue Triage | % (/) | ✓/✗ | ✓/✗ | | P0 Resolution | open | ✓/✗ | ✓/✗ | | Documentation | / features | ✓/✗ | ✓/✗ | @@ -187,6 +211,9 @@ After the subagents finish, output a short executive summary directly to the use | Versioning Policy | | N/A | ✓/✗ | | Stable Release | | ✓/✗ | ✓/✗ | +If a baseline file was found, add a note below the table: +> **Baseline**: {N} failures in `baseline.yml` ({list of categories, e.g. "18 auth scenarios"}). Core suite: {core_rate}%. + --- **High-Priority Fixes:** @@ -236,7 +263,11 @@ Read these reference files when you need the detailed content for evaluation pro /mcp-sdk-tier-audit ~/src/mcp/go-sdk http://localhost:3002 "/tmp/go-conformance-client" # C# SDK — server + client conformance -/mcp-sdk-tier-audit ~/src/mcp/csharp-sdk http://localhost:3003 "dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient" +# Two C#-specific requirements in the client-cmd: +# --framework net9.0 : required because the project targets net8.0/net9.0/net10.0 +# -- $MCP_CONFORMANCE_SCENARIO : the runner sets this env var and uses shell:true, so the +# shell expands it; dotnet passes [scenario, url] to the program +/mcp-sdk-tier-audit ~/src/mcp/csharp-sdk http://localhost:3003 "dotnet run --project ~/src/mcp/csharp-sdk/tests/ModelContextProtocol.ConformanceClient --framework net9.0 -- $MCP_CONFORMANCE_SCENARIO" # Any SDK — server conformance only (no client) /mcp-sdk-tier-audit ~/src/mcp/some-sdk http://localhost:3004 diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index fcd346a..dd1e512 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -22,7 +22,8 @@ Write two files to `results/` in the conformance repo: | # | Requirement | Tier 1 Standard | Tier 2 Standard | Current Value | T1? | T2? | Gap | | --- | ----------------------- | --------------------------------- | ---------------------------- | --------------------------------- | ----------- | ----------- | ------------------ | -| 1 | Conformance Tests | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 1a | Server Conformance | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 1b | Client Conformance | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 2 | Issue Triage | >= 90% within 2 biz days | >= 80% within 1 month | {compliance}% ({triaged}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 3 | Critical Bug Resolution | All P0s within 7 days | All P0s within 2 weeks | {open P0 count} open | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 4 | Stable Release | Required + clear versioning | At least one stable release | {version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | @@ -39,7 +40,7 @@ Write two files to `results/` in the conformance repo: --- -## Conformance Details +## Server Conformance Details Pass rate: {X}% ({passed}/{total}) @@ -50,6 +51,29 @@ Pass rate: {X}% ({passed}/{total}) --- +## Client Conformance Details + +Full suite pass rate: {X}% ({passed}/{total}) + +> **Suite breakdown**: Core: {core_pass}/{core_total} ({core_rate}%), Auth: {auth_pass}/{auth_total} ({auth_rate}%) +> **Baseline**: {N} known expected failures documented in `{baseline_file}` ({categories}) + +### Core Scenarios + +| Scenario | Status | Checks | +| -------- | ----------- | ---------------- | +| {name} | {PASS/FAIL} | {passed}/{total} | +| ... | ... | ... | + +### Auth Scenarios + +| Scenario | Status | Checks | Notes | +| -------- | ----------- | ---------------- | ----- | +| {name} | {PASS/FAIL} | {passed}/{total} | {in baseline? / unexpected} | +| ... | ... | ... | ... | + +--- + ## Issue Triage Details Analysis period: Last {N} issues diff --git a/src/tier-check/checks/conformance.ts b/src/tier-check/checks/test-conformance-results.ts similarity index 93% rename from src/tier-check/checks/conformance.ts rename to src/tier-check/checks/test-conformance-results.ts index e47d567..def0f1e 100644 --- a/src/tier-check/checks/conformance.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -15,10 +15,7 @@ interface ConformanceCheck { * Parse conformance results from an output directory. * The conformance CLI saves checks.json per scenario under outputDir//server/ or client/. */ -function parseOutputDir( - outputDir: string, - mode: 'server' | 'client' -): ConformanceResult { +function parseOutputDir(outputDir: string): ConformanceResult { if (!existsSync(outputDir)) { return { status: 'fail', @@ -36,7 +33,7 @@ function parseOutputDir( const entries = readdirSync(outputDir); for (const scenarioName of entries) { - const checksPath = join(outputDir, scenarioName, mode, 'checks.json'); + const checksPath = join(outputDir, scenarioName, 'checks.json'); if (!existsSync(checksPath)) continue; try { @@ -112,7 +109,7 @@ export async function checkConformance(options: { // Non-zero exit is expected when tests fail — results are still in outputDir } - return parseOutputDir(outputDir, 'server'); + return parseOutputDir(outputDir); } /** @@ -148,5 +145,5 @@ export async function checkClientConformance(options: { // Non-zero exit is expected when tests fail — results are still in outputDir } - return parseOutputDir(outputDir, 'client'); + return parseOutputDir(outputDir); } diff --git a/src/tier-check/index.ts b/src/tier-check/index.ts index 7846e4c..5416748 100644 --- a/src/tier-check/index.ts +++ b/src/tier-check/index.ts @@ -1,6 +1,9 @@ import { Command } from 'commander'; import { Octokit } from '@octokit/rest'; -import { checkConformance, checkClientConformance } from './checks/conformance'; +import { + checkConformance, + checkClientConformance +} from './checks/test-conformance-results'; import { checkLabels } from './checks/labels'; import { checkTriage } from './checks/triage'; import { checkP0Resolution } from './checks/p0'; From b70833411383751bb6f7743d0fa630fe408ebba7 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 16:23:19 +0000 Subject: [PATCH 30/34] style: prettier formatting --- .../skills/mcp-sdk-tier-audit/references/report-template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index dd1e512..3607fa5 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -67,10 +67,10 @@ Full suite pass rate: {X}% ({passed}/{total}) ### Auth Scenarios -| Scenario | Status | Checks | Notes | -| -------- | ----------- | ---------------- | ----- | +| Scenario | Status | Checks | Notes | +| -------- | ----------- | ---------------- | --------------------------- | | {name} | {PASS/FAIL} | {passed}/{total} | {in baseline? / unexpected} | -| ... | ... | ... | ... | +| ... | ... | ... | ... | --- From ba1591fd3508391abc5f60e978ffabf6ecbddb68 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 16:32:57 +0000 Subject: [PATCH 31/34] 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 --- .../checks/test-conformance-results.ts | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/tier-check/checks/test-conformance-results.ts b/src/tier-check/checks/test-conformance-results.ts index def0f1e..7f2d1be 100644 --- a/src/tier-check/checks/test-conformance-results.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -3,6 +3,7 @@ import { mkdtempSync, readFileSync, readdirSync, existsSync } from 'fs'; import { join } from 'path'; import { tmpdir } from 'os'; import { ConformanceResult } from '../types'; +import { listScenarios, listActiveClientScenarios } from '../../scenarios'; interface ConformanceCheck { name: string; @@ -76,6 +77,61 @@ function parseOutputDir(outputDir: string): ConformanceResult { }; } +/** + * Strip the timestamp suffix from a result directory name. + * Result dirs are named `{scenario}-{ISO timestamp}` where the timestamp + * has colons/dots replaced with dashes (e.g., `initialize-2026-02-12T16-08-37-806Z`). + * Server scenarios also have a `server-` prefix (e.g., `server-ping-2026-02-12T16-08-37-806Z`). + */ +function stripTimestamp(dirName: string): string { + return dirName.replace(/-\d{4}-\d{2}-\d{2}T[\d-]+Z$/, ''); +} + +/** + * Reconcile parsed results against the full list of expected scenarios. + * Any expected scenario that didn't produce results is counted as a failure. + * This ensures the denominator reflects the full test suite, not just + * scenarios that ran successfully enough to write checks.json. + */ +function reconcileWithExpected( + result: ConformanceResult, + expectedScenarios: string[], + resultPrefix?: string +): ConformanceResult { + const reportedNames = new Set( + result.details.map((d) => { + let name = stripTimestamp(d.scenario); + if (resultPrefix) { + name = name.replace(new RegExp(`^${resultPrefix}-`), ''); + } + return name; + }) + ); + + for (const expected of expectedScenarios) { + if (!reportedNames.has(expected)) { + result.failed++; + result.total++; + result.details.push({ + scenario: expected, + passed: false, + checks_passed: 0, + checks_failed: 0 + }); + } + } + + result.pass_rate = result.total > 0 ? result.passed / result.total : 0; + result.status = + result.pass_rate >= 1.0 + ? 'pass' + : result.pass_rate >= 0.8 + ? 'partial' + : 'fail'; + + return result; +} + /** * Run server conformance tests by shelling out to the conformance CLI. */ @@ -109,7 +165,11 @@ export async function checkConformance(options: { // Non-zero exit is expected when tests fail — results are still in outputDir } - return parseOutputDir(outputDir); + return reconcileWithExpected( + parseOutputDir(outputDir), + listActiveClientScenarios(), + 'server' + ); } /** @@ -145,5 +205,8 @@ export async function checkClientConformance(options: { // Non-zero exit is expected when tests fail — results are still in outputDir } - return parseOutputDir(outputDir); + return reconcileWithExpected( + parseOutputDir(outputDir), + listScenarios() + ); } From 1e1cfa4a3ea0d58114836621572a86b72c0e4dad Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 16:57:52 +0000 Subject: [PATCH 32/34] 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 --- .../references/docs-coverage-prompt.md | 36 ++++++++++++++++--- .../checks/test-conformance-results.ts | 5 +-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md index 8e7beb8..86bbcc5 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/docs-coverage-prompt.md @@ -102,10 +102,38 @@ All 48 non-experimental features MUST appear in the table. Do not skip or merge - {If FAIL: list the core features missing documentation} ``` -## Important Notes +## What Counts as "Documented" + +A feature is "documented" only if there is **prose documentation** (in README, docs/, or similar) explaining what the feature does, when to use it, and how it works. The following do **not** count as documentation on their own: + +- Example code without accompanying prose explanation +- Conformance test servers or test fixtures +- Source code, even with comments or docstrings +- Mere existence of an API (e.g., a function existing in the SDK) + +**Examples supplement documentation but do not replace it.** A feature with a working example in `examples/` but no prose explaining the feature is PARTIAL, not PASS. A feature with only a conformance server implementation and no user-facing docs is FAIL. + +### Verdict criteria + +- **PASS**: Prose documentation exists explaining the feature AND at least one runnable or near-runnable code example +- **PARTIAL**: Either prose docs exist but no examples, OR examples exist but no prose docs +- **FAIL**: No prose documentation and no examples. Also use FAIL if the feature is only demonstrated in test/conformance code with no user-facing docs or examples + +### What counts as an "example" + +- Runnable code in an `examples/` directory +- Code snippets embedded in prose documentation (README, docs/\*.md) +- Go `Example*` test functions (these render on pkg.go.dev and are a language convention) +- Examples in test files count only if they are clearly labeled as examples or referenced from documentation + +### What does NOT count as an example + +- Conformance test server implementations +- Internal test fixtures +- Source code of the SDK itself + +## Other Important Notes -- A feature is "documented" if there is prose or API reference explaining what it does and how to use it. Mere existence of source code does not count as documentation. -- "Has examples" means there is runnable or near-runnable code showing the feature in use. This can be in docs, README, or an examples/ directory. -- Examples in test files count only if they are clearly labeled as examples or referenced from documentation. - If the SDK does not implement a feature at all, mark it as "FAIL" for documentation but note "Not implemented" in the Where column. - Be thorough: check README, docs/, examples/, API references, and inline docstrings. +- Apply these criteria consistently across all features. Do not give credit for documentation that doesn't exist. diff --git a/src/tier-check/checks/test-conformance-results.ts b/src/tier-check/checks/test-conformance-results.ts index 7f2d1be..801d648 100644 --- a/src/tier-check/checks/test-conformance-results.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -205,8 +205,5 @@ export async function checkClientConformance(options: { // Non-zero exit is expected when tests fail — results are still in outputDir } - return reconcileWithExpected( - parseOutputDir(outputDir), - listScenarios() - ); + return reconcileWithExpected(parseOutputDir(outputDir), listScenarios()); } From ffde2d94db33b3a1164b360e6b3650e9ae165093 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 17:16:08 +0000 Subject: [PATCH 33/34] 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 --- .claude/skills/mcp-sdk-tier-audit/SKILL.md | 2 ++ .claude/skills/mcp-sdk-tier-audit/references/report-template.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.claude/skills/mcp-sdk-tier-audit/SKILL.md b/.claude/skills/mcp-sdk-tier-audit/SKILL.md index 2954414..234a257 100644 --- a/.claude/skills/mcp-sdk-tier-audit/SKILL.md +++ b/.claude/skills/mcp-sdk-tier-audit/SKILL.md @@ -204,7 +204,9 @@ After the subagents finish, output a short executive summary directly to the use | — Core scenarios | / (%) | — | — | | — Auth scenarios | / (%) | — | — | | Issue Triage | % (/) | ✓/✗ | ✓/✗ | +| Labels | / | ✓/✗ | ✓/✗ | | P0 Resolution | open | ✓/✗ | ✓/✗ | +| Spec Tracking | d gap | ✓/✗ | ✓/✗ | | Documentation | / features | ✓/✗ | ✓/✗ | | Dependency Policy | | ✓/✗ | ✓/✗ | | Roadmap | | ✓/✗ | ✓/✗ | diff --git a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md index 3607fa5..d77e199 100644 --- a/.claude/skills/mcp-sdk-tier-audit/references/report-template.md +++ b/.claude/skills/mcp-sdk-tier-audit/references/report-template.md @@ -25,8 +25,10 @@ Write two files to `results/` in the conformance repo: | 1a | Server Conformance | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 1b | Client Conformance | 100% pass rate | >= 80% pass rate | {X}% ({passed}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 2 | Issue Triage | >= 90% within 2 biz days | >= 80% within 1 month | {compliance}% ({triaged}/{total}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 2b | Labels | 12 required labels | 12 required labels | {present}/{required} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 3 | Critical Bug Resolution | All P0s within 7 days | All P0s within 2 weeks | {open P0 count} open | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 4 | Stable Release | Required + clear versioning | At least one stable release | {version} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | +| 4b | Spec Tracking | Timeline agreed per release | Within 6 months | {days_gap}d gap ({PASS/FAIL}) | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 5 | Documentation | Comprehensive w/ examples | Basic docs for core features | {pass}/{total} features | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 6 | Dependency Policy | Published update policy | Published update policy | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | | 7 | Roadmap | Published roadmap | Plan toward Tier 1 | {Found/Not found} | {PASS/FAIL} | {PASS/FAIL} | {detail or "None"} | From abed710dd21756cb07eab8cb95f9705409aff620 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Thu, 12 Feb 2026 17:58:11 +0000 Subject: [PATCH 34/34] fix: reuse ConformanceCheck type from src/types.ts instead of redefining --- src/tier-check/checks/test-conformance-results.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/tier-check/checks/test-conformance-results.ts b/src/tier-check/checks/test-conformance-results.ts index 801d648..bef2059 100644 --- a/src/tier-check/checks/test-conformance-results.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -4,13 +4,7 @@ import { join } from 'path'; import { tmpdir } from 'os'; import { ConformanceResult } from '../types'; import { listScenarios, listActiveClientScenarios } from '../../scenarios'; - -interface ConformanceCheck { - name: string; - status: 'SUCCESS' | 'FAILURE' | 'WARNING'; - description?: string; - errorMessage?: string; -} +import { ConformanceCheck } from '../../types'; /** * Parse conformance results from an output directory.