{"_id":"countly-mcp-server","_rev":"10-1f6dade1c7ee2d5d6b0439cdbe8c38b2","name":"countly-mcp-server","dist-tags":{"latest":"1.7.0"},"versions":{"1.0.0":{"name":"countly-mcp-server","version":"1.0.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.0.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"}],"dist":{"shasum":"f61b7e2135d81bbbfc9dfc8339e3907d102a35a3","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.0.0.tgz","fileCount":83,"integrity":"sha512-V36VDmf8rjSGWmya514yO9mOVL6ATI4gF0IihOXETAevatfp9vMY4H2joMKR4dFIAfcW0AAOCVv5sX/qvsoF5w==","signatures":[{"sig":"MEQCIH30Luy4axNyr8PvDBHBfRMWL+RJDtiHSv2OoPjPQX6mAiA+W3NCFSO6i0nmaFTJsAvbDDvtToJ9QrniFi5YRcCPGA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":366272},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"2e04b021e406d891d8a2f9f93d2fb6a734da484f","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","start":"node build/index.js --http","test:ci":"vitest run --coverage","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"10.9.2","description":"MCP server for Countly Analytics Platform","directories":{},"_nodeVersion":"22.17.1","dependencies":{"axios":"^1.6.0","dotenv":"^17.2.2","@modelcontextprotocol/sdk":"^1.17.4"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","vitest":"^3.2.4","typescript":"^5.3.0","@types/node":"^20.0.0","@vitest/coverage-v8":"^3.2.4"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.0.0_1762526711620_0.5112124884930411","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"countly-mcp-server","version":"1.0.1","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.0.1","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"dist":{"shasum":"f3727ed275e9bf67d442fc754df5ea5b9adfad25","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.0.1.tgz","fileCount":79,"integrity":"sha512-J9ckoGBIBXwnGKu/OhGuZdFdDUZuPlX/ioe8dY18B9Imzx67p6rcVQWFCXHN12t3k6LWUnf5q7oLrtlGaaGHGQ==","signatures":[{"sig":"MEQCIAp0hG79r7ANa08UvqWOCg4k7VBlGna/6JD/3nk1MIqlAiBP8EtfNvtZdGnAtFyzjDVcTdpnHWyqdo6RPCFozC5DtQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":353726},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"1ef45ee7bc2a52ac89382eebbf1582463fe7459d","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"10.9.2","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"22.17.1","dependencies":{"axios":"^1.13.2","dotenv":"^17.2.3","@modelcontextprotocol/sdk":"^1.21.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.1","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20.19.24","lint-staged":"^16.2.6","@vitest/coverage-v8":"^3.2.4","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.46.3"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.0.1_1762547593890_0.15424740250650393","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"countly-mcp-server","version":"1.1.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.1.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"dist":{"shasum":"8f65456459467b07d81edb9829682892914601e5","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.1.0.tgz","fileCount":187,"integrity":"sha512-7YJRfneOocLhckdIozoyokLy+vwHjtyzfP1UJ5yUwkQFX+1yBiVltVN4cqxQL+TS+5oovqSNxgmzRJxZIZmwCw==","signatures":[{"sig":"MEUCIG8I0VT4DYdCzOzN6O7xSvvYdOm2ZjiYfbJyxyJqDuMdAiEAjANhwzvxJ9N7jM5vMRyg+xaWiYf4qZ3qCvZCuOXMoq4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1462745},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"fa031b96233c268f2a6c5773703124904521b781","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"10.9.2","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"22.17.1","dependencies":{"axios":"^1.13.2","dotenv":"^17.2.3","countly-sdk-nodejs":"^24.10.3","@modelcontextprotocol/sdk":"^1.24.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.1","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20.19.25","lint-staged":"^16.2.7","@vitest/coverage-v8":"^3.2.4","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.47.0"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.1.0_1764943592598_0.8798848667585375","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"countly-mcp-server","version":"1.2.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.2.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"261f6a0842ee6a1680660f62e7788e9f3e2b6645","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.2.0.tgz","fileCount":187,"integrity":"sha512-7SKM3R2uiHI1hP5Mi3E22ZnC6zwjIglGMetk+JBT2fCWTVnEAco3KRxfTDtULckrsdj4+athB231F7+niyXFRA==","signatures":[{"sig":"MEUCIQC6IN82IiuHIA1Mmge+aqAZlCQLEG9kxLehbs/mFwm1fAIgE5TBvr9uNjSutaa1aWOICK+2xjwe1oZQNAlnGZNnsak=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1465171},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"a41c4dae4c9c895095c70b97ba7859697baaf6fa","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.15.2","dotenv":"^17.4.1","countly-sdk-nodejs":"^24.10.3","@modelcontextprotocol/sdk":"^1.27.1"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.4","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20.19.39","lint-staged":"^16.4.0","@vitest/coverage-v8":"^3.2.4","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.58.1"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.2.0_1776887971177_0.8915885427079617","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"countly-mcp-server","version":"1.2.1","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.2.1","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"44d0712088300293dda7b91ebb5588d5bf073ae8","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.2.1.tgz","fileCount":187,"integrity":"sha512-kulhG28afQBPx4UIsGjTUmc+A9ylqjM4nkx/f6U/4bKxU1jz+FuDGl0KAwiz1qxdFUSn8nKvsTR2grIen/FyIw==","signatures":[{"sig":"MEUCIQCt7tr/B/SxE4hD0nD4/toF6ZFoKNDyMz5nHS87jIPHIgIgNlS6cNjA7L2sRqv2xbilA/XU4qQEs8O69+MfwNmYwOA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1465900},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"d7a1497b9a25637dcc7f5c9969cc2bf081024baa","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.15.2","dotenv":"^17.4.1","countly-sdk-nodejs":"^24.10.3","@modelcontextprotocol/sdk":"^1.27.1"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.4","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20.19.39","lint-staged":"^16.4.0","@vitest/coverage-v8":"^3.2.4","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.58.1"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.2.1_1776888940557_0.3568474333204237","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"countly-mcp-server","version":"1.3.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.3.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"741e5a2dbbcdcb5a7aea0791037f1118b9faa11b","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.3.0.tgz","fileCount":191,"integrity":"sha512-ZGscRkWVNs/uNpiB+XB2iRzspIGKvdjBJ8EqTXZlX4b1vYYQXztOF1L2zzopDPP4Wudpm/aZFM9azrSH2GW1sw==","signatures":[{"sig":"MEUCIQCV8ztnfqdWVInCpJIb4O9u9WCSHb+vezMpg2ow5ylBPQIgX1xjtLaqk+JMVkNlgc5KsUK9X3G/AbxIImtOlxwF0jY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1564688},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"ee4b7a3fe7103e1d15ff7b0afcf2a64bb965785f","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.15.2","dotenv":"^17.4.2","countly-sdk-nodejs":"^24.10.3","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.4","vitest":"^3.2.4","typescript":"^5.9.3","@types/node":"^20.19.39","lint-staged":"^16.4.0","@vitest/coverage-v8":"^3.2.4","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.3.0_1776961086673_0.8938122949768903","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"countly-mcp-server","version":"1.4.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.4.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"53bece82d91027d74df895677798ec37110c836f","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.4.0.tgz","fileCount":199,"integrity":"sha512-olMNKfraHrND9Av7wdg8GEFcixW8Xi9oIdf599UYUruaJ4kxFU2Ki+RiCjT3Nyj08LWqHxUOR9eHwVDTSa6ylA==","signatures":[{"sig":"MEUCIGe7+yJCDruK7qEfPtHV4EvdJjU+cZYr7xZnQOXT6I6iAiEAk0iTIcydiuwxNP7KsOVlPoSLC/OMb9PwPxghEWby7gM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1752262},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"77bcbd3d68749c5a1b98f5d47a86889a236772ce","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.18.1","dotenv":"^17.4.2","countly-sdk-nodejs":"^24.10.4","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.4","vitest":"^4.1.8","typescript":"^5.9.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@vitest/coverage-v8":"^4.1.9","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.61.0"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.4.0_1783628799300_0.803330843642956","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"countly-mcp-server","version":"1.5.0","keywords":["mcp","countly","analytics","server"],"author":{"name":"Countly MCP Server"},"license":"MIT","_id":"countly-mcp-server@1.5.0","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"3880c8acd10b1505ba72474c748e4f308857a575","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.5.0.tgz","fileCount":211,"integrity":"sha512-fvjIr+/c7GRfYg9XP55oQz87XNYZeZWh1wpt6aICOWyQySjpbh6tPcty6czdoBZuV0iyXu2RVkREtRTvmnH8yA==","signatures":[{"sig":"MEUCIFcq+QXFQ/It1ewEl3Wrj8hpc/nlINuWi5harc7ZcgXBAiEAjYky8KmhibSQr9+dzX1H4LR2w/fSh3XL2syzEMoy0c4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1815772},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=18"},"gitHead":"b1af1ac31ee28e1ef08fb38a7905721d4667f189","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.19.0","dotenv":"^17.4.2","ipaddr.js":"^1.9.1","countly-sdk-nodejs":"^24.10.4","@modelcontextprotocol/sdk":"^1.30.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.5","vitest":"^4.1.8","typescript":"^5.9.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@vitest/coverage-v8":"^4.1.10","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.67.0"},"_npmOperationalInternal":{"tmp":"tmp/countly-mcp-server_1.5.0_1787736557766_0.22141939206817152","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"_id":"countly-mcp-server@1.7.0","bin":{"countly-mcp-server":"build/index.js"},"dist":{"shasum":"316a316ea0fb2f96f9f701fd7ebc2ee762282883","tarball":"https://registry.npmjs.org/countly-mcp-server/-/countly-mcp-server-1.7.0.tgz","fileCount":315,"integrity":"sha512-H5XP+/Cb/YxwsjOxQ7/tIVSgevBfkffarFQwffPFKuH0JedZ9tDlV2jf8sMZ0giufQKnHeqi67ynhnfZMVJd/A==","signatures":[{"sig":"MEUCIBsT/8oxEa+bbUFvtB647AlzzqhIYpNDafDF4pbpbknkAiEA48h9qoHc0FbJXg5LVelvm+tQubgeJ8YPjAmcn+IIJL8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIG4BfPl/pzKKz6A0IFygZU8Hk1JsOdKnOtSdHZAbEytfAiEA/1wdKwi6haampVwJw7waLYUY0wrrSz8X4I9xsNxZRBk="}],"unpackedSize":2441478},"main":"build/index.js","name":"countly-mcp-server","type":"module","_from":"file:/private/tmp/countly-mcp-server-1.7.0.tgz","types":"build/index.d.ts","author":{"name":"Countly MCP Server"},"engines":{"node":">=18"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./build/*":"./build/*","./library":{"types":"./build/library.d.ts","default":"./build/library.js"},"./package.json":"./package.json"},"license":"MIT","scripts":{"dev":"tsc --watch","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.build.json","start":"node build/index.js --http","prepack":"npm run build","prepare":"[ -d .git ] && husky || echo 'Skipping husky (not a git repository)'","test:ci":"vitest run --coverage","lint:fix":"eslint . --ext .ts --fix","test:e2e":"npm run build && vitest run --config vitest.e2e.config.ts","test:watch":"vitest --watch","start:stdio":"node build/index.js","test:coverage":"vitest run --coverage"},"version":"1.7.0","_npmUser":{"name":"ar2rsawseen","email":"as@count.ly"},"keywords":["mcp","countly","analytics","server"],"_resolved":"/private/tmp/countly-mcp-server-1.7.0.tgz","_integrity":"sha512-H5XP+/Cb/YxwsjOxQ7/tIVSgevBfkffarFQwffPFKuH0JedZ9tDlV2jf8sMZ0giufQKnHeqi67ynhnfZMVJd/A==","_npmVersion":"11.12.1","description":"MCP server for Countly Analytics Platform","directories":{},"lint-staged":{"*.ts":["eslint --fix"]},"maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"_nodeVersion":"24.15.0","dependencies":{"axios":"^1.20.0","dotenv":"^17.4.2","ipaddr.js":"^1.9.1","countly-sdk-nodejs":"^24.10.4","@modelcontextprotocol/sdk":"^1.31.0"},"_hasShrinkwrap":false,"devDependencies":{"nock":"^13.5.6","husky":"^9.1.7","eslint":"^9.39.5","vitest":"^4.1.8","typescript":"^5.9.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@vitest/coverage-v8":"^4.1.11","eslint-plugin-import":"^2.32.0","@typescript-eslint/parser":"^8.46.3","@typescript-eslint/eslint-plugin":"^8.71.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/countly-mcp-server_1.7.0_1791360409356_0.5399396156170448"}}},"time":{"created":"2025-11-07T14:45:11.620Z","modified":"2026-10-07T08:06:49.705Z","1.0.0":"2025-11-07T14:45:11.833Z","1.0.1":"2025-11-07T20:33:14.115Z","1.1.0":"2025-12-05T14:06:32.834Z","1.2.0":"2026-04-22T19:59:31.364Z","1.2.1":"2026-04-22T20:15:40.767Z","1.3.0":"2026-04-23T16:18:06.834Z","1.4.0":"2026-07-09T20:26:39.473Z","1.5.0":"2026-08-26T09:29:17.933Z","1.7.0":"2026-10-07T08:06:49.438Z"},"author":{"name":"Countly MCP Server"},"license":"MIT","keywords":["mcp","countly","analytics","server"],"description":"MCP server for Countly Analytics Platform","maintainers":[{"name":"ar2rsawseen","email":"as@count.ly"},{"name":"ironic_badger","email":"kadikis.arturs@gmail.com"}],"readme":"# Countly MCP Server\n\nA Model Context Protocol (MCP) server for [Countly Analytics Platform](https://countly.com). This server enables AI assistants and MCP clients to interact with Countly's analytics data, manage applications, view dashboards, track events, and perform comprehensive analytics operations.\n\n## About Countly\n\nCountly is an open-source, enterprise-grade product analytics platform. It helps track user behavior, monitor application performance, and gain insights into user engagement. This MCP server provides programmatic access to all major Countly features through a standard protocol interface.\n\n## What is MCP?\n\nThe Model Context Protocol (MCP) is an open protocol that enables seamless integration between AI applications and external data sources. This server implements MCP to allow AI assistants like Claude to interact with your Countly analytics data naturally through conversation.\n\n## Requirements\n\n### Server Requirements\n- **Node.js 18+** (for local installation) OR **Docker** (recommended)\n- **Countly Server**: Access to a Countly instance (cloud or self-hosted): Countly Lite, Countly Enterprise or Countly Platform (see [Supported Countly Editions](#supported-countly-editions))\n- **Auth Token**: Valid Countly authentication token with appropriate permissions\n\n### Client Requirements\n- **MCP Protocol Version**: `2025-03-26` (Streamable HTTP specification)\n- **Compatible Clients**:\n  - VS Code MCP Extension (latest version)\n  - Claude Desktop (recent versions supporting 2025-03-26 spec)\n  - Any MCP client implementing the Streamable HTTP transport protocol\n\n> ⚠️ **Note**: For SSE type this server uses `StreamableHTTPServerTransport` which implements the modern MCP specification (2025-03-26). Older MCP clients that only support the legacy SSE protocol (2024-11-05) are not compatible. Please ensure your MCP client is up-to-date.\n\n## Features\n\n- **209 Tools** across 43 categories for comprehensive Countly operations\n- **Resources** for AI context - Access read-only Countly data (app configs, event schemas, analytics overviews)\n- **Prompts** for common tasks - Pre-built templates for crash analysis, engagement reports, and more\n- **Multiple Transport Options**: Supports both stdio (recommended) and HTTP/SSE connections\n- **Flexible Authentication**: Environment variables, HTTP headers, URL parameters, or token files\n- **Edition-Aware**: Detects Countly Lite, Enterprise or Platform on connection and only exposes the tools that server and the connected user can use\n- **Docker Support**: Pre-built Docker images with multi-architecture support (amd64, arm64)\n- **Usage Analytics**: Usage reporting to stats.count.ly under your Countly server's domain (on by default; `ENABLE_ANALYTICS=false` opts out)\n-\n\n## Supported Countly Editions\n\nThe server works with every Countly flavor and detects which one it is talking to on the first request for a server URL and token. The result is cached for 10 minutes.\n\n| Edition | What it is | How it is detected |\n|---|---|---|\n| **Countly Lite** | `countly-server` | No `/v2` API, no enterprise plugins |\n| **Countly Enterprise** | `countly-server` + enterprise plugins | No `/v2` API, enterprise plugins present (drill, funnels, cohorts, …) |\n| **Countly Platform** | `countly-platform`, the new architecture | Answers the `/v2` API (new UI), or Platform-only endpoints/plugins when running without it |\n\nBased on the detection, `tools/list` only contains tools that will work:\n\n- **Plugins**: tools whose Countly plugin is not enabled are hidden (e.g. cohorts on Lite, server logs on Platform). Global admins read the real plugin list. For other users the edition's default plugin set is assumed, because Countly only shows the plugin list to global admins.\n- **User permissions**: tools the connected user could never run are hidden, based on the user's feature permissions (create/read/update/delete per app, app admin, global admin), including group permissions. A read-only user sees roughly half the tools.\n- **Explanations instead of failures**: calling a hidden tool returns an error naming the missing plugin or permission, so the assistant can tell the user what is missing.\n\nDetection never hides tools on a guess: if the server cannot be reached or the user's permissions cannot be read, the configured tools stay available. `get_version` reports the detected edition. Set `COUNTLY_AUTO_DETECT=false` to turn detection off. Details are in [TOOLS_CONFIGURATION.md](TOOLS_CONFIGURATION.md#server-detection-and-plugin-based-tool-availability).\n\n## MCP Capabilities\n\nThis server implements the full MCP specification with support for:\n\n### Tools (209 available)\nExecute Countly operations like analytics queries, app management, crash analysis, etc. Each connection only sees the tools its Countly edition, plugins and user permissions support (see [Supported Countly Editions](#supported-countly-editions)).\n\n### Resources\nRead-only access to Countly data for AI context:\n- `countly://app/{app_id}/config` - Application configuration and metadata\n- `countly://app/{app_id}/events` - Event definitions and schemas  \n- `countly://app/{app_id}/overview` - Current analytics overview with key metrics\n\nResources provide AI assistants with context without requiring tool calls, making conversations more efficient.\n\n### Prompts\nPre-built analysis templates exposed as slash commands:\n- `analyze_crash_trends` - Analyze crash and error patterns\n- `generate_engagement_report` - Comprehensive user engagement analysis\n- `compare_app_versions` - Compare performance between versions\n- `user_retention_analysis` - Analyze retention patterns and cohorts\n- `funnel_optimization` - Conversion funnel analysis and suggestions\n- `event_health_check` - Event tracking implementation quality check\n- `identify_churn_risk` - Find users showing decreased engagement\n- `performance_dashboard` - Comprehensive performance overview\n\nPrompts guide AI assistants through complex multi-step workflows automatically.\n\n- 🔐 Multiple authentication methods (HTTP headers, environment variables, file-based)\n- 📊 Comprehensive Countly API access\n- ⚙️ Fine-grained tools configuration with CRUD operation control per category\n- 🐳 Docker support with production-ready configuration\n- 🔄 Support for both stdio and HTTP transports\n- 🏥 Built-in health checks\n- 🔒 Secure token handling with cryptographically secure session IDs\n- 🌐 Multi-client support with per-client credential passing\n- 🚨 **Enhanced error handling** with detailed API error messages\n\n## Quick Start\n\n### Prerequisites\n\nBefore starting, ensure you have:\n- Access to a Countly instance (cloud or self-hosted)\n- Valid Countly authentication token with appropriate permissions\n- Node.js 18+ (for local installation) OR Docker (recommended)\n- MCP client supporting protocol version 2025-03-26 (Streamable HTTP)\n\n### Using npx (No Installation)\n\nRun the published package directly with `npx` — no clone or build required:\n\n```bash\n# stdio mode (for MCP clients like Claude Desktop, VS Code)\nCOUNTLY_SERVER_URL=https://your-countly-instance.com \\\nCOUNTLY_AUTH_TOKEN=your-countly-auth-token \\\nnpx -y countly-mcp-server\n\n# HTTP mode (binds localhost; see \"Server-side token in HTTP mode\" before exposing it)\nCOUNTLY_SERVER_URL=https://your-countly-instance.com \\\nCOUNTLY_AUTH_TOKEN=your-countly-auth-token \\\nnpx -y countly-mcp-server --http\n```\n\nExample MCP client configuration (stdio):\n\n```json\n{\n  \"mcpServers\": {\n    \"countly\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"countly-mcp-server\"],\n      \"env\": {\n        \"COUNTLY_SERVER_URL\": \"https://your-countly-instance.com\",\n        \"COUNTLY_AUTH_TOKEN\": \"your-countly-auth-token\"\n      }\n    }\n  }\n}\n```\n\n### Using Docker (Recommended)\n\n1. **Create a token file:**\n   ```bash\n   echo \"your-countly-auth-token\" > countly_token.txt\n   ```\n\n2. **Create a `.env` file:**\n   ```bash\n   cp .env.example .env\n   # Edit .env and set your COUNTLY_SERVER_URL\n   ```\n\n3. **Run with Docker Compose:**\n   ```bash\n   docker-compose up -d\n   ```\n\n4. **Access the server:**\n   - HTTP/SSE mode: `http://localhost:3000/mcp`\n   - Health check: `http://localhost:3000/health`\n   - Default port: 3000 (configurable)\n\n### Using Docker Run\n\n```bash\ndocker run -d \\\n  --name countly-mcp-server \\\n  -p 3000:3000 \\\n  -e COUNTLY_SERVER_URL=https://your-countly-instance.com \\\n  -e COUNTLY_AUTH_TOKEN_FILE=/run/secrets/countly_token \\\n  -v $(pwd)/countly_token.txt:/run/secrets/countly_token:ro \\\n  countly-mcp-server\n```\n\n### Using Node.js\n\n1. **Install dependencies:**\n   ```bash\n   npm install\n   ```\n\n2. **Build the project:**\n   ```bash\n   npm run build\n   ```\n\n3. **Configure environment:**\n   ```bash\n   cp .env.example .env\n   # Edit .env with your settings\n   ```\n\n4. **Run the server:**\n   ```bash\n   # HTTP mode\n   npm start\n   \n   # stdio mode (for MCP clients)\n   npm run start:stdio\n   ```\n\n## Authentication\n\nThe server supports multiple authentication methods (in priority order):\n\n1. **Tool Arguments**\n   - Passed as `countly_auth_token` parameter in individual tool calls\n   - Overrides every other source for that call\n\n2. **HTTP Headers** (recommended for HTTP/SSE transport)\n   - Pass via `X-Countly-Server-Url` and `X-Countly-Auth-Token` headers\n   - Supported by VS Code MCP extension and other HTTP clients\n   - See [VS Code MCP Configuration](examples/vscode-mcp.md) for details\n\n3. **URL Parameters** (alternative for HTTP/SSE transport)\n   - Pass as query string: `?server_url=https://your-server.count.ly&auth_token=your-api-key`\n   - Useful for quick testing or tools that don't support custom headers\n   - Less secure than headers, use headers when possible\n\n4. **Environment Variable**\n   - Set `COUNTLY_AUTH_TOKEN` in environment\n   - Recommended for stdio transport mode\n\n5. **Token File** (recommended for production)\n   - Set `COUNTLY_AUTH_TOKEN_FILE` pointing to a file containing the token\n   - Useful with Docker secrets\n\nA token the caller supplies (1–3) always wins over the server's own (4–5);\nthe server-side token is only used for a request that brings none.\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `COUNTLY_SERVER_URL` | Yes | `https://api.count.ly` | Your Countly server URL |\n| `COUNTLY_AUTH_TOKEN` | No* | - | Authentication token (direct) |\n| `COUNTLY_AUTH_TOKEN_FILE` | No* | - | Path to file containing auth token |\n| `COUNTLY_TIMEOUT` | No | `30000` | Request timeout in milliseconds |\n| `ENABLE_ANALYTICS` | No | `true` | Usage analytics to stats.count.ly under your Countly server's domain (set to `false` to opt out) |\n| `COUNTLY_AUTO_DETECT` | No | `true` | Detect Countly Lite / Enterprise / Platform and hide tools the server doesn't support (set to `false` to always show all configured tools) |\n| `COUNTLY_TOOLS_{CATEGORY}` | No | `ALL` | Control available tools per category (see below) |\n| `COUNTLY_TOOLS_ALL` | No | `ALL` | Default permission for all categories |\n| `COUNTLY_CORS_ALLOWED_ORIGINS` | No | `*` | Comma-separated list of allowed CORS origins (HTTP transport). Leave unset or `*` for wide-open; use specific origins in production (e.g. `https://app.example.com,https://dash.example.com`). When a server-side token is configured, browser requests to `/mcp` are refused unless their origin is listed here explicitly; `*` does not count. |\n| `COUNTLY_RATE_LIMIT_RPM` | No | `120` | Per-IP requests per minute on the `/mcp` endpoint (HTTP transport). Set to `0` to disable. |\n| `COUNTLY_TRUST_PROXY` | No | `false` | When `true`, use `X-Forwarded-For` for the rate-limit client IP. Only enable when the server is behind a trusted reverse proxy that sets this header. |\n| `COUNTLY_MAX_BODY_BYTES` | No | `1048576` | Maximum request-body size accepted on `/mcp` (HTTP transport). Requests over the limit get `413 Payload Too Large`. Set to `0` to disable. |\n| `COUNTLY_MAX_CONCURRENT_PER_IP` | No | `50` | Maximum simultaneous TCP connections per client IP (HTTP transport). Over-limit connections are dropped. Set to `0` to disable. |\n| `COUNTLY_REQUEST_LOG` | No | `false` | When `true`, emit one NDJSON line per request to stderr (`{ts, ip, method, path, status, durationMs, rateLimitHit}`). Useful for piping into a log aggregator to spot abuse patterns. |\n\n*At least one authentication method must be configured\n\n### Analytics Tracking\n\nThe MCP server reports usage analytics to `stats.count.ly` to help improve the product, the same way the Countly platform reports its own server telemetry. Analytics are **enabled by default**; opt out with `ENABLE_ANALYTICS=false`.\n\n**Device ID: your Countly server's domain.** Events are reported under the domain of the Countly server the MCP server talks to (`COUNTLY_SERVER_URL`, or the per-request server URL in multi-tenant HTTP mode), with the scheme and trailing slashes removed, e.g. `countly.example.com` or `countly.example.com:8443/countly`. This is the same device ID the Countly platform uses for its own telemetry, so both line up on the stats server. Usage goes to the Countly server telemetry app on stats.count.ly (the app the Countly platform itself reports to), so MCP usage and the server's own telemetry sit under one device.\n\nWhen there is no usable domain (no server URL, or `localhost`), nothing is reported. In multi-tenant HTTP mode with no `COUNTLY_SERVER_URL`, that means visits to the welcome page, health checks, favicon and manifest requests, server start and the session are not reported; only MCP requests, which carry their server URL, are.\n\n**What is tracked:**\n- Your Countly server's domain (as the device ID, above)\n- Transport type used (stdio vs HTTP)\n- Tool execution metrics (success/failure, duration, tool names)\n- Authentication methods used (headers, env, file, args)\n- HTTP endpoint access patterns\n- Error occurrences (the error type and tool name only, no message)\n- Server start events\n- A truncated hash of the server URL, attached as the `server` segment on every event\n\n**What is NOT tracked:**\n- Authentication tokens or credentials\n- User data or analytics content\n- Personal information\n- Tool arguments or request/response bodies\n\n**To opt out:**\n```bash\nexport ENABLE_ANALYTICS=false\n```\n\nOr in your `.env` file:\n```\nENABLE_ANALYTICS=false\n```\n\nWhen the tools are embedded in another process through `countly-mcp-server/library`, the host decides whether and under which device ID usage is reported (see \"Embedding in another process\").\n\n### Tools Configuration\n\nThe server supports fine-grained control over which MCP tools are available and which CRUD operations they can perform. This is useful for security, governance, or creating read-only deployments.\n\nConfigure tools by category using environment variables:\n\n```bash\n# Format: COUNTLY_TOOLS_{CATEGORY}=CRUD\n# Where CRUD letters represent: Create, Read, Update, Delete operations\n\n# Examples:\nCOUNTLY_TOOLS_APPS=CR          # Apps: Create and Read only\nCOUNTLY_TOOLS_DATABASE=R       # Database: Read-only access\nCOUNTLY_TOOLS_CRASHES=CRUD     # Crashes: Full access\nCOUNTLY_TOOLS_ALERTS=NONE      # Alerts: Completely disabled\n\n# Set default for all categories:\nCOUNTLY_TOOLS_ALL=R            # Read-only mode for all tools\n```\n\n**Available Categories** (subset — see TOOLS_CONFIGURATION.md for all 42):\n- `CORE` - Core tools (ping, get_version, get_plugins) (3 tools)\n- `APPS` - Application management (6 tools)\n- `ANALYTICS` - Analytics data retrieval (7 tools)\n- `CRASHES` - Crash analytics and management (10 tools)\n- `NOTES` - Notes management (3 tools)\n- `EVENTS` - Event configuration (1 tool)\n- `ALERTS` - Alert management (3 tools)\n- `VIEWS` - Views analytics (3 tools)\n- `DATABASE` - Direct database access (5 tools)\n- `DASHBOARD_USERS` - Dashboard user management (1 tool)\n- `APP_USERS` - App user management (3 tools)\n\nFor complete documentation, examples, and per-tool CRUD mappings, see **[TOOLS_CONFIGURATION.md](TOOLS_CONFIGURATION.md)**.\n\n## Security & Production Hardening\n\nThe HTTP transport is designed to be usable both as a public-facing MCP\nendpoint (e.g. `mcp.count.ly`) and as a self-hosted single-tenant server.\nThe defaults favor compatibility; operators should opt into the tighter\nsettings below based on their deployment model.\n\n### Multi-tenant isolation\n\nThe HTTP transport is safe to use with multiple concurrent clients using\ndifferent Countly auth tokens. Each request gets its own outbound axios\ninstance with the `countly-token` header baked in, and each tenant's apps\ncache is keyed by SHA-256(token) so one tenant's apps cannot leak into\nanother tenant's `resolveAppId` lookup.\n\nNo operator configuration is required for this.\n\n### SSRF\n\nCaller-supplied server URLs (via `X-Countly-Server-Url` header or\n`?server_url=` query param) are validated against an SSRF denylist —\nloopback, link-local, RFC 1918, carrier-grade NAT, cloud metadata\nendpoints (`169.254.169.254`), `.local`/`.localhost`, and non-HTTP(S)\nschemes are rejected with a 400. This is a syntactic check; defense\nagainst DNS-rebinding still requires egress firewalling the server.\n\n### Credentials in URLs are deprecated\n\nPassing the auth token via `?auth_token=` is supported for backward\ncompatibility but emits a rate-limited security warning to stderr.\nTokens in URLs leak into access logs, browser history, and Referer\nheaders. Migrate callers to `X-Countly-Auth-Token` — URL-param support\nwill be removed in a future release.\n\n### Rate limiting\n\nThe `/mcp` endpoint has a per-IP sliding-window rate limiter, defaulting\nto 120 requests per minute. Tune via `COUNTLY_RATE_LIMIT_RPM=<n>`\n(set to `0` to disable). Behind a trusted reverse proxy, set\n`COUNTLY_TRUST_PROXY=true` so the first `X-Forwarded-For` hop is used as\nthe client IP.\n\n### Resource-exhaustion defenses\n\nAdditional protections layered on top of the application-level rate limit:\n\n- **Request body cap** (`COUNTLY_MAX_BODY_BYTES`, default 1 MiB) — `413\n  Payload Too Large` + socket destroyed for oversize bodies. Checked both\n  upfront via `Content-Length` and streamingly (for chunked / lying\n  clients).\n- **Per-IP concurrent connection cap** (`COUNTLY_MAX_CONCURRENT_PER_IP`,\n  default 50) — over-limit TCP connections are dropped before the TLS\n  handshake, closing the slow-loris amplification.\n- **Server timeouts** — `requestTimeout=30s`, `headersTimeout=10s`,\n  `keepAliveTimeout=5s`, `timeout=60s`. Slow clients can't keep sockets\n  open indefinitely.\n\nFor operators that want per-request audit logs for abuse detection, set\n`COUNTLY_REQUEST_LOG=true`. The server will emit one NDJSON line per\nrequest to stderr, containing only the fields listed in the env-var\ntable — no auth tokens, no bodies, no headers.\n\n### CORS\n\nThe default is `Access-Control-Allow-Origin: *` so browser-based MCP\nclients from any origin can connect. If your deployment only needs to\nserve specific origins, lock it down:\n\n```bash\nCOUNTLY_CORS_ALLOWED_ORIGINS=\"https://dash.example.com,https://ops.example.com\"\n```\n\nThe server will then echo only allowed origins and add `Vary: Origin`.\nPre-flight requests from disallowed origins get a 403.\n\nWhen the server holds its own token (`COUNTLY_AUTH_TOKEN` or\n`COUNTLY_AUTH_TOKEN_FILE`), `/mcp` refuses every request that carries an\n`Origin` header with a 403, unless that origin is listed explicitly in\n`COUNTLY_CORS_ALLOWED_ORIGINS` (the `*` default does not count). MCP\nclients such as Claude Desktop, Claude Code, VS Code and Cursor send no\n`Origin` header and are unaffected. This stops a web page open in the\noperator's browser, including one using DNS rebinding, from driving a\nserver that holds a token. Servers without a configured token, where every\ncaller brings its own, are not affected by this rule.\n\n### Server-side token in HTTP mode\n\n`COUNTLY_AUTH_TOKEN` and `COUNTLY_AUTH_TOKEN_FILE` exist for stdio mode,\nwhere the MCP client launches the server as its own child process. In HTTP\nmode the server does **not** authenticate its callers: when one is set,\nany caller that reaches `/mcp` without supplying its own token acts with\nthe configured one, with all the permissions that token carries.\n\nOnly configure a server-side token in HTTP mode when the endpoint is\nreachable from a trusted network alone: bound to localhost, behind a\nfirewall, or behind a reverse proxy that authenticates callers. The server\nlogs a warning at startup when it runs this way. For a shared or\ninternet-facing deployment, leave both variables unset and have each\nclient send its own token in the `X-Countly-Auth-Token` header.\n\n### Self-hosted single-tenant deployments\n\nIf you're running this as a single-tenant server (e.g. `docker run` on a\nVPS for your own AI assistant), prefer one of:\n\n- **Bind to localhost only** and tunnel through SSH:\n  `docker run -p 127.0.0.1:3000:3000 ...`\n- **Bind behind a reverse proxy** (Caddy, Nginx, Traefik) that terminates\n  TLS, adds authentication if needed, and sets a trusted `X-Forwarded-For`\n  (then set `COUNTLY_TRUST_PROXY=true`).\n\nThe default Dockerfile binds to `0.0.0.0:3000` so it works inside a\ncontainer without extra flags. This means `docker run -p 3000:3000 ...`\nexposes the MCP endpoint to the public internet — use an explicit local\nbind, a reverse proxy, or an external firewall if that's not what you\nwant. This matters most when the container is given a server-side token:\nsee [Server-side token in HTTP mode](#server-side-token-in-http-mode).\n\n### Telemetry\n\nAnalytics are **enabled by default** and report under your Countly server's\ndomain; opt out with `ENABLE_ANALYTICS=false`. No authentication tokens,\ntool arguments or error messages are ever sent to `stats.count.ly`; an error\nis reported as its type and the tool it came from.\n\n## Docker Deployment\n\n### Docker Hub\n\nPull the image from Docker Hub:\n```bash\ndocker pull countly/countly-mcp-server:latest\n```\n\n### Build Locally\n\n```bash\ndocker build -t countly-mcp-server .\n```\n\n### Docker Compose\n\nThe included `docker-compose.yml` provides a production-ready setup with:\n- Docker secrets for secure token storage\n- Health checks\n- Resource limits\n- Automatic restart\n- Proper logging configuration\n\n### Docker Swarm / Kubernetes\n\nFor orchestrated deployments, use external secrets:\n\n**Docker Swarm:**\n```bash\n# Create secret\necho \"your-token\" | docker secret create countly_token -\n\n# Deploy stack\ndocker stack deploy -c docker-compose.yml countly\n```\n\n**Kubernetes:**\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: countly-token\ntype: Opaque\nstringData:\n  token: your-countly-auth-token\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: countly-mcp-server\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: countly-mcp-server\n  template:\n    metadata:\n      labels:\n        app: countly-mcp-server\n    spec:\n      containers:\n      - name: countly-mcp-server\n        image: countly-mcp-server:latest\n        ports:\n        - containerPort: 3000\n        env:\n        - name: COUNTLY_SERVER_URL\n          value: \"https://your-countly-instance.com\"\n        - name: COUNTLY_AUTH_TOKEN_FILE\n          value: \"/run/secrets/countly_token\"\n        volumeMounts:\n        - name: token\n          mountPath: /run/secrets\n          readOnly: true\n      volumes:\n      - name: token\n        secret:\n          secretName: countly-token\n          items:\n          - key: token\n            path: countly_token\n```\n\n## MCP Client Configuration\n\n### Claude Desktop\n\nThe most common use case is with Claude Desktop. Add to your Claude configuration file:\n\n**Location**: \n- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n**Using Docker:**\n\n```json\n{\n  \"mcpServers\": {\n    \"countly\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"-i\",\n        \"--rm\",\n        \"-e\", \"COUNTLY_SERVER_URL=https://your-countly-instance.com\",\n        \"-e\", \"COUNTLY_AUTH_TOKEN=your-token-here\",\n        \"countly-mcp-server\",\n        \"node\", \"build/index.js\"\n      ]\n    }\n  }\n}\n```\n\n**Using local installation:**\n\n```json\n{\n  \"mcpServers\": {\n    \"countly\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/countly-mcp-server/build/index.js\"],\n      \"env\": {\n        \"COUNTLY_SERVER_URL\": \"https://your-countly-instance.com\",\n        \"COUNTLY_AUTH_TOKEN\": \"your-token-here\"\n      }\n    }\n  }\n}\n```\n\n**Using environment variable for token (alternative):**\n\n```json\n{\n  \"mcpServers\": {\n    \"countly\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/countly-mcp-server/build/index.js\"],\n      \"env\": {\n        \"COUNTLY_SERVER_URL\": \"https://your-countly-instance.com\",\n        \"COUNTLY_AUTH_TOKEN\": \"your-token-here\"\n      }\n    }\n  }\n}\n```\n\n### Other MCP Clients\n\nThis server is compatible with any MCP client that supports:\n- **stdio transport** (default) - For local/desktop clients (uses environment variables for auth)\n- **HTTP/SSE transport** - For web-based or remote clients (uses HTTP headers for auth)\n\nFor HTTP mode, clients should connect to: `http://your-server:3000/mcp`\n\n## Available Tools\n\nThe server provides 209 tools across 43 categories for comprehensive Countly integration. Tools marked **(Platform)** exist only on Countly Platform with its `/v2` API. Tools marked **(v2 on Platform)** use the richer Platform `/v2` endpoints there, and the classic endpoints on Lite and Enterprise.\n\n### Core Tools (OpenAI/ChatGPT Compatible)\n- **`ping`** - Check if Countly server is healthy and reachable\n- **`get_version`** - Check what version of Countly is running on the server\n- **`get_plugins`** - Get list of installed plugins on the server\n\n### App Management\n- **`apps_list`** (v2 on Platform) - List all applications; on Platform with your role (admin/user) per app\n- **`apps_get_by_name`** (v2 on Platform) - Get app details by name\n- **`apps_create`** - Create new application\n- **`apps_update`** - Update app settings\n- **`apps_delete`** - Delete application\n- **`apps_reset`** - Reset app data\n\n### Analytics & Dashboards\n- **`query_data`** - Analytics data by predefined methods (locations, carriers, devices, etc.), event data, or drill segmentation. On Platform, use `drill_query` for metrics, formulas and cohorts\n- **`app_analytics_summary`** - General app summary and analytics overview\n- **`slipping_users`** - Identify inactive app users\n- **`session_frequency`** - Session frequency distribution across time buckets (f=0: first session, f=1: 1-24h, f=2: 1 day, through f=11: 30+ days)\n- **`user_loyalty`** - User loyalty data showing session count distribution across loyalty buckets (1 session, 2 sessions, 3-5, 6-9, 10-19, 20-49, 50-99, 100-499, 500+)\n- **`session_durations`** - Session duration distribution across duration buckets (0-10 sec, 11-30 sec, 31-60 sec, 1-3 min, 3-10 min, 10-30 min, 30-60 min, 1+ hour)\n\n### Events\n- **`events_create`** - Define event with metadata and configuration\n- **`events_list`** (v2 on Platform) - List all events and their segments, including internal Countly events with exact database structure; on Platform with search, paging, display names and drill-only events\n- **`events_summary`** (Platform) - All custom events with count, sum, duration and per-occurrence averages for a period\n- **`events_top`** (Platform) - Events ranked by count, average sum and average duration\n- **`events_movers`** (Platform) - Fastest-growing and newly appearing events vs the previous period, with daily series\n- **`events_delete`** - Delete events and their data\n\n### Dashboard User Management\n- **`dashboard_users`** (v2 on Platform) - List all dashboard users (admin/management users who access the Countly dashboard); on Platform as compact rows with role and app access\n\n### App User Management\n- **`app_users_create`** - Create app user (end-user being tracked in your application)\n- **`app_users_delete`** - Delete app users (end-users) matching a query\n- **`app_users_update`** - Update app user properties\n\n### Alerts & Notifications\n- **`alerts_create`** - Create alert configuration\n- **`alerts_delete`** - Delete alert\n- **`alerts_list`** - List all alerts\n\n### Notes\n- **`notes_list`** (v2 on Platform) - List all dashboard notes\n- **`notes_create`** (v2 on Platform) - Create note; on Platform with private/shared/global visibility and optional event scope (hidden from the legacy dashboard)\n- **`notes_update`** (Platform) - Edit a note's text, time, color, visibility or event scope\n- **`notes_delete`** (v2 on Platform) - Delete note\n\n### Database Operations\n- **`databases_list`** - List available databases\n- **`databases_query`** - Query database collections\n- **`databases_document`** - Get specific document\n- **`collections_aggregate`** - Run aggregation pipelines\n- **`collections_indexes`** - View collection indexes\n\n### Crash Analytics\n- **`crash_groups_list`** (v2 on Platform) - List crash groups for an app; on Platform with server-side search and sorting\n- **`crashes_stats_get`** - Get crash statistics and graphs\n- **`crashes_get`** - View crash details\n- **`crash_group_breakdown`** (Platform) - Distribution of a crash group over a field (OS version, device, app version, …)\n- **`crash_group_users`** (Platform) - Users affected by a crash group\n- **`crash_jira_issues`** (Platform, requires `crashes-jira` plugin) - Jira issues linked to crash groups\n- **`crashes_resolve`** (v2 on Platform) - Mark crash as resolved\n- **`crashes_unresolve`** (v2 on Platform) - Mark crash as unresolved\n- **`crashes_hide`** (v2 on Platform) - Hide crash from view\n- **`crashes_show`** (v2 on Platform) - Show hidden crash\n- **`crashes_comment_add`** - Add comment to crash\n- **`crashes_comment_update`** - Edit crash comment\n- **`crashes_comment_delete`** - Delete crash comment\n\n### Drill Segmentation (requires `drill` plugin)\n- **`drill_query`** (Platform) - Ad-hoc analytics over raw events: count, unique users, sum, average, percentiles, cohort and formula metrics, filters, breakdowns, time series and paging\n- **`queriable_fields_list`** (v2 on Platform) - Get available properties for segmentation\n- **`metadata_get`** (v2 on Platform) - Event definitions, segments and system fields for building queries\n- **`drill_bookmarks_list`** (v2 on Platform) - List saved segmentation queries; on Platform all saved queries of an app (or all yours), including old-UI bookmarks\n- **`drill_bookmarks_create`** (v2 on Platform) - Save a segmentation query; on Platform also any `drill_query` metrics, filter and breakdowns\n- **`drill_bookmarks_delete`** (v2 on Platform) - Delete a saved query\n- **`drill_saved_query_run`** (Platform) - Run a saved drill query, optionally over another period\n- **`drill_property_values`** (Platform) - Distinct values of a user property, custom property or event segment, for building filters\n\n### User Profiles (requires `users` plugin)\n- **`user_profiles_query`** (v2 on Platform) - Query users with MongoDB filters; on Platform also free-text search, sorting, paging and totals\n- **`user_profiles_breakdown`** (v2 on Platform) - Break down user counts by a property; on Platform with a top-N limit and each value's share\n- **`user_profiles_get`** - Get specific user details by UID\n\n### Cohorts (requires `cohorts` plugin)\n- **`cohorts_list`** - List all user cohorts with filtering\n- **`cohorts_data`** - Get cohort data over a period\n- **`cohorts_create`** - Create behavioral cohort based on user actions\n- **`cohorts_update`** - Update cohort configuration\n- **`cohorts_delete`** - Delete a cohort\n\n### Funnels (requires `funnels` plugin)\n- **`funnels_list`** (v2 on Platform) - List all conversion funnels\n- **`funnels_data`** (v2 on Platform) - Get funnel analytics data with filtering; on Platform adds median and p95 time between steps\n- **`funnels_step_users`** (v2 on Platform) - Get users who reached a specific step; on Platform with full profiles\n- **`funnels_dropoff_users`** (v2 on Platform) - Get users who dropped off between steps; on Platform with full profiles\n- **`funnels_create`** - Create conversion funnel with event sequence\n- **`funnels_update`** - Update funnel configuration\n- **`funnels_delete`** - Delete a funnel\n- **`funnels_breakdown`** (Platform) - Users who reached a step, split by a property\n- **`funnels_trends`** (Platform) - Daily entered, completed and conversion rate\n- **`funnels_user_progress`** (Platform) - How far one user got in every funnel\n\n### Formulas (requires `formulas` plugin)\n- **`formulas_run`** - Run mathematical formulas on metrics (sessions, events, users) with filters and segments\n- **`formulas_list`** - List all saved formulas\n- **`formulas_save`** - Create or update a saved formula\n- **`formulas_delete`** - Delete a saved formula\n\n### Live/Concurrent Users (requires `concurrent_users` plugin)\n- **`live_users`** (v2 on Platform) - Get current online user count and new users at this moment\n- **`live_metrics`** - Get breakdown by countries, devices and carriers for users currently online\n- **`live_last_hour`** (v2 on Platform) - Get minute-by-minute data for the last hour (60 data points)\n- **`live_last_day`** (v2 on Platform) - Get hour-by-hour data for the last day (24 data points)\n- **`live_last_30_days`** (v2 on Platform) - Get daily data for the last 30 days (30 data points)\n- **`live_overall`** - Get maximum values for online users (peak concurrent usage records)\n\n### Retention (requires `retention_segments` plugin)\n- **`retention`** - Get retention data showing consecutive event streaks. Supports three types: Full (strict - breaks on first skip), Classic (Day N - specific days independently), Unbounded (lenient - any return counts)\n\n### Remote Config (requires `remote-config` plugin)\n- **`remote_configs_list`** - List all remote config parameters and conditions\n- **`remote_config_conditions_add`** - Add user segmentation condition using MongoDB queries\n- **`remote_config_conditions_update`** - Update existing condition criteria\n- **`remote_config_conditions_delete`** - Delete a condition (if not in use)\n- **`remote_config_parameters_add`** - Add parameter with default and conditional values\n- **`remote_config_parameters_update`** - Update parameter values, conditions, or status\n- **`remote_config_parameters_delete`** - Delete a parameter\n\n### A/B Testing (requires `ab-testing` plugin)\n- **`ab_experiments_list`** - List all A/B testing experiments with statuses and results\n- **`ab_experiments_details`** - Get detailed experiment info including variants and statistical significance\n- **`ab_experiments_create`** - Create new experiment with variants, user targeting, and goals\n- **`ab_experiments_start`** - Start experiment to begin collecting data\n- **`ab_experiments_stop`** - Stop running experiment\n- **`ab_experiments_delete`** - Delete experiment and all its data\n\n### Logger (requires `logger` plugin)\n- **`sdk_logs_list`** (v2 on Platform) - List incoming data logs sent by SDK to the server for debugging and monitoring; on Platform with paging and filters by request type, SDK, time range and problem requests\n\n### SDKs (requires `sdk` plugin)\n- **`sdk_stats_get`** - Get statistics about SDKs sending data (names, versions, request types, health checks)\n- **`sdk_config_get`** - Get SDK configuration settings controlling SDK behavior and enabled features\n\n### Compliance Hub (requires `compliance-hub` plugin)\n- **`consents_stats`** - Get aggregated consent statistics showing which consents users gave and when\n- **`consents_list`** - List specific users and their consent status\n- **`consents_history_search`** - Search consent history records with detailed audit trail\n\n### Filtering Rules (requires `block` plugin, Enterprise)\n- **`filtering_rules_list`** - List all blocking rules that filter incoming requests\n- **`filtering_rules_create`** - Create rule to block requests based on MongoDB conditions (IP, version, device properties)\n- **`filtering_rules_update`** - Update existing blocking rule configuration\n- **`filtering_rules_toggle_status`** - Enable or disable a blocking rule\n- **`filtering_rules_delete`** - Delete a blocking rule\n\n### Datapoint (requires `server-stats` plugin)\n- **`datapoints_stats`** - Get data points collected per app per datapoint type. Data points measure collected data and are tied to server specs and billing.\n- **`datapoints_top_apps`** - Get top apps ranked by data point collection for understanding data usage and billing\n- **`datapoints_punch_card`** - Get hourly data point breakdown punchcard showing server load patterns for capacity planning\n\n### Server Logs (requires `errorlogs` plugin)\n- **`server_logs_files_list`** - List available server log files (only available in non-Docker deployments)\n- **`server_logs_contents`** - Get contents of a specific server log file for debugging and monitoring (only available in non-Docker deployments)\n\n### Email Reports (requires `reports` plugin)\n- **`email_reports_list`** (v2 on Platform) - List all email reports configured for an app; on Platform across apps with an optional app and title filter\n- **`email_reports_core_create`** (v2 on Platform) - Create a core email report with metrics like analytics, events, crashes, and star-rating\n- **`email_reports_dashboard_create`** (v2 on Platform) - Create a dashboard email report for specific dashboards; on Platform for new-UI dashboards\n- **`email_reports_update`** (v2 on Platform) - Update an existing email report configuration\n- **`email_reports_preview`** (v2 on Platform) - Preview an email report to see what it will look like before sending; on Platform as readable text\n- **`email_reports_send`** (v2 on Platform) - Manually trigger sending an email report immediately\n- **`email_reports_delete`** (v2 on Platform) - Delete an email report configuration\n\n### Views (requires `views` plugin)\n- **`views_table`** - Per-view metrics table (views, users, duration, bounces, exits)\n- **`views_data`** - View metrics over time\n- **`views_top`** (Platform) - Top views per metric (count, duration, bounce rate, landings, exits, scroll depth)\n\n### Dashboards (requires `dashboards` plugin)\n\nOn Countly Platform with the new UI, the dashboard tools work with the new-UI dashboards (v2). Their widgets use the Platform widget format (drill, funnel, retention, profiles, active and online users), and `dashboards_data` returns each widget's results.\n\n- **`dashboards_list`** - List all available dashboards (with optional schema-only parameter)\n- **`dashboards_data`** - Get widgets and data for a specific dashboard with time period filtering\n- **`dashboards_create`** - Create a new dashboard with sharing settings, auto-refresh configuration, and theme\n- **`dashboards_update`** - Update dashboard configuration (name, sharing, refresh rate, theme)\n- **`dashboards_delete`** - Delete a dashboard by ID\n- **`dashboards_widget_add`** - Add a widget to a dashboard with full configuration (title, feature, widget type, apps, metrics, visualization)\n- **`dashboards_widget_update`** - Update a widget on a dashboard\n- **`dashboards_widget_remove`** - Remove a widget from a dashboard\n\n### Times of Day (requires `times-of-day` plugin)\n- **`times_of_day`** - Get user behavior patterns in their local time for a specific event. Shows when users are most active throughout the day (by hour) and week (by day). Useful for understanding optimal engagement times and scheduling.\n\n### Hooks (requires `hooks` plugin)\n- **`hooks_list`** (v2 on Platform) - List all webhooks/hooks configured for an app. Shows triggers, effects, and configuration details. On Platform also across apps, with enabled/text filters, paging and run counters.\n- **`hooks_get`** (Platform) - Get one hook with its configuration, run counters and its last failed runs with error messages.\n- **`hooks_test`** (v2 on Platform) - Test a hook configuration with mock data before creating it. Useful for validating trigger conditions and effect actions.\n- **`hooks_create`** (v2 on Platform) - Create a new webhook/hook with various trigger types (IncomingDataTrigger, APIEndPointTrigger, InternalEventTrigger, ScheduledTrigger) and effects (HTTPEffect, EmailEffect, CustomCodeEffect).\n- **`hooks_update`** (v2 on Platform) - Update an existing webhook/hook configuration.\n- **`hooks_delete`** (v2 on Platform) - Delete a webhook/hook by its ID.\n\n### Journeys (requires `journey_engine` plugin)\nOn Countly Platform all journey tools use the `/v2` API. Its first write on a journey created in the old dashboard moves that journey to the new UI.\n- **`journeys_list`** (v2 on Platform) - List journeys with status, versions and usage counters; on Platform with status/search filters, paging and counts per status\n- **`journeys_get`** (v2 on Platform) - Get one journey with its versions and block graph\n- **`journeys_create`** (v2 on Platform) - Create a new journey (definition plus first draft version) from a block graph; on Platform also with a description and conversion goal\n- **`journeys_update`** (v2 on Platform) - Update a journey's name, per-user limit and/or the blocks of one of its versions; on Platform also description and goal\n- **`journeys_delete`** (v2 on Platform) - Soft-delete a journey and all its versions\n- **`journeys_publish`** (v2 on Platform) - Publish (activate) a journey version; on Lite/Enterprise it can also unpublish to draft\n- **`journeys_pause`** (v2 on Platform) - Pause an active journey version and its running instances\n- **`journeys_resume`** (v2 on Platform) - Resume a paused journey version\n- **`journeys_complete`** (Platform) - End an active or paused journey for good\n- **`journeys_block_reference`** - Get the journey block JSON schema reference (block types, per-subtype fields, validation rules, sample graphs) for authoring blocks\n- **`journeys_templates`** (Platform) - Ready-made journey templates with their block graphs\n- **`journeys_stats_summary`** (v2 on Platform) - Summary KPIs for a journey (users entered/engaged/completed/dropped off) with period-over-period change; on Platform also goal conversion\n- **`journeys_stats_table`** (v2 on Platform) - Journey instances (one row per user run) with pagination\n- **`journeys_stats_performance`** (v2 on Platform) - Time-series journey performance data for trend charts\n- **`journeys_stats_uids`** (v2 on Platform) - List user UIDs behind a journey metric (entered, completed, dropped off, goal converted, ...)\n- **`journeys_stats_blocks`** (Platform) - Per-block funnel: users who entered and completed each block\n- **`journeys_stats_content`** (Platform) - In-app content engagement per message: shown, interacted, button clicks\n- **`journeys_stats_active_users`** (Platform) - Users active in a journey, with a daily/weekly/monthly breakdown\n\n### Content (requires `content` plugin)\nOn Countly Platform these tools manage the new content messages (popup, banner, carousel, survey, push). Legacy content blocks are listed too, and can be read, previewed and deleted, but not edited.\n- **`content_blocks_list`** (v2 on Platform) - List content for an app; on Platform with search, status and format filters and paging\n- **`content_blocks_get`** (v2 on Platform) - Get one content block / message with its full definition\n- **`content_blocks_preview`** (v2 on Platform) - Get a browser preview URL showing the content rendered exactly as end users see it\n- **`content_blocks_create`** (v2 on Platform) - Create content that can be delivered through journeys; on Platform a content message built from slides\n- **`content_blocks_update`** (v2 on Platform) - Update existing content (on Lite/Enterprise: title, type, blocks, favorite; on Platform: name, status, slides, styling, placement, translations)\n- **`content_blocks_delete`** (v2 on Platform) - Delete content (fails while it is still used in a journey or campaign)\n- **`content_assets_list`** (v2 on Platform) - List uploaded content images with metadata; on Platform with search, tags and paging\n- **`content_assets_upload`** (v2 on Platform) - Upload an image asset (base64; max 5MB, or 10MB on Platform)\n- **`content_assets_update`** (v2 on Platform) - Update an asset's name and/or tags\n- **`content_assets_delete`** (v2 on Platform) - Delete an uploaded content asset\n- **`content_langs_list`** - List languages eligible for content translations\n\n### Flows (requires `flows` plugin)\n- **`flows_list`** (Platform) - List saved user flows with anchor, direction, period and status\n- **`flows_get`** (Platform) - Definition of one saved flow\n- **`flows_data`** (Platform) - Top events per step from the anchor event, with the strongest transitions\n- **`flows_dropoff`** (Platform) - What users did instead of an expected next step\n\n### Ratings (requires `star-rating` plugin)\n- **`ratings_widgets_list`** (Platform) - Rating widgets with status, times shown, responses and average rating\n- **`ratings_stats`** (Platform) - Responses, average and 1-5 distribution of one widget for a period\n- **`ratings_comments`** (Platform) - Individual responses (rating, comment, email, user) of one widget\n\n### Campaigns (requires `campaigns` plugin)\n- **`campaigns_list`** (Platform) - Push, in-app, survey and rating campaigns with status and delivery counters\n- **`campaigns_get`** (Platform) - Full definition of one campaign\n- **`campaigns_results`** (Platform) - Delivery funnel of one campaign (events and users per stage)\n\n### AI Assistants (requires `ai-assistants` plugin)\n- **`ai_assistants_analytics`** (Platform) - LLM assistant analytics: overview, conversations, tools, models, quality, cost, performance, adoption\n\n### Tasks & Notifications\n- **`tasks_list`** (Platform) - Background tasks and long-running reports with status and timing\n- **`task_result`** (Platform) - Stored result of a finished background task\n- **`notifications_list`** (Platform) - The connected user's dashboard notifications and unread count\n\n### Geo, Revenue\n- **`geo_locations_list`** (Platform, requires `geo` plugin) - Saved geo locations (geofences)\n- **`revenue_iap_events`** (Platform, requires `revenue` plugin) - Events configured as in-app purchases\n\n### Stage (requires `stage` plugin and a Stage View or Edit level)\n- **`stage_reference`** (Platform) - Scene and demo company format: looks, themes, steps, delivery modes, layers, paper sizes, accepted piece ids\n- **`stage_status`** (Platform) - Whether the server serves Stage's public host, on which name, and why not\n- **`stage_pieces_list`** (Platform) - Pieces the server accepts in scene layers, with what each renders and when to use it\n- **`stage_pieces_get`** (Platform) - One piece's props (kinds, options, defaults), example start props and data grid\n- **`stage_templates_list`** (Platform) - Starters and Library examples to start from: decks, one-pagers, responsive sections, patterns\n- **`stage_templates_get`** (Platform) - One template's outline or full scene\n- **`stage_scenarios_list`** (Platform) - Recorded product walkthroughs an app page plays, with their chapters\n- **`stage_scenarios_get`** (Platform) - One scenario's chapters and, optionally, its script steps\n- **`stage_scenes_list`** (Platform) - Scenes with canvas size, revision, authors and publishing state\n- **`stage_scenes_get`** (Platform) - One scene: outline (look, delivery, steps, layers) or full JSON, versions, public URLs and embed snippet\n- **`stage_scenes_create`** (Platform) - Create a scene draft from a template, from JSON, or empty with name, look, theme, delivery and size (A4 / Letter)\n- **`stage_scenes_update`** (Platform) - Save a scene draft: replace its JSON or change single fields; concurrent saves are refused\n- **`stage_scenes_edit`** (Platform) - Build or change a scene with operations: layers, steps, scenarios played, delivery, responsive fit and breakpoints; checked before saving\n- **`stage_scenes_validate`** (Platform) - Dry-run a scene: would it save and publish, what the server drops, which props pieces ignore\n- **`stage_scenes_delete`** (Platform) - Delete a never-published scene\n- **`stage_scenes_publish`** (Platform) - Publish the saved scene as a new immutable version; returns URLs and embed snippets per delivery (presentation, player, single page)\n- **`stage_scenes_set_latest`** (Platform) - Roll the published scene back or forward to a stored version\n- **`stage_scenes_unpublish`** (Platform) - Hide a published scene (pinned version URLs keep working)\n- **`stage_scenes_restore`** (Platform) - Show an unpublished scene again\n- **`stage_companies_list`** (Platform) - Demo companies with public / referenced state\n- **`stage_companies_get`** (Platform) - One demo company: base project, colours, renames, volume scale\n- **`stage_companies_create`** (Platform) - Create a demo company that dresses a mock project for a prospect\n- **`stage_companies_update`** (Platform) - Change a demo company (refused once a published version names it)\n\nAll tools support flexible app identification via either `app_id` or `app_name` parameter.\n\n## Embedding in another process\n\nThe package also ships a library entry point for hosts that authenticate callers themselves and want to serve the tools in-process (Countly mounts it at `/v2/mcp`). It never reads credentials from the environment, headers, query parameters or tool arguments: the host supplies them per request.\n\n```ts\nimport { createMcpHandler, requiredOperations, getToolCatalog } from 'countly-mcp-server/library';\n\nconst mcp = createMcpHandler({\n  countlyUrl: 'http://127.0.0.1:3001',            // trusted, used as-is\n  onToolCall: (report) => recordStats(report),     // optional; errors are swallowed\n});\n\n// Express route, body already parsed:\napp.post('/v2/mcp', async (req, res) => {\n  await mcp.handle(req, res, req.body, {\n    upstreamToken,                // sent as the countly-token header\n    grantId,                      // keys the per-connection app cache\n    operations: ['R'],            // CRUD operations the grant allows\n    admin: false,                 // hides adminOnly tools\n  });\n});\n```\n\n`getToolCatalog()` returns each tool's category, CRUD operation, `possibleOperations`, area, and `adminOnly` flag. Library mode lists and calls tools through the same pipeline as the standalone modes: the server is detected once per grant, so on Countly Platform tools use the `/v2` API and tools the server cannot serve are hidden. Tools outside the grant are not listed; calling one is an unknown-tool error, and a call the grant does not allow comes back as an `isError` result the assistant can read, without contacting Countly. Per-grant caches are bounded, so a long-running host keeps a fixed amount of memory.\n\nSome tools write depending on their arguments: `formulas_run` with a `mode` other than `\"unsaved\"` and `retention` with `save_report` also need `C`, `alerts_create` with an `alert_config._id` is an update (`U`), and `events_create` can overwrite an existing event so it needs `C` and `U`. Each call is checked against the operations its own arguments need. `requiredOperations(body)` returns them for every `tools/call` in a JSON-RPC body (`{ tool, operation, adminOnly }[]`), so the host can answer `403 insufficient_scope` before handing the request over; `toolsCalledIn(body)` still returns just the tool names.\n\nThe tools act with the upstream token's own rights: which apps a call can reach is decided by Countly, as for any other API request.\n\nUsage analytics in library mode are driven by the host. Pass `analytics` to report tool usage to the Countly server telemetry app on stats.count.ly, with the same events the standalone modes send (`server_started`, `transport_used`, `tool_executed`, `tool_execution_time`, `tool_category_used`, `error_occurred`):\n\n```ts\ncreateMcpHandler({\n  countlyUrl,\n  analytics: {\n    isEnabled: () => hostTrackingIsOn(),  // read before every event and every send\n    deviceId: () => hostDeviceId(),       // report under the host's own identity\n    host: 'countly',                      // optional label, sent as a segment\n  },\n});\n```\n\nThe host decides when reporting is allowed and under which device id; nothing is sent without both. Library mode never initializes the global Countly SDK (a host may already use it for its own telemetry) and never loads the standalone modes' analytics module. No URLs, tokens, arguments or error messages are sent, only tool names, categories, outcomes and durations.\n\n## Health Check\n\nThe server includes a health check endpoint at `/health` (HTTP mode only):\n\n```bash\ncurl http://localhost:3000/health\n```\n\nResponse:\n```json\n{\n  \"status\": \"healthy\",\n  \"timestamp\": \"2025-10-10T12:00:00.000Z\"\n}\n```\n\n## Server Discovery\n\nThe server provides a `.well-known` discovery endpoint for automated configuration (HTTP mode only):\n\n```bash\ncurl http://localhost:3000/.well-known/mcp-manifest.json\n```\n\nThis manifest provides server metadata including:\n- Server name, version, and description\n- Supported MCP protocol version\n- Available endpoints (MCP, health, etc.)\n- Supported transports (stdio, HTTP/SSE)\n- Server capabilities (tool count, categories, features)\n- Authentication methods\n- Documentation links\n- Repository information\n\nThis endpoint can be used by MCP clients for automatic server discovery and capability detection.\n\n## MCP Endpoint\n\nWhen running in HTTP mode, the MCP protocol endpoint is available at:\n- **Path**: `/mcp`\n- **Transport**: Server-Sent Events (SSE)\n- **Full URL**: `http://localhost:3000/mcp`\n\nThis endpoint handles all MCP protocol communication using the SSE transport method.\n\n## Project Structure\n\n```\ncountly-mcp-server/\n├── src/\n│   └── index.ts          # Main server implementation\n├── build/                # Compiled JavaScript output\n├── docs/                 # Additional documentation\n├── .env.example          # Environment configuration template\n├── docker-compose.yml    # Docker Compose configuration\n├── Dockerfile            # Docker image definition\n├── DOCKER.md             # Detailed Docker deployment guide\n└── README.md             # This file\n```\n\n## Development\n\n### Watch Mode\n\n```bash\nnpm run dev\n```\n\n## Testing\n\nRun automated tests:\n\n```bash\n# Run all tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Generate coverage report\nnpm run test:coverage\n\n# Run tests for CI\nnpm run test:ci\n```\n\n**Testing Documentation:**\n- See [docs/TESTING.md](./docs/TESTING.md) for complete testing guide\n- See [docs/TESTING_SUMMARY.md](./docs/TESTING_SUMMARY.md) for testing strategy\n\n**Current Coverage:**\n- Authentication and credential handling\n- Tool handlers and parameter validation\n- HTTP client configuration\n- Transport layer (stdio and HTTP/SSE)\n- End-to-end server connectivity\n- Error handling\n\n---\n\n1. **Never commit tokens** to version control\n2. **Use Docker secrets** or environment variables for production\n3. **Restrict file permissions** on token files (`chmod 600`)\n4. **Use HTTPS** for Countly server connections\n5. **Rotate tokens** regularly\n6. **Use read-only mounts** for token files in Docker\n\n## Troubleshooting\n\n### Connection Issues\n\n```bash\n# Test connectivity\ncurl https://your-countly-instance.com/o/apps/mine?auth_token=your-token\n\n# Check Docker logs\ndocker logs countly-mcp-server\n\n# Check container health\ndocker ps\n```\n\n### Authentication Errors\n\nVerify your token and ensure it has proper permissions in Countly.\n\n## License\n\nMIT\n\n## Support\n\nFor issues and questions:\n- GitHub Issues: [countly/countly-mcp-server](https://github.com/countly/countly-mcp-server)\n- Countly Community: [https://community.count.ly](https://community.count.ly)\n\n## CI/CD\n\nThis project uses GitHub Actions for automated testing and deployment:\n\n- **Automated Tests**: Run on every pull request and push to main/develop\n  - Tests across Node.js 18, 20, and 22\n  - TypeScript compilation verification\n  - Test coverage reporting\n  - Build smoke tests\n- **Docker Publishing**: Automated builds on version tags (`v*.*.*`)\n  - Multi-architecture support (amd64, arm64)\n  - Automatic latest tag updates\n  - Tests must pass before publishing\n\nSee [.github/AUTOMATED_TESTING.md](./.github/AUTOMATED_TESTING.md) for details.\n\n## Contributing\n\nContributions are welcome! Please read our contributing guidelines before submitting PRs.\n\n**Development Workflow:**\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes and add tests\n4. Run `npm test` locally\n5. Submit a pull request\n6. GitHub Actions will automatically run tests\n7. Address any feedback and ensure tests pass\n","readmeFilename":"README.md"}