{"_id":"@cyanmycelium/mcp-core","_rev":"15-2fd5c414b26c637cd24506eedd03d710","name":"@cyanmycelium/mcp-core","dist-tags":{"latest":"1.4.0"},"versions":{"0.1.0":{"name":"@cyanmycelium/mcp-core","version":"0.1.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.1.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"c0f075fa209f777a2450b6ea19467ad64c4861c1","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.1.0.tgz","fileCount":123,"integrity":"sha512-3AHbiUdaMfn+vT3863tqiG17CWzpJq3DOV42EaeoXtvLhUz7Hvq1QabUvSWq3ECsmkKUwuqv7asetTcokXm4zg==","signatures":[{"sig":"MEYCIQCRh1dMX8pW0jpWGiD4sYJxchD7XII/jU4gjkOo3n2C/AIhAK9Iw/mnFCMaxr2z1A+l2ZZg1Yvrw2230WIH5kwORajP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":592318},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"638b711df91bc49c5c3a0b5483a4f7cccc985a0d","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"npm run clean && npm run compile","clean":"rimraf dist tsconfig.build.tsbuildinfo","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest"},"_npmUser":{"name":"gaume","email":"gaume.pelletier@gmail.com"},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"10.9.3","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"22.20.0","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.1.0_1779179394962_0.5726156217484819","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cyanmycelium/mcp-core","version":"0.1.1","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.1.1","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"9187e210b0554b7298f9c91fbec9af760410926f","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.1.1.tgz","fileCount":52,"integrity":"sha512-XsOosQoqynZF/Sq+S7LSkYR5nsRHx+jnkMyRuVyHe7GbsKHrntuFxFryncNrNYl0mGLV4xka6d3hy+umyGssaA==","signatures":[{"sig":"MEUCIBIothOyTbWaRg1/4NKWd/pCk8hGUyodD3QOghoIisTjAiEAzpynSCDL1Hst/x0eZ5rPv1/k0DrSuAhNeGIm59mmnp8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":729026},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"54b439174b3a14ccd1a2a466e48e2bd7b4a2dd96","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.14.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.1.1_1779194443933_0.8619209604119056","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cyanmycelium/mcp-core","version":"0.2.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.2.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"52584d4bfddb91db63b58b27304f3bbe63f51b31","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.2.0.tgz","fileCount":52,"integrity":"sha512-HjwAFusxqByFbKOXztk7TT9VQedf+xU7lb7LEm0NHr9bVU3CGkVfha6FYsv3BiFBDT2yVTAgT20oIkpnuNso4Q==","signatures":[{"sig":"MEUCIA7Nvu8uTOK862/W9hBlLxnBUv76YQ+xy9NOHONqsjC4AiEAoZZhFOpPGOe68O19rjN6MEce7cz2cgWc+7ukWZuK/y4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":782329},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"0a9d0f6a69893ed1573b4e284ee647a27a61a321","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.14.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.2.0_1779205583832_0.5660813858619602","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@cyanmycelium/mcp-core","version":"0.2.1","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.2.1","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"341849cb06787a660cba896d1c47292fcbbcced5","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.2.1.tgz","fileCount":52,"integrity":"sha512-jkSJD2sMbBoapL4ECyXg2+nLaxg/Xk8ejGAfnaey3FLv1C9Vsol/3c5PgSnnQ+EZoZWSkCzZxzX77FhIBICYVw==","signatures":[{"sig":"MEQCIA9oQix4GGPJWucJsHYzDNJmhuTX7UVU+1biTlVboVO+AiA5S49K/07RNxRkBBLE/91pS2LE9nxIC1B1jT4YDoUu0g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":786926},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"7fd4508c118ad2b33b2970302d239704f0ee135e","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.15.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.2.1_1779463642385_0.9441069112069582","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@cyanmycelium/mcp-core","version":"0.3.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.3.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"36efded1713995bd9987d7cf14a7824d5a39537b","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.3.0.tgz","fileCount":53,"integrity":"sha512-rU/3XKpMmTp/LEfpDswIlKI6uCb1TSInzmg8XZiOSxhIzbDtpQqWb/bKAVcqKk8IidmlMITE0pFMzpZ3+6I0UQ==","signatures":[{"sig":"MEUCIQDuiChays448/5jrtRwzBHnModjcFcSFXVv6iEs3TspfwIgLgo8jvLEvM24T6NGFhC3jSprq1P/siH4VpjYEMibZ/k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":908879},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"8d7eca19742324f79fadc1a602bfe443e7d18231","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.15.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.3.0_1779889681167_0.16324228013406983","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@cyanmycelium/mcp-core","version":"0.4.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.4.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"8e16ccdf98549949c096960d5f1e670a73ada777","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.4.0.tgz","fileCount":55,"integrity":"sha512-azKAH/qSqGau8Efe4hWt8Pg9V1Pz66QBKL1utFEtWfEBUUuFhi8QkDY1Ar9xuocxelWzp7SR/DUYHXVKa2PUtw==","signatures":[{"sig":"MEUCIA3RjKuNrJgHEdIwwil2uMscJDH51OyHbiW0/c/DdtFhAiEA8bVDTK/PPctMrD8UAZjVhYCE0DxeO0y2u5a2HOXbz6k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1089813},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"b042b0ba8d58a751eb29fa68075b2e2e43b65cee","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.18.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.4.0_1785170385292_0.2996147568023937","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@cyanmycelium/mcp-core","version":"0.5.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.5.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"dd505a0a5508dcd32192f069bc34da7bc45ddb00","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.5.0.tgz","fileCount":53,"integrity":"sha512-HUzm8RLnlks1Jvim+eJk1XGJLli+Mp1Q7+zTXF2fZLwbayzMWJ5dJPzkyQ33VywuH2Gv3dgvQVm9EqOQpl2tYg==","signatures":[{"sig":"MEUCIA33nDm+kqJTVwCM95CY4MZRofWlHCSn78Ok0JtPLfC0AiEAwlwRDRpsAhEotIQc1jl9WN6Sm/Odt465WJAF7p7ifNA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1012652},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"f8781cba49f69e0e2afe4f893d42a1e638201928","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsc -b tsconfig.build.json -w","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","compile":"tsc -b tsconfig.build.json","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.18.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.5.0_1785175139308_0.9275936968919665","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@cyanmycelium/mcp-core","version":"0.6.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.6.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"c2d4c40f66245bcc63bf8ffe4c05898d7744eb02","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.6.0.tgz","fileCount":57,"integrity":"sha512-An+lUM/kV4TQt39yTlJ0TERmQZxxzRebnBfHrbj1jOzEFdg00ZLWQ2V1XG3mXRaBmAk/U+84u3AU9tdZOFAdMg==","signatures":[{"sig":"MEUCIQDaYBGmdhG45fo8fOM2CZqjaMPZw5OG3mNYz3PYb8sHXAIgUqgSX4GrotY6sUN1XKREToS1qkCYJhopeef07qDBtYo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1151824},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"54801df9c02f0e2b7cb172a85043820ce49e70fb","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.18.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.6.0_1785229311286_0.33519256233640915","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@cyanmycelium/mcp-core","version":"0.7.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@0.7.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"60dc04c4d18348c8a19fbecd7a1959da6af953b3","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-0.7.0.tgz","fileCount":58,"integrity":"sha512-PqLYKLAJj7hIQqkxlk+hUgjjPC2XuDvz9cNBeiWF3s/0sklJLqr13XlhVU8vu3vQz6MfQ9//gm2/fVFD2nCdog==","signatures":[{"sig":"MEYCIQD2PCpZnwDQii4MdcGA6lGQoGPE18EGbIXGXkPdQ3i/AQIhAORezZPGG5bxinM3v8Zk2RVjJ86t7YqXtq7bEZ5vIR6+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1184688},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"56039b698abe19f4721495bb0a0dafc26e96a0e8","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.18.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_0.7.0_1785231468967_0.03941471947149222","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@cyanmycelium/mcp-core","version":"1.0.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@1.0.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"450b7945e6208271e8bdcfcf71fecb7e140ad539","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.0.0.tgz","fileCount":58,"integrity":"sha512-VKc3iqwgkAB6gznAqzFhFjYWy9d05BlPTKpb8W/NgScb+kYB3YbU6l9QhO+sR/6Ysz9sRCr7tmLa010fPQzmCw==","signatures":[{"sig":"MEQCIHOISN4sOMii7m97vVzhbKpPeq4sBguDmeEOFfXmROvDAiAej9TvraxfjNuQuqKWqM28C4wMb+FgDn4d+2mhCFYcYg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDaFEJY/z5WX7kHrB5l4RuCZ7oo3O4Umo1R3AAOtH7WyAiBfRkiOy3yyqCDboMexG5klPsPEz7WosNobsB/tU7x//g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1225377},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"4efac00c3ee88d45d009ad33d902902148990ebf","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.19.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_1.0.0_1789230797783_0.1355286347982776","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cyanmycelium/mcp-core","version":"1.1.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@1.1.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"3f2b13312ef5942a217fcc229ce14d715975e589","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.1.0.tgz","fileCount":59,"integrity":"sha512-zyiGul2MNssA08p7dk4nei6JXJyw2mpFvCZMZgDhc0QVOdlmyfRACAZ5276+n8i5MCqdIbYRWOpSDhykpgMjIA==","signatures":[{"sig":"MEYCIQC7/Y5bEWoe+YnjoouKMyGliUOwQnEt3h1sDirNguOTtgIhAPEi7WFBlY+zWl/2Tl0AndAWpHLqCmxoWIf8qR1Cs42W","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC7BSRno2AWuQKQ2Kpm/+ht9EsO4mkNmNlXuU4pI7SDaQIgL/OPRsj5hgFwysnDLvvYAsnKkoTOlslD6+tdA2g90MU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1343668},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"1273ab042c32f88277c015dc4b1bf637fb683e48","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.19.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_1.1.0_1789981410871_0.6925556080217568","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@cyanmycelium/mcp-core","version":"1.2.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@1.2.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"082d4a9b9f1c72c069dd8a9c0d9dd266db7dfb69","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.2.0.tgz","fileCount":59,"integrity":"sha512-qAmwlyPPrIkKB9+LvZsQ4o6iNRRCi403PUIcAPouGCBGTAbjaLaTEqquPop58kXk0P7Dd1ggBFuzGoEP9E403w==","signatures":[{"sig":"MEYCIQDQGj9LqNGHX4/lAm9PMPHtauiRGG6s9E04oxzvXWw6WgIhAJlDq8T2Yjga6HLjCMNEPwQGSUfnr1eE+5BSvLdNP3kf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDXRjb+Y9kqDmcY2CZqzxL+TVzVK+gNW9r+AQUqBiw0vAiAAkZkyhLhek6GbGlTCIJm06OSveDUL+Z0Plv1xPDY16A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1396333},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"4ae033558a6deb0ac0c95ee4853945e0625d9d6c","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.19.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_1.2.0_1789990675731_0.4285156009931632","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@cyanmycelium/mcp-core","version":"1.2.1","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@1.2.1","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"3050e073292981b28a7ce4a61379f98917c886d6","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.2.1.tgz","fileCount":59,"integrity":"sha512-Goh8kZI+ALMGzkQvn8VJpMJ1vZDyCtNSaoKb/QfD0OaBonKFnA4rRicuyD0aW/7cECDL6arKJ54oE7imG0uXqg==","signatures":[{"sig":"MEYCIQDqOP1nsYLHvGVc1i/0/3sMEk0wZ3CrienqA93KjKctEAIhANmPg5Zqt+hNBKQ049sUnMHxYARywmjdwHPGymJ+2Xab","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC8QTEN7H4HnFVmbVnsz1vT4r/IMri2UZRiN8XCeET44QIhAL0ZEnpP/EhRCR7W/3gu7ewx/dPEYXhwd/cbThIE4Fqm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1397015},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"ec43126387dda9233f8da569a6fd1fe4104ffc5b","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.19.1","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_1.2.1_1789991732458_0.2507110204572387","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@cyanmycelium/mcp-core","version":"1.3.0","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","_id":"@cyanmycelium/mcp-core@1.3.0","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"homepage":"https://github.com/pandaGaume/mcp-core#readme","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"f6c20d8f1a956cfa46c2a54b116b1bbbf09f6faf","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.3.0.tgz","fileCount":61,"integrity":"sha512-3DsWIl7AKQkqQoxT4Wa3TqVQTwqPf5rAdUPYnPFHBB5lbest/MGb8rf/eZuhwFg4kPxjUbrz4jRNxQDUnuvjHw==","signatures":[{"sig":"MEQCICt3tYBGQO8yPRjWUhgraB1YFIfAAoRr5u1Bp1yO1EcoAiBFVSyL1XMp/yRL874C5mPfnl2yjY05ZHS93FN3zHFNpw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDN2HgEMlc7dwXf3BP761EmbMLsieyd2Wts8uV+g0ptrAiEAjLcBDvPRSkHSsit/UvjZsg1mho6zHl+t0Z2Dyga4Jco=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1605411},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"8a9ff56118b25da14bf338663c846106ac88a350","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"df6c5824-8bf8-4339-920b-5a949bc57127"}},"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.20.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-core_1.3.0_1790766249107_0.6403967542141529","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"_id":"@cyanmycelium/mcp-core@1.4.0","bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"dist":{"shasum":"b7d082ecd2248a2d4ec0f0ce9c5c2cb23a6a36f1","tarball":"https://registry.npmjs.org/@cyanmycelium/mcp-core/-/mcp-core-1.4.0.tgz","fileCount":61,"integrity":"sha512-+4UZu2+rpPlZmnMfv0XnUPIoaxL9uxuPPbh/i0Nx51A0wl4/hQhpnBaDYqGqTy4s3h8WtHpHBJ2H+Hnetn5MpA==","signatures":[{"sig":"MEYCIQDNYewEbFOP7iOadjJkznPkc31JOHeKyuglaBVNluOxhAIhAIjdfvTuVuOfQNAI/yxqArCXvxWstnKWk+rGm7i/4vI2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCQdnDI54XpUW+HV+WmgnUTkIx5+ZDC9hkZNTUaJCz9hwIhAPcI+s9rlKllDSZ0CEG8Y5tSoTll2HQPXdR7ZNLXuwZd"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cyanmycelium%2fmcp-core@1.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1623077},"main":"./dist/index.js","name":"@cyanmycelium/mcp-core","type":"module","types":"./dist/index.d.ts","author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"module":"./dist/index.js","engines":{"node":">=20.11.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./llm":{"types":"./dist/llm/index.d.ts","import":"./dist/llm/index.js","default":"./dist/llm/index.js"},"./node":{"types":"./dist/node/index.d.ts","import":"./dist/node/index.js","default":"./dist/node/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./dist/server/index.js"}},"gitHead":"358d31969537e369b2d03c914a248ac7816d773b","license":"Apache-2.0","scripts":{"lint":"eslint \"src/**/*.ts\" \"tests/**/*.ts\"","test":"vitest run","build":"tsup","clean":"rimraf dist","watch":"tsup --watch","format":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix","typecheck":"tsc -p tsconfig.json --noEmit","format:fix":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","test:watch":"vitest","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags"},"version":"1.4.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"df6c5824-8bf8-4339-920b-5a949bc57127"}},"homepage":"https://github.com/pandaGaume/mcp-core#readme","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"_npmVersion":"11.21.0","description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","directories":{},"maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"sideEffects":false,"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","tslib":"^2.8.1","eslint":"^8.57.0","rimraf":"~6.0.1","vitest":"^1.6.0","prettier":"^3.2.0","typescript":"^5.4.0","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-core_1.4.0_1790856611424_0.046246524203906514"}}},"time":{"created":"2026-05-19T08:29:54.878Z","modified":"2026-10-01T12:10:14.289Z","0.1.0":"2026-05-19T08:29:55.200Z","0.1.1":"2026-05-19T12:40:44.131Z","0.2.0":"2026-05-19T15:46:23.980Z","0.2.1":"2026-05-22T15:27:22.552Z","0.3.0":"2026-05-27T13:48:01.348Z","0.4.0":"2026-07-27T16:39:45.463Z","0.5.0":"2026-07-27T17:58:59.488Z","0.6.0":"2026-07-28T09:01:51.487Z","0.7.0":"2026-07-28T09:37:49.141Z","1.0.0":"2026-09-12T16:33:17.886Z","1.1.0":"2026-09-21T09:03:30.970Z","1.2.0":"2026-09-21T11:37:55.843Z","1.2.1":"2026-09-21T11:55:32.536Z","1.3.0":"2026-09-30T11:04:09.207Z","1.4.0":"2026-10-01T12:10:11.547Z"},"bugs":{"url":"https://github.com/pandaGaume/mcp-core/issues"},"author":{"url":"CyanMycelium","name":"Guillaume Pelletier"},"license":"Apache-2.0","homepage":"https://github.com/pandaGaume/mcp-core#readme","keywords":["mcp","model-context-protocol","jsonrpc","behavior","grammar","cyanmycelium"],"repository":{"url":"git+https://github.com/pandaGaume/mcp-core.git","type":"git"},"description":"Engine-neutral Model Context Protocol primitives: behaviors, adapters, grammars, server, transports, client and LLM bridge.","maintainers":[{"name":"gaume","email":"gaume.pelletier@gmail.com"}],"readme":"[![npm](https://img.shields.io/npm/v/@cyanmycelium/mcp-core)](https://www.npmjs.com/package/@cyanmycelium/mcp-core)\n[![CI](https://github.com/pandaGaume/mcp-core/actions/workflows/ci.yml/badge.svg)](https://github.com/pandaGaume/mcp-core/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)\n\n# @cyanmycelium/mcp-core\n\nEngine-neutral primitives for building [Model Context Protocol](https://modelcontextprotocol.io/) servers and clients in TypeScript.\n\n**Coding agent?** Read [AGENTS.md](AGENTS.md) first: the whole integration on one page, with the failure modes that stay silent.\n\n---\n\n## Why this package\n\nThe official MCP TypeScript SDK gives you JSON-RPC plumbing and a way to register tools and resources. That is enough for a script that exposes a handful of functions. It is not enough when:\n\n- you need **multiple LLM clients** to see different tool descriptions on the same server (Claude wants concise, an internal tool prefers verbose);\n- the **set of live resources changes** while sessions are open (objects added, renamed, removed) and the agent must be notified;\n- the **same tool catalog** must run against different backends (a 3D engine, a geo viewer, a node graph, a test mock);\n- a tool may exist conceptually but is **not supported on this particular instance** (e.g. orbit on a fixed camera), and you want the client to never see it instead of getting an error;\n- you want **agents to rewrite their own tool descriptions mid-session** and persist that across reconnects.\n\n`@cyanmycelium/mcp-core` is the abstraction stack that makes those concerns first-class instead of bolt-ons. It is engine-neutral, runtime-agnostic, and has been used in production behind a multi-backend MCP server.\n\n## The four-layer stack\n\n```\n   ┌──────────────────────────────────────────────────────┐\n   │  GRAMMAR    composable description overrides,        │\n   │             resolved per session, mutable at runtime │\n   └──────────────────────────────────────────────────────┘\n                              ▲ applied to\n   ┌──────────────────────────────────────────────────────┐\n   │  BEHAVIOR   identity, namespace, tool/resource       │\n   │             schemas (the MCP-side contract)          │\n   └──────────────────────────────────────────────────────┘\n                              ▲ delegates runtime ops to\n   ┌──────────────────────────────────────────────────────┐\n   │  ADAPTER    runtime, executes against the actual     │\n   │             host objects, emits change events        │\n   └──────────────────────────────────────────────────────┘\n                              ▲ produces / consumes\n   ┌──────────────────────────────────────────────────────┐\n   │  STATE      serializable, read-only snapshots of     │\n   │             those objects (resource contents)        │\n   └──────────────────────────────────────────────────────┘\n```\n\nEach layer is independently testable. Each layer can be swapped without touching the others.\n\n| Layer | You write | Reused across |\n|---|---|---|\n| Behavior | Schemas of tools/resources, namespace, URI template | All hosts |\n| Adapter | Live binding to a backend (3D scene, graph, DB, API) | One backend at a time |\n| State | TypeScript interfaces describing resource contents | All hosts |\n| Grammar | JSON files of description overrides | All hosts, selected per client |\n\n## What you get over a flat `{tool, schema, handler}` setup\n\n| Capability | Flat MCP | This package |\n|---|---|---|\n| Per-session tool descriptions | no | `McpGrammarResolver(clientInfo) -> key` |\n| Runtime mutation of descriptions | no | `McpGrammarStore` + `McpGrammarBehavior` |\n| Hide tools per instance type | manual error in handler | `getToolSupport(toolName, resourceType?)` returns `None`/`Partial`/`Full` |\n| RFC 6570 URI templates with fallback matching | no | static index + template regex match |\n| Live resource change notifications | manual | `adapter.onResourcesChanged`, `onResourceContentChanged` |\n| Same tools across multiple backends | duplicate per backend | one Behavior, swap the Adapter |\n| Tree-shakeable browser/Node split | one bundle | subpath exports (`.`, `./server`, `./client`, `./llm`, `./node`) |\n\n## Install\n\n```sh\nnpm install @cyanmycelium/mcp-core\n```\n\nWiring a server to a real client is covered in **[HOWTO.md](HOWTO.md)**: stdio for the clients installed on a machine (Claude Desktop, Claude Code, Codex), HTTPS for the ones running on a vendor's servers (Claude.ai in a browser, ChatGPT on the web), and how to tell which case you are in.\n\n## Runtimes\n\nRuns in both Node.js and the browser, and implements the two transports the MCP specification defines: stdio and Streamable HTTP, plus `LoopbackTransport` for a server and client sharing a process.\n\nRoles matter here, because a transport means two opposite things depending on which end you are. A server launched as a subprocess speaks through its own `stdin`/`stdout`; the client that launched it speaks through the child's. Over HTTP, one side issues requests and the other terminates them.\n\n| Transport | Server side | Client side |\n|---|---|---|\n| stdio | `StdioTransport` | `ChildProcessTransport` |\n| Streamable HTTP | `StreamableHttpEndpoint` | `StreamableHttpTransport` |\n| loopback | `LoopbackTransport` (both ends of one pair) | |\n\nBoth standard transports, both roles.\n\n## What to import for what\n\n| What you are building | Packages | Piece to use |\n|---|---|---|\n| MCP server launched as a subprocess (Claude Desktop, a CLI agent) | `mcp-core` | `StdioTransport` |\n| MCP server reachable over HTTP by remote clients | `mcp-core` | `StreamableHttpEndpoint` |\n| MCP client talking to a remote server | `mcp-core` | `StreamableHttpTransport` |\n| MCP server and client inside one process | `mcp-core` | `LoopbackTransport` |\n| MCP server inside a browser, exposed to the outside | `mcp-core` + [`mcp-broker-provider`](https://www.npmjs.com/package/@cyanmycelium/mcp-broker-provider) | `MultiplexTransport` |\n| Several servers federated behind one endpoint, with central auth | the above, plus [`mcp-broker`](https://www.npmjs.com/package/@cyanmycelium/mcp-broker) **run as a process** | n/a |\n| MCP client driving a third-party server as a subprocess (`npx some-mcp-server`) | `mcp-core` | `ChildProcessTransport` |\n\nTwo readings that trip people up.\n\nA Node MCP server needs **nothing but this package**. The broker is a relay, not a way to write a server. You reach for it when you have several servers to federate, credentials to centralise, or browsers to get out of, not to expose one server.\n\nAnd the broker is a process you run (`npx @cyanmycelium/mcp-broker`), not a dependency you bundle. Your server stays on `mcp-core` and publishes itself into a slot; what you pay is an extra process, not extra code in your artifact.\n\nThe WebSocket tunnel to that broker is CyanMycelium topology rather than protocol, which is why it lives in `mcp-broker-provider` and not here: this package stays a faithful implementation of the specification and nothing else.\n\n## Protocol coverage\n\nRevisions accepted during the handshake: `2025-11-25` (default), `2025-06-18`, `2025-03-26`, `2024-11-05`. The server echoes the revision the client requested when it appears in that list, and answers with its newest otherwise; the client announces `2025-11-25` and disconnects if the server replies with a revision it cannot speak. Narrow the accepted set with `withOptions({ protocolVersions: [...] })`, or pin one revision by returning `protocolVersion` from your `IMcpInitializer`.\n\n| Area | Status |\n|---|---|\n| `initialize`, version negotiation, `notifications/initialized` | yes |\n| `tools/list`, `tools/call`, `notifications/tools/list_changed` | yes |\n| `resources/list`, `resources/templates/list`, `resources/read`, `notifications/resources/list_changed` | yes |\n| `resources/subscribe`, `resources/unsubscribe`, `notifications/resources/updated` | yes (1.3.0) |\n| `prompts/list`, `prompts/get`, `notifications/prompts/list_changed` | yes (1.3.0) |\n| `completion/complete` | yes (1.3.0) |\n| `logging/setLevel`, `notifications/message` | yes (1.3.0), opt-in with `withOptions({ logging: true })` |\n| `structuredContent` and `outputSchema` on tools | yes |\n| `title`, `icons`, `annotations`, `_meta` on tools, resources and templates | yes |\n| Request `params._meta` handed to adapters and behaviors (`IMcpRequestContext`) | yes (1.4.0) |\n| Binary resources (`blob`), `audio` and `resource_link` content blocks | yes |\n| `ping` (both directions) | yes |\n| Pagination (`cursor` / `nextCursor`) | client follows it; server returns single pages |\n| Progress, cancellation, sampling, roots, elicitation, tasks | not yet |\n| Transports | stdio and Streamable HTTP, both roles each, plus loopback |\n| Streamable HTTP: sessions, `MCP-Protocol-Version`, SSE resumption, `DELETE` teardown | yes |\n| OAuth 2.1 resource server: RFC 9728 metadata, `WWW-Authenticate` challenges, audience-bound tokens, 401/403 | yes, server side |\n| OAuth client flow: metadata discovery, PKCE, `resource` parameter, step-up | not yet: supply a token via `IStreamableHttpTransportOptions.headers` |\n\n`IMcpRequestContext` contains the peer-provided JSON-RPC `requestId`, the MCP\n`method`, optional `params._meta`, and a server-generated `sequence`. The\nsequence is monotonic and unique for the lifetime of one `McpServer`, so an\nadapter can correlate traces even when a peer reuses a JSON-RPC id after its\nprevious request has completed.\n\nEvery request a client may send is listed per revision in `MCP_SERVER_REQUEST_METHODS`, and `tests/spec.coverage.test.ts` sends each one to a server: a `-32601` fails the build unless the method is declared in `MCP_SERVER_UNSUPPORTED_METHODS` with a reason (today only the experimental `tasks/*`). That test is what was missing when subscriptions, prompts, completion and logging all answered `-32601` for five revisions.\n\nTool execution failures come back as `isError: true` results rather than JSON-RPC errors, which is what the spec asks for so the model can self-correct. Protocol errors stay protocol errors: an unknown tool is `-32602`, an unknown resource `-32002`, a JSON-RPC batch `-32600` (batching was removed from MCP in `2025-06-18`).\n\n`McpResourceContent` is a union of a text and a binary variant, so reading one means narrowing on the field you need:\n\n```ts\nconst content = await client.readResource(\"app://logo\");\nconst bytes = content.text !== undefined ? Buffer.from(content.text) : Buffer.from(content.blob, \"base64\");\n```\n\n## Subpath entry points\n\n```ts\nimport { McpBehavior, McpAdapterBase, McpGrammar, McpToolResults } from \"@cyanmycelium/mcp-core\";\nimport { negotiateProtocolVersion, parseChallengeHeader }          from \"@cyanmycelium/mcp-core\"; // protocol + auth primitives\nimport { McpServer, McpServerBuilder, LoopbackTransport }          from \"@cyanmycelium/mcp-core/server\";\nimport { McpClient }                                               from \"@cyanmycelium/mcp-core/client\";\nimport { LlmClient }                                               from \"@cyanmycelium/mcp-core/llm\";\nimport { StdioTransport, ChildProcessTransport,\n         StreamableHttpTransport, StreamableHttpEndpoint }         from \"@cyanmycelium/mcp-core/node\"; // Node-only\n```\n\nTree-shaking ensures browser bundles never pull `node:*` modules.\n\nThe root entry point holds everything that depends on nothing: the behavior stack, protocol-version negotiation, and the OAuth pieces (metadata document, challenge building **and parsing**, canonical resource URI). They sit there rather than under `/node` because a browser client needs the same pieces in reverse: it parses the challenge a server builds.\n\n## Quick start: a minimal MCP server\n\nA behavior owns the **schemas**, an adapter owns the **execution**. The server wires them together with a transport.\n\n```ts\nimport {\n    McpAdapterBase,\n    McpBehavior,\n    McpBehaviorOptions,\n    McpResource,\n    McpResourceContent,\n    McpTool,\n    McpToolResult,\n    McpToolResults,\n} from \"@cyanmycelium/mcp-core\";\nimport { McpServerBuilder } from \"@cyanmycelium/mcp-core/server\";\nimport { StdioTransport }   from \"@cyanmycelium/mcp-core/node\";\n\n// 1. State: read-only snapshot of the resource (here a single counter).\ninterface CounterState {\n    value: number;\n}\n\n// 2. Adapter: executes against the real object.\nclass CounterAdapter extends McpAdapterBase {\n    public static readonly URI = \"app://counter\";\n    private _value = 0;\n\n    constructor() {\n        super(\"app\");\n    }\n\n    public async readResourceAsync(uri: string): Promise<McpResourceContent | undefined> {\n        if (uri !== CounterAdapter.URI) return undefined;\n        const state: CounterState = { value: this._value };\n        return { uri, mimeType: \"application/json\", text: JSON.stringify(state) };\n    }\n\n    public async executeToolAsync(\n        _uri: string,\n        toolName: string,\n        args: Record<string, unknown>,\n    ): Promise<McpToolResult> {\n        switch (toolName) {\n            case \"counter_increment\":\n                this._value += (args.by as number | undefined) ?? 1;\n                this._forwardResourceContentChanged(CounterAdapter.URI);\n                return McpToolResults.json({ value: this._value });\n\n            case \"counter_reset\":\n                this._value = 0;\n                this._forwardResourceContentChanged(CounterAdapter.URI);\n                return McpToolResults.text(\"counter reset\");\n\n            default:\n                return McpToolResults.error(`unknown tool: ${toolName}`);\n        }\n    }\n}\n\n// 3. Behavior: declares what the world sees. No execution code here.\nclass CounterBehavior extends McpBehavior {\n    public static readonly NAMESPACE = \"counter\";\n\n    constructor(adapter: CounterAdapter, options: McpBehaviorOptions = {}) {\n        super(adapter, { ...options, namespace: options.namespace ?? CounterBehavior.NAMESPACE });\n    }\n\n    protected override _buildResources(): McpResource[] {\n        return [{ uri: CounterAdapter.URI, name: \"Counter\", mimeType: \"application/json\" }];\n    }\n\n    protected override _buildTools(): McpTool[] {\n        return [\n            {\n                name: \"counter_increment\",\n                description: \"Add `by` (default 1) to the counter and return its new value.\",\n                inputSchema: {\n                    type: \"object\",\n                    properties: { by: { type: \"number\", description: \"Increment amount.\" } },\n                    additionalProperties: false,\n                },\n            },\n            {\n                name: \"counter_reset\",\n                description: \"Reset the counter to zero.\",\n                inputSchema: { type: \"object\", properties: {}, additionalProperties: false },\n            },\n        ];\n    }\n}\n\n// 4. Server: wire transport + behaviors.\nconst adapter = new CounterAdapter();\nconst server = new McpServerBuilder()\n    .withName(\"counter-demo\")\n    .withTransport(new StdioTransport())\n    .register(new CounterBehavior(adapter))\n    .build();\n\nawait server.start();\n```\n\nSave as `server.ts`, build, run with `node server.js`. Any MCP client (Claude Desktop, an SDK, a hand-rolled JSON-RPC over stdio) can now call `counter_increment` and `counter_reset` and read `app://counter`.\n\n## The Grammar layer\n\nA grammar is a set of **description overrides** that the server applies on top of the behavior's baseline schemas before sending them to the client. The grammar layer is **modular**: multiple grammars can coexist in the same server and be selected per session by source (the calling client), by target (LLM provider, prompt dialect), or by locale.\n\nAs of 0.3.0, four layers stack with explicit precedence (low → high):\n\n| # | Layer | Owner | When to use |\n|---|---|---|---|\n| 1 | Behavior | The behavior class (`_buildGrammars()`) | The behavior ships its own multi-language baselines, autonomous, no external file required |\n| 2 | Adapter | The behavior's adapter (`getGrammar(key)`) | Engine-specific binding nudges a few descriptions without forking the behavior |\n| 3 | Static | Application (`builder.withGrammar(key, g)`) | App-wide override at build time (replaces a baseline for every session) |\n| 4 | Store | Runtime (`McpGrammarStore`, via `McpGrammarBehavior`) | The agent (or operator) edits live descriptions per-profile, with `tools/list_changed` notifications |\n\n`McpGrammar.merge(...layers)` aggregates them in priority order: same-key entries in later layers win, missing entries cascade from earlier ones. The behavior is never required to know about static, store, or adapter layers: they merge transparently at the server.\n\nWhat a grammar may override, per session:\n\n| Target | Fields | Lookup key |\n|---|---|---|\n| Tool | `title`, `description`, and each `inputSchema` property description (dot-notation for nested objects, e.g. `\"patch.position\"`, and through the `items` of an array of objects, e.g. `\"crew.count\"`; since 1.0.1) | tool name |\n| Resource | `name`, `title`, `description` | resource `uri` |\n| Resource template | `name`, `title`, `description` | `uriTemplate` |\n\n`title` is the display name a client shows instead of the programmatic `name`, so it is the field to localise; `name` stays stable because clients and models address tools by it.\n\n### Static grammars selected per client\n\n```ts\nimport { McpGrammar } from \"@cyanmycelium/mcp-core\";\n\nconst concise = McpGrammar.fromJSON({\n    counter_increment: {\n        description: \"Add `by` to the counter.\",\n        properties: { by: \"How much to add.\" },\n    },\n});\n\nconst verbose = McpGrammar.fromJSON({\n    counter_increment: {\n        description:\n            \"Atomically increments the in-memory counter by the given amount \" +\n            \"and returns the new value. The previous value is not retained.\",\n    },\n});\n\nconst server = new McpServerBuilder()\n    .withName(\"counter-demo\")\n    .withTransport(new StdioTransport())\n    .withGrammar(\"concise\", concise)\n    .withGrammar(\"verbose\", verbose)\n    .withGrammarResolver((clientInfo) =>\n        clientInfo.name.toLowerCase().includes(\"claude\") ? \"concise\" : \"verbose\",\n    )\n    .register(new CounterBehavior(adapter))\n    .build();\n```\n\nClaude sees the short description, every other client sees the long one. **No conditional code in the behavior**.\n\n### Behavior-owned multi-language baselines\n\nSince 0.3.0, a behavior can ship its own grammars in code (one entry per `<agent>:<locale>[@version]` key it supports) without any external JSON files or broker layer. The application becomes autonomous on i18n; the broker is only needed if you want operator-editable overrides at runtime.\n\n```ts\nimport { McpBehavior, McpGrammar } from \"@cyanmycelium/mcp-core\";\n\nclass CounterBehavior extends McpBehavior {\n    protected override _buildGrammars(): Map<string, McpGrammar> {\n        return new Map([\n            [\"default:en\", McpGrammar.fromJSON({\n                tools: { counter_increment: {\n                    description: \"Add `by` (default 1) to the counter and return its new value.\",\n                    properties: { by: \"Increment amount.\" },\n                }},\n            })],\n            [\"default:fr\", McpGrammar.fromJSON({\n                tools: { counter_increment: {\n                    description: \"Ajoute `by` (1 par défaut) au compteur et retourne sa nouvelle valeur.\",\n                    properties: { by: \"Quantité à ajouter.\" },\n                }},\n            })],\n            [\"claude:fr\", McpGrammar.fromJSON({\n                tools: { counter_increment: {\n                    description: \"Incrément atomique du compteur. Renvoie la valeur post-mutation.\",\n                }},\n            })],\n        ]);\n    }\n    // _buildTools(), executeToolAsync(), etc.\n}\n```\n\n### The `withGrammarResolver` policy\n\n`withGrammarResolver` accepts two forms. Pass a custom function for arbitrary logic, or a declarative `GrammarResolverOptions` to use the built-in `<agent>:<locale>[@version]` composer:\n\n```ts\nimport { McpServerBuilder } from \"@cyanmycelium/mcp-core\";\n\n// Declarative: locale + agent + (opt-in) version with progressive narrowing.\nconst server = new McpServerBuilder()\n    .withName(\"counter-demo\")\n    .withTransport(new StdioTransport())\n    .register(new CounterBehavior(adapter))\n    .withGrammarResolver({\n        localeSource: (_, caps) => caps?.locale ?? process.env.LOCALE,\n        // versionFrom: (_, caps) => caps?.protocolVersion,   // opt-in\n    })\n    .build();\n```\n\nFor a Claude client requesting locale `fr-CA`, the resolver emits the chain `[\"claude:fr-ca\", \"claude:fr\", \"default:fr-ca\", \"default:fr\", \"claude:en\", \"default:en\"]`. The server tries each in order and picks the first key for which at least one of the four layers has registered a grammar: so the behavior's `default:fr` matches even when a more specific Canadian-French variant is not shipped.\n\nThe fallback narrowing order (`[\"version\", \"locale-region\", \"locale\", \"agent\"]` by default) and key composition are both customizable; see `GrammarResolverOptions` for the full surface.\n\n### The server's words, a directory of files, and the wording rule (1.1.0)\n\nA grammar can carry the server's own words next to its tools': a `server` section with the one-line `description` (used for `serverInfo.description` when the initializer sets none) and the `instructions` a session receives (used when the initializer sets none). The `initialize` result also carries the key of the wording that was matched, in `_meta.grammar`, so a client can record which wording it was given.\n\n```json\n{\n    \"server\": { \"description\": \"A task's own files\", \"instructions\": \"Every path is relative to the task.\" },\n    \"tools\": { \"list\": { \"title\": \"List\", \"description\": \"The files of a task.\", \"properties\": { \"taskId\": \"the task\" } } },\n    \"resources\": { \"ws://writes\": { \"name\": \"Writes\", \"description\": \"Every write.\" } }\n}\n```\n\nWith that, a behavior's code can declare structure only (tool names and schemas, resource URIs) and leave every word to grammar files. Two helpers make it a discipline rather than a habit:\n\n- `loadGrammarDirectory(dir, { surface })` (`@cyanmycelium/mcp-core/node`) reads `<dir>/<agent>/<locale>.json`, composes each `<agent>:<locale>` grammar as the family's file laid over `<dir>/default/<locale>.json`, checks every file against the surface it describes (`McpGrammar.check`: a tool, a property, a resource the surface lacks is a problem, named with its file) and returns the grammars, the files with their sha256, and the problems. `builder.withGrammars(loaded.grammars)` registers them at once.\n- `builder.withWordingRule(\"default:en\")` checks at `build()` that every tool and every resource has a description in one place only: inline in the behavior, or in the named grammar, never both, never neither. A text can then not drift between two copies.\n\n### Phrases: the sentences a host says or shows (1.2.0)\n\nA host has words that describe no tool: what a voice says about a task, what a page writes under a step. They belong to the same wording as the tools' words, in the same files, chosen by the same resolver. A grammar therefore carries a `phrases` section: keyed sentences with `{holes}` filled at use.\n\n```json\n{\n    \"server\": { \"description\": \"The factory's front\" },\n    \"tools\": { \"request\": { \"description\": \"Ask for what is missing.\" } },\n    \"phrases\": {\n        \"step.fit\": \"Model fitted on {rows} rows, rmse {rmse}.\",\n        \"end.proposed\": \"Proposed to the station: {proposalId}.\"\n    }\n}\n```\n\n- `grammar.phrase(\"step.fit\", { rows: 19, rmse: 0.0008 })` fills the holes. A key the grammar lacks comes back as the key itself, so a missing sentence is seen where it should have been read; a hole with no value reads `?`, never an invented value. `fillPhrase` and `phraseHoles` do the same on a bare template.\n- `merge` overlays phrases like the rest (a family file rewords a sentence, never erases one); `toJSON` writes them back.\n- `reference.comparePhrases(other)` lists the keys `other` lacks or adds and the phrases whose holes differ; `loadGrammarDirectory(dir, { referenceLocale: \"en\" })` runs it for every file: a `default/<locale>` file must carry the reference locale's keys and holes, a family file may reword a subset. A locale that drifts is a named problem, like a tool the surface lacks. `check({ phrases: [...keys the host reads] })` refuses a phrase under a key nobody reads.\n- The server serves a session its phrases: once `initialize` has resolved the session's wording, `resources/list` includes `grammar://phrases` (when that wording carries phrases) and `resources/read` on it returns `{ \"grammar\": \"<key>\", \"phrases\": { ... } }`. A page or a voice reads them through its own MCP session, in the language it announced, and fills them with `McpGrammar.fromJSON({ phrases }).phrase(key, values)`; no second loader, no file served on the side.\n\n### Runtime mutation by the agent itself\n\n`McpGrammarBehavior` exposes the grammar store as a regular MCP behavior with six tools (`grammar_list`, `grammar_read`, `grammar_set`, `grammar_delete`, `grammar_import`, `grammar_export`). The agent can rewrite its own tool descriptions during a session, and the server emits `notifications/tools/list_changed` so clients re-fetch the updated schemas.\n\n```ts\nimport { McpGrammarBehavior, McpGrammarStore } from \"@cyanmycelium/mcp-core\";\n\nconst store = new McpGrammarStore();\n\nconst server = new McpServerBuilder()\n    .withName(\"counter-demo\")\n    .withTransport(new StdioTransport())\n    .withGrammarStore(store)\n    .register(new CounterBehavior(adapter), new McpGrammarBehavior(store))\n    .build();\n```\n\nPersist `store.toJSON()` to disk between runs to keep agent-authored descriptions across restarts.\n\n## Per-resource tool support\n\nThe adapter declares which tools apply to which resource types. The behavior filters tools accordingly before advertising them.\n\n```ts\nimport { ToolSupport } from \"@cyanmycelium/mcp-core\";\n\nclass CameraAdapter extends McpAdapterBase {\n    public override getToolSupport(\n        toolName: string,\n        resourceType?: string,\n    ): ToolSupport | undefined {\n        if (toolName === \"camera_orbit\" && resourceType === \"fixed-camera\") {\n            return ToolSupport.None;  // hidden from tools/list for fixed cameras\n        }\n        if (toolName === \"camera_follow_path\" && resourceType === \"fps-camera\") {\n            return ToolSupport.Partial;  // visible, but with caveats in description\n        }\n        return undefined;  // Full (default)\n    }\n}\n```\n\nThe client never sees tools it cannot actually call. No error spam.\n\n## Change notifications, prompts, completion, logging (1.3.0)\n\n**Resource subscriptions.** The server advertises `resources: { subscribe: true, listChanged: true }` as soon as a behavior exposes a resource or a template, and answers `resources/subscribe` / `resources/unsubscribe` itself: it keeps the set of URIs the session subscribed to, matched exactly, and forgets it on disconnect. Subscribing to a URI nothing can read is `-32002`; unsubscribing is always a success.\n\nA behavior never sends a notification; it reports a change, and the server decides who hears it. With an adapter, that is the event it has always had:\n\n```ts\nclass GaugeAdapter extends McpAdapterBase {\n    set(value: number): void {\n        this._value = value;\n        this._forwardResourceContentChanged(\"plant://gauge\"); // notifications/resources/updated, to a subscribed session only\n    }\n    reshape(): void {\n        this._forwardResourceChanged(); // re-index + notifications/resources/list_changed\n    }\n}\n```\n\n`McpBehavior` forwards both as `onResourceUpdated` / `onResourcesListChanged`, and drops its cached copy of the changed content first, so the read that follows is fresh. Before 1.3.0 the adapter raised these events and nothing listened. A behavior written from scratch implements the same two optional event sources, plus `onPromptsChanged`. Content the server serves without a behavior can be announced with `server.notifyResourceUpdated(uri)`, which returns whether anything was sent.\n\nOn the client: `client.onResourceUpdated.subscribe(uri => ...)`, then `await client.subscribeResource(uri)`.\n\n**Prompts.** A behavior contributes `getPrompts()` and `getPromptAsync(name, args)`; the server advertises `prompts` only when one of them has some. Unknown names, missing required arguments and non-string argument values are `-32602`.\n\n**Completion.** A behavior with `completeAsync(ref, argument, context)` makes the server advertise `completions`. A `ref/prompt` goes to the behavior listing that prompt, a `ref/resource` to the one declaring that `uriTemplate`; answers are capped at 100 values with `total` and `hasMore` set.\n\n**Logging.** Off by default, since a server that advertises `logging` promises to emit it. With `withOptions({ logging: true })` the server advertises it, answers `logging/setLevel`, and `server.log(level, data, logger?)` emits `notifications/message` at or above the level the client set (`info` until it sets one).\n\nA custom `IMcpServerHandlers` written before 1.3.0 keeps working: the handlers for these methods are optional, and the server falls back to its own.\n\n## URI templates (RFC 6570)\n\nDeclare templated resources so clients can discover the URI shape without enumerating every instance.\n\n```ts\nprotected override _buildTemplate(): McpResourceTemplate[] {\n    return [{\n        uriTemplate: \"app://camera/{cameraId}\",\n        name: \"Camera\",\n        description: \"Any camera in the active scene, by id.\",\n        mimeType: \"application/json\",\n    }];\n}\n```\n\nWhen a tool call arrives with a concrete URI (`app://camera/main`), the server matches it against templates if no exact static resource matches. The adapter receives the resolved URI and can parse the variables itself.\n\n## One behavior, many adapters\n\nThe behavior owns the schemas. The adapter owns the execution. Any adapter that satisfies the contract can be paired with the same behavior, so the same tool catalog runs against different backends without rewriting a single schema.\n\nReusing the `CounterBehavior` from the Quick start:\n\n```ts\nimport { IMcpBehaviorAdapter } from \"@cyanmycelium/mcp-core\";\n\nconst behavior = (adapter: IMcpBehaviorAdapter) =>\n    new CounterBehavior(adapter, { namespace: \"counter\" });\n\n// Same tools, different execution backends.\nserver.register(behavior(new InMemoryCounterAdapter()));   // tests, demos\nserver.register(behavior(new RedisCounterAdapter(redis))); // production\nserver.register(behavior(new DbCounterAdapter(db)));       // persisted\n```\n\nThe pattern scales to richer domains: a single behavior describing mesh operations can run against a BabylonJS scene, a Cesium viewer, or an in-memory fixture, with the LLM-facing schemas never changing.\n\n## Transports\n\nA server never opens its own connection: it is handed a transport, and `withTransport()` is required before `build()`. Framing, reconnection and authentication belong to whoever understands the medium.\n\n| Transport | Module | Use case |\n|---|---|---|\n| `StdioTransport` | `@cyanmycelium/mcp-core/node` | Line-delimited JSON-RPC over **this** process's stdin/stdout, for a server that someone else launched. |\n| `ChildProcessTransport` | `@cyanmycelium/mcp-core/node` | The mirror: launches an MCP server as a subprocess and speaks to **its** stdio. How most published servers are actually run. |\n| `StreamableHttpTransport` | `@cyanmycelium/mcp-core/node` | The MCP standard for remote servers: POST plus an SSE stream, with sessions and resumption. Client side. |\n| `StreamableHttpEndpoint` | `@cyanmycelium/mcp-core/node` | The same transport, server side, as a `(req, res)` handler you mount on your own HTTP server. |\n| `LoopbackTransport` | `@cyanmycelium/mcp-core/server` | Server and client in the same process. Tests, local dev, embedded use. |\n\nImplement `IMessageTransport` for anything else (WebRTC, postMessage, gRPC). The WebSocket tunnel to a CyanMycelium broker lives in [`@cyanmycelium/mcp-broker-provider`](https://www.npmjs.com/package/@cyanmycelium/mcp-broker-provider), which is where `DirectTransport` and `MultiplexTransport` moved in `0.5.0`.\n\n### What `start()` resolving does and does not mean\n\n`await server.start()` resolves when **the transport reports itself open**. It is not a statement about the far end. Over stdio the two coincide, but over a tunnel (a broker slot, a relay, a reverse proxy) the socket is open long before the peer says whether it will serve this server at all, and a refusal arrives afterwards as an ordinary transport error. So do not print \"connected\" or \"published\" there; print it when the first `initialize` request arrives.\n\nTwo optional events carry what `start()` cannot:\n\n```ts\nconst server = new McpServerBuilder().withName(\"my-app\").withTransport(transport).build();\n\nserver.onTransportError?.subscribe((error) => console.warn(\"[my-app] transport:\", error.message));\nserver.onDisconnected?.subscribe(() => console.warn(\"[my-app] transport closed, the next session renegotiates\"));\n\nawait server.start();\n```\n\n| | fires when |\n|---|---|\n| `start()` rejects | the transport failed **before** reporting open |\n| `onTransportError` | the transport reports an error **after** open: a refused slot, an error frame from a tunnel, a socket protocol fault, a reset |\n| `onDisconnected` | the transport closed and the session state was dropped; reconnecting stays the transport's business |\n\nWhen nothing is subscribed to `onTransportError`, the error is written to `console.error` rather than dropped: an unobserved transport failure is a bug, not a quiet success. Both members are optional on `IMcpServer` so existing implementations of the interface keep compiling; `McpServer` always provides them.\n\n### Driving a server you launch\n\n`ChildProcessTransport` is what lets an `McpClient` use the servers people actually publish, which ship as a command rather than a listening endpoint:\n\n```ts\nimport { McpClient } from \"@cyanmycelium/mcp-core/client\";\nimport { ChildProcessTransport } from \"@cyanmycelium/mcp-core/node\";\n\nconst transport = new ChildProcessTransport({\n    command: \"npx\",\n    args: [\"-y\", \"some-mcp-server\"],\n    // stdio servers take their credentials from the environment: the spec\n    // reserves the OAuth flow for HTTP transports.\n    env: { API_TOKEN: process.env.API_TOKEN ?? \"\" },\n    stderr: (line) => console.warn(`[server] ${line}`),\n});\n\nconst client = new McpClient({ name: \"my-agent\", version: \"1.0.0\" }, transport);\nawait client.connect();\n```\n\n`close()` follows the shutdown sequence the spec prescribes rather than killing outright: it closes the child's stdin so the server can finish on its own, sends `SIGTERM` if it lingers, then `SIGKILL`. Await `transport.exited` to know when the process is really gone.\n\nA line on `stderr` means nothing is wrong: servers are explicitly allowed to log anything there, so it is routed to you and never mistaken for protocol.\n\n### Reaching a remote server\n\n`StreamableHttpTransport` connects an `McpClient` to a remote MCP endpoint:\n\n```ts\nimport { McpClient } from \"@cyanmycelium/mcp-core/client\";\nimport { StreamableHttpTransport } from \"@cyanmycelium/mcp-core/node\";\n\nconst transport = new StreamableHttpTransport(\"https://example.com/mcp\", {\n    // A function, not an object: read fresh per request, so rotating the token\n    // takes effect without rebuilding the transport and losing the session.\n    headers: () => ({ Authorization: `Bearer ${tokens.current}` }),\n});\nconst client = new McpClient({ name: \"my-agent\", version: \"1.0.0\" }, transport);\nawait client.connect();\n```\n\nA plain object works too and is snapshotted at construction. OAuth itself is not implemented: the transport carries whatever credential you give it, and does not yet discover an authorization server or run a token flow.\n\n### Serving Streamable HTTP\n\n`StreamableHttpEndpoint` is the other half: a request handler, not a server. It opens no socket, so listening, TLS and routing stay with your application while sessions, framing and the protocol's status codes stay with the package.\n\n```ts\nimport { createServer } from \"node:http\";\nimport { McpServerBuilder } from \"@cyanmycelium/mcp-core/server\";\nimport { StreamableHttpEndpoint } from \"@cyanmycelium/mcp-core/node\";\n\nconst endpoint = new StreamableHttpEndpoint({\n    // One MCP server per session: a negotiated revision and a resolved grammar\n    // belong to one client. Behaviors are shared: they point at your state.\n    createServer: (transport) => new McpServerBuilder().withName(\"my-app\").withTransport(transport).register(behavior).build(),\n    allowedOrigins: [\"https://app.example.com\"],\n});\n\ncreateServer((req, res) => void endpoint.handleRequest(req, res)).listen(3000);\n```\n\nMount it the same way in Express or Fastify. A `POST` carrying a request is answered as `application/json`; notifications get `202`; server-initiated messages travel on the standalone `GET` stream. Session ids are issued on the `initialize` response and required afterwards, `DELETE` terminates a session, and a request naming a terminated one gets `404` so the client knows to re-initialize.\n\n`Origin` is validated and refused with `403` unless listed in `allowedOrigins`, which is closed by default: without that check any web page can drive a local MCP server through DNS rebinding. A request with no `Origin` header cannot come from a browser and is allowed.\n\nThe `403` body names the value that was refused and what it was compared against, because the mismatch is usually invisible from the outside (a scheme, a port, a trailing slash):\n\n```json\n{\n    \"error\": \"invalid_origin\",\n    \"error_description\": \"Origin \\\"http://app.example.com\\\" is not allowed: allowedOrigins holds \\\"https://app.example.com\\\". Origins are compared verbatim, so scheme, host, port and the absence of a trailing slash must all match.\"\n}\n```\n\nLeaving `allowedOrigins` unset says so in its own words, since a closed door by design and a typo look identical from the client.\n\n### Protecting it with OAuth\n\nPass `auth` and the endpoint becomes an OAuth 2.1 protected resource: it validates the bearer token, answers `401` and `403` with the RFC 9728 challenge, and hands the validated principal to your factory.\n\n```ts\nconst endpoint = new StreamableHttpEndpoint({\n    createServer: (transport, sessionId, principal) => buildServerFor(transport, principal),\n    auth: {\n        resource: \"https://mcp.example.com/mcp\", // RFC 8707 canonical URI; tokens must name it\n        validator: myTokenValidator,             // you verify the token, however you like\n        authorizationServers: [\"https://auth.example.com\"],\n        metadataUrl: \"https://mcp.example.com/.well-known/oauth-protected-resource/mcp\",\n        requiredScopes: [\"mcp:call\"],\n    },\n});\n\n// Serve the discovery document yourself, unauthenticated, since a client\n// fetches it precisely because it has no token yet.\nendpoint.protectedResourceMetadata();\n```\n\nMCP defines no token format and no authorization server, so neither does this package: `ITokenValidator` is the single seam, and verifying a JWT stays with your application. Everything above it (the metadata document, the challenge header and its parser, the canonical resource URI, the 401/403 semantics) lives in `@cyanmycelium/mcp-core` itself rather than under `/node`, because a client needs the same pieces in reverse and they depend on nothing.\n\nThe client hands the negotiated revision to the transport, which stamps `MCP-Protocol-Version` on every subsequent request. Session ids are captured and echoed automatically, the standalone GET stream is opened after initialization (with or without a session) and re-established with `Last-Event-ID` when the server closes it, honouring the SSE `retry` delay. A session terminated server-side (HTTP 404) surfaces as a transport close, since recovering means a fresh `initialize`; call `client.connect()` again to start a new session. `close()` sends an HTTP DELETE to release the session.\n\n## Package layout\n\n```\nsrc/\n  index.ts                       everything isomorphic, re-exported\n  interfaces/                    all shared contracts (one file per topic + barrel)\n  mcp.protocol.ts                revisions supported + version negotiation\n  mcp.auth.ts                    OAuth resource-server primitives (metadata, challenge, RFC 8707 URI)\n  mcp.adapter.ts                 McpAdapterBase\n  mcp.behavior.ts                McpBehavior (extends McpBehaviorBase)\n  mcp.behaviorBase.ts            McpBehaviorBase, McpBehaviorOptions(Builder)\n  mcp.grammar.ts                 McpGrammar (layer + merge + fromJSON/toJSON)\n  mcp.grammarStore.ts            McpGrammarStore (persistable, observable)\n  mcp.grammarBehavior.ts         McpGrammarBehavior (store exposed as MCP behavior)\n  mcp.toolResult.ts              McpToolResults.{text,json,resource,link,image,audio,error}\n  mcp.resolver.ts                grammar key resolution from client identity\n  server/                        McpServer, McpServerBuilder, JSON-RPC helpers, LoopbackTransport\n  client/                        McpClient\n  llm/                           LLM bridge interfaces and a generic client\n  node/                          Node-only: StdioTransport, ChildProcessTransport,\n                                 StreamableHttpTransport, StreamableHttpEndpoint\n```\n\nThe split is deliberate: anything that touches `node:*` lives under `node/`, everything else is isomorphic. That is why the OAuth and protocol primitives sit at the root while the HTTP wiring that uses them does not.\n\n## Development\n\n```sh\nnpm install\nnpm run build      # tsup, bundles each entry point, emits .d.ts\nnpm run typecheck  # tsc --noEmit, the only type gate: tsup transpiles without checking\nnpm test           # vitest run\nnpm run lint\nnpm run lint:fix\nnpm run format:fix\n```\n\nRequires Node 20.11+.\n\n`typecheck` is not redundant with `build`. tsup strips types rather than verifying them, and vitest does the same, so without it nothing would ever check the sources or the tests. It runs in CI between `build` and `test`.\n\n## License\n\nApache-2.0. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}