npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

datazen-api-mcp

v1.2.0

Published

Spec-driven MCP server exposing the DataZen DZFunctionAppCore HTTP API to LLM clients

Readme

DataZen API MCP

A spec-driven stdio MCP server that exposes the DataZen DZFunctionAppCore HTTP API as MCP tools. Tool definitions live in dz-api-spec.json; the server (src/index.ts) is generic and loads that spec at startup — regenerating the spec never requires editing the server.

This build exposes the 17 approved endpoints listed in datazen-tools.csv: agent health/status, job listing, history, logs and output, variables, connection metadata, and job start/stop/activate. Everything else is intentionally excluded — dashboard, job versions, change-log reads, dependencies, statistics, /connections (returns secrets), agent-wide /output, and the dynamic-job endpoints (dynamic jobs are not supported yet).

Configure

Set these as env vars (see .env.example) or in your MCP client config:

| Var | Required | Meaning | |---|---|---| | DZ_FUNCTIONS_BASE_URL | yes | Function app base URL, e.g. https://<funcapp>.azurewebsites.net/api. A trailing /api is tolerated and stripped — spec paths already start /api/{agentId}/.... | | DZ_DEPLOYMENT | no | cloud (default) or selfhosted — see Cloud vs self-hosted. | | DZ_AGENT_ID | cloud only | Agent GUID — substituted into every route and sent as X-API-DZ-AgentId. Required for cloud; ignored when self-hosted. | | DZ_CLIENT_ID | yes | Client id for Basic auth. | | DZ_SECRET | yes | Secret (or 32-char service token) for Basic auth. | | DZ_SPEC_PATH | no | Path to the spec JSON. Default: dz-api-spec.json next to package.json. | | DZ_TIMEOUT_MS | no | Per-call HTTP timeout. Default 120000. | | DZ_LOG_DEBUG | no | 1 adds X-API-DZ-LogDebug: 1 for 401 diagnostics. |

These are the same vars used by datazen-pipeline-mcp, so one set of values drives both — provided DZ_FUNCTIONS_BASE_URL ends in /api. That form works for both: this server strips the trailing /api and re-adds it from the spec path, while datazen-pipeline-mcp requires it. Omitting /api works here but breaks datazen-pipeline-mcp.

Missing a required var exits at startup with datazen-api-mcp: missing required environment variable <NAME> on stderr.

Cloud vs self-hosted

DataZen is reachable two ways, and they differ in whether an agent id means anything. Cloud hosts many agents, so a call has to say which one it is for. A self-hosted deployment is the agent — there is nothing to address, and it needs no agent id:

| | DZ_DEPLOYMENT=cloud (default) | DZ_DEPLOYMENT=selfhosted | |---|---|---| | Route | /api/{agentId}/ping | /api/ping | | X-API-DZ-AgentId header | sent | not sent | | DZ_AGENT_ID | required | ignored (warns if set) | | DZ_CLIENT_ID / DZ_SECRET | required | required |

Self-hosted still authenticates — only the agent addressing goes away:

{ "mcpServers": { "datazen-api": {
    "command": "npx",
    "args": ["-y", "datazen-api-mcp"],
    "env": {
      "DZ_FUNCTIONS_BASE_URL": "http://localhost:7071/api",
      "DZ_DEPLOYMENT": "selfhosted",
      "DZ_CLIENT_ID": "...",
      "DZ_SECRET": "..."
    }
} } }

DZ_DEPLOYMENT is validated: any value other than cloud or selfhosted exits at startup rather than falling back to a default, so a typo like self-hosted fails immediately instead of becoming a puzzling 404 on the first tool call.

Renamed vars. DZ_AGENT_ID, DZ_CLIENT_ID and DZ_SECRET were previously ENZO_AGENT_ID, ENZO_CLIENT_ID and ENZO_SECRET. The old names still work but log a deprecation warning on startup.

This server does not load .env — there is no dotenv dependency. .env.example documents the vars; supply them via the real environment or your MCP client's env block.

