{
  "markdown": "# EzStat MCP Server\n\nA standalone [Model Context Protocol](https://modelcontextprotocol.io) server for\n[EzStat](https://ezstat.dev). Let Claude / Cursor / any MCP-compatible agent **push and read your\nmetrics natively** — no copy-paste, no dashboard hop. This is the product behind the\n\"metrics your agents write and read themselves\" positioning: every agent that touches your\ncode can also touch your observability.\n\nThe server speaks **stdio** (the standard transport for local agent runners) and — as a\nhosted endpoint at **`https://mcp.ezstat.dev`** — **streamable HTTP**, exposing the same\nseven focused tools. Each tool description is written for an agent audience so the model\nknows when to call it.\n\n## Hosted endpoint — zero install\n\nAgents can connect to the hosted streamable-HTTP endpoint with nothing but an EzStat API\nkey — no npm install, no local process:\n\n```json\n{\n  \"mcpServers\": {\n    \"ezstat\": {\n      \"type\": \"http\",\n      \"url\": \"https://mcp.ezstat.dev\",\n      \"headers\": {\n        \"Authorization\": \"Bearer ezkey_your_api_key_here\"\n      }\n    }\n  }\n}\n```\n\n- **Multi-tenant**: every request carries *your* key as `Authorization: Bearer <ezkey>`;\n  the server holds no key of its own and each connection only ever sees its own account.\n- **Discovery is free**: `initialize` and `tools/list` work without a key, so clients and\n  registry inspectors can introspect the tool surface before you configure anything.\n- **Tool calls require the key**: a call without one (or with an invalid one) returns a\n  clean in-band MCP tool error telling the agent what to send — never a hang or a crash.\n- **Stateless**: no sessions are issued or required; each POST is self-contained.\n\nThis hosted endpoint also satisfies the requirements for hosted/remote listings on MCP\nregistries (e.g. Smithery's hosted-server path) — see `server.json`'s `remotes` entry.\n\nThe stdio transport below remains fully supported and is still the right choice when you\nwant the server running locally under your own runner.\n\n## Tools\n\n| Tool           | What it does                                                                                       |\n| -------------- | -------------------------------------------------------------------------------------------------- |\n| `track_metric` | Record a metric point your app \"produced\" — counter (+N, default +1) or gauge (e.g. 42.5 ms).      |\n| `ask_ezstat`   | Ask a natural-language question about your metrics (the agent-read path).                         |\n| `read_stat`    | Structured read of a stat: latest value + series + summary (count/min/max/avg/sum) for a window.   |\n| `list_stats`   | List the account's metrics (names + types + description).                                         |\n| `create_alert` | Create a webhook alert on a stat (threshold / %-change / heartbeat / sustained).                   |\n| `list_alerts`  | List the account's alerts (id, stat, condition, channel, enabled, last fire).                      |\n| `delete_alert` | Delete an alert by id.                                                                             |\n\nTool descriptions are tuned for agent reasoning — see `src/server.ts`.\n\n## Install (Claude Desktop / Claude Code / Cursor)\n\n### One-line install (npm/pnpm)\n\n```bash\n# pnpm\npnpm add -g ezstat-mcp-server\n\n# npm\nnpm install -g ezstat-mcp-server\n```\n\n### Configure the MCP client\n\n**Claude Desktop** (`~/.config/Claude/claude_desktop_config.json` on macOS/Linux,\n`%APPDATA%\\Claude\\claude_desktop_config.json` on Windows):\n\n```json\n{\n  \"mcpServers\": {\n    \"ezstat\": {\n      \"command\": \"ezstat-mcp-server\",\n      \"env\": {\n        \"EZSTAT_API_KEY\": \"ezkey_your_api_key_here\"\n      }\n    }\n  }\n}\n```\n\n**Cursor** (`~/.cursor/mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"ezstat\": {\n      \"command\": \"ezstat-mcp-server\",\n      \"env\": {\n        \"EZSTAT_API_KEY\": \"ezkey_your_api_key_here\"\n      }\n    }\n  }\n}\n```\n\nGet your API key from <https://ezstat.dev> (it's the \"ezkey\").\n\n### Smithery\n\n```bash\nnpx -y @smithery/cli install ezstat-mcp-server --client claude\n```\n\nOr visit <https://smithery.ai/server/ezstat-mcp-server> and click **Install**.\n\n## About EzStat\n\n[EzStat](https://ezstat.dev) is a dead-simple hosted metrics service: **one HTTP POST in,\na live chart out**. No SDK, no collector daemon, no YAML, no dashboard builder. Counters\nand value/gauge stats auto-create on first POST; charts, share/embed, and CSV/JSON export\nare built in, and **Ask-Your-Data** (live) answers plain-English questions from your own\nmetrics, with every number verified against the retrieved data before it reaches you.\n\nFlat monthly pricing by tracked stats — **$19 / $49 / $149** — plus a card-gated free tier\n(no charge; see your data live before paying). Your data is yours: export any time, cancel\nany time. Anomaly detection and metric correlations are live. Features that are not shipped yet (alerts, weekly digest) are\nmarked *coming soon* on the site rather than sold — what you see live is what works.\n\n### Coming from StatHat?\n\nIf your `api.stathat.com` calls stopped and your dashboards went dark: EzStat speaks\n**StatHat's wire format** — the same `/ez`, `/c`, `/v` endpoints, same params, same\nresponse. The migration is usually one line:\n\n```bash\n# before\ncurl -X POST https://api.stathat.com/ez -d \"stat=messages sent\" -d \"ezkey=KEY\" -d \"count=1\"\n# after — change the host, use your EzStat key; stats auto-create\ncurl -X POST https://api.ezstat.dev/ez -d \"stat=messages sent\" -d \"ezkey=EZSTAT_KEY\" -d \"count=1\"\n```\n\n**One gotcha, and it is the important one: check the response BODY, not the status code.**\nBecause the wire format is StatHat's, a *rejected* write (stale key, wrong key, quota hit)\nstill returns **HTTP 200**, with the verdict in the body — `{\"status\":200,\"msg\":\"ok\"}` means\nrecorded, `{\"status\":\"error\",\"msg\":\"...\"}` means it was not. An unmodified StatHat client\nreports those as successes while your charts keep rendering old data, so nothing looks\nbroken. New code should send `X-EzStat-Strict: 1` on `/ez` and get real HTTP status codes\ninstead. (This server already does the right thing: it treats an `error` body as a failure\nregardless of the HTTP code.) After switching, confirm points are *arriving* with\n[ezstat.dev/tools/ezstat-verify.py](https://ezstat.dev/tools/ezstat-verify.py) — documented\nat [ezstat.dev/docs#verify](https://ezstat.dev/docs#verify).\n\nMost StatHat client libraries take a base-URL override in one line. Saved a StatHat\nCSV/JSON export? The importer recreates your stats and backfills history (8 MB / 500k\npoints per file). Full guide: [docs/stathat-migration.md](docs/stathat-migration.md) ·\n[ezstat.dev/migrate/stathat](https://ezstat.dev/migrate/stathat) — including the migrator\ndeal: free tier to see it live first, a 12-month price-lock, and white-glove import for\nthe first 25 migrations.\n\n### Why agent-native metrics\n\nYour coding agent deploys, tests, and ships — it should also be the one tracking and\nreading the numbers. That's this server: metrics your agents write and read themselves.\nThe reasoning: [docs/agent-native-metrics.md](docs/agent-native-metrics.md) · comparison\nwith StatHat/StatFlow/Datadog: [ezstat.dev/vs](https://ezstat.dev/vs).\n\n## Environment variables\n\n| Variable               | Required | Default                       | Notes                                                          |\n| ---------------------- | -------- | ----------------------------- | -------------------------------------------------------------- |\n| `EZSTAT_API_KEY`       | **yes**  | —                             | Your EzStat API key (the \"ezkey\"). Never hardcode. Never log. |\n| `EZSTAT_BASE_URL`      | no       | `https://api.ezstat.dev`      | Override for staging / self-hosted.                            |\n| `EZSTAT_TIMEOUT_MS`    | no       | `10000`                       | Per-request timeout in milliseconds.                           |\n| `EZSTAT_INGEST_PATH`   | no       | `/api/ez`                     | Override if you proxy the EZ endpoint.                         |\n| `EZSTAT_QUERY_PATH`    | no       | `/api/v1/query`               | Ask-Your-Data path.                                            |\n| `EZSTAT_STATS_LIST_PATH` | no     | `/api/v1/stats`               | Stats list path.                                               |\n\nA starter `.env.example` is shipped.\n\n## How it talks to EzStat\n\nThe tools map to real EzStat API routes (all auth by EzStat API key):\n\n| Tool           | Method | Path                       | Auth                                  |\n| -------------- | ------ | -------------------------- | ------------------------------------- |\n| `track_metric` | POST   | `/api/ez`                  | `ezkey` in JSON body                  |\n| `ask_ezstat`   | POST   | `/api/v1/query`            | `Authorization: Bearer <ezkey>`       |\n| `read_stat`    | GET    | `/api/v1/stats/:name`      | `Authorization: Bearer <ezkey>`       |\n| `list_stats`   | GET    | `/api/v1/stats`            | `Authorization: Bearer <ezkey>`       |\n| `create_alert` | POST   | `/api/v1/alerts`           | `Authorization: Bearer <ezkey>`       |\n| `list_alerts`  | GET    | `/api/v1/alerts`           | `Authorization: Bearer <ezkey>`       |\n| `delete_alert` | DELETE | `/api/v1/alerts/:id`       | `Authorization: Bearer <ezkey>`       |\n\n- `track_metric` calls the StatHat-compatible EZ ingest (`{\"ezkey\",\"stat\",\"count\"?,\"value\"?,\"t\"?}`).\n  Counter semantics: omit both `count` and `value` to record `count=1` (counter +1).\n- `ask_ezstat` calls Ask-Your-Data (`{\"query\":\"...\"}` → `{answer, data, intent, ...}`).\n  This is the agent read path — count it as an agent read for usage tracking.\n- `read_stat` returns the stat's recent series + summary; pass `from`/`to` (Unix seconds) to\n  bound the window. `resolution` rolls up to `minute`/`hour`/`day`.\n- `list_stats` returns the account's stats; pass `type` to filter to `counter` or `value`.\n\n## Build & run locally\n\n```bash\npnpm install\npnpm build       # tsc → dist/\npnpm start       # node dist/index.js  (stdio MCP server)\npnpm test        # vitest run  — fully mocked network, no real HTTP\npnpm dev         # tsx watch src/index.ts\n```\n\n`pnpm start` requires `EZSTAT_API_KEY` to be set; the server exits with a clear error\notherwise (and never logs the key).\n\n## Security\n\n- The API key is read **only** from `EZSTAT_API_KEY` — never hardcoded, never printed.\n- All error messages are scrubbed: the API key is never included in tool results.\n- HTTP errors carry a stable machine-readable `code` (`unauthorized`, `rate_limited`,\n  `timeout`, `not_found`, `server_error`, ...) and a human-readable `message` safe to relay.\n- Tests mock the network — no real HTTP leaves the test process.\n\n## Registry metadata\n\nFor Smithery / mcp.so / Glama listings:\n\n- **Name**: `ezstat-mcp-server`\n- **Display name**: EzStat\n- **Description**: Push and read metrics with EzStat from any AI agent. Track counters and\n  values, then ask natural-language questions over your production telemetry.\n- **Homepage**: <https://ezstat.dev>\n- **Version**: `0.8.0`\n- **Transport**: `stdio` (local) + `streamable-http` (hosted at `https://mcp.ezstat.dev`)\n- **License**: MIT\n- **Repository**: this package's source\n\nThe `mcp` block in `package.json` carries the same metadata so registry crawlers pick it up.\n\n## Listing steps (what to submit, where)\n\n1. **Smithery**: push the repo to GitHub, then run\n   `npx -y @smithery/cli publish` (or submit via the web UI). The shipped\n   `smithery.yaml` provides the install schema.\n2. **mcp.so**: submit at <https://mcp.so/submit> with the metadata above + the GitHub URL.\n3. **Glama**: submit at <https://glama.ai/mcp/submit>.\n\nThe package is **not** published to npm automatically — publish manually after a release\nreview.\n\n## License\n\nMIT.\n",
  "bytes": 11798,
  "sha": "6a3347085c4ae3929beb859da3c3e3cd6f285e7744ab0b5bf9c3540734eb8511",
  "repo_slug": "clira-dev/ezstat-mcp-server",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_ezstat_ezstat_mcp_server_893f816a/readme"
}