{"_id":"@booyaka/mcp-vet","_rev":"18-45b621496499a422cc5c73936a9062c2","name":"@booyaka/mcp-vet","dist-tags":{"latest":"0.15.0"},"versions":{"0.2.0":{"name":"@booyaka/mcp-vet","version":"0.2.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.2.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"327cbf33738bad6845c44ca5155f6384e9439d2d","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.2.0.tgz","fileCount":17,"integrity":"sha512-dOlCm24VlsMlEhpgJYkDzCwqw171vlqUGQEhOH29vA/fiVE2FS5peD1al6FihxSk8hl8/f0pl6nomWziTVLiXg==","signatures":[{"sig":"MEUCIQDePSLS1h+JFrBNVAfwwu9DiG4gpS9aCkgfqYAooCTsrQIgFEhihwHysLJfK4zWgEl+h1keg4tob20nHfj7Lk4JQT4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":80555},"type":"commonjs","engines":{"node":">=18"},"gitHead":"d5ebbb68f363d5119eb19c1c89d04064e5c39c1e","scripts":{"test":"npm run build && node --test test/scan.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"_nodeVersion":"22.18.0","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.2.0_1784721450282_0.7335258829029787","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@booyaka/mcp-vet","version":"0.3.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.3.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"8a362fbb58fddfaae714cecea5a4d3d5f8c0abe0","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.3.0.tgz","fileCount":34,"integrity":"sha512-13Af5Kn2fDLk0Yv9OoMaomQTAU0WLbAes0zFoLejpihM9o4M6kVgtHpOFl4yQ/K0RJvMtQcZTqce4VhFSe22qA==","signatures":[{"sig":"MEUCIC/NlPRGzPTO5MK4s2nI/UUF943GdJb42HDELFuT3xTmAiEArxFJjfsj59wDViw4HxfmwBYlQqu4EzsTy0xBbSTOwXA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":121949},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"2ff9d6f672ee5f6bf2d7fc69faa40e5048c412eb","scripts":{"test":"npm run build && node --test test/scan.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.3.0_1784736364385_0.28995876451721236","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@booyaka/mcp-vet","version":"0.4.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.4.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"54b5a8c83537283f977230be284766dfb6b2e294","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.4.0.tgz","fileCount":37,"integrity":"sha512-p2epwwLPXoBXKPtdW0GXZVUS8dnisZ5LXxFDzvukouO1HxBhVfphCSexCtZQLwm1377JwDm0dxWUwFj8MuEkTw==","signatures":[{"sig":"MEYCIQCTJIl30kkywjLS6DNN5GPcEfOBOESXVIU7pgpB3fxQ5QIhAJuGOQfliVO8Q6TSCLADsFlDYcBffakiQnwnywKc2A6X","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":159472},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"5fda61dbf904593657b37d37d7ccdca9ddc7f043","scripts":{"test":"npm run build && node --test test/scan.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.4.0_1784807130071_0.7831607376573575","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@booyaka/mcp-vet","version":"0.5.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.5.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"235a91db8989d0b45a4f673b697280f3c4748524","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.5.0.tgz","fileCount":43,"integrity":"sha512-wHySQYq7/dQXCf07kVRorbwpduyAiIIHAfcJbSGy7URClq7HKnQayQuouRLRTR2YPAjLe21IIyUpPARTlNsBlg==","signatures":[{"sig":"MEUCIQDLvAHT5qvE9cuH30EKcyJwXot9BepEfnlIXTj6rF5opAIgYUEDm9CeDLyeOqRdlAB8OzsNEZxwuUJ96ZMYMAiEZ9w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":207454},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"8a5eab90dbb3ea0ea88ed6c16d590310374247a5","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.8.2","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.5.0_1784826373971_0.5211044575231645","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@booyaka/mcp-vet","version":"0.6.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.6.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"e09d3ab38262c41e652f451f45e2b799ac6e03fa","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.6.0.tgz","fileCount":43,"integrity":"sha512-rwnAA7DsX08U4p5X4BNzFMlOXDaZJ2G+t47dNdqV6HW1CiAjf/5oNWP8cW5MyzbdVKQ1pBnduyuI1R+MskY/0Q==","signatures":[{"sig":"MEQCIC+z7vE/cFpHAb2Ex+z7mZv7qJr3D60pQVRDq+ju/3EiAiBZkIw/F5yx+LmBD/n/8YpvLhnTl5xBi5msQ9yHAZR9zw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":220496},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"220942d18712549bb1770f80cdc4a3ba6b009b8e","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.6.0_1784898809293_0.48971159413317955","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@booyaka/mcp-vet","version":"0.7.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.7.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"00a1d3184ebc3de9728ffd7c9e51d25aa88d7c23","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.7.0.tgz","fileCount":43,"integrity":"sha512-d74EDzkTETevI6gfm9h55jIVdIYNKjhEXtW32bp/OnORQv09msChqs665zM1DpIdfiU/IANl8T43vwEJKemITA==","signatures":[{"sig":"MEUCIQCkWnIlo1MvgCPyrVBI5tcFGOTOF+T8/BdFNP0NpkRPGAIgYnI5DLCEzyV+sghbW62z0X0wiL/StV+37vJ7DUBfvio=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":241039},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"0a902921f1ca5201749ef02933d90eaeebed176b","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"chalk":"^4.1.2","ts-morph":"^23.0.0","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.7.0_1784968868344_0.0434945974036709","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@booyaka/mcp-vet","version":"0.8.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.8.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"68d5b774c129eafc425c929aaa198369123fc9ef","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.8.0.tgz","fileCount":45,"integrity":"sha512-Op39rG+uB6xYsRts752PatF+F3rup04lFLAtTQzZE5e30tftKEvwqh95AWC3UN4RbyUQZdFa/UWgP65rAZlxSQ==","signatures":[{"sig":"MEYCIQCgqTn2bnZMvSa7z++aRELW0ih1LWFERCrpLyJjl+YsmQIhAN5QtSSIa+00OOGMqCchiPtxnrzHlTL15VySsqrXvM18","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":244516},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"cbdb0b464621d5697ab5a0e611673b32a74241be","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the 2026-07-28 Model Context Protocol spec release candidate.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.8.0_1785148272705_0.6862462645424068","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@booyaka/mcp-vet","version":"0.9.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.9.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"3e9e78075d32dfa3bffbebe2e2aab13ac230d0c5","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.9.0.tgz","fileCount":45,"integrity":"sha512-hzN0QOCutmp0NyOMHNxZl6YW4McYhlfCBIy56s7rPyw26UcIuR8jPnR9CaSEHOqVxgkaFjH19TA09TCzzAYCxQ==","signatures":[{"sig":"MEUCIBqZpbfN6P0bCPiDqmKpV+6yB9mH2vATQ/aHpjMhZZzfAiEAitHHnsNM3QNc9ioBRd45tuxI3tG0KGi33TVJdfKqang=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":300028},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"518c5a8503225caabe9621afc15caa5e3e7ee0f0","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.9.0_1785246262719_0.0467746587923763","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@booyaka/mcp-vet","version":"0.10.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.10.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"8709c5aff45b6617e07b8c1c367a3c580ffc2bf9","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.10.0.tgz","fileCount":45,"integrity":"sha512-OXhO9ZGDjKv0gH/yU1mzm1obF2ppPZv6jRFw/qb15T5Fi5cWjpElA2QSwgoVqWm9LH7fXwKBni3ao+jNXgae+w==","signatures":[{"sig":"MEQCIEJAoZ9r7snyT1O3gqnX4fToi+p4V+eiFhm/74bLtkBVAiB4e2nPC3pHaGM4jBJHz2gHHYcudM92f2/mFi3xy3SS4g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":334745},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"3068c18bfdfaf1c7bc870821ea0084aa42757e0f","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.10.0_1785556631746_0.4227893110568719","host":"s3://npm-registry-packages-npm-production"}},"0.10.1":{"name":"@booyaka/mcp-vet","version":"0.10.1","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.10.1","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"a9457fb858ded98f09b091f2af411c8e9d28b30e","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.10.1.tgz","fileCount":45,"integrity":"sha512-wZ43qVZlojhz6i3wGetKoUMmCBN8fKG2BseCp4pMBagL8dIGJQ2Qaa8sX/9PmaJAxlHnH3jOdWxHNFFRVmmLJA==","signatures":[{"sig":"MEQCIBdJt4yyVUGXWOq7K0lIOVJMVRKRvKJeJ5+JpfEaBD9UAiAJv0L2/sYQwbdeh52/0N2RIA97n3zgGN/13MoNzcp5pA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":338275},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"5308d7707391bc04fe6f4ba4ef7a857fe11a9276","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.10.1_1785560493712_0.5161982027609291","host":"s3://npm-registry-packages-npm-production"}},"0.10.2":{"name":"@booyaka/mcp-vet","version":"0.10.2","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.10.2","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"cba811937be1cecb60ae4aebce207017a6e1ad91","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.10.2.tgz","fileCount":45,"integrity":"sha512-T3s7tVp84MI0fWr74PckXx7qcoA2bemVecFtOd3tiB3uNLA3D4ki2cL1WE4QUvIdMbTAcZnlw8SRzfMHJZitKg==","signatures":[{"sig":"MEYCIQDfBWXMnYdrZdX7o7ba0tmu+G3T4DvsyMpDJhNVm/vClQIhAJpgJvHPFdtaxO8Dy5IIzmFauQ0FpXe8NXW1nXOxT/8z","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":342891},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"b7be25e113d44f51be36a5f05323d839cf2f215e","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.10.2_1785560936111_0.641952057944494","host":"s3://npm-registry-packages-npm-production"}},"0.10.3":{"name":"@booyaka/mcp-vet","version":"0.10.3","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.10.3","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"d899fc5a994cd228bc5c43dbb3b9861428a698ce","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.10.3.tgz","fileCount":45,"integrity":"sha512-ZuO7PjGNkeT0/yev97uW+w6AImiMtmQU0vNB1gRfxekP7N/XX3wE7akUKmPuc6gWcE6cgTkjEBB+yElsWFgzkg==","signatures":[{"sig":"MEUCIHSljW3kU+9OOwhLiRSQB9hU5Riq3V+D+Pi+DgMG3AxbAiEAqIXIAIiNmxbvdBSQNy5eQhIcKadb98LFbRLMx/RtJFk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":351334},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"1af6eed99b4d51e804ab6b1e0e4efe9ab173b60b","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.9.3","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.10.3_1785562472587_0.024529017689658872","host":"s3://npm-registry-packages-npm-production"}},"0.10.4":{"name":"@booyaka/mcp-vet","version":"0.10.4","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.10.4","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"c44be5760432345f8f665eabb309d0ab89d23f29","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.10.4.tgz","fileCount":45,"integrity":"sha512-vSNM4UFug2sRqLR0L60OrPPVTBA7KDKyTNcWOCtRoK2PJ2AEw7LJz3HvaiUH3wRcsFUqkptajiR8LmyZir7iaQ==","signatures":[{"sig":"MEYCIQCsTCeuDwyzkDmUR2BtLko7yeInt0+3UWhUx482aN3Z0gIhANr5My1Wci3VorP4lDGrPSzqMi6v4as6cABGvlp3GFnS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.10.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":372355},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"38d369d671766b18af2f9347b86c2b5d401dc121","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"booyaka","email":"cbosch101@gmail.com"},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"10.8.2","description":"Scan MCP server source code for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.10.4_1786246576299_0.5046592021375886","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@booyaka/mcp-vet","version":"0.11.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.11.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"2ac39626db652486a9f0b236c09f268db82ebc31","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.11.0.tgz","fileCount":52,"integrity":"sha512-AJUjLfI1Kkx7F+unATyg6yUvjSnc1T3b5x5Lr/g3lE2hgttFF+XWPCEtgKFTgLJLBXqZOAHUCE3coDI7gBxb1Q==","signatures":[{"sig":"MEYCIQDit9AE+IHfDUj6LqAcOcETOCtpqFadLd5QOPe9V8jjmwIhAKfcfwXU6nq6Scushk301VGjMpxKMRWQD4JoINifOo2N","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":440261},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"c67b9fad2876fc95c7358cafbf4c9aa20aa9af6e","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs test/plugin.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c8bc93d8-9851-4bbe-a5ed-31a1a4288486"}},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"11.19.0","description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.11.0_1787018463594_0.608428490034908","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@booyaka/mcp-vet","version":"0.12.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.12.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"db0a18325d62a1b5a39b90b5d2075aa763aabd48","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.12.0.tgz","fileCount":54,"integrity":"sha512-Y1heu3dn8NhUU5MjjiQaEY1ThaiswluxaLrQzR5mCydbwHsfFJGeQPHssQhEmxJjQnxAi0Np0mymEiZSRkVtTQ==","signatures":[{"sig":"MEUCIQDROEeUESYVKeyCM5t4BTpNiU5ZrXnU5FuSkPK5OgDUfgIgMamrkqW195sHw4mYOYFav45B0rSi77y2CZsd8Hr2Gx4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.12.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":493113},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"56a22b00a4068064e4ac83151754fbda87a82fca","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs test/plugin.test.mjs test/py-sdk.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c8bc93d8-9851-4bbe-a5ed-31a1a4288486"}},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"11.19.0","description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.12.0_1787706742112_0.05495203612404187","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"@booyaka/mcp-vet","version":"0.13.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.13.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"eb0b25d4e2487974e38f41015c87a0800b8923c2","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.13.0.tgz","fileCount":54,"integrity":"sha512-ELXde/fe/AlrnNx6kiP/WABUXylKu7hJm2gzE4Z8Q4yMRQLM3oXd3HDoTujHHzt9aW3MnADLR4cVjxkQhraC6w==","signatures":[{"sig":"MEYCIQCp97lRw10Cc72QfOM3BNDACQgZRBcqmrOL+gvxTx0ZmAIhAJ/tK7vMlfAE3bxUToobRN2bk+2NAt2XohwvQL7CMjaA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.13.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":511392},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"4405e0a64f10447f147ee6f53b278b5cc8ab797f","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs test/plugin.test.mjs test/py-sdk.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c8bc93d8-9851-4bbe-a5ed-31a1a4288486"}},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"11.19.1","description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.13.0_1788226112269_0.480014015975591","host":"s3://npm-registry-packages-npm-production"}},"0.14.0":{"name":"@booyaka/mcp-vet","version":"0.14.0","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin","typescript-sdk","python-sdk","codemod"],"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","_id":"@booyaka/mcp-vet@0.14.0","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"homepage":"https://github.com/Booyaka101/mcp-vet#readme","bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"bin":{"mcp-vet":"dist/cli.js"},"dist":{"shasum":"a080a808bff1f48417b861a2004b8b426335d5b3","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.14.0.tgz","fileCount":54,"integrity":"sha512-JR8cQO47V9uMTK8saPcRgrtt90E/SPBHWSmS8xJk+IYod1gos9OfaJrdEhIgbUwbc7NyaB+LGQ8jfEuF+CPP+Q==","signatures":[{"sig":"MEYCIQCbF/wWYhxUi8KdtC1xto258hHBNuHu65yRo9akB2MHjgIhAO0sNPFWRLuJtrQRJ/SNzTlxj9E274IgD/ewg+uyAqSp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.14.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":585996},"main":"dist/index.js","type":"commonjs","types":"dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"f02a1f59ee8c64187718e7083c9087044e619436","scripts":{"test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs test/plugin.test.mjs test/py-sdk.test.mjs test/ts-sdk.test.mjs","build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c8bc93d8-9851-4bbe-a5ed-31a1a4288486"}},"repository":{"url":"git+https://github.com/Booyaka101/mcp-vet.git","type":"git"},"_npmVersion":"11.19.1","description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification, plus the Python and TypeScript SDK v1→v2 migrations.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","dependencies":{"ts-morph":"^28.0.0","commander":"^15.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.4","@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-vet_0.14.0_1788510314748_0.19031666581483875","host":"s3://npm-registry-packages-npm-production"}},"0.15.0":{"name":"@booyaka/mcp-vet","version":"0.15.0","description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification, plus the Python and TypeScript SDK v1→v2 migrations.","type":"commonjs","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"sideEffects":false,"bin":{"mcp-vet":"dist/cli.js"},"engines":{"node":">=22"},"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"repository":{"type":"git","url":"git+https://github.com/Booyaka101/mcp-vet.git"},"bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"homepage":"https://github.com/Booyaka101/mcp-vet#readme","publishConfig":{"access":"public"},"keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin","typescript-sdk","python-sdk","codemod"],"license":"MIT","scripts":{"build":"tsc -p tsconfig.json && node scripts/copy-assets.mjs","prepare":"npm run build","test":"npm run build && node --test test/scan.test.mjs test/probe.test.mjs test/plugin.test.mjs test/py-sdk.test.mjs test/ts-sdk.test.mjs"},"dependencies":{"commander":"^15.0.0","ts-morph":"^28.0.0"},"devDependencies":{"@types/node":"^26.1.1","typescript":"^5.5.4"},"gitHead":"61277af58f0c191d3de51e4e01eb2504f2603349","_id":"@booyaka/mcp-vet@0.15.0","_nodeVersion":"22.23.2","_npmVersion":"11.19.1","dist":{"integrity":"sha512-8Rb13qmYtvrVdy1gE2yJ3VvEQVufT9My8wJ2tKPYpyX1XjFH/ZJwL9XHAr42vf3h2AuJKY8g2+/zi362JscKRg==","shasum":"bcc0e856004bfdf5a62ed18ae67529f82a8ebf58","tarball":"https://registry.npmjs.org/@booyaka/mcp-vet/-/mcp-vet-0.15.0.tgz","fileCount":54,"unpackedSize":612624,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@booyaka%2fmcp-vet@0.15.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEDGH4g+KUaePYg7BqyKEapY/5cR91Cfh6i2xDUYfmqFAiBawk86A1KGmQlJRXO1WKgdC+m4JbbcFbGZzn9lHpevSw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c8bc93d8-9851-4bbe-a5ed-31a1a4288486"}},"directories":{},"maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-vet_0.15.0_1788514456181_0.16827548740450982"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T11:57:30.195Z","modified":"2026-09-04T09:34:16.597Z","0.2.0":"2026-07-22T11:57:30.470Z","0.3.0":"2026-07-22T16:06:04.600Z","0.4.0":"2026-07-23T11:45:30.209Z","0.5.0":"2026-07-23T17:06:14.118Z","0.6.0":"2026-07-24T13:13:29.439Z","0.7.0":"2026-07-25T08:41:08.483Z","0.8.0":"2026-07-27T10:31:12.861Z","0.9.0":"2026-07-28T13:44:22.887Z","0.10.0":"2026-08-01T03:57:11.884Z","0.10.1":"2026-08-01T05:01:33.911Z","0.10.2":"2026-08-01T05:08:56.257Z","0.10.3":"2026-08-01T05:34:32.729Z","0.10.4":"2026-08-09T03:36:16.449Z","0.11.0":"2026-08-18T02:01:03.752Z","0.12.0":"2026-08-26T01:12:22.260Z","0.13.0":"2026-09-01T01:28:32.433Z","0.14.0":"2026-09-04T08:25:14.941Z","0.15.0":"2026-09-04T09:34:16.305Z"},"bugs":{"url":"https://github.com/Booyaka101/mcp-vet/issues"},"author":{"name":"Booyaka101","email":"cbosch101@gmail.com"},"license":"MIT","homepage":"https://github.com/Booyaka101/mcp-vet#readme","keywords":["mcp","model-context-protocol","linter","static-analysis","migration","breaking-changes","2026-07-28","sarif","ci","ast","cli","typescript","python","sse","streamable-http","agent-plugins","copilot","plugin","typescript-sdk","python-sdk","codemod"],"repository":{"type":"git","url":"git+https://github.com/Booyaka101/mcp-vet.git"},"description":"Scan MCP server source code and Agent Plugins 1.0 packages for patterns that break under the final 2026-07-28 Model Context Protocol specification, plus the Python and TypeScript SDK v1→v2 migrations.","maintainers":[{"name":"booyaka","email":"cbosch101@gmail.com"}],"readme":"# mcp-vet\n\n[![npm version](https://img.shields.io/npm/v/@booyaka/mcp-vet.svg)](https://www.npmjs.com/package/@booyaka/mcp-vet)\n[![CI](https://github.com/Booyaka101/mcp-vet/actions/workflows/ci.yml/badge.svg)](https://github.com/Booyaka101/mcp-vet/actions/workflows/ci.yml)\n[![node](https://img.shields.io/node/v/@booyaka/mcp-vet.svg)](https://nodejs.org)\n[![license: MIT](https://img.shields.io/npm/l/@booyaka/mcp-vet.svg)](./LICENSE)\n\n**On July 28, 2026 the Model Context Protocol ships its `2026-07-28` specification as final** — and it removes several things that today's MCP servers rely on. `mcp-vet` is a zero-config CLI that scans your MCP server source (TypeScript, JavaScript, and Python) for the exact patterns that will break client interop on that date, and tells you what to change. Since 0.11.0 it also vets [Agent Plugins 1.0 packages](#vet-an-agent-plugins-10-package-mcp-vet-plugin), the plugin format that went GA in VS Code and GitHub Copilot on 2026-08-12 and ships MCP servers via `mcp.json`. On top of the 22 protocol rules it carries two advisory SDK-migration groups: [`PY_SDK_V1_*`](#-python-sdk-v1-vs-v2-py_sdk_v1_-added-in-0120) for the Python SDK v1→v2 port and [`TS_SDK_V1_*`](#-typescript-sdk-v1-vs-v2-ts_sdk_v1_-added-in-0140) for the TypeScript one.\n\n- Final Key Changes list: <https://modelcontextprotocol.io/specification/2026-07-28/changelog>\n- Deprecated-features registry: <https://modelcontextprotocol.io/specification/2026-07-28/deprecated>\n- Release-candidate announcement: <https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/>\n- Every rule's source sentence, pinned verbatim: [docs/SPEC-2026-07-28.md](./docs/SPEC-2026-07-28.md)\n\n> **URL note.** The dated permalink 404'd on release day (0.9.0 cited\n> `/specification/draft/`); it resolves as of 2026-08-01 and every rule docUrl\n> now cites it — a `/draft/` URL silently drifts at the next revision, and a\n> test asserts no rule cites one.\n\n```bash\nnpx @booyaka/mcp-vet .\n```\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/Booyaka101/mcp-vet/main/assets/demo.png\" alt=\"mcp-vet scanning a server — BREAKING and DEPRECATED findings with before/after fixes and confidence tags\" width=\"720\">\n</p>\n\nNo account, no API key — the scan parses your code locally (ts-morph for TS/JS, a bundled Python `ast` script for `.py`), makes no network calls, and exits non-zero if it finds anything **BREAKING**, so you can drop it straight into CI. (The opt-in [`mcp-vet probe`](#vet-a-running-server-mcp-vet-probe) is the one command that talks to a server — and only the one you point it at.)\n\n## What actually happens on July 28\n\n**July 28 is a specification release date, not a switch that remotely disables your deployment.** Nothing reaches into running servers and turns them off. Breakage appears when a **client and server pair negotiates or requires the new revision** — a client that sends `2026-07-28`-style requests (per-request `_meta`, no handshake, routing headers) against a server that still expects `2025-11-25` semantics, or vice versa.\n\nTwo practical consequences:\n\n- **Your rollout is a window, not a day.** Until every client you care about has moved, keep **both** revisions in your production test matrix: a `2025-11-25` path and a `2026-07-28` path. `mcp-vet fixtures` emits wire-level test fixtures for exactly this (see [Runtime conformance fixtures](#runtime-conformance-fixtures)).\n- **Silent acceptance is the worst failure mode.** A server that quietly processes an old-revision request under new semantics (or the reverse) corrupts behavior instead of failing loudly. Verify *refusal* behavior, not just the happy path.\n\nThe scan tells you *what to change in your source*; the date tells you *when clients start expecting it*.\n\n---\n\n## Real-world example\n\nPointed at the [official MCP TypeScript SDK's own example servers](https://github.com/modelcontextprotocol/typescript-sdk/tree/main/examples), `mcp-vet` finds the patterns that the `2026-07-28` spec breaks:\n\n```text\nlegacy-routing.ts:36:29  BREAKING   MCP_SESSION_ID [high]\n    const sid = req.headers['mcp-session-id'] as string | undefined;\nlegacy-routing.ts:41:13  BREAKING   MCP_SESSION_ID [medium]\n    sessionIdGenerator: () => randomUUID(),\nlegacy-routing.ts:70:26  BREAKING   MCP_SESSION_ID [high]\n    exposedHeaders: ['Mcp-Session-Id', 'WWW-Authenticate', ...]\nsse-polling.ts:34:29     DEPRECATED LOGGING_CAP    [high]\n    capabilities: { logging: {} }\nsse-polling.ts:102:29    BREAKING   MCP_SESSION_ID [high]\n    const sid = req.headers['mcp-session-id'] as string | undefined;\nsse-polling.ts:107:13    BREAKING   MCP_SESSION_ID [medium]\n    sessionIdGenerator: () => randomUUID(),\n\n6 finding(s): 5 BREAKING, 1 DEPRECATED\n```\n\nNote it catches the `sessionIdGenerator` session usage — the real signal in SDK-based servers, which usually never write the literal `Mcp-Session-Id` string. And it stays quiet where it should: the `Mcp-Session-Id` mentioned in a *comment*, the `initialize` in a comment in `dual-era.ts`, and the `sampling/createMessage` in `sampling.ts` (which appears only in comments and behind the `requestSampling()` helper) are all left alone. That precision — structural AST checks, not text matching — is what keeps the noise down on a real codebase: **6 findings, 0 false positives on these files.** (Across the full labeled corpus it's 256/258 true positives — see [BENCHMARK.md](./BENCHMARK.md).)\n\n---\n\n## What it detects\n\n### 🔴 BREAKING (fails the build — exit code 1)\n\n| ID | Pattern |\n| --- | --- |\n| `MCP_SESSION_ID` | `Mcp-Session-Id` header / `mcpSessionId` variable / client-side session ownership (`sessionId` passed to or read from a client transport) |\n| `INITIALIZE_HANDLER` | `initialize` / `notifications/initialized` handler registration |\n| `ERROR_CODE_32002` | the numeric error code `-32002` |\n| `ERROR_CODE_RENUMBERED` | `-32001` / `-32003` / `-32004` **in a JSON-RPC error `code` position** → `-32020` / `-32021` / `-32022` |\n| `TASKS_LEGACY` | `tasks/get` · `tasks/update` · `tasks/cancel` legacy method strings |\n| `TASKS_LIST_REMOVED` | `tasks/list` — removed entirely (no replacement listing method) |\n| `TASKS_RESULT_REMOVED` | `tasks/result` — removed; poll with `tasks/get` instead (SEP-2663) |\n| `PING_REMOVED` | `ping` in MCP method-registration context · `PingRequestSchema` · Python `types.PingRequest` |\n| `RESOURCE_SUBSCRIBE_REMOVED` | `resources/subscribe` · `resources/unsubscribe` · `SubscribeRequestSchema` · `UnsubscribeRequestSchema` → `subscriptions/listen` |\n| `ROOTS_LIST_CHANGED_REMOVED` | `notifications/roots/list_changed` · `RootsListChangedNotificationSchema` |\n| `LOGGING_SETLEVEL_REMOVED` | `logging/setLevel` · `SetLevelRequestSchema` |\n| `SSE_RESUMABILITY_REMOVED` | `Last-Event-ID` / `lastEventId` · `eventStore` · `resumptionToken` / `onresumptiontoken` on a Streamable HTTP transport |\n| `ELICITATION_COMPLETE_REMOVED` | `notifications/elicitation/complete` · `elicitationId` |\n\n> **The two reclassified rules matter most if you scanned with ≤ 0.8.0.**\n> `logging/setLevel` and `notifications/roots/list_changed` used to report as\n> DEPRECATED warnings (exit 0) under `LOGGING_CAP` / `ROOTS_CAP`. The final\n> changelog *removes* them — *\"Remove `ping`, `logging/setLevel`, and\n> `notifications/roots/list_changed`\"* — so they now fail the build, while the\n> `logging` / `roots` **capability keys** stay DEPRECATED. A test locks that\n> split so it can't regress.\n\n### 🟡 DEPRECATED (warns only — exit code 0)\n\nRemoval windows come from the [deprecated-features registry](https://modelcontextprotocol.io/specification/2026-07-28/deprecated), quoted verbatim in each finding — not a hardcoded grace period.\n\n| ID | Pattern | Earliest removal (registry) |\n| --- | --- | --- |\n| `ROOTS_CAP` | `roots` capability | first revision released on or after 2027-07-28 |\n| `SAMPLING_CAP` | `sampling` capability | first revision released on or after 2027-07-28 |\n| `LOGGING_CAP` | `logging` capability | first revision released on or after 2027-07-28 |\n| `INCLUDE_CONTEXT_VALUES` | `includeContext` set to `\"thisServer\"` / `\"allServers\"` | follows Sampling |\n| `OAUTH_DCR` | RFC7591 dynamic client registration (`registration_endpoint`, …) → Client ID Metadata Documents | first revision released on or after 2027-07-28 |\n| `SSE_TRANSPORT_DEPRECATED` | the HTTP+SSE transport (SEP-2596): `SSEServerTransport` / `SSEClientTransport` / `SseServerTransport` and the SDK sse module paths (ungated); `sse_client` / `sse_app` / `connect_sse` / `handle_post_message` and a literal `transport: 'sse'` (MCP-context-gated); the hand-rolled two-endpoint shape (`text/event-stream` **plus** an `event: endpoint` write — `text/event-stream` alone never fires) → Streamable HTTP | three months after SEP-2596 reaches Final (quoted verbatim from the registry — the SEP is Final, but the registry still states the relative clause, so mcp-vet computes nothing) |\n\nThree more report at this exit-0 tier without being deprecations: the final\nchangelog's **authorization-hardening MUSTs** (Minor changes 7/8/9). They are\ncorrectness requirements on code that still works, so they warn instead of\nfailing the build — and all three are gated on file-level MCP context (like\n`SSE_RESUMABILITY_REMOVED`), so a plain OAuth client in an unrelated file\nstays clean (locked by `negatives/plain-oauth-client.ts` / `.py`):\n\n| ID | Fires when (in an MCP-context file) | Source |\n| --- | --- | --- |\n| `AUTH_ISS_UNVALIDATED` | an authorization-code redemption (`grant_type` `'authorization_code'`) with no `iss`/`issuer` read or comparison anywhere in the file — *\"MCP clients MUST validate a present `iss` against the recorded issuer before redeeming the authorization code\"* | [SEP-2468](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2468) / RFC 9207 |\n| `AUTH_DCR_NO_APPLICATION_TYPE` | a **hand-rolled** registration body (`redirect_uris` + `client_name`) with no `application_type` — *\"Require MCP clients to specify an appropriate `application_type` during Dynamic Client Registration\"*; the fix also points at Client ID Metadata Documents (DCR is Deprecated, PR #2858). Bodies routed through an SDK that supplies the parameter (python-sdk's `OAuthClientMetadata` default, typescript-sdk's `deriveApplicationType`) are already correct and stay clean | [SEP-837](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/837) |\n| `AUTH_CREDENTIALS_NOT_ISSUER_KEYED` | persisted `client_id`/`client_secret` stored under a bare constant key or a server/resource-URL variable — *\"clients MUST key persisted credentials by the issuer identifier\"*; an issuer-derived key is the migrated form | [SEP-2352](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2352) |\n\n### 🐍 Python SDK v1 vs v2 (`PY_SDK_V1_*`, added in 0.12.0)\n\nMCP Python SDK **v2.0.0 went stable 2026-07-28** (v2.1.1 shipped 2026-08-25)\nand renamed or removed most of the v1 API surface. These 12 rules fire on v1\nSDK vocabulary in a project whose **declared** `mcp` dependency resolves to\nmajor 2, where that vocabulary is either a hard import-time crash (v2.1.1\nships `mcp/server/fastmcp.py` as a stub that raises `ModuleNotFoundError`) or\na silent behavior change. They are SDK-level, not protocol-level, and all warn\nat exit 0. Every message quotes the\n[migration guide](https://py.sdk.modelcontextprotocol.io/v2/migration/) or a\n[release body](https://github.com/modelcontextprotocol/python-sdk/releases).\n\n| ID | Fires on (in a file that imports `mcp`) |\n| --- | --- |\n| `PY_SDK_V1_FASTMCP` | `from mcp.server.fastmcp import FastMCP` → `from mcp.server.mcpserver import MCPServer`. A hard `ModuleNotFoundError` under v2 |\n| `PY_SDK_V1_MCPERROR` | `McpError` → `MCPError` |\n| `PY_SDK_V1_CAMEL_FIELDS` | attribute/kwarg access to `inputSchema` / `outputSchema` / `isError` / `nextCursor` → snake_case. Raw JSON dicts stay clean, because the wire format is still camelCase in v2 |\n| `PY_SDK_V1_STREAMABLEHTTP_CLIENT` | `streamablehttp_client` → `streamable_http_client` |\n| `PY_SDK_V1_WEBSOCKET` | `mcp.client.websocket` / `websocket_client`. The WebSocket transport, and the `ws` extra, are removed entirely |\n| `PY_SDK_V1_GET_CONTEXT` | `.get_context()` → a `ctx: Context` handler parameter, since context is injected now |\n| `PY_SDK_V1_TIMEDELTA` | a timeout kwarg passed `timedelta(...)` → float seconds. Client request timeouts now raise `-32001` `REQUEST_TIMEOUT` instead of 408 |\n| `PY_SDK_V1_ENV` | `MCP_*` environment variables next to `environ`/`getenv`. v2 never reads them, and the guide notes they never took effect in v1 either |\n| `PY_SDK_V1_OAUTH` | `RFC7523OAuthClientProvider` / `JWTParameters` (removed), `scopes=` on client-credentials providers → `scope=`, and `OAuthClientProvider(timeout=)` (removed) |\n| `PY_SDK_V1_CACHE_FALSE` | `Client(cache=False)` → `Client(cache=None)` |\n| `PY_SDK_V1_FILERESOURCE` | `FileResource(is_binary=...)` → `encoding: str \\| None`. Passing `is_binary=` now raises `ValidationError` |\n| `PY_SDK_V1_HTTPX` | `import httpx` in a project whose mcp resolves to v2. v2 depends on `httpx2>=2.5.0` instead, so declare httpx yourself or port the import. A declared direct httpx dependency stays clean |\n\n**Gating (`--py-sdk auto`, the default).** The declared `mcp` specifier is\nread from the nearest `uv.lock` / `poetry.lock` (exact version, wins),\n`pyproject.toml` (PEP 621 dependencies, optional-dependency extras, PEP 735\ngroups, and poetry tables), or `requirements*.txt`, walking up from each\nPython file and stopping at the repository boundary, so an unrelated parent\nmanifest can never decide the gate:\n\n- resolves to **v2**: the group is active;\n- resolves to **v1**: the group is suppressed and one informational line\n  names v2.1.1 (2026-08-25) as available (preview with `--py-sdk v2`);\n- **unresolvable** (no manifest, no `mcp` entry, or a range like `>=1.26`\n  that admits both majors): active, with every finding annotated\n  *\"(mcp version undetermined)\"*.\n\n`--py-sdk v1|v2` forces a side; `--no-py-sdk` removes the group entirely and\nreproduces pre-0.12.0 output byte for byte. The group is additionally gated\nper file on an actual `mcp` import, so a local class named `FastMCP` in a\nnon-MCP file stays clean, and it never gates the 22 protocol rules. A fully\nv2-ported server importing `mcp.server.sse`, still a real module in v2.1.1,\nkeeps its SSE findings, which is exactly the under-report 0.12.0 fixes.\n\n### 🟦 TypeScript SDK v1 vs v2 (`TS_SDK_V1_*`, added in 0.14.0)\n\nThe monolithic `@modelcontextprotocol/sdk` was retired on **2026-07-27**, when\n`@modelcontextprotocol/client`, `@modelcontextprotocol/server`,\n`@modelcontextprotocol/core` and the framework adapters (`/node`, `/express`,\n`/hono`, `/fastify`) all went stable at 2.0.0. These 17 rules fire on v1 SDK\nvocabulary in a project whose **declared** dependencies resolve to that split.\nLike the Python group they are SDK-level, not protocol-level, and all warn at\nexit 0. Pinning back to `@modelcontextprotocol/sdk@^1` remains valid, the guide\ndescribes v1/v2 coexistence during a staged migration, and it sets no\nend-of-support date for v1.x, so neither does any message here. Every message\nquotes\n[docs/migration/upgrade-to-v2.md](https://ts.sdk.modelcontextprotocol.io/v2/migration/upgrade-to-v2.html).\n\n| ID | Fires on (in a file that imports `@modelcontextprotocol/*`) |\n| --- | --- |\n| `TS_SDK_V1_MONOLITH` | any `@modelcontextprotocol/sdk/...` import, with the destination named per path (`types.js` → `@modelcontextprotocol/core`, `server/express` → `@modelcontextprotocol/express`, …). Suppressed on the SSE paths `SSE_TRANSPORT_DEPRECATED` already owns |\n| `TS_SDK_V1_MCPERROR` | `McpError` → `ProtocolError`; `ErrorCode` → `ProtocolErrorCode`; `ErrorCode.RequestTimeout` / `.ConnectionClosed` → `SdkErrorCode` |\n| `TS_SDK_V1_HTTP_ERROR` | `StreamableHTTPError` → `SdkHttpError` |\n| `TS_SDK_V1_JSONRPC_ERROR` | `JSONRPCError` → `JSONRPCErrorResponse`, plus `JSONRPCErrorSchema` and `isJSONRPCError` |\n| `TS_SDK_V1_JSONRPC_RESPONSE` | `JSONRPCResponse` / `JSONRPCResponseSchema` / `isJSONRPCResponse`. **A silent widening, not a rename**: v1 validated only *result* responses, v2 reuses the name for `result | error`, so a migrated `.parse()` accepts errors it used to reject. Rename to the `…ResultResponse…` forms to keep v1 behaviour |\n| `TS_SDK_V1_HANDLER_EXTRA` | `RequestHandlerExtra` and the `extra.*` reads: `extra.signal` → `ctx.mcpReq.signal`, `extra.requestId` → `ctx.mcpReq.id`, `extra.sendRequest` → `ctx.mcpReq.send`, `extra.requestInfo` → `ctx.http?.req`, and the rest of the table. `ctx.http` is undefined on stdio |\n| `TS_SDK_V1_SCHEMA_HANDLER` | `setRequestHandler(CallToolRequestSchema, …)` → `setRequestHandler('tools/call', …)`; custom methods take the 3-argument form |\n| `TS_SDK_V1_VARIADIC_REG` | `server.tool(` / `.prompt(` / `.resource(` → `registerTool` / `registerPrompt` / `registerResource` |\n| `TS_SDK_V1_WEBSOCKET` | `WebSocketClientTransport`, or the `sdk/client/websocket` module. Removed, because WebSocket is not a spec transport |\n| `TS_SDK_V1_NODE_HTTP_TRANSPORT` | `StreamableHTTPServerTransport` → `NodeStreamableHTTPServerTransport` from `@modelcontextprotocol/node` (or `WebStandardStreamableHTTPServerTransport` on Workers/Deno/Bun) |\n| `TS_SDK_V1_ZOD_COMPAT` | `server/zod-compat.js`, `server/zod-json-schema-compat.js`, and the removed helpers. Only `schemaToJson` (→ `fromJsonSchema()`) and `parseSchemaAsync` (→ `z.safeParseAsync()`) have a route forward; the guide says `getSchemaShape`, `getSchemaDescription`, `isOptionalSchema` and `unwrapOptionalSchema` have none |\n| `TS_SDK_V1_AUTH_MOVED` | `@modelcontextprotocol/sdk/server/auth/**` → `@modelcontextprotocol/server-legacy/auth` (frozen v1 copy), `@modelcontextprotocol/express`, or `@modelcontextprotocol/server` |\n| `TS_SDK_V1_RESOURCE_REF` | `ResourceReference` / `ResourceReferenceSchema` → `ResourceTemplateReference` / `…Schema`; the `ResourceTemplate` type from `types.js` → `ResourceTemplateType` |\n| `TS_SDK_V1_COMPLETABLE_NESTING` | `completable(schema.optional(), cb)` → `completable(schema, cb).optional()`. v2 resolves completion metadata after unwrapping the optional, so the v1 nesting returns empty completion lists and nothing errors |\n| `TS_SDK_V1_FINISH_AUTH` | `finishAuth(code)` with a bare code string. v2 validates `iss` from the callback, so pass the callback URL's `URLSearchParams` instead. Advisory: the guide calls the two one-argument forms statically indistinguishable, so this needs a string literal or a plainly code-named binding |\n| `TS_SDK_V1_ISOMORPHIC_HEADERS` | `IsomorphicHeaders` → the Web Standard `Headers` type |\n| `TS_SDK_V1_ZOD3` | a `zod` import in a project whose declared zod range admits below `^4.2.0`. v1's peer was `^3.25 \\|\\| ^4.0`, which \"installs and typechecks cleanly under v2 and only fails at runtime\" |\n\n**Gating (`--ts-sdk auto`, the default).** The declared family is read from the\nnearest `package.json` (any dependency block) plus `package-lock.json` /\n`pnpm-lock.yaml` / `yarn.lock`, walking up from each `.ts`/`.js` file and\nstopping at the repository boundary, so an unrelated parent manifest can never\ndecide the gate:\n\n- declares any of **client / server / core**: the group is active;\n- declares **`@modelcontextprotocol/sdk` ^1** and nothing else: the group is\n  suppressed and one informational line names the v2 packages and their\n  2026-07-27 npm date (preview with `--ts-sdk v2`);\n- declares **both**: a staged migration. The group runs, and a note points out\n  that objects must not flow between v1-imported and v2-imported code;\n- **unresolvable** (no manifest, no MCP entry, or a range like `*` that names\n  no major): active, with every finding annotated\n  *\"(SDK version undetermined)\"*.\n\n`--ts-sdk v1|v2` forces a side; `--no-ts-sdk` removes the group entirely and\nreproduces pre-0.14.0 output byte for byte. Like the Python group it is\nadditionally gated per file on an actual `@modelcontextprotocol/*` import, so a\nlocal class named `McpError` stays clean, and it never gates the 22 protocol\nrules. Aliased (`import { McpError as Boom }`), namespace (`import * as sdk`),\n`require()` and `export … from` forms all resolve.\n\n#### Worked example\n\nA one-line `server.ts` in a project whose `package.json` declares\n`@modelcontextprotocol/server: \"^2.0.0\"`:\n\n```ts\nimport { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';\n\nexport function badParams(): never {\n  throw new McpError(ErrorCode.InvalidParams, 'unknown resource');\n}\n```\n\n```console\n$ mcp-vet server.ts\n\nserver.ts\nserver.ts:4:10  DEPRECATED  TS_SDK_V1_MCPERROR [high]\n    The migration guide renames the error surface: McpError → ProtocolError; ErrorCode → ProtocolErrorCode. …\n    — before:\n      4: import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';\n    + after:\n      import { ProtocolError, ProtocolErrorCode, SdkErrorCode } from '@modelcontextprotocol/core';\n\n      throw new ProtocolError(ProtocolErrorCode.InvalidParams, \"unknown resource\");\nserver.ts:4:37  DEPRECATED  TS_SDK_V1_MONOLITH [high]\n    The migration guide splits the single `@modelcontextprotocol/sdk` package into … types.js schemas moved to @modelcontextprotocol/core.\n    — before:\n      4: import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';\n    + after:\n      // v2 (Node 20+): npx @modelcontextprotocol/codemod@latest v1-to-v2 .\n      import { MCPServer } from '@modelcontextprotocol/server';\n      import { CallToolResultSchema } from '@modelcontextprotocol/core';\n      import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';\n\n2 finding(s): 0 BREAKING, 2 DEPRECATED\n22 spec rules, 0 breaking; 13 TypeScript SDK rules, 2 advisory\n\n$ echo $?\n0\n```\n\nOne import line, two things to fix, and the build still passes. That is what\nthe advisory tier means. The whole port is `npx @modelcontextprotocol/codemod@latest\nv1-to-v2 .`; these rules tell you whether you still need to run it, and what the\ncodemod left behind.\n\n### Confidence\n\nEvery finding carries a **confidence** so you can tune signal-to-noise with `--min-confidence`:\n\n- **high** — exact/deterministic match (session id, `-32002`, tasks methods), a structurally-verified capability (the `roots`/`sampling`/`logging` key is really *inside* a `capabilities` object), or an `initialize` string used as a method name (handler registration, `switch` case, or `req.method === 'initialize'`).\n- **medium** — a `roots`/`sampling`/`logging` key/string within 5 lines of a `capabilities` mention but not structurally verified; a real `sessionIdGenerator`; client-side session ownership (`sessionId`/`session_id` passed to or read from a transport/client).\n- **low** — a bare `'initialize'` string with no registration context.\n\n---\n\n## Before / after for each BREAKING pattern\n\n### 1. `Mcp-Session-Id` — sessions are removed\n\n> *\"The `Mcp-Session-Id` header and the protocol-level session that came with it are also removed.\"*\n\n```ts\n// ❌ before\nconst sessionId = req.headers['Mcp-Session-Id'];\nres.setHeader('Mcp-Session-Id', sessionId);\n\n// ✅ after — no session header; client info & capabilities arrive in per-request _meta\nfunction handle(req) {\n  const meta = req.params?._meta ?? {};\n  // route on meta, not on a session id\n}\n```\n\nThis cuts both ways — **client-side session ownership breaks too**, even against a server that scans clean. A lot of tool-reliability bugs only show up when the server is stateless but the client still behaves as if it owns a session:\n\n```ts\n// ❌ before — the client resumes a stored session\nconst transport = new StreamableHTTPClientTransport(url, { sessionId: stored });\npersist(transport.sessionId);\n\n// ✅ after — stateless: no stored session id, full _meta on every request\nconst transport = new StreamableHTTPClientTransport(url, { sessionId: undefined });\n```\n\n`mcp-vet` flags a client transport constructed with a real `sessionId`/`session_id` and reads of `transport.sessionId` (medium confidence). The migrated `sessionId: undefined` / `session_id=None` forms are recognized and left alone.\n\n### 2. `initialize` / `notifications/initialized` — the handshake is removed\n\n> *\"The `initialize`/`initialized` handshake is removed. The protocol version, client info, and client capabilities that used to be exchanged once at connection time now travel in `_meta` on every request.\"*\n\n```ts\n// ❌ before\nserver.setRequestHandler('initialize', async (req) => ({ protocolVersion, capabilities }));\nserver.setNotificationHandler('notifications/initialized', () => {});\n\n// ✅ after — read the handshake data from _meta on every request\nfunction handle(req) {\n  const { protocolVersion, clientInfo, capabilities } = req.params?._meta ?? {};\n}\n```\n\n### 3. Error code `-32002` → `-32602`\n\n> *\"The error code for a missing resource changes from the MCP-custom `-32002` to the JSON-RPC standard `-32602` Invalid Params.\"*\n\n```ts\n// ❌ before\nreturn { error: { code: -32002, message: 'Resource not found' } };\n\n// ✅ after\nreturn { error: { code: -32602, message: 'Invalid params' } };\n```\n\nThis one is purely mechanical, so `mcp-vet --fix` rewrites it for you in place.\n\n### 4. Legacy Tasks methods — redesigned to a handle-based lifecycle\n\n> *\"A server can answer `tools/call` with a task handle, and the client drives it with `tasks/get`, `tasks/update`, and `tasks/cancel`. Anyone who shipped against the `2025-11-25` experimental Tasks API will need to migrate to the new lifecycle.\"*\n\n```ts\n// ❌ before — legacy experimental argument shapes\nswitch (method) {\n  case 'tasks/get':    return getTask(id);\n  case 'tasks/update': return updateTask(id);\n  case 'tasks/cancel': return cancelTask(id);\n}\n\n// ✅ after — tools/call returns a task handle; the same method names now carry\n// the NEW argument shapes. mcp-vet flags every use for manual review against\n// the 2026-07-28 schema.\n```\n\n### 5. `ping`, `logging/setLevel`, `notifications/roots/list_changed` — removed\n\n> *\"Remove `ping`, `logging/setLevel`, and `notifications/roots/list_changed`. Log level is now set per-request via `io.modelcontextprotocol/logLevel` in `_meta`; servers MUST NOT emit `notifications/message` for requests that did not include this field.\"*\n\n```ts\n// ❌ before\nserver.setRequestHandler(PingRequestSchema, async () => ({}));\nserver.setRequestHandler(SetLevelRequestSchema, async (r) => setLevel(r.params.level));\nserver.notification({ method: 'notifications/roots/list_changed' });\n\n// ✅ after — ping is gone (liveness is transport-level); read the level per request\nfunction handle(req) {\n  const level = req.params?._meta?.['io.modelcontextprotocol/logLevel'];\n  // ...and emit notifications/message ONLY when that field was present\n}\n```\n\nA `/ping` health-check route, a bare `'ping'` string, or a tool merely *named*\n`ping` is **not** flagged — the rule requires MCP method-registration context.\n\n### 6. `resources/subscribe` / `resources/unsubscribe` → `subscriptions/listen`\n\n> *\"Replace the HTTP GET endpoint and `resources/subscribe`/`resources/unsubscribe` with `subscriptions/listen`: a single long-lived POST-response stream for opted-in server-to-client change notifications.\"*\n\n```ts\n// ❌ before\nserver.setRequestHandler(SubscribeRequestSchema, async ({ params }) => subscribe(params.uri));\n\n// ✅ after — the client opts into specific types; the server tags notifications\n{\n  method: 'subscriptions/listen',\n  params: { subscriptions: { toolsListChanged: true, resourcesListChanged: true } },\n}\n// every notification on that stream carries\n// _meta['io.modelcontextprotocol/subscriptionId']\n```\n\n### 7. SSE resumability — removed\n\n> *\"Remove SSE stream resumability and message redelivery (the `Last-Event-ID` header and SSE event IDs) from the Streamable HTTP transport. A broken response stream loses the in-flight request; clients MUST re-issue it as a new request with a new request ID.\"*\n\n```ts\n// ❌ before\nconst transport = new StreamableHTTPServerTransport({ eventStore });\nconst lastEventId = req.headers['last-event-id'];\n\n// ✅ after — no event store, no resumption token; retry as a NEW request id\nconst transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n```\n\nA non-MCP SSE client that legitimately uses `Last-Event-ID` stays clean — the\nrule is gated on MCP context (locked by `test/fixtures/negatives/sse-client.ts`).\n\n### 8. Error codes `-32001` / `-32003` / `-32004` → `-32020` / `-32021` / `-32022`\n\n> *\"`-32000` to `-32019` remains implementation-defined (existing SDK usage is grandfathered), `-32020` to `-32099` is reserved for the MCP specification. Renumber the error codes introduced in this draft accordingly — `HeaderMismatch` `-32001` → `-32020`, `MissingRequiredClientCapability` `-32003` → `-32021`, `UnsupportedProtocolVersion` `-32004` → `-32022`.\"*\n\n```ts\n// ❌ before\nreturn { error: { code: -32004, message: 'Unsupported protocol version' } };\n\n// ✅ after\nreturn { error: { code: -32022, message: 'Unsupported protocol version' } };\n```\n\nBecause `-32000..-32019` is grandfathered, this only fires in a JSON-RPC error\n`code` position (a `code:` key, an `*Error(...)` construction, or a comparison\nagainst `code`) — an implementation-defined `-32001` constant elsewhere is left\nalone. Mechanical, so **`--fix` rewrites all three** alongside `-32002`.\n\n### 9. `tasks/list` — removed entirely\n\n> *\"The `tasks/list` method is removed — it was unsafe once protocol-level sessions were gone. There is no replacement listing method.\"*\n\n```ts\n// ❌ before\ncase 'tasks/list': return listTasks();\n\n// ✅ after — there is nothing to enumerate server-side. A client tracks the\n// task handles it got back from its own tools/call responses.\n```\n\n---\n\n## Needs manual review (not statically detectable)\n\n`mcp-vet` catches every 2026-07-28 change that has a concrete code-level signal (a header, a method string, an error code, a capability key). A few changes are real but **can't be found reliably by static analysis** — they're architectural or depend on runtime wiring. A clean scan is not a promise that these are handled, so check them by hand:\n\n- **The long-lived server→client SSE push channel is removed** — a server may only send requests to the client *while it is actively processing a client request*. Standing push streams / out-of-band notifications need rework.\n- **Streamable HTTP now requires `Mcp-Method` and `Mcp-Name` headers** that mirror the JSON-RPC body; servers must reject requests where headers and body disagree.\n- **Tool schemas may now be full JSON Schema 2020-12** (`oneOf`/`anyOf`/`$ref`/conditionals); do not auto-dereference external `$ref` URIs. The *dialect* half of this — schemas still declaring or using draft-07 forms — **is** detectable at runtime: [`mcp-vet probe`](#vet-a-running-server-mcp-vet-probe) checks it against your live server.\n\n(Until 0.9.0, *auth hardening* was on this list. It no longer is: the three\nauthorization MUSTs are covered by the `AUTH_*` static rules above and the\n`dcr-still-advertised` / `auth-metadata-missing-iss` probe checks. What remains\nuncovered is the helper-indirection recall boundary — see\n[Known limitations](#known-limitations).)\n\nThe CLI prints a one-line reminder of these after every scan.\n\n## Runtime conformance fixtures\n\nStatic analysis proves known legacy patterns are *absent* from your source. Only wire-level tests prove your running server actually *speaks* the 2026-07-28 contract. `mcp-vet` ships both halves:\n\n```bash\nnpx @booyaka/mcp-vet fixtures ./mcp-fixtures\n```\n\nwrites eleven ready-to-fire JSON fixtures plus a `CHECKLIST.md`, covering the runtime behaviors a linter cannot see:\n\n1. `server/discover` replaces the initialize handshake\n2. per-request `_meta` (protocolVersion, clientInfo, capabilities) — including explicit refusal when `_meta` is missing\n3. `Mcp-Method` / `Mcp-Name` routing headers, including the header/body-mismatch rejection case\n4. stateless auth context (no session-bound token cache)\n5. task-handle lifecycle: creation, `tasks/get` polling, resume on another instance, `tasks/list` and `tasks/result` returning method-not-found\n6. duplicate request delivery (idempotency under retries)\n7. retry against a different server instance (no sticky in-memory state)\n8. `tools/list` cache invalidation\n9. downgrade/refusal: old-revision requests get an explicit error, never silent acceptance under the wrong semantics\n10. `subscriptions/listen` opt-in: the client opts into specific types, the server acknowledges and tags notifications with `io.modelcontextprotocol/subscriptionId`, and `resources/subscribe` now answers `-32601`\n11. MRTR: the server returns `resultType: \"input_required\"` with `inputRequests`, and the client retries the **original** request carrying `inputResponses`\n\nEach fixture is a plain JSON description (`send` headers + JSON-RPC body, `expect` notes) you can replay with curl, supertest, pytest + httpx, or any HTTP harness. The checklist also spells out the **dual-version rollout matrix** — run both `2025-11-25` and `2026-07-28` paths until your clients have all moved — and a **client-side assumptions** list (session resume, per-request `_meta`, retries landing on other instances, `tools/list` revalidation).\n\n## Vet a running server (`mcp-vet probe`)\n\nWhere the scan reads your *source*, `probe` talks to your *running server* over the wire — stdio (a command it spawns) or Streamable HTTP (a URL) — and checks the 2026-07-28 violations that only exist at runtime (`run` is an alias: `mcp-vet run …` ≡ `mcp-vet probe …`):\n\n| ID | Severity | What it checks |\n| --- | --- | --- |\n| `json-schema-dialect` | 🟡 WARN | calls `tools/list` and inspects every tool's `inputSchema`/`outputSchema` for a pre-2020-12 JSON Schema dialect ([SEP-2106](https://modelcontextprotocol.io/seps/2106-json-schema-2020-12)) — an explicit draft-04/-06/-07 `$schema` (**high** confidence), or no `$schema` but draft-only keyword forms: `definitions` instead of `$defs`, `$ref: \"#/definitions/…\"`, boolean `exclusiveMinimum`/`exclusiveMaximum`, array-form `items` (**medium** confidence) |\n| `requires-initialize-handshake` | 🔴 ERROR | with `--spec-version 2026-07-28`: makes a **stateless first request** — no `initialize`, protocolVersion/clientInfo/clientCapabilities in namespaced `_meta` keys per the RC — and flags a server that rejects it or hangs waiting for the removed handshake. A valid `tools` array in the answer is asserted, not just a 200 |\n| `missing-server-discover` | 🔴 ERROR | with `--spec-version 2026-07-28`: calls the **`server/discover`** RPC that every 2026-07-28 server MUST implement ([SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575) — it replaces the handshake for up-front capability discovery) and flags a server whose answer is an error or lacks the required `capabilities` key. (The spec defines `server/discover` as JSON-RPC only — 2026-07-28 *removes* the HTTP GET endpoint, so there is no `GET /mcp/discover` to fall back to) |\n| `legacy-resource-error-code` | 🔴 ERROR | with `--spec-version 2026-07-28`: reads a deliberately nonexistent resource URI and flags a server that still answers with the MCP-custom **`-32002`** instead of the JSON-RPC standard **`-32602`** (Invalid Params). Servers without `resources/read` (`-32601`) are skipped, not flagged |\n\n```bash\n# vet the schemas of a stdio server (spawns the command; a lone .js file runs with Node)\nnpx @booyaka/mcp-vet probe node ./dist/server.js\n\n# full 2026-07-28 readiness: stateless first contact + server/discover +\n# resource error code + schema dialects\nnpx @booyaka/mcp-vet probe --spec-version 2026-07-28 http://localhost:3000/mcp\n```\n\n```text\nmcp-vet probe — node ./dist/server.js · spec 2026-07-28 · stdio · 12 tool(s) listed\n  stateless probe: stateless tools/list was rejected: -32002 Server not initialized\n  fallback probe: initialize handshake + tools/list succeeded\n  server/discover: rejected (-32601)\n  resource error-code check skipped — server does not implement resources/read (-32601)\n\nERROR  requires-initialize-handshake [high]\n    The server rejected (or hung on) a stateless 2026-07-28-style first request ...\nERROR  missing-server-discover [high]\n    The 2026-07-28 spec requires every server to implement the server/discover RPC ...\nWARN   json-schema-dialect [high]\n    tool \"echo\" inputSchema: $schema = http://json-schema.org/draft-07/schema# (draft-07)\n```\n\nThe stateless verdict is **cross-checked** before it becomes a violation: `requires-initialize-handshake` is only emitted when the classic `2025-11-25` handshake path *does* work — a dead or non-MCP server is an operational error (exit 2), never a false violation. The `server/discover` and error-code checks then run on whichever contact path succeeded, so even a handshake-only server gets its complete migration report in one probe. The dialect walker recurses only into schema positions (applicators like `properties`/`allOf`), so a *property* literally named `definitions` is never mistaken for the draft-07 keyword, and an explicit 2020-12 `$schema` declaration is trusted.\n\n### `--spec-version` — which revision to vet against\n\n| Value | Behavior |\n| --- | --- |\n| `2025-11-25` *(default)* | today's stable contract: classic `initialize` handshake, then the `json-schema-dialect` check. **No 2026-07-28 assertions run** — a fully 2025-era server probes clean |\n| `2026-07-28` | the full new-spec compliance suite: stateless first contact, required `server/discover`, `-32602` resource error code, plus the dialect check |\n\n**Migration note.** The default stays `2025-11-25` so existing CI invocations keep their exact behavior — add the flag when *you* are ready, not when the spec ships. A practical rollout:\n\n1. Today: `mcp-vet probe <server>` (unchanged) plus the static scan in CI.\n2. When you start migrating: add a second CI job with `--spec-version 2026-07-28 --fail-on none` to *see* the new-spec violations without failing the build.\n3. When your server targets `2026-07-28` (e.g. after moving to `@modelcontextprotocol/server` 2.x): drop `--fail-on none` so the three ERROR-level checks gate the build. A correctly migrated server passes all of them; the pre-migration server fails `requires-initialize-handshake` and `missing-server-discover` immediately.\n4. Keep a `2025-11-25` probe in the matrix until every client you serve has moved (the rollout is a window, not a day — see [What actually happens on July 28](#what-actually-happens-on-july-28)).\n\n### `--spec 2026-07-28` — the extra compliance suite\n\n`--spec` is a shorthand for `--spec-version` that **also** runs thirteen additional wire-level checks *on top of* the ones above. `--spec 2026-07-28` vets against the new revision **and** adds the suite; plain `--spec-version 2026-07-28` is unchanged and never runs it, so existing CI invocations keep their exact behavior.\n\n```bash\n# full readiness AND the extra compliance suite\nnpx @booyaka/mcp-vet probe --spec 2026-07-28 node ./dist/server.js\n```\n\n| ID | Severity | What it checks |\n| --- | --- | --- |\n| `stateless-no-session` | 🔴 ERROR | sends `tools/list` with **no** `Mcp-Session-Id` and flags a server that rejects it with a session error — sessions are removed on 2026-07-28 (SEP-2567), so a stateless request must be served |\n| `stateless-no-init` | 🔴 ERROR | sends `tools/list` with **no** `initialize`/`initialized` handshake and flags a server that rejects it as uninitialized — the handshake is removed (SEP-2575); a compliant server answers the first request directly |\n| `required-headers` | 🔴 ERROR | sends a request carrying the now-required `Mcp-Method` / `Mcp-Name` routing headers and flags a server that errors on them. Skipped for **stdio** targets (there are no request headers over stdio) |\n| `deprecated-sampling` | 🟡 WARN | observes a server-initiated `sampling/createMessage` request. Sampling is deprecated in 2026-07-28 and **eligible for removal July 2027** — migrate to a direct LLM provider API |\n| `deprecated-roots` | 🟡 WARN | flags a `roots/list` that returns a result — the roots capability is deprecated |\n| `deprecated-logging` | 🟡 WARN | observes a server-emitted `notifications/message` — the MCP logging protocol is deprecated; migrate to stderr (stdio) or OpenTelemetry |\n| `missing-result-type` | 🔴 ERROR | every result must carry `resultType` — `\"complete\"` or `\"input_required\"` (SEP-2322). Inspects `tools/list` plus `prompts/list`, `resources/list`, `resources/templates/list`; endpoints the server doesn't implement are skipped |\n| `missing-cacheable-fields` | 🟡 WARN | the cacheable list results must carry `ttlMs` and a `cacheScope` of `\"public\"` or `\"private\"` (SEP-2549) |\n| `legacy-error-code-renumbered` | 🔴 ERROR | sends an unsupported `protocolVersion` and flags a server still answering `-32001` / `-32003` / `-32004` instead of `-32020` / `-32021` / `-32022` |\n| `ping-still-answered` | 🟡 WARN | sends a `ping` and flags a server that returns a **result** instead of `-32601` — the method is removed |\n| `dcr-still-advertised` | 🟡 WARN | fetches the authorization-server metadata (RFC 9728 protected-resource lookup, then RFC 8414, falling back to the MCP origin) and flags one that still advertises `registration_endpoint` with **no** `client_id_metadata_document_supported` alternative — DCR is Deprecated in favour of Client ID Metadata Documents (PR #2858) |\n| `auth-metadata-missing-iss` | 🟡 WARN | flags authorization-server metadata that omits `authorization_response_iss_parameter_supported` — clients cannot rely on the RFC 9207 `iss` mix-up protection SEP-2468 requires them to validate |\n| `legacy-sse-transport` | 🟡 WARN | issues a fresh `GET` on the endpoint with `Accept: text/event-stream` after the standard probe completes, and flags a server whose answer is a 2xx `text/event-stream` stream that actually delivers an `event: endpoint` frame — the legacy two-endpoint HTTP+SSE transport (Deprecated, SEP-2596; the GET endpoint itself is removed by SEP-2575). A 405/404/non-SSE/JSON answer is a clean note; an SSE stream that never names an endpoint before `--timeout` is inconclusive, never a violation. Skipped for **stdio** targets |\n\nEvery one of these is cross-checked the same way the rest of the probe is — an\ninconclusive outcome is reported as a note, never as a violation, and a dead or\nnon-MCP server is an operational error (exit 2). The two auth-metadata checks\nspecifically: stdio targets skip them (well-known metadata is an HTTP concern),\nand a server that advertises no OAuth metadata at all is an inconclusive note —\nmany MCP servers use no OAuth, and that is not a violation. The two `stateless-*` checks\nspecifically: a server that answers a stateless, session-less, handshake-less `tools/list` passes both; one that rejects it is classified by *why* — a `session` error trips `stateless-no-session`, an `uninitialized` error trips `stateless-no-init` (a session rejection trips both, since a sessionful server is also not answering the first request directly). The two `deprecated-sampling` / `deprecated-logging` checks watch for server→client traffic for a short window (up to the spec's 5 s, bounded by `--timeout`) and report only what the server actually sends — a server that never samples or logs stays clean. The suite runs on its own fresh connection after the standard probe completes, so the ERROR checks above are unaffected.\n\nProbe findings use the same report formats as the scan: `--json` (machine-readable array on stdout) and `--sarif [file]` (SARIF 2.1.0 — `ERROR` maps to `error`, `WARN` to `warning`), plus `--fail-on breaking|any|none` (default `breaking`: exit 1 only on `ERROR`), `--timeout <ms>` (default 8000, also the hang-detection window), `--quiet`, and `--color`/`--no-color`.\n\nTry it against the official reference server — the July 2026 `@modelcontextprotocol/server-everything` (beta 2026-07-28 SDK) answers stateless requests and already returns the new `-32602` resource error code, but it does not implement `server/discover` yet and its tool schemas still declare draft-07 — `probe` reports exactly that (1 ERROR, 13 WARN):\n\n```bash\nnpx @booyaka/mcp-vet probe --spec-version 2026-07-28 npx -y @modelcontextprotocol/server-everything stdio\n```\n\n## Vet an Agent Plugins 1.0 package (`mcp-vet plugin`)\n\nAgent Plugins 1.0 went GA on 2026-08-12 in VS Code, Copilot CLI, the GitHub\nCopilot SDK, and the Copilot app, installed by default from the Awesome Copilot\nmarketplace. A plugin is a directory with a `plugin.json` manifest, an optional\n`skills/` folder, and an optional `mcp.json` declaring MCP servers, which makes\n`mcp.json` a first-class distribution channel for MCP servers.\n\nThe plugin format is one protocol revision behind the protocol it packages. The\n1.0.0 schema still accepts `type: \"sse\"`, which the MCP 2026-07-28 spec\nreclassifies as Deprecated (SEP-2596) and whose stream resumability it removes.\n\n**Schema-valid and spec-conformant are not the same thing here.** The published\n`plugin.schema.json` rejects two manifest conditions the spec requires clients\nto accept:\n[agent-plugins-spec#77](https://github.com/agentplugins/agent-plugins-spec/issues/77).\n§5.2 says clients *\"MUST report and ignore each unknown field and MUST continue\nloading the plugin\"*, and §8.1 says a non-object `extensions` means the client\n*\"MUST report and ignore the field and continue loading components\"* — but the\nschema closes the root (`additionalProperties: false`) and types `extensions`\nas an object, so a validate-and-reject tool calls both fatal. Since 0.13.0,\n`plugin.json` findings are therefore severity-split by what a conformant client\nactually does:\n\n- **FATAL** — a conformant client rejects the plugin (no manifest, unparsable\n  JSON, missing/wrong-typed required field, unrecognized `$schema` version, a\n  name outside §5.5). Exits 1.\n- **TOLERATED** — a conformant client reports the condition and keeps loading\n  (unknown top-level field §5.2, non-object `extensions` §8.1). Reported,\n  exits 0.\n- **INFO** — context only. One exists: alongside a §5.5 name violation,\n  mcp-vet notes that the official schema's negative-lookahead name pattern\n  cannot compile under RE2, so Go-based validators fail at schema compile time\n  instead of reporting the name\n  ([agent-plugins-spec#76](https://github.com/agentplugins/agent-plugins-spec/issues/76)).\n\nEvery envelope finding also carries the 1.0.0 spec `section` it cites — in the\nterminal (`§5.2` next to the rule id), the JSON report, and SARIF\n`properties.section`. And per §8.1's *\"MUST ignore manifest entries for\nnamespaces it does not implement without validating the contents of their\nvalues\"*, nothing inside `extensions` is validated at all — an unmodelled\nnamespace containing anything produces zero findings.\n\n```bash\nnpx @booyaka/mcp-vet plugin ./my-plugin\n```\n\nvets the whole package in one pass:\n\n1. **Envelope.** `plugin.json` and `mcp.json` against the canonical 1.0.0\n   schemas, vendored under\n   [`schemas/agent-plugins/1.0.0/`](./schemas/agent-plugins/1.0.0/) (fetched\n   2026-08-18 from\n   [plugin.schema.json](https://agent-plugins.org/schemas/1.0.0/plugin.schema.json)\n   and\n   [mcp.schema.json](https://agent-plugins.org/schemas/1.0.0/mcp.schema.json);\n   the skill-layout prose is pinned verbatim in\n   [`skill-layout.md`](./schemas/agent-plugins/1.0.0/skill-layout.md)).\n   Validation is offline, which the spec requires: clients MUST NOT retrieve a\n   schema while loading a plugin.\n2. **Semantics the schema can't express.** Single-token stdio commands, cwd\n   containment (`./../x` passes the schema's prefix pattern but escapes the\n   root), reserved env names, and the URL security rules.\n3. **The protocol inside the envelope.** A stdio server whose `command` is a\n   `./`-relative path into the plugin gets its bundled TS/JS/Python source\n   scanned with the same 22 static rules as `mcp-vet <paths>`, reported\n   plugin-relative with `file:line:col`. Servers that can't be scanned are\n   never silently skipped: a bare launcher token (`npx`, `uvx`, `node`,\n   `python`) is reported as unscannable by design with the reason printed, and\n   remote entries point you at `mcp-vet probe <url>`.\n\n### The new rules\n\n| Rule | Tier | Fires when |\n| --- | --- | --- |\n| `PLUGIN_MANIFEST_INVALID` | 🔴 FATAL | `plugin.json` violates a requirement conformant clients reject: absent manifest or unparsable JSON (§5.1), a missing/wrong-typed/empty required field (§5.3), an unrecognized `$schema` version (§5.2), or a `name` breaking §5.5's 1–64-char lowercase pattern (no `--` or `..`) |\n| `PLUGIN_UNKNOWN_FIELD` | 🔵 TOLERATED | an unknown top-level manifest field. §5.2 makes clients report and ignore it and keep loading, so mcp-vet reports it and exits 0. A field named `skills` or `mcpServers` gets a note that those components will not load (§6.1 discovers them from `skills/` and `mcp.json` only) |\n| `PLUGIN_EXTENSIONS_NOT_OBJECT` | 🔵 TOLERATED | `extensions` is a string, number, array or null. §8.1 makes clients report and ignore the field and continue loading components. Fires exactly once, never per interior key |\n| `PLUGIN_NAME_RE2_LOOKAHEAD` | ⚪ INFO | rides along with a §5.5 name violation: the official schema's negative-lookahead pattern does not compile under RE2, so Go-based validators error out at schema compile time instead of reporting the name (spec issue #76) |\n| `PLUGIN_MCP_INVALID` | 🔴 BREAKING | `mcp.json` fails the 1.0.0 MCP schema. The root must be exactly `$schema` + `mcpServers`, and each server must match exactly one closed variant (`stdio`, `streamable-http`, `sse`). Unknown types, cross-variant fields, and containment failures land here |\n| `PLUGIN_CMD_NOT_SINGLE_TOKEN` | 🔴 BREAKING | a stdio `command` is not a single executable token, bare or beginning with `./`. Clients don't shell-split: `\"node server.js\"` is looked up as an executable literally named `node server.js` |\n| `PLUGIN_CWD_ESCAPE` | 🔴 BREAKING | `cwd` doesn't start with `./`, `${PLUGIN_ROOT}` or `${PLUGIN_DATA}`, or starts with `./` but resolves outside the plugin root |\n| `PLUGIN_ENV_RESERVED` | 🔴 BREAKING | `env` contains an entry named `PLUGIN_ROOT` or `PLUGIN_DATA`. The spec reserves both, and such an entry makes the server configuration invalid |\n| `PLUGIN_REMOTE_INSECURE_URL` | 🔴 BREAKING | a `streamable-http`/`sse` `url` is not an absolute HTTP(S) URL, carries user information or a fragment, or uses plain HTTP on a non-loopback host. Loopback means exactly `localhost`, `127.0.0.0/8`, or `[::1]`. The spec says *non-loopback*, not *non-localhost*, so `http://127.0.0.1:3000/mcp` and `http://[::1]:3000/mcp` are fine |\n| `PLUGIN_SSE_TRANSPORT` | 🟡 DEPRECATED | any server declares `type: \"sse\"`, the HTTP+SSE transport the MCP 2026-07-28 spec reclassifies as Deprecated (SEP-2596; the source-side counterpart is `SSE_TRANSPORT_DEPRECATED`) |\n| `PLUGIN_SKILL_LAYOUT` | 🟡 DEPRECATED | a `SKILL.md` sits anywhere other than `skills/<name>/SKILL.md`. Clients MUST NOT recurse deeper, so a nested skill isn't an error. It's silently invisible, which is worse |\n\n### Worked example\n\nGiven a plugin whose `mcp.json` is:\n\n```json\n{\n  \"$schema\": \"https://agent-plugins.org/schemas/1.0.0/mcp.schema.json\",\n  \"mcpServers\": {\n    \"legacy\": { \"type\": \"sse\", \"url\": \"http://example.com/mcp\" },\n    \"local\": { \"type\": \"stdio\", \"command\": \"node server.js\", \"cwd\": \"../shared\" }\n  }\n}\n```\n\n`mcp-vet plugin ./my-plugin` reports (fixture-locked in\n`test/fixtures/plugins/worked-example`):\n\n```text\nmcp.json:5:7   DEPRECATED  PLUGIN_SSE_TRANSPORT         legacy: type \"sse\" is the HTTP+SSE transport, Deprecated by MCP 2026-07-28 (SEP-2596)\nmcp.json:6:7   BREAKING    PLUGIN_REMOTE_INSECURE_URL   legacy: non-loopback host \"example.com\" over plain HTTP — non-loopback endpoints MUST use HTTPS\nmcp.json:10:7  BREAKING    PLUGIN_CMD_NOT_SINGLE_TOKEN  local: \"node server.js\" is 2 tokens — clients do not shell-split, so pass arguments via \"args\"\nmcp.json:11:7  BREAKING    PLUGIN_CWD_ESCAPE            local: \"../shared\" does not start with ./, ${PLUGIN_ROOT} or ${PLUGIN_DATA}\n\n4 finding(s): 3 BREAKING, 1 DEPRECATED   → exit 1\n```\n\nAnd the TOLERATED side, on the manifest shape reported in\n[dotnet/skills#1087](https://github.com/dotnet/skills/issues/1087)\n(fixture-locked in `test/fixtures/plugins/dotnet-1087`) — `plugin.json`\ndeclaring `\"skills\": []` and `\"mcpServers\": {}` at the top level:\n\n```text\nplugin.json:4:3  TOLERATED  PLUGIN_UNKNOWN_FIELD §5.2 [high]\n    unknown top-level field \"skills\" — a conformant client reports this and continues loading;\n    note: skills declared here will NOT load — §6.1 discovers skills only from the skills/ directory\nplugin.json:5:3  TOLERATED  PLUGIN_UNKNOWN_FIELD §5.2 [high]\n    unknown top-level field \"mcpServers\" — a conformant client reports this and continues loading;\n    note: MCP servers declared here will NOT load — §6.1 discovers MCP servers only from mcp.json at the plugin root\n\n2 finding(s): 2 TOLERATED   → exit 0\n```\n\nBefore 0.13.0 those were two schema violations and an exit 1 — mcp-vet said\nthe plugin was broken while every conformant client loads it.\n\n### Edge cases it gets right\n\n- A missing `mcp.json` is valid and silent (spec §6.2: an absent component\n  location MUST NOT be treated as an error), and `mcpServers` may legally be\n  empty.\n- A reverse-domain top-level directory such as `com.github.copilot/` is a\n  legal client-extension directory and is ignored, not flagged.\n- A `$schema` pinning a version mcp-vet does not know stays FATAL — §5.2 makes\n  clients reject an unrecognized version, so that is not a tolerated drift.\n- `extensions` set to a string is TOLERATED exactly once, not once per\n  interior key; an unmodelled namespace whose value is an object containing\n  anything at all produces zero findings (§8.1).\n- A plugin bundling a non-source executable (say a compiled binary) as its\n  server gets an explicit \"can't audit this\" note, not silence.\n\n`--json`, `--sarif`, `--fail-on`, and the exit-code contract are shared with\nthe scan: any FATAL or BREAKING finding exits 1; TOLERATED, DEPRECATED and\nINFO exit 0 (`--fail-on any` still fails on them); unusable input exits 2.\nIn SARIF, TOLERATED and INFO map to level `note`.\n\n## Where mcp-vet fits (and where it doesn't)\n\n**The probe half is not novel, and this README won't pretend otherwise.** Other\ntools already check a running server over the wire, and some of them already\ncover ground the `--spec 2026-07-28` suite covers:\n\n| Tool | What it is | Overlap |\n| --- | --- | --- |\n| [`@modelcontextprotocol/conformance`](https://github.com/modelcontextprotocol/conformance) — `npx @modelcontextprotocol/conformance server --url <url>` | The **official** wire test suite. Its README notes that *\"dated versions through 2025-11-25 use the stateful lifecycle (initialize handshake), while the 2026 draft (2026-07-28) uses the stateless lifecycle (per-request `_meta`)\"* | The authority on wire conformance. If you can boot your server, **run it** — it is more complete at the protocol level than any third-party probe, mcp-vet's included |\n| [`mcp-spec-check`](https://www.npmjs.com/package/mcp-spec-check) (Roee-Tsur) | Zero-install black-box URL probe for 2026-07-28 readiness | Already ships cache-metadata, MRTR and resources-subscribe checks — genuinely prior art for three of mcp-vet's thirteen `--spec` checks |\n| [`mcpfit`](https://github.com/printemps-tokyo/mcpfit) (printemps-tokyo) | Go CLI auditing a running server against the stateless spec | Already ships a `cache-hints` check for `ttlMs`/`cacheScope` |\n| [`@hiai-gg/agent-plugins-doctor`](https://www.npmjs.com/package/@hiai-gg/agent-plugins-doctor) (0.0.6, 2026-08-08) | Agent Plugins envelope validator: plugin.json/mcp.json/SKILL.md against the 1.0.0 spec, secret/path-traversal auditing, a client compatibility matrix, 12 autofixes | Real overlap on the *envelope* (`PLUGIN_MANIFEST_INVALID`/`PLUGIN_MCP_INVALID` territory). It says nothing about MCP protocol revisions, the SSE deprecation, or the server source a plugin bundles. That protocol-inside-the-envelope audit is what `mcp-vet plugin` adds |\n\n**The uncontested claim is the other half: static source analysis.** mcp-vet\nreads your *source* — TypeScript/JavaScript via ts-morph, Python via a bundled\n`ast` script — and reports `file:line:col`, SARIF, and `--fix`. That means:\n\n- **It runs in CI on a pull request**, before anything is deployed, without\n  booting a server, provisioning a URL, or having a working build.\n- **It points at the line to change**, not at a wire symptom. A probe can tell\n  you a result lacks `resultType`; only source analysis tells you\n  `src/handlers/tools.ts:142` is the return statement that omits it.\n- **It fixes what is mechanical** — `--fix` rewrites `-32002 → -32602` and the\n  three renumbered codes in place, with `--dry-run` to preview.\n- **It covers code paths a probe never reaches** — an error branch that fires\n  once a month, a client-side session resume, a handler registered but not\n  exercised by a smoke test.\n\nThe two halves are complements, not competitors. The honest recommendation:\n**static scan in CI on every PR (mcp-vet), official conformance suite against a\ndeployed instance before release.** mcp-vet ships the probe so you can get a\nfirst signal without wiring up a second tool — not as a replacement for the\nofficial suite.\n\n## Usage\n\n```bash\nnpx @booyaka/mcp-vet [paths...]        # scan directories and/or files (default: current directory)\nnpx @booyaka/mcp-vet . --fix           # scan, and auto-apply the mechanical -32002 → -32602 rewrite\nnpx @booyaka/mcp-vet ./src ./packages  # multiple roots\nnpx @booyaka/mcp-vet server.py         # a single file\nnpx @booyaka/mcp-vet fixtures ./dir    # write runtime conformance fixtures + checklist (default: ./mcp-vet-fixtures)\nnpx @booyaka/mcp-vet probe <url|cmd>   # vet a RUNNING server's wire behavior (see section above; alias: run)\nnpx @booyaka/mcp-vet plugin <dir>      # vet an Agent Plugins 1.0 package (envelope + bundled server source)\n```\n\nGlobs `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` and `**/*.py`, skipping `node_modules`, `.git`, `__pycache__`, `dist`, and `build`.\n\n### Options\n\n| Flag | Description |\n| --- | --- |\n| `--github-annotations` | emit GitHub Actions `::error` / `::warning` annotations to stdout |\n| `--sarif [file]` | write a SARIF 2.1.0 report (default `mcp-vet.sarif`) for GitHub code scanning |\n| `--out-dir <dir>` | where to write `mcp-vet-report.md` / `mcp-vet-results.json` (default: cwd) |\n| `--no-files` | don't write the markdown/json report files |\n| `--only <ids>` | only run these rule ids, comma/space separated (spec, `PY_SDK_V1_*` or `TS_SDK_V1_*`) |\n| `--disable <ids>` | skip these rule ids |\n| `--fail-on <level>` | non-zero exit on `breaking` (default), `any`, or `none` |\n| `--fix` | auto-apply the safe mechanical fixes in place (currently `-32002` → `-32602`) |\n| `--dry-run` | with `--fix`: print the rewrites that would be made, without changing files |\n| `--json` | print findings as a JSON array to stdout (pure JSON — notices go to stderr) |\n| `--min-confidence <level>` | report only findings at/above `high`, `medium`, or `low` (default) |\n| `--ignore <glob>` | ignore paths matching a gitignore-style glob (repeatable) |\n| `--max-file-size <kb>` | skip files larger than N KB (default 1536; `0` = no limit) |\n| `--no-py-fallback` | disable the regex fallback used when no Python interpreter is found |\n| `--py-sdk <mode>` | Python SDK v1→v2 migration rules: `auto` (default; reads the declared `mcp` specifier), `v1`, or `v2` |\n| `--no-py-sdk` | disable the `PY_SDK_V1_*` rule group entirely (pre-0.12.0 output) |\n| `--ts-sdk <mode>` | TypeScript SDK v1→v2 migration rules: `auto` (default; reads the declared `@modelcontextprotocol` packages), `v1`, or `v2` |\n| `--no-ts-sdk` | disable the `TS_SDK_V1_*` rule group entirely (pre-0.14.0 output) |\n| `--config <path>` | path to a config file (see below) |\n| `--color` / `--no-color` | force or disable colored output |\n| `--quiet` | suppress the human-readable terminal report |\n| `-v, --version` | print version |\n\n### Suppressing findings inline\n\nRecognized in any comment style (`//` or `#`):\n\n```ts\nconst x = -32002; // mcp-vet-disable-line ERROR_CODE_32002\n// mcp-vet-disable-next-line\nconst y = 'Mcp-Session-Id';\n```\n\n- `mcp-vet-disable-line [IDS]` — suppress on the same line.\n- `mcp-vet-disable-next-line [IDS]` — suppress on the following line.\n- `mcp-vet-disable-file` — suppress the whole file.\n\nOmitting the ids suppresses **all** rules on that line/file; listing ids (e.g. `ERROR_CODE_32002`) suppresses only those. Any rule id works, including the `PY_SDK_V1_*` and `TS_SDK_V1_*` groups. An id the parser does not recognize is ignored, so a typo falls back to suppressing everything on the line — check `mcp-vet --only <id>` if a suppression is wider than you meant.\n\n### Config file\n\nDrop a `.mcpvetrc.json` (or `mcp-vet.config.json`) in your project root; CLI flags override it.\n\n```json\n{\n  \"ignore\": [\"**/generated/**\", \"vendor/\"],\n  \"disable\": [\"LOGGING_CAP\"],\n  \"failOn\": \"breaking\",\n  \"minConfidence\": \"medium\",\n  \"maxFileSizeKb\": 2048,\n  \"pythonFallback\": true,\n  \"pySdk\": \"auto\",\n  \"tsSdk\": \"auto\"\n}\n```\n\n`only` / `disable` accept any rule id, including the `PY_SDK_V1_*` and\n`TS_SDK_V1_*` groups. A JSON Schema for the file ships as\n[`schema/mcpvetrc.schema.json`](schema/mcpvetrc.schema.json) — point `$schema`\nat it for editor autocomplete.\n\nYou can also list ignore globs one-per-line in a `.mcpvetignore` file.\n\n### Outputs\n\n1. **Terminal** — compiler-style `file:line:col`, red for BREAKING, yellow for DEPRECATED, grouped by file, with before/after snippets and a `[confidence]` tag.\n2. **`mcp-vet-report.md`** — a Markdown table (File · Line · Pattern · Severity · Confidence · Explanation).\n3. **`mcp-vet-results.json`** — a structured JSON array of every finding (line, column, confidence, docUrl, before/after, source analyzer, and `section` — the Agent Plugins 1.0.0 spec section on envelope findings, `null` elsewhere).\n4. **`--github-annotations`** — native GitHub Actions annotations that surface inline on the PR diff.\n5. **`--sarif`** — SARIF 2.1.0 for GitHub Advanced Security \"code scanning\" (uploads via `github/codeql-action/upload-sarif`).\n\n### Exit codes\n\n- `0` — clean, only DEPRECATED findings, or `--fail-on none`.\n- `1` — findings that trip `--fail-on` (BREAKING by default).\n- `2` — operational error (bad path, unreadable config, invalid flag/rule id).\n\n---\n\n## Use it in CI\n\n```yaml\n# .github/workflows/mcp-vet.yml\nname: mcp-vet\non: [push, pull_request]\njobs:\n  vet:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v7\n      - uses: actions/setup-node@v7\n        with: { node-version: '20' }\n      - run: npx @booyaka/mcp-vet . --github-annotations\n```\n\n`setup-node` runners already include Python 3, which `mcp-vet` uses to scan `.py` files. If no interpreter is found, it automatically falls back to a regex scanner (reduced precision) unless you pass `--no-py-fallback`; TypeScript/JavaScript scanning is unaffected either way.\n\nTo upload results to GitHub code scanning instead:\n\n```yaml\n      - run: npx @booyaka/mcp-vet . --sarif mcp-vet.sarif --fail-on none\n      - uses: github/codeql-action/upload-sarif@v4\n        with: { sarif_file: mcp-vet.sarif }\n```\n\n### Local git hooks\n\nCatch it before it reaches CI. With [husky](https://typicode.github.io/husky/) + [lint-staged](https://github.com/lint-staged/lint-staged):\n\n```json\n// package.json\n{\n  \"lint-staged\": {\n    \"*.{ts,tsx,js,jsx,mjs,cjs,py}\": \"mcp-vet\"\n  }\n}\n```\n\nOr with [pre-commit](https://pre-commit.com) (Python projects):\n\n```yaml\n# .pre-commit-config.yaml\nrepos:\n  - repo: local\n    hooks:\n      - id: mcp-vet\n        name: mcp-vet\n        entry: npx @booyaka/mcp-vet\n        language: system\n        files: \\.(ts|tsx|js|jsx|mjs|cjs|py)$\n```\n\n### Why there's no `--baseline`\n\nSome linters let you \"grandfather\" existing findings so CI stays green. `mcp-vet` deliberately doesn't: this is a **one-time migration to a spec that ships on a fixed date**, and a suppressed finding is code that will break on July 28. The point is for the build to fail until it's actually fixed. For the rare intentional exception, use targeted [inline suppression](#suppressing-findings-inline) — an explicit, reviewable, per-line decision.\n\n### Large repositories\n\n`mcp-vet` skips `node_modules`, `.git`, `dist`, `build`, and `__pycache__` by default, chunks the Python subprocess, and takes `--max-file-size`. On a big monorepo, scope the scan to the packages that ship MCP servers (`mcp-vet ./packages/server ./services/mcp`) and add `--ignore` globs for generated code.\n\n---\n\n## How it works\n\n- **TypeScript / JavaScript** — parsed with [`ts-morph`](https://ts-morph.com); the analyzer walks the AST and emits normalized tokens (string literals, signed numeric literals, identifiers, object keys) annotated with structural capability context and registration context.\n- **Python** — a bundled script (`dist/python/mcp_ast_scan.py`) runs `ast.parse` + a context-tracking walk in a subprocess (chunked for large repos) and emits the same token shape (with character-accurate columns). When no interpreter exists, a regex fallback covers the deterministic rules.\n- A single rule engine applies all 22 protocol rules to those tokens, so TS and Python behave identically. Findings are de-duplicated per (line, column, rule) and can be suppressed inline. The two SDK-migration groups run alongside it, gated on the declared SDK version, and de-duplicate per (line, rule) — one import list is one thing to fix.\n\nIt matches the w","readmeFilename":"README.md"}