diff --git a/apps/mcp-analytics/custom-dispatcher/hono-server/.gitignore b/apps/mcp-analytics/custom-dispatcher/hono-server/.gitignore new file mode 100644 index 000000000..4c49bd78f --- /dev/null +++ b/apps/mcp-analytics/custom-dispatcher/hono-server/.gitignore @@ -0,0 +1 @@ +.env diff --git a/apps/mcp-analytics/custom-dispatcher/hono-server/package-lock.json b/apps/mcp-analytics/custom-dispatcher/hono-server/package-lock.json new file mode 100644 index 000000000..f0372a08a --- /dev/null +++ b/apps/mcp-analytics/custom-dispatcher/hono-server/package-lock.json @@ -0,0 +1,639 @@ +{ + "name": "wb-mcp-hono-dispatcher", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wb-mcp-hono-dispatcher", + "version": "0.0.0", + "dependencies": { + "@hono/node-server": "^1.13.7", + "@posthog/mcp": "0.25.0", + "hono": "^4.6.14", + "posthog-node": "^5.59.0" + }, + "devDependencies": { + "tsx": "^4.19.2", + "typescript": "^5.6.3" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.17", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.17.tgz", + "integrity": "sha512-dSneS5qhiauZWGDCeK4o695Xd9nUNjviSZCMQrj10eetr8Uln1ucn6bbphOM6UynAMMtNIzZNSpL9vnASJwrPQ==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@posthog/core": { + "version": "1.61.2", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.61.2.tgz", + "integrity": "sha512-l3b6Dc2NmItwmyu6ot7K2jtStQOAQjZw/PB/gpZwk2W6SBCbvPg6YJzReSBSQLuok19ridbfVNk70a5hgoGX2Q==", + "license": "MIT", + "dependencies": { + "@posthog/types": "^1.418.0" + } + }, + "node_modules/@posthog/mcp": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@posthog/mcp/-/mcp-0.25.0.tgz", + "integrity": "sha512-YV4J09e4eEyibDcS6D7BCCaDMfojkPiMWoZLoXCg3LECgAyyN3esOX4ROT4vquBiFJGz/Tugf3o0jBKZJf6pgA==", + "license": "MIT", + "dependencies": { + "@posthog/core": "^1.61.1" + }, + "engines": { + "node": "^20.20.0 || >=22.22.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": ">=1.26.0", + "@modelcontextprotocol/server": ">=2.0.0", + "posthog-node": "^5.0.0" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + }, + "@modelcontextprotocol/server": { + "optional": true + } + } + }, + "node_modules/@posthog/types": { + "version": "1.418.0", + "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.418.0.tgz", + "integrity": "sha512-WqDXUWH1R8OilBp2PfDpQIRZSCs3QyOnw7H3YK7lvZLCMIsOqSZAKJrrqYWt4f7FvnVCACRuNGCC0HKh3J/HWw==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hono": { + "version": "4.13.14", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.14.tgz", + "integrity": "sha512-yhRLQ21U6qa9Hsu2N7Qcbh8tE+WKEcoErjIo56LeSGiGXGp9sA7UpE86Ui9uexb61KakiGwuHMn2QdV7w6i6kQ==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/posthog-node": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.59.0.tgz", + "integrity": "sha512-vn8lr3WTKLNHe9DtP3oXT82+Ywoeo17nPapOH269vlKmbrSZiv6aTsokeGXXlXgkffhI6POk3+CKgBN3ADEONg==", + "license": "MIT", + "dependencies": { + "@posthog/core": "^1.61.2" + }, + "engines": { + "node": "^20.20.0 || >=22.22.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.2.0", + "rxjs": "^7.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "rxjs": { + "optional": true + } + } + }, + "node_modules/tsx": { + "version": "4.23.15", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz", + "integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/apps/mcp-analytics/custom-dispatcher/hono-server/package.json b/apps/mcp-analytics/custom-dispatcher/hono-server/package.json index 48d679e66..f5657e9e1 100644 --- a/apps/mcp-analytics/custom-dispatcher/hono-server/package.json +++ b/apps/mcp-analytics/custom-dispatcher/hono-server/package.json @@ -10,7 +10,9 @@ }, "dependencies": { "@hono/node-server": "^1.13.7", - "hono": "^4.6.14" + "@posthog/mcp": "0.25.0", + "hono": "^4.6.14", + "posthog-node": "^5.59.0" }, "devDependencies": { "tsx": "^4.19.2", diff --git a/apps/mcp-analytics/custom-dispatcher/hono-server/posthog-mcp-analytics-report.md b/apps/mcp-analytics/custom-dispatcher/hono-server/posthog-mcp-analytics-report.md new file mode 100644 index 000000000..d89f794dc --- /dev/null +++ b/apps/mcp-analytics/custom-dispatcher/hono-server/posthog-mcp-analytics-report.md @@ -0,0 +1,37 @@ +# PostHog MCP Analytics Setup + +## Changes made + +- Detected a TypeScript Hono MCP server using a custom JSON-RPC dispatcher and applied the custom-dispatcher (Path C) integration. +- Installed `@posthog/mcp` pinned to `0.25.0` and added `posthog-node`. +- Created one module-scope `PostHogMCP` client using `POSTHOG_PROJECT_TOKEN` and `POSTHOG_HOST` from the environment. +- Added MCP initialize, tool-list, successful tool-call, and failed tool-call analytics without changing the existing tool implementations. +- Added tool schema preparation for agent intent and self-reported model capture, and ensured SDK-owned arguments are removed before tool dispatch. +- Captured request protocol, client user-agent, vendor-client metadata, tool descriptions, durations, responses, and errors when available. +- Enabled exception autocapture and graceful PostHog shutdown on `SIGTERM`. +- Added the provided PostHog project token and host to `.env`. + +The server will emit canonical `$mcp_initialize`, `$mcp_tools_list`, and `$mcp_tool_call` events. Failed calls remain `$mcp_tool_call` events with `$mcp_is_error = true` and may also emit a sibling `$exception` event. + +## Files modified or created + +- `src/index.ts` — initialized `PostHogMCP` and instrumented the custom MCP dispatcher. +- `package.json` — added the PostHog dependencies with the MCP SDK pinned. +- `package-lock.json` — recorded installed dependency versions. +- `.env` — added the project token and ingestion host. +- `posthog-mcp-analytics-report.md` — this report. + +## Verification + +- `npm run build` completed successfully (`tsc --noEmit`). +- Confirmed both required PostHog environment keys are present. +- Confirmed `tools/list` uses `prepareToolList`, `tools/call` dispatches cleaned arguments from `prepareToolCall`, and analytics are drained during shutdown. + +## Manual steps + +- Configure `POSTHOG_PROJECT_TOKEN` and `POSTHOG_HOST` in the deployed server environment; do not rely on the local `.env` file in production. +- Ensure the process that starts the server loads `.env` during local development, or export the two variables before running `npm start`. +- Restart the MCP server and make a `tools/list` request followed by a tool call. The `$mcp_*` events will then appear in PostHog. +- `@posthog/mcp` is pre-1.0, so review release notes before future upgrades. + +See the [PostHog MCP analytics documentation](https://posthog.com/docs/mcp-analytics) for dashboards and the event reference. diff --git a/apps/mcp-analytics/custom-dispatcher/hono-server/src/index.ts b/apps/mcp-analytics/custom-dispatcher/hono-server/src/index.ts index 5d881a004..7e4f7e2e2 100644 --- a/apps/mcp-analytics/custom-dispatcher/hono-server/src/index.ts +++ b/apps/mcp-analytics/custom-dispatcher/hono-server/src/index.ts @@ -1,4 +1,5 @@ import { serve } from '@hono/node-server' +import { PostHogMCP } from '@posthog/mcp' import { Hono } from 'hono' // A custom MCP dispatcher: it speaks the MCP JSON-RPC protocol directly over @@ -45,39 +46,126 @@ function runTool(name: string, args: Record): unknown { } } +const projectToken = process.env.POSTHOG_PROJECT_TOKEN +const posthogHost = process.env.POSTHOG_HOST + +if ((!projectToken || !posthogHost) && process.env.NODE_ENV !== 'production') { + throw new Error( + 'POSTHOG_PROJECT_TOKEN and POSTHOG_HOST variables required by PostHog are missing or un-configured, this causes events to be silently missed. This error stops appearing once both variables are configured', + ) +} + +const posthog = + projectToken && posthogHost + ? new PostHogMCP(projectToken, { + host: posthogHost, + captureModel: true, + enableConversationId: false, + enableExceptionAutocapture: true, + }) + : undefined + const app = new Hono() app.post('/mcp', async (c) => { const body = (await c.req.json()) as JsonRpcRequest + const captureContext = { + protocolVersion: c.req.header('MCP-Protocol-Version'), + clientUserAgent: c.req.header('user-agent'), + vendorClient: c.req.header('x-anthropic-client'), + } if (body.method === 'initialize') { - return c.json({ - jsonrpc: '2.0', - id: body.id, - result: { - protocolVersion: '2024-11-05', - capabilities: { tools: {} }, - serverInfo: { name: 'workbench-hono-dispatcher', version: '1.0.0' }, - }, + const start = Date.now() + const result = { + protocolVersion: '2024-11-05', + capabilities: { tools: {} }, + serverInfo: { name: 'workbench-hono-dispatcher', version: '1.0.0' }, + } + const rawClientInfo = body.params?.clientInfo + const clientInfo = + rawClientInfo && typeof rawClientInfo === 'object' + ? (rawClientInfo as Record) + : undefined + + posthog?.captureInitialize({ + ...captureContext, + protocolVersion: result.protocolVersion, + clientName: typeof clientInfo?.name === 'string' ? clientInfo.name : undefined, + clientVersion: typeof clientInfo?.version === 'string' ? clientInfo.version : undefined, + parameters: body.params, + response: result, + durationMs: Date.now() - start, }) + + return c.json({ jsonrpc: '2.0', id: body.id, result }) } if (body.method === 'tools/list') { - return c.json({ jsonrpc: '2.0', id: body.id, result: { tools: TOOLS } }) + const start = Date.now() + const tools = posthog?.prepareToolList(TOOLS) ?? TOOLS + const result = { tools } + + posthog?.captureToolsList({ + ...captureContext, + toolNames: tools.map((tool) => tool.name), + parameters: body.params, + durationMs: Date.now() - start, + }) + + return c.json({ jsonrpc: '2.0', id: body.id, result }) } if (body.method === 'tools/call') { + const start = Date.now() const params = body.params ?? {} const name = String(params.name) - const args = (params.arguments as Record) ?? {} + const rawArgs = (params.arguments as Record) ?? {} + const originalTool = TOOLS.find((tool) => tool.name === name) + const rawRequestMeta = params._meta + const requestMeta = + rawRequestMeta && typeof rawRequestMeta === 'object' + ? (rawRequestMeta as Record) + : undefined + const preparedCall = posthog?.prepareToolCall(name, rawArgs, { + originalTool, + requestMeta, + }) + const args = posthog ? (preparedCall?.args ?? {}) : rawArgs + try { - return c.json({ jsonrpc: '2.0', id: body.id, result: runTool(name, args) }) + const result = runTool(name, args) + posthog?.captureToolCall({ + ...captureContext, + toolName: name, + toolDescription: originalTool?.description, + parameters: args, + response: result, + durationMs: Date.now() - start, + isError: false, + intent: preparedCall?.intent, + intentSource: preparedCall?.intentSource, + llmModel: preparedCall?.llmModel, + llmModelSource: preparedCall?.llmModelSource, + }) + return c.json({ jsonrpc: '2.0', id: body.id, result }) } catch (err) { - return c.json({ - jsonrpc: '2.0', - id: body.id, - result: { isError: true, content: [{ type: 'text', text: String(err) }] }, + const result = { isError: true, content: [{ type: 'text', text: String(err) }] } + posthog?.captureToolCall({ + ...captureContext, + toolName: name, + toolDescription: originalTool?.description, + parameters: args, + response: result, + durationMs: Date.now() - start, + isError: true, + error: err, + intent: preparedCall?.intent, + intentSource: preparedCall?.intentSource, + llmModel: preparedCall?.llmModel, + llmModelSource: preparedCall?.llmModelSource, }) + return c.json({ jsonrpc: '2.0', id: body.id, result }) } } @@ -89,3 +177,8 @@ app.post('/mcp', async (c) => { }) serve({ fetch: app.fetch, port: 3000 }) + +process.on('SIGTERM', async () => { + await posthog?.shutdown() + process.exit(0) +})