{"_id":"@ai-universe/mcp-server-utils","_rev":"16-6c927abbea6f7daf5ac7f1c379d3c2bf","name":"@ai-universe/mcp-server-utils","dist-tags":{"latest":"1.3.2"},"versions":{"1.0.0":{"name":"@ai-universe/mcp-server-utils","version":"1.0.0","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"079e025f7ea938a6fd341a15f39400724f68dae7","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.0.tgz","fileCount":28,"integrity":"sha512-qwxCh2clAIbw8VvXoVFe0+spH6q6IGUodM/wYl3LQcqO92t8KrguHl1sr89O/CGM0vWdL/Cg8E6DLV11+6S9xg==","signatures":[{"sig":"MEUCICd9+wA4ZZDoKarG1HiU4CTEHmI5OIo/wWbp8JcezRJ6AiEAoYiYYT/L7TFWsnu9ih/TnW4Vibf1fRz/2DWInxtFsR4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29608},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"build":"tsc","clean":"rm -rf dist"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"10.8.2","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"cors":"^2.8.5","express":"^4.18.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","@types/express":"^4.17.21"},"peerDependencies":{"fastmcp":"^3.16.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.0_1759145576665_0.042058367334159685","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@ai-universe/mcp-server-utils","version":"1.0.1","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.1","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"aec7130e200f0d9a638e8b39c061c29d0b47b4e2","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.1.tgz","fileCount":51,"integrity":"sha512-JHb01yxhznnfN+N/DYqwUy7Wa26lCIODjYJFz/pANHrcfEivFK72cPUs/dYwlFjBpdtQQC8nuBvetPcx+UxEyA==","signatures":[{"sig":"MEYCIQDcuzOHnsFKKSLjBqBX9UUNvymMamWUvHteucPTOxDWdgIhAMhxzcvXGX85kYHe0412MvIc0Liwjo5D1OSPQvQ6xuv6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97051},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"11.5.1","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"24.6.0","dependencies":{"cors":"^2.8.5","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","@types/express":"^4.17.21"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"peerDependencies":{"fastmcp":"^3.16.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.1_1759808421440_0.683815443215791","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@ai-universe/mcp-server-utils","version":"1.0.2","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.2","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"dd463e53ec747028e9114196666189324d3a0a1e","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.2.tgz","fileCount":98,"integrity":"sha512-rgrxmOsfktq9Ge1wQ+fcHeAB3wCiQEO39inEMw8f6zEgz+URrcrDs55TQxPFAzfmHrGOaDh+hOon6qWUUZPPUg==","signatures":[{"sig":"MEUCIQDjl8dXa7oDlzLMnMUgw/3oykxNbvJNJ1qVuzeAceIeXQIgGjX1OmOKo2qyDsAKbxbOwUtQLoxYBvFzIas0DuPSWog=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":399014},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^3.22.3","jest":"^29.7.0","fastmcp":"^3.16.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"peerDependencies":{"zod":"^3.22.3","fastmcp":"^3.16.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.2_1762597966571_0.5309883338981343","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@ai-universe/mcp-server-utils","version":"1.0.3","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.3","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"daf9c985909db8ca1f14a5773fdd1f73cbac04ea","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.3.tgz","fileCount":109,"integrity":"sha512-s4Mv2nW2eYAx2oqrzdxmQQbrJenL1OLgtH19mIfG2x6AKMHop1xm5yqhyDs6Ro4UwypPbkskKjBOTe6F7PSswg==","signatures":[{"sig":"MEYCIQDqjhGSnyFKYZsUVc4kGWMUwz1pXm9G2hQ1Wv2mATm2nAIhAN1psNBBj/KmMJ3XA8C6YhX0qhA5CEZLdJCIhQfnl5rX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":625938},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"11.5.1","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"24.6.0","dependencies":{"cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^3.22.3","jest":"^29.7.0","fastmcp":"^3.16.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"peerDependencies":{"zod":"^3.22.3","fastmcp":"^3.16.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.3_1762656283946_0.047308789338819324","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@ai-universe/mcp-server-utils","version":"1.0.4","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.4","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"71c015eafe041c2f03cd1dd6190ea7858bec4f17","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.4.tgz","fileCount":109,"integrity":"sha512-Ck5T6587ip4hLLck7mIkeyFyWQ4va9zoLw45KmuH9IaVpfUhp0pocb4zdRwDvHR7+liaFu2rM6/hL1/UBrUVCA==","signatures":[{"sig":"MEYCIQDwjmOjsKRksnIs7Kqk4tk8tgryBvaeSQ93Rdq745iSFAIhAPxi5zLm77YjFlRnFAJ1GCziVA8fveJmi2zTXTtPWQaC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":621383},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"11.5.1","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"24.6.0","dependencies":{"cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^3.22.3","jest":"^29.7.0","fastmcp":"^3.16.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"peerDependencies":{"zod":"^3.22.3","fastmcp":"^3.16.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.4_1762656546088_0.6480252635010391","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@ai-universe/mcp-server-utils","version":"1.0.5","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.0.5","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"9fa6266ea214d60a4fc05d23769c6aac20c2c581","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.0.5.tgz","fileCount":109,"integrity":"sha512-GoLuF1e9VmRr95Lutzp8mPnm0X8R5K07eMM1mcJmTTeiCrA5jHAKsYyTWIKYwRPyqXKjLoaEFdusKbJ9/ec6gA==","signatures":[{"sig":"MEYCIQC8w5jSnMlkX4Xw4zzI2HmWeI8DH3yYyEdyGbdfx6rahQIhAJWGcFfZ9qFX3dQ7AwhHStJ1jg8eNz0qRoPfUpw08osT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3238098},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.0.5_1762676052846_0.35566420890398787","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@ai-universe/mcp-server-utils","version":"1.1.0","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.1.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"faea92262daf984404644feb5780fe28bd9fe7af","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.1.0.tgz","fileCount":124,"integrity":"sha512-182JV12s0+OoP4j5qzDdwHrAVL5+0VNvsDeDSfCZM5OhanZbRlg1AQEC+0Xsj6aIjVdgjVof/q4KnzGw5VB7ow==","signatures":[{"sig":"MEQCICN2G8YNAYJDqhrTv+hByIbKcb9/zw5qfFKaiI0kcLQeAiBNR97gl2sSKqq40YAVqEAb+xkFo4IXRG7LEojqawqicQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3281796},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.1.0_1762679719415_0.7798211204347814","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@ai-universe/mcp-server-utils","version":"1.2.0","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"e716f009cbc6a8fa51082755e920d08f14800243","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.0.tgz","fileCount":126,"integrity":"sha512-z8gQz37Q/PPpr0VJLme+Zm9ZY9o9G/bWbeKBA6X8FTpAhnXuELPA5V9obuBX7QegJx6xj9CwnwUwHqkJygCMcA==","signatures":[{"sig":"MEYCIQCrUl9noI2uTaJ81LExKrM1nCyFDEjDoEj9fOqiyR/hJwIhAMCaY4pC6CNn8fgRdnXtfZP00RhYMLcsJGwVUu7U8i/0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3309537},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.0_1762680477243_0.45172351603188066","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@ai-universe/mcp-server-utils","version":"1.2.1","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.1","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"432959deb8fada21cbc324e6efd0b0949f55f17f","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.1.tgz","fileCount":126,"integrity":"sha512-O4cIXJVZN27ODg6AQw/5+ZqLjtelx7itk4WQCispiGuXK3l080qly7+BFCdzFV4gqSEsgPJCkgi80iq9CvtPZQ==","signatures":[{"sig":"MEQCIEbmoqT7M0j9vXoPlxD+c/XdPM4kCUDda8Ajto2Llm1wAiBofIkSybXMoZ2L7GPh1R9nnRtw1DryhwkZSeh8ATrhCA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3310011},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.1_1762680736622_0.2657303824659425","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@ai-universe/mcp-server-utils","version":"1.2.2","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.2","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"0678486d3705712ffb4c53d60967f15f2d0c6faa","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.2.tgz","fileCount":126,"integrity":"sha512-VNqlaWA87iLaE55yj0/0Rrvwx3uBD6SLytM88qvChKQRdYE2z9eP54TUAYYWGq2LuZEcqyJe3p46Upl77MVC7A==","signatures":[{"sig":"MEYCIQDgmI/XnJbpRVhenjXyRyBob/Kv5HJlrPORiRhNermzNQIhAIoE3KRmA9IWmF3Ea+7bT2V/e6hA3pDE3xgLOhZRhK6d","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3308251},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.2_1762681584681_0.6846417687181996","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@ai-universe/mcp-server-utils","version":"1.2.3","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.3","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"048e8c18af413154819165ca4afd0d82a97bbf60","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.3.tgz","fileCount":126,"integrity":"sha512-wwEI4srPfUefeNu1v0x7OhlsLYFiNTv2hv9LXAHs7/4XLs+qTlYJhT+ULZk1JCEAht+cI2gL70psqg0uQNBRwA==","signatures":[{"sig":"MEQCIAQkQPn8+9Bf9HLz8Uoc3FYtbL0vDRXqYmFTL1T/A04DAiAstdKwJ1NWDzV3Knv+yNXI0UPm7r0HC/L6TO1Q2LkgKw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3308227},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.3_1762683645804_0.7998058777935604","host":"s3://npm-registry-packages-npm-production"}},"1.2.4":{"name":"@ai-universe/mcp-server-utils","version":"1.2.4","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.4","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"19bec65b1fe0223af9c36a6172a841c376f7c455","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.4.tgz","fileCount":126,"integrity":"sha512-t6WWIVQbJi+32cMJODvfWtcqPYQB2IJUeVZ3qrDX5nvZXsgW8eyEP3G6bQ4BRM62AzqfryVL8JUuJ9/sGUF4AA==","signatures":[{"sig":"MEUCIQDsX37Vw+AhuycVIi3LQNc7gL4mDmQsJxtd4n2Su3WCIgIgB9tu51amKd3buvQfdWxnM5hPeojIfLXtPbppgMxJn4w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3309854},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","typescript":"^5.3.3","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","@types/jest":"^29.5.12"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.4_1762684371606_0.9722466775262761","host":"s3://npm-registry-packages-npm-production"}},"1.2.5":{"name":"@ai-universe/mcp-server-utils","version":"1.2.5","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.2.5","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"4e8a08b57c81fd6d792a17c71f59b725dc299f07","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.2.5.tgz","fileCount":134,"integrity":"sha512-7p4M3MQkPsWhvBrg6WUHGwe4FSUWaUgY/n1gvrD6RM2uzZrgLaATNRGAwCcosqZHUY4cjSdfmbVNEmh4T3A+MQ==","signatures":[{"sig":"MEYCIQCpcykxp1j38n2FZjo535yo4dYEuXrYW5+pSUSU5KVn9QIhAM/oiTIXpm/LXKRiBTUHp727Ze7WvKfb6e4BgFaqriFi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3333350},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"11.5.1","description":"Shared MCP server utilities for AI Universe services","directories":{},"_nodeVersion":"24.6.0","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.12.0","jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.9.3","@types/jest":"^29.5.12","ajv-formats":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.2.5_1762707028724_0.6559057472046832","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@ai-universe/mcp-server-utils","version":"1.3.0","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.3.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"1fca08734285926fa8a8ec47522b909ea74ce3f7","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.3.0.tgz","fileCount":151,"integrity":"sha512-a0ZBN9lcix8f9DlwxK4IGxVzvlZzoryWN2qR8J/Zy7yAvddXJLynKPvZ8BNcnBJ/1y3zm2Qy5jEaWmIKme0lRg==","signatures":[{"sig":"MEUCIDVDevJRhw9Cje6oMi7RFTNPt4g6eIyVeTCP3ivTPgShAiEAtUEdH+BKkYLKGyFHkDikNRnW8obZLgRAJ1pxRtbd+eM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3481943},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"876753e9eac9fb65b53793801d7329e87867bbe1","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities and TypeScript server launcher for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.12.0","jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.9.3","@types/jest":"^29.5.12","ajv-formats":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.3.0_1762927152095_0.6124071840013201","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@ai-universe/mcp-server-utils","version":"1.3.1","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/mcp-server-utils@1.3.1","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"cef6675c7d80f233658420cef79ea516dc9ccd2c","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.3.1.tgz","fileCount":161,"integrity":"sha512-sOK4CJWmcMU9Y8JcYTERJoZMlQevV7OWePnYHt5ekM3rLLwzx77mScVbSOXGuDicnEMWoLbSGTsQzKr/lQE8fA==","signatures":[{"sig":"MEYCIQDRjygNruKW3CrlnZHxNco4Dn0Z+0QHU60TzZBRBhi4+wIhAOiUL1nGja3qd63f8dd23jSaJOjQElkgFJProwWS4j8L","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3538261},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","scripts":{"test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs","test:watch":"jest --watch"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"Shared MCP server utilities and TypeScript server launcher for AI Universe services","directories":{},"_nodeVersion":"20.19.4","dependencies":{"zod":"^3.22.3","cors":"^2.8.5","axios":"^1.13.2","express":"^4.18.2","fastmcp":"^3.16.0","@types/cors":"^2.8.17","@types/node":"^20.11.19","async-mutex":"^0.5.0","@types/express":"^4.17.21","firebase-admin":"^13.6.0","@google-cloud/secret-manager":"^6.1.1","@ai-universe/mcp-conversation-client":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.12.0","jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.9.3","@types/jest":"^29.5.12","ajv-formats":"^3.0.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-utils_1.3.1_1763189573042_0.9407829057918531","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"name":"@ai-universe/mcp-server-utils","version":"1.3.2","description":"Shared MCP server utilities and TypeScript server launcher for AI Universe services","type":"module","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","prepare":"node ../../scripts/run-build-if-ready.mjs","clean":"rm -rf dist","test":"jest","test:watch":"jest --watch"},"dependencies":{"@ai-universe/mcp-conversation-client":"^2.0.2","@google-cloud/monitoring":"^5.3.1","@google-cloud/secret-manager":"^6.1.1","@types/cors":"^2.8.17","@types/express":"^4.17.21","@types/node":"^20.11.19","async-mutex":"^0.5.0","axios":"^1.13.2","cors":"^2.8.5","express":"^4.18.2","fastmcp":"^3.16.0","firebase-admin":"^13.6.0","zod":"^3.22.3"},"devDependencies":{"@types/jest":"^29.5.12","ajv":"^8.12.0","ajv-formats":"^3.0.1","jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.9.3"},"keywords":["mcp","fastmcp","server","utilities","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","publishConfig":{"access":"public"},"_id":"@ai-universe/mcp-server-utils@1.3.2","_nodeVersion":"20.19.4","_npmVersion":"8.19.4","dist":{"integrity":"sha512-2PfivDOxJD+I/8GWqeDEKw7RZ3tuZegC96HMWg6UiT0SfEMaE3F7XaJhcXMFpEDaIHD5RhnHiJkxmpGlO0tPaA==","shasum":"c670cea35646ca487d8285efbb637ef979baf52e","tarball":"https://registry.npmjs.org/@ai-universe/mcp-server-utils/-/mcp-server-utils-1.3.2.tgz","fileCount":181,"unpackedSize":3747644,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBk40TwRMiIYkdnwGfIZ6WAOIiLnjYzV/coxfCFh3B8oAiAShQ1JGrFsl6YGPLg1thge6U3fwTM1cDKi22R0ZBwwNA=="}]},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"directories":{},"maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-server-utils_1.3.2_1763755327801_0.7029631653528277"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-29T11:32:56.584Z","modified":"2025-11-21T20:02:08.544Z","1.0.0":"2025-09-29T11:32:56.848Z","1.0.1":"2025-10-07T03:40:21.620Z","1.0.2":"2025-11-08T10:32:46.815Z","1.0.3":"2025-11-09T02:44:44.212Z","1.0.4":"2025-11-09T02:49:06.340Z","1.0.5":"2025-11-09T08:14:13.141Z","1.1.0":"2025-11-09T09:15:19.655Z","1.2.0":"2025-11-09T09:27:57.503Z","1.2.1":"2025-11-09T09:32:16.844Z","1.2.2":"2025-11-09T09:46:24.900Z","1.2.3":"2025-11-09T10:20:46.028Z","1.2.4":"2025-11-09T10:32:51.873Z","1.2.5":"2025-11-09T16:50:28.915Z","1.3.0":"2025-11-12T05:59:12.309Z","1.3.1":"2025-11-15T06:52:53.275Z","1.3.2":"2025-11-21T20:02:08.010Z"},"author":{"name":"AI Universe Team"},"license":"MIT","keywords":["mcp","fastmcp","server","utilities","ai-universe"],"description":"Shared MCP server utilities and TypeScript server launcher for AI Universe services","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"readme":"# @ai-universe/mcp-server-utils\n\nComprehensive utilities for building and operating [FastMCP](https://github.com/modelcontextprotocol/servers) servers in production. The package bundles HTTP proxy helpers, Express middleware wiring, lifecycle management, port discovery, CORS hardening, and ready-to-use tool scaffolding so client teams can focus on business logic instead of server plumbing.\n\n## Table of contents\n\n1. [When to use this package](#when-to-use-this-package)\n2. [Key capabilities](#key-capabilities)\n3. [Installation](#installation)\n4. [Quick start: ship an HTTP-accessible MCP server](#quick-start-ship-an-http-accessible-mcp-server)\n5. [Package modules at a glance](#package-modules-at-a-glance)\n6. [HTTP proxy helper](#http-proxy-helper)\n7. [Port discovery utilities](#port-discovery-utilities)\n8. [Wildcard-aware CORS configuration](#wildcard-aware-cors-configuration)\n9. [Server factory & agent integration](#server-factory--agent-integration)\n10. [Server lifecycle management](#server-lifecycle-management)\n11. [Tool helper catalog](#tool-helper-catalog)\n12. [TypeScript Server Launcher](#typescript-server-launcher)\n13. [Bundled Conversation MCP client](#bundled-conversation-mcp-client)\n14. [Logging, error handling, and security notes](#logging-error-handling-and-security-notes)\n15. [TypeScript reference](#typescript-reference)\n16. [Testing your integration](#testing-your-integration)\n17. [Troubleshooting & FAQs](#troubleshooting--faqs)\n18. [Requirements](#requirements)\n19. [License](#license)\n\n---\n\n## When to use this package\n\nChoose `@ai-universe/mcp-server-utils` whenever you need:\n\n- A **drop-in HTTP proxy** so any FastMCP server can be consumed over HTTP(S) without clients speaking STDIO.\n- **Safe CORS handling** that supports wildcard domains (e.g., `https://*.mydomain.com`) while preventing regex injection.\n- **Predictable port assignment** across developer machines and containers.\n- **Lifecycle orchestration** that wraps startup/shutdown hooks and handles POSIX signals.\n- A library of **battle-tested tool helpers** for health checks, version reporting, and diagnostics.\n\n## Key capabilities\n\n- **TypeScript Server Launcher** - Generic framework for launching TypeScript servers locally with automated port management, process control, dependency installation, builds, and watch mode support.\n- **HTTP proxy server** with Express wiring and JSON HTTP stream transport defaults.\n- **Port management** with bounded search windows, randomized selection, and error reporting for exhaustion conditions.\n- **Process management** with PID tracking, graceful termination, port reclamation, and parent process detection.\n- **Build orchestration** with dependency checking, TypeScript compilation, and custom preparation hooks.\n- **CORS configuration** that normalizes origins, optionally allows `null`, and compiles wildcard expressions into safe regex patterns.\n- **Server factory** with agent/tool registration, initialization hooks, and health-check tooling.\n- **Lifecycle manager** that standardizes `onStart`, `onStop`, and `onError` workflows and wires graceful shutdown handlers.\n- **Tool decorators** to add logging and resilient error handling around existing FastMCP tools.\n- **Latency tracker** utilities for structured per-stage/model observability with pluggable loggers. Verbose latency logging is\n  enabled by default; set `MCP_VERBOSE_LATENCY_LOGGING=false` to silence detailed metrics.\n- **Bundled conversation client** re-export so typed conversation helpers are available without pulling a second package.\n\n## Installation\n\n```bash\nnpm install @ai-universe/mcp-server-utils fastmcp express cors\n```\n\n> **New in 1.0.2:** The package now bundles the `@ai-universe/mcp-conversation-client` so you don't need to install it separately\n> to consume conversation tooling helpers. Import it directly from `@ai-universe/mcp-server-utils`.\n\n> **Optional:** Install `zod` (or your validation library of choice) if you want schema-based parameter validation like the examples below.\n\n> **Tip:** The package assumes Node.js 18+ so you can rely on the built-in `node:http` and `node:net` modules. Install `fastmcp` 3.16.0 or later for HTTP stream transport support.\n\n## Quick start: ship an HTTP-accessible MCP server\n\n```typescript\nimport {\n  createHealthCheckTool,\n  createMCPServer,\n  createWildcardCorsOptions,\n  startFastMcpHttpProxy,\n} from '@ai-universe/mcp-server-utils';\n\nasync function main() {\n  // 1. Compose tools and agents with the server factory\n  const server = await createMCPServer({\n    name: 'sample-mcp',\n    version: '1.2.0',\n    instructions: 'Sample MCP server for demos',\n    tools: [createHealthCheckTool('1.2.0')],\n    onInitialize: async (mcp) => {\n      // custom warm-up logic, logging, or registrations\n    },\n  });\n\n  // 2. Configure CORS with wildcard origin support\n  const corsOptions = createWildcardCorsOptions({\n    allowedOrigins: [\n      'https://*.mydomain.com',\n      'http://localhost:*',\n    ],\n    allowNullOrigin: true,\n  });\n\n  // 3. Expose the FastMCP server via an HTTP proxy\n  const { expressServer, mcpPort } = await startFastMcpHttpProxy({\n    server,\n    listenPort: 8080,\n    host: '0.0.0.0',\n    corsOptions,\n    configureApp: (app) => {\n      app.get('/health', (_req, res) => res.json({ status: 'ok' }));\n    },\n  });\n\n  console.log(`MCP transport bound to localhost:${mcpPort}`);\n  console.log('HTTP proxy listening on http://0.0.0.0:8080');\n\n  // 4. Optional: wire graceful shutdown\n  process.on('SIGINT', async () => {\n    expressServer.close();\n    await server.stop?.();\n    process.exit(0);\n  });\n}\n\nvoid main().catch((error) => {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\nThis example:\n\n1. Uses `createMCPServer` to standardize tool and agent registration.\n2. Builds a strict yet flexible CORS policy with wildcards.\n3. Launches the HTTP proxy, which internally spins up a FastMCP HTTP stream on a reserved loopback port.\n4. Adds a custom Express health endpoint while keeping MCP traffic under `/mcp` (the default proxy path).\n\n## Package modules at a glance\n\n| Module | Purpose | Highlights |\n| ------ | ------- | ---------- |\n| `startFastMcpHttpProxy` | Spin up Express + FastMCP HTTP transport | Configurable host/port, pluggable logger, overridable HTTP module for tests. |\n| `findAvailablePort` | Determine a free TCP port | Searches up or down with hard bounds and informative errors. |\n| `createWildcardCorsOptions` | Build wildcard-aware CORS options | Normalizes origins, supports `null`, compiles regex safely. |\n| `wildcardToSafeRegex` | Convert `*` patterns into safe regex | Escapes all metacharacters and collapses repeated wildcards. |\n| `createMCPServer` (ServerFactory) | Factory for FastMCP servers | Registers tools/agents, runs async initialization hooks. |\n| `ServerLifecycleManager` | Manage start/stop hooks | Tracks running state, propagates errors, integrates graceful shutdown. |\n| `ToolHelpers` | Ready-made tools & decorators | Echo, version, status, health check tools plus logging/error wrappers. |\n| `LatencyTracker` | Capture and persist per-stage/model metrics | Structured logging hooks, snapshotting, and optional `/tmp` persistence for offline analysis. |\n| `ConversationMCPClient` (re-export) | Typed MCP client for convo servers | Ships from `@ai-universe/mcp-conversation-client` for conversation CRUD, replies, and health checks. |\n\n## HTTP proxy helper\n\n`startFastMcpHttpProxy(options)` launches two servers under the hood:\n\n1. **FastMCP HTTP stream** – started on the reserved loopback port (defaults to `45000`). You can opt-in to fallback scanning if the port is already in use.\n2. **Express proxy** – listens on your specified host/port and forwards `/mcp` traffic (or any custom `proxyPath`) to the internal transport.\n\n### Options\n\n| Option | Type | Default | Description |\n| ------ | ---- | ------- | ----------- |\n| `server` | `FastMCP` | required | The MCP instance to expose. |\n| `listenPort` | `number` | required | External Express port. |\n| `host` | `string` | `'localhost'` | Binding host/IP. |\n| `corsOptions` | `CorsOptions` | `undefined` | Pass CORS middleware configuration (use `createWildcardCorsOptions`). |\n| `proxyPath` | `string` | `'/mcp'` | HTTP path that proxies to the MCP server. |\n| `logger` | `LoggerLike` | `undefined` | Optional logger with `info`/`error` methods for startup and failure events. |\n| `startPort` | `number` | `45000` | Seed port used when fallback scanning is enabled. |\n| `loopbackPort` | `number` | `process.env.FASTMCP_LOOPBACK_PORT \\|\\| 45000` | Reserved loopback port to attempt first. |\n| `allowLoopbackFallback` | `boolean` | `false` | When `true`, falls back to scanning for a free port if the reserved port is busy. |\n| `portSearchDirection` | `'up' \\| 'down'` | `'down'` | Direction to look for free ports when fallback scanning is active. |\n| `httpModule` | `typeof http` | `node:http` | Injectable for testing with `undici` or mocks. |\n| `configureApp` | `(app) => void` | `undefined` | Callback to register custom Express middleware/routes before proxy wiring. |\n\n### Return value\n\nA promise resolving to `{ app, expressServer, mcpPort }`, allowing you to add further middleware, close the Express server, or inspect which internal port was allocated.\n\n### Error handling\n\n- Proxy failures emit a `502` JSON response with diagnostic details and log to `logger.error` if provided.\n- Request stream errors close the upstream proxy and invoke the logger for easier observability.\n- Express server errors bubble via the same logger so you can integrate with Datadog, Cloud Logging, etc.\n\n## Port discovery utilities\n\n`findAvailablePort(startPort, direction)` searches deterministically for an open TCP port.\n\n- The search is **bounded** to avoid endless loops: it stops after 1000 attempts or reaching the min/max thresholds.\n- For downward searches, ports lower than `2000` short-circuit with a descriptive error; upward searches cap at `startPort + 1000`.\n- Ports are verified by opening a transient `node:net` server; a 10 ms delay ensures the OS releases the port before reuse.\n\nUse it directly when orchestrating multiple MCP servers or when deploying inside container orchestrators that need deterministic port windows.\n\n## Wildcard-aware CORS configuration\n\n`createWildcardCorsOptions(params)` produces a `cors` middleware configuration with security-focused defaults.\n\n- Origins are trimmed and deduplicated, with trailing slashes removed for consistent comparisons.\n- Origins with `*` convert to safe regex via `wildcardToSafeRegex`, which escapes all regex metacharacters and collapses repeated wildcards to mitigate ReDoS risks.\n- Supports explicit method/header lists, `credentials: true`, caching (`maxAge`), and custom `optionsSuccessStatus` for legacy browsers.\n\n### Example: lock down staging origins\n\n```typescript\nconst corsOptions = createWildcardCorsOptions({\n  allowedOrigins: [\n    'https://*.staging.example.com',\n    'https://portal.example.com',\n  ],\n  allowNullOrigin: false,\n  methods: ['GET', 'POST'],\n  allowedHeaders: ['Content-Type', 'X-Session-Id'],\n});\n```\n\n## Server factory & agent integration\n\n`createMCPServer(options)` provides a declarative way to assemble your FastMCP server.\n\n- Accepts `tools` arrays directly; each tool is registered in the order provided.\n- Supports `agents` implementing a simple `register(server)` contract so teams can encapsulate their own tool bundles.\n- `onInitialize` allows asynchronous setup (e.g., database connections, vector store warm-up) after registration but before exposure.\n- Ships with `createHealthCheckTool(version, additionalInfo)` for standardized health responses including ISO timestamps and version metadata.\n\n### Agent interface sketch\n\n```typescript\nclass WeatherAgent implements Agent {\n  constructor(private readonly tool: FastMCP.Tool) {}\n\n  async register(server: FastMCP) {\n    server.addTool(this.tool);\n  }\n}\n```\n\n## Server lifecycle management\n\nUse `ServerLifecycleManager` to coordinate startup/shutdown logic and ensure hooks are respected.\n\n```typescript\nimport { ServerLifecycleManager, setupGracefulShutdown } from '@ai-universe/mcp-server-utils';\n\nconst lifecycle = new ServerLifecycleManager(server, {\n  onStart: async (svc) => svc.start({ transportType: 'stdio' }),\n  onStop: async () => console.log('Stopped!'),\n  onError: async (error) => console.error('Lifecycle error', error),\n});\n\nawait lifecycle.start();\nsetupGracefulShutdown(lifecycle);\n```\n\n- `start()` and `stop()` enforce idempotency, throwing if you double-start and short-circuiting if you double-stop.\n- Hooks execute sequentially and any thrown error is routed through `onError` before rethrow, letting you centralize alerting.\n- `setupGracefulShutdown` listens for `SIGINT`, `SIGTERM`, and `SIGQUIT`, logging progress and exiting with the proper code based on shutdown success.\n\n## TypeScript Server Launcher\n\nThe `TypeScriptServerLauncher` is a generic, production-ready framework for launching TypeScript servers locally with comprehensive automation and reliability features. Perfect for development environments and CI/CD pipelines.\n\n### Features\n\n- **Smart Port Management**: Preferred port with automatic fallback, randomized search to avoid thundering herd, and forced port reclamation\n- **Process Control**: PID file tracking, graceful/forceful termination, parent process detection, and orphan cleanup\n- **Build Automation**: Dependency checking, TypeScript compilation, custom prepare scripts, and shared library preparation\n- **Development Workflow**: Watch mode with auto-restart, production mode for testing, retry logic for port conflicts (EADDRINUSE)\n- **Lifecycle Hooks**: Custom callbacks at build, start, and exit events\n\n### Quick Example\n\n```typescript\nimport { TypeScriptServerLauncher } from '@ai-universe/mcp-server-utils';\n\nconst launcher = new TypeScriptServerLauncher({\n  projectRoot: '/path/to/project',\n  serverDir: 'backend',\n  devCommand: ['npm', 'run', 'dev'],\n  startCommand: ['npm', 'run', 'start'],\n  preferredPort: 2000,\n  watchMode: true,\n  onServerStarted: async (port, pid) => {\n    console.log(`✅ Server started on port ${port} with PID ${pid}`);\n  }\n});\n\nawait launcher.launch();\n```\n\n### Configuration Options\n\n```typescript\ninterface ServerLauncherConfig {\n  // Required\n  serverDir: string;              // Server directory (e.g., 'backend')\n  devCommand: string[];           // Dev mode command (e.g., ['npm', 'run', 'dev'])\n  startCommand: string[];         // Production command (e.g., ['npm', 'run', 'start'])\n\n  // Optional - Paths\n  projectRoot?: string;           // Project root (defaults to process.cwd())\n  pidFile?: string;               // PID file path (defaults to '.local-server.pid')\n  prepareScriptPath?: string;     // Custom prepare script\n\n  // Optional - Port Configuration\n  preferredPort?: number;         // Preferred port (defaults to 2000)\n  minPort?: number;               // Min port for fallback (defaults to 2000)\n  maxPort?: number;               // Max port for fallback (defaults to 2500)\n  forcePort?: boolean;            // Force reclaim preferred port (defaults to false)\n\n  // Optional - Build Configuration\n  buildCommand?: string[];        // Build command (defaults to ['npm', 'run', 'build'])\n  skipDependencyInstall?: boolean;// Skip npm install (defaults to false)\n  skipBuild?: boolean;            // Skip build step (defaults to false)\n\n  // Optional - Runtime\n  watchMode?: boolean;            // Enable watch mode (defaults to true)\n  env?: Record<string, string>;   // Custom environment variables\n  maxRetries?: number;            // Max retries for EADDRINUSE (defaults to 3)\n\n  // Optional - Lifecycle Hooks\n  onBeforeBuild?: () => Promise<void> | void;\n  onAfterBuild?: () => Promise<void> | void;\n  onServerStarted?: (port: number, pid: number) => Promise<void> | void;\n  onServerExit?: (code: number | null) => Promise<void> | void;\n}\n```\n\n### Usage Patterns\n\n#### Basic Development Server\n\n```typescript\nconst launcher = new TypeScriptServerLauncher({\n  projectRoot: __dirname,\n  serverDir: 'backend',\n  devCommand: ['npm', 'run', 'dev'],\n  startCommand: ['npm', 'run', 'start'],\n  watchMode: true\n});\n\nawait launcher.launch();\n```\n\n#### Production-like Testing\n\n```typescript\nconst launcher = new TypeScriptServerLauncher({\n  serverDir: 'backend',\n  devCommand: ['npm', 'run', 'dev'],\n  startCommand: ['npm', 'run', 'start'],\n  watchMode: false,  // Disable auto-restart\n  preferredPort: 8080,\n  env: {\n    NODE_ENV: 'production',\n    LOG_LEVEL: 'info'\n  }\n});\n\nawait launcher.launch();\n```\n\n#### Custom Build Pipeline\n\n```typescript\nconst launcher = new TypeScriptServerLauncher({\n  serverDir: 'backend',\n  devCommand: ['npm', 'run', 'dev'],\n  startCommand: ['npm', 'run', 'start'],\n  prepareScriptPath: 'scripts/prepare-monorepo.mjs',\n  onBeforeBuild: async () => {\n    console.log('🔨 Running custom pre-build tasks...');\n    // Custom validation, code generation, etc.\n  },\n  onAfterBuild: async () => {\n    console.log('✅ Build completed, running post-build tasks...');\n    // Asset optimization, cache warming, etc.\n  }\n});\n\nawait launcher.launch();\n```\n\n#### Port Conflict Handling\n\n```typescript\nconst launcher = new TypeScriptServerLauncher({\n  serverDir: 'backend',\n  devCommand: ['npm', 'run', 'dev'],\n  startCommand: ['npm', 'run', 'start'],\n  preferredPort: 2000,\n  forcePort: true,  // Kill existing processes on port 2000\n  maxRetries: 5,    // Retry up to 5 times on EADDRINUSE\n  onServerStarted: async (port, pid) => {\n    if (port !== 2000) {\n      console.warn(`⚠️  Using fallback port ${port} instead of 2000`);\n    }\n  }\n});\n\nawait launcher.launch();\n```\n\n### Standalone Utilities\n\nThe launcher is built on modular utilities that can be used independently:\n\n#### Enhanced Port Finder\n\n```typescript\nimport { findAvailablePort, isPortAvailable } from '@ai-universe/mcp-server-utils';\n\n// Randomized search in range (avoids thundering herd)\nconst port = await findAvailablePort({\n  minPort: 2000,\n  maxPort: 2500\n});\n\n// Check specific port\nconst available = await isPortAvailable(2000);\n```\n\n#### Process Manager\n\n```typescript\nimport {\n  terminateProcessByPid,\n  reclaimPort,\n  readPidFile,\n  writePidFile\n} from '@ai-universe/mcp-server-utils';\n\n// Graceful/forceful termination\nawait terminateProcessByPid(12345);\n\n// Reclaim port by killing processes\nawait reclaimPort(2000);\n\n// PID file management\nwritePidFile('/tmp/server.pid', process.pid);\nconst pid = readPidFile('/tmp/server.pid');\n```\n\n#### Build Orchestrator\n\n```typescript\nimport {\n  checkAndInstallDependencies,\n  buildTypeScript,\n  runCustomPrepareScript\n} from '@ai-universe/mcp-server-utils';\n\n// Ensure dependencies are current\ncheckAndInstallDependencies('/path/to/backend');\n\n// Build TypeScript project\nbuildTypeScript('/path/to/backend', ['npm', 'run', 'build']);\n\n// Run custom preparation\nrunCustomPrepareScript('/path/to/script.mjs', '/path/to/workdir');\n```\n\n### Environment Variables\n\nThe launcher respects these environment variables (can be overridden in config):\n\n- `RUN_LOCAL_SERVER_PREFERRED_PORT` - Override preferred port\n- `RUN_LOCAL_SERVER_MIN_PORT` - Override minimum port for fallback\n- `RUN_LOCAL_SERVER_MAX_PORT` - Override maximum port for fallback\n- `CORS_ALLOWED_ORIGINS` - CORS configuration for server\n- `FASTMCP_LOOPBACK_PORT` - MCP loopback port (if applicable)\n\n### Integration Example (AI Universe)\n\nSee `scripts/run-local-server.ts` for a real-world example of integrating `TypeScriptServerLauncher` with:\n- Shared library preparation (`prepare-shared-libs.mjs`)\n- Custom logging and lifecycle hooks\n- Environment-based configuration\n- macOS Terminal integration via wrapper script\n\n### Error Handling\n\nThe launcher includes comprehensive error handling:\n\n- **Port Conflicts**: Automatic retry with new port selection\n- **Build Failures**: Clear error messages with exit codes\n- **Process Crashes**: Graceful shutdown and cleanup\n- **Signal Handling**: Proper cleanup on SIGINT/SIGTERM\n\n### Best Practices\n\n1. **Always use PID files** for reliable process tracking across restarts\n2. **Enable watch mode** in development for fast iteration\n3. **Use forcePort sparingly** - it kills existing processes\n4. **Implement lifecycle hooks** for custom logging and monitoring\n5. **Test with watchMode: false** to verify production behavior\n\n## Tool helper catalog\n\n| Helper | Description | Output |\n| ------ | ----------- | ------ |\n| `createEchoTool()` | Quick connectivity check—echoes incoming message with timestamp. | JSON string `{ echo, timestamp }` |\n| `createVersionTool(version, info?)` | Returns version metadata plus optional extra fields. | Pretty-printed JSON |\n| `createStatusTool(statusProvider)` | Wraps any status provider function and adds timestamps. | Pretty-printed JSON |\n| `createHealthCheckTool(version, info?)` | Standard health endpoint that pairs nicely with HTTP `/health`. | Pretty-printed JSON |\n| `withErrorHandling(tool, handler?)` | Converts thrown errors into structured JSON payloads with timestamps; custom handler can map errors to friendly messages. | JSON string `{ error: true, message, timestamp }` |\n| `withLogging(tool, logger?)` | Logs parameters, success duration, and failures using provided logger or `console.log`. | Returns original tool result |\n\nCompose them to instrument your own tools without rewriting boilerplate:\n\n```typescript\nimport { z } from 'zod';\n\nconst rawTool = {\n  name: 'plan-trip',\n  description: 'Generate itineraries',\n  parameters: z.object({ destination: z.string() }),\n  execute: async ({ destination }) => `Planning trip to ${destination}`,\n};\n\nconst safeTool = withLogging(withErrorHandling(rawTool));\n```\n\n## Bundled Conversation MCP client\n\n`@ai-universe/mcp-server-utils` now re-exports every symbol from\n`@ai-universe/mcp-conversation-client`, letting you wire conversation-aware\nservers without installing a second package. The dependency is version-locked so\nyour MCP tooling and client stay in sync.\n\n```typescript\nimport {\n  ConversationMCPClient,\n  ConversationAuthHandler,\n} from '@ai-universe/mcp-server-utils';\n\nconst client = new ConversationMCPClient({\n  serverUrl: 'https://ai-universe-convo-mcp.example.com',\n  auth: new ConversationAuthHandler({\n    getAccessToken: async () => process.env.CONVO_TOKEN!,\n  }),\n});\n\nconst { conversations } = await client.listConversations({ userId: 'user-123' });\n```\n\nAll helpers, types, and error utilities from the dedicated conversation client\npackage are available through this entrypoint. Existing imports from\n`@ai-universe/mcp-conversation-client` continue to work; the re-export simply\nremoves the need for a separate installation step when you already depend on the\nserver utilities bundle.\n\n## Logging, error handling, and security notes\n\n- Provide a `logger` with `info`/`error` when starting the proxy to surface port selection, startup milestones, and runtime failures to your observability stack.\n- Combine `withErrorHandling` and `withLogging` to guarantee client-friendly error payloads while still surfacing stack traces in logs.\n- CORS normalization plus `wildcardToSafeRegex` safeguards against unescaped regex characters in user-provided wildcard origins, mitigating injection vectors.\n- `findAvailablePort` enforces strict bounds, preventing runaway searches that could degrade host performance.\n- Toggle verbose latency instrumentation globally by setting `MCP_VERBOSE_LATENCY_LOGGING=false`. The flag defaults to `true`\n  and takes precedence over the legacy `SECOND_OPINION_VERBOSE_LOGGING` toggle (which is only consulted when the new\n  variable is unset). Persistence to `/tmp/<repo>/<branch>/<flow>-<timestamp>.json` artifacts continues regardless of\n  verbosity settings.\n- Call `LatencyTracker.logSummary(status, { includeContextKeys: [...] })` to emit the aggregated longest-stage/slowest-model\n  report while allowlisting only non-sensitive context keys for log output.\n\n```typescript\nimport { setLatencyTrackerLogger } from '@ai-universe/mcp-server-utils';\n\nsetLatencyTrackerLogger(console);\n// Set MCP_VERBOSE_LATENCY_LOGGING=false to disable structured latency logs\n```\n\n## TypeScript reference\n\nAll exports are surfaced through the package root for ergonomic imports.\n\n```typescript\nimport {\n  startFastMcpHttpProxy,\n  findAvailablePort,\n  createWildcardCorsOptions,\n  wildcardToSafeRegex,\n  createMCPServer,\n  createHealthCheckTool,\n  ServerLifecycleManager,\n  setupGracefulShutdown,\n  createEchoTool,\n  createVersionTool,\n  createStatusTool,\n  withErrorHandling,\n  withLogging,\n} from '@ai-universe/mcp-server-utils';\n```\n\nTypes such as `StartFastMcpHttpProxyOptions`, `CreateServerOptions`, `ServerLifecycleHooks`, and decorators’ parameter types are all exported for TypeScript projects to compose their own wrappers.\n\n## Testing your integration\n\nWhile this package itself is framework-agnostic, recommended checks include:\n\n- Unit-test your agent registrations by asserting `server.getTool('name')` exists after calling `createMCPServer`.\n- Spin up the HTTP proxy with `supertest` against the returned Express `app` to verify routing and CORS responses.\n- Mock the `httpModule` option with `node:http` stubs if you need deterministic proxy behavior in unit tests.\n\n## Troubleshooting & FAQs\n\n**The proxy fails with “Bad Gateway”.** Ensure the internal FastMCP HTTP stream is reachable. The error payload includes the underlying message; pipe it into your logging pipeline via the provided `logger`.\n\n**My wildcard origin isn’t matching.** The helper trims trailing slashes and expects your pattern without them (`https://*.example.com`, not `https://*.example.com/`). Verify the incoming origin after Express normalization.\n\n**How do I stop the server cleanly in containers?** Instantiate `ServerLifecycleManager` and call `setupGracefulShutdown`. It captures SIGINT/SIGTERM/SIGQUIT and exits `0` on success, `1` on failure.\n\n**Can I use STDIO transport instead of HTTP?** Yes—`ServerLifecycleManager` is transport-agnostic. The HTTP proxy helper is optional; you can still use the factory, lifecycle, and tool helpers when running STDIO-only services.\n\n## Requirements\n\n- Node.js 18+\n- FastMCP 3.16.0+\n- Express 4.18+\n- cors 2.8+\n\n> **Optional:** Bring your own validation library (e.g., `zod`) for tool schemas if you need runtime parameter validation.\n\n## License\n\nMIT\n\nThis package is part of the AI Universe project. Refer to the main repository for contribution guidelines.\n","readmeFilename":"README.md"}