The secret ends up in your client config file — use a dedicated service token, not an admin clientId:secret, when possible. With Hermes, prefer ${VAR} interpolation (see below) so no secret is written to config.yaml.

Build & test

npm install
npm run build
npm run smoke                       # self-contained: no live function app needed
node smoke.mjs --spec dz-api-spec.json   # validate the generated spec

Register

Published to npm as datazen-api-mcp. Run it via npx -y datazen-api-mcp (no local build/checkout required), or launch it by absolute path to dist/index.js after npm run build if you're working from a clone of this repo.

Hermes agent

Hermes agent registers MCP servers in an mcp_servers: block in $HERMES_HOME/config.yaml (or ~/.hermes/config.yaml when HERMES_HOME is unset):

mcp_servers:
  datazen-api:
    command: "npx"
    args: ["-y", "datazen-api-mcp"]
    env:
      DZ_AGENT_ID: ${DZ_AGENT_ID}
      DZ_CLIENT_ID: ${DZ_CLIENT_ID}
      DZ_SECRET: ${DZ_SECRET}
      DZ_FUNCTIONS_BASE_URL: ${DZ_FUNCTIONS_BASE_URL}

(Use command: "node", args: ["<absolute-path>/dist/index.js"] instead if you're running from a local clone after npm run build.)

Keep credentials out of config.yaml: ${VAR} placeholders are interpolated from the environment, including $HERMES_HOME/.env, which Hermes loads at startup. Put the real values there:

# $HERMES_HOME/.env
DZ_AGENT_ID=...
DZ_CLIENT_ID=...
DZ_SECRET=...
DZ_FUNCTIONS_BASE_URL=https://<funcapp>.azurewebsites.net/api

An unset variable is not an error — Hermes leaves the literal string ${DZ_AGENT_ID} in place, which surfaces later as a confusing 401 from the function app. If auth fails, check .env first.

Or add it from the CLI. --args consumes the rest of the line, so it must come last:

hermes mcp add datazen-api --command npx --args -y datazen-api-mcp

This registers command/args only. hermes mcp add does accept --env KEY=VALUE (which must come before --args), but that puts credentials in your shell history — add the env: block with ${VAR} placeholders as above instead.

Then verify it connects, and reload after any config.yaml change:

hermes mcp test datazen-api   # confirm it connects and lists the tools
# ...and inside `hermes chat`:
/reload-mcp                   # re-read config.yaml without restarting the session

dz_job_start, dz_job_stop and dz_job_active change agent state. To expose only the read-only tools, add a tools.include whitelist. Prefer include over exclude here: regenerating the spec can add tools, and a whitelist won't surface them to the model until you opt in.

    tools:
      include: [dz_ping, dz_version, dz_status, dz_jobs, dz_jobs_summary, dz_job_status,
                dz_job_history, dz_job_log, dz_job_output, dz_job_info, dz_job_changelogs,
                dz_variables, dz_variable_get, dz_connections_info]

If your Hermes install was built without MCP support, enable it once with cd $HERMES_HOME/hermes-agent && uv pip install -e ".[mcp]".

Claude Code

claude mcp add datazen-api \
  -e DZ_FUNCTIONS_BASE_URL=https://... -e DZ_AGENT_ID=... -e DZ_CLIENT_ID=... -e DZ_SECRET=... \
  -- npx -y datazen-api-mcp

Claude Desktop

claude_desktop_config.json:

{ "mcpServers": { "datazen-api": {
    "command": "npx",
    "args": ["-y", "datazen-api-mcp"],
    "env": { "DZ_FUNCTIONS_BASE_URL": "https://...", "DZ_AGENT_ID": "...", "DZ_CLIENT_ID": "...", "DZ_SECRET": "..." }
} } }

Regenerating the spec

Re-run the /datazen-api-mcp skill. It rereads the HTTP-triggered functions under DZiPaaS/DZFunctionAppCore/Functions/, overwrites dz-api-spec.json, and re-runs the smoke test. Do not hand-edit the server for spec changes.