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

@eddalabs/karbonity-mcp

v0.2.3

Published

Karbonity MCP server (stdio) with optional local Midnight agent wallet — connect Claude Code / Claude Desktop to the Karbonity certificate marketplace

Readme

karbonity-mcp — connect AI agents to Karbonity

npm

Two packages, one per Midnight network. Everything below uses the Preview names; for Preprod substitute them as follows (both can be installed side by side):

| | Preview | Preprod | |---|---|---| | npm package | @eddalabs/karbonity-mcp | @eddalabs/karbonity-mcp-preprod | | command | karbonity-mcp | karbonity-mcp-preprod | | server name in Claude | karbonity | karbonity-preprod | | config dir (login, wallet) | ~/.karbonity | ~/.karbonity-preprod | | faucet | https://faucet.preview.midnight.network/ | https://faucet.preprod.midnight.network/ | | agent wallet chain access | public Preview endpoints | your own Blockfrost Midnight Preprod project id |

Preprod is only served through Blockfrost, which authenticates with a token in the URL, so the package can't ship one. Only the optional agent wallet (section C) needs it; browsing, the bot tools and draft links work without it. Give it to the server in its environment, or store it once:

claude mcp add karbonity-preprod -s local -e KARBONITY_BLOCKFROST_PROJECT_ID='preprod…' \
  -e KARBONITY_WALLET_PASSPHRASE='…' -- karbonity-mcp-preprod serve
# or: karbonity-mcp-preprod init --blockfrost-project-id preprod…   (stored in ~/.karbonity-preprod/config.json, 0600)

karbonity-mcp-preprod doctor shows which network, backend and chain endpoints it uses.

Karbonity exposes one MCP tool catalog (packages/mcp-core) over two transports. Pick the one that matches where your agent runs:

| You use… | Transport | Setup | |---|---|---| | Claude.ai (web/desktop/mobile chat), Cowork | Remote HTTP — https://<deployment>.convex.site/mcp | A. Remote connector | | Claude Code or Claude Desktop on your machine | Local stdio — karbonity-mcp serve | B. Local server |

Both give the same 20 tools (browse the marketplace, your certificates, create/list/price/burn via the bot, and buy/redeem/withdraw/swap). The difference is wallet actions:

  • Remote: buy / redeem / withdraw_seller_funds / swap_night return a URL. Open it, review, and sign in the web UI with your own wallet (Lace or passkey). The server never holds a key.
  • Local + agent wallet: the same tools execute on your machine with a dedicated, funded agent wallet. See C.

Amounts everywhere are decimal strings in the smallest Night unit (2000000 = 2 Night).


One-time backend setup (operator)

Do this once per deployment. Already done for the dev deployment animated-spoonbill-938.

  1. Clerk Dashboard → OAuth applications → Create
    • Client type Public (PKCE, no secret).
    • Redirect URIs: https://claude.ai/api/mcp/auth_callback http://127.0.0.1:44831/callback http://localhost/callback
    • Leave Generate access tokens as JWTs on.
    • Optional: enable Dynamic client registration so Claude.ai can add the connector by URL alone.
  2. Convex environment variables (npx convex env set … in packages/backend):
    • CONTRACT_ADDRESS — the mini-private-buyer contract (same as VITE_CONTRACT_ADDRESS)
    • SITE_URL — web app origin, used for draft links (e.g. http://localhost:5173)
    • MCP_OAUTH_ISSUER — optional; defaults to CLERK_FRONTEND_API_URL
    • MCP_OAUTH_AUDIENCE — any value enables agent auth; off disables it
  3. Deploy: npx convex dev --once (use Node 22 — Node 23 segfaults the Convex CLI).

How auth works: Clerk issues OAuth access tokens as JWTs signed by the same JWKS as your web session. convex/auth.config.js trusts them with a Custom JWT provider, so ctx.auth sees the same Clerk user id and every existing Convex function works unchanged for agents.


A. Remote connector (Claude.ai)

  1. Claude.ai → Settings → Connectors → Add custom connector.
  2. URL: https://animated-spoonbill-938.convex.site/mcp
  3. If Dynamic client registration is off in Clerk: open Advanced settings and paste the OAuth app's Client ID (GmOu49U0Yux4yxUE on dev). No secret.
  4. Click Connect → sign in with your Karbonity (Clerk) account → done.

Claude Code can also use the remote server: claude mcp add --transport http karbonity-remote https://animated-spoonbill-938.convex.site/mcp --client-id GmOu49U0Yux4yxUE


B. Local server (Claude Code / Desktop) — Linux or WSL

Requires Node ≥ 20 on Linux (on Windows, inside WSL). Not supported natively on Windows.

1. Install

npm install -g @eddalabs/karbonity-mcp
karbonity-mcp doctor        # shows backend, login, wallet and proof-server status

The production backend is built in — no configuration step. (karbonity-mcp init --convex-site … --contract … only if you run your own deployment.)

2. Log in

karbonity-mcp login         # opens a browser URL; sign in with your Karbonity account

The token is stored in ~/.karbonity/auth.json (mode 0600) and refreshed automatically. karbonity-mcp logout forgets it.

3. Register with Claude

Claude Code (run inside the project you want it in):

claude mcp add karbonity -s local -- karbonity-mcp serve

Claude Desktop on Linux — paste into claude_desktop_config.json:

{ "mcpServers": { "karbonity": { "command": "karbonity-mcp", "args": ["serve"] } } }

(karbonity-mcp desktop-config prints this for you.)

Per-project, zero install — drop a .mcp.json at the repo root and everyone who opens it gets the server (Claude Code asks each user to approve the project's servers on first use):

{
  "mcpServers": {
    "karbonity": {
      "command": "npx",
      "args": ["-y", "@eddalabs/karbonity-mcp", "serve"],
      "env": { "KARBONITY_WALLET_PASSPHRASE": "${KARBONITY_WALLET_PASSPHRASE:-}" }
    }
  }
}

Claude Code expands ${VAR} and ${VAR:-default} in .mcp.json, so the file references the passphrase without containing it — each user exports KARBONITY_WALLET_PASSPHRASE in their own shell (or leaves it unset and gets the draft flow). Keep the :- default: without it, an unset variable is passed through as the literal text ${KARBONITY_WALLET_PASSPHRASE}. Never put the passphrase itself in a committed file.

No global install? Any client can run it straight from npm instead:

{ "mcpServers": { "karbonity": { "command": "npx", "args": ["-y", "@eddalabs/karbonity-mcp", "serve"] } } }

The first launch downloads ~66 MB, which can trip the client's startup timeout; after that it is cached. A global install starts instantly, so it is the better default.

Claude Desktop on Windows, code in WSL — Desktop runs on Windows, so it must start the server inside your distro through wsl.exe. Run in WSL:

karbonity-mcp desktop-config --windows

and paste the output into %APPDATA%\Claude\claude_desktop_config.json, then restart Desktop. It looks like:

{ "mcpServers": { "karbonity": { "command": "wsl.exe",
  "args": ["-d", "Ubuntu", "--", "/home/<you>/.nvm/versions/node/v22.x/bin/node",
           "/home/<you>/.nvm/versions/node/v22.x/lib/node_modules/@eddalabs/karbonity-mcp/dist/cli.js", "serve"] } } }

Windows is the one place absolute paths are unavoidable: wsl.exe starts no login shell, so npm's global bin (and nvm) are not on PATH — karbonity-mcp alone would not be found. desktop-config --windows fills the paths in for you. The browser sign-in from login opens on Windows and reaches WSL through WSL2's localhost forwarding.

Then /mcp in Claude Code (or restart Desktop). You should see 20 karbonity tools. Try: "list my certificates", "what's for sale?", "create a Solar certificate and list it for 2 Night".

Never run karbonity-mcp serve by hand for normal use — Claude launches it and talks to it over stdin/stdout.

From source (contributors)

pnpm --filter @eddalabs/karbonity-mcp build     # → packages/mcp-cli/dist (bundle + 65 MB prover keys)
claude mcp add karbonity -s local -- node $PWD/packages/mcp-cli/dist/cli.js serve

pnpm dev runs the TypeScript directly through tsx.


C. Optional: local agent wallet

Without this, wallet actions return draft URLs (same as the remote connector). With it, the local server signs and proves on your machine.

Why a separate wallet: your passkey wallet's seed comes from WebAuthn PRF and cannot run headless; Lace lives in the browser. So the agent gets its own identity. Fund it only with what you're willing to let an agent spend; sweep it to revoke.

karbonity-mcp wallet init            # prints the 24-word phrase ONCE; asks for a passphrase
karbonity-mcp wallet show            # addresses + seller id

The mnemonic is encrypted with your passphrase (scrypt + AES-GCM) in ~/.karbonity/wallet.enc.

  1. Fund the unshielded address from wallet show at https://faucet.preview.midnight.network/

  2. Run a proof server on 127.0.0.1:6300:

    karbonity-mcp proof-server start --max-k 17    # Docker required
    karbonity-mcp proof-server status | logs | stop

    Why local: generating a proof means giving the prover your witness (zero-knowledge protects verifiers, not the prover). A remote proof server would therefore see your secretNonce on every transaction. Keep it on your machine unless the server is inside your own trust domain.

    About --max-k. The image fetches PLONK parameters from srs.midnight.network automatically — it prefetches k=10..15 at startup and pulls higher k on demand, which stalls the first proof that needs one. buy and redeem are fine on the defaults; shield/unshield need k=16 and 17 (≈13 MB and ≈25 MB). --max-k 17 downloads them up front into ~/.karbonity/zk-params, which is then bind-mounted — raise the number if other circuits need more (each k doubles: k=18 ≈ 50 MB, k=19 ≈ 100 MB). Files already present are skipped, so re-running is cheap.

    Already have a parameter cache? --params-dir /path/to/zk-params mounts it as-is, no downloads. Running your own server elsewhere? karbonity-mcp init --proof-server URL.

  3. Give the server the passphrase — it cannot prompt, because stdin is the MCP channel:

    claude mcp remove karbonity -s local
    claude mcp add karbonity -s local -e KARBONITY_WALLET_PASSPHRASE='…' -- karbonity-mcp serve
    # Claude Desktop (incl. Windows+WSL): KARBONITY_WALLET_PASSPHRASE='…' karbonity-mcp desktop-config --windows --with-passphrase

    (The passphrase is then stored in plain text in that config file. If you'd rather not, leave it unset and use draft URLs.)

  4. /mcp → reconnect. A wallet_info tool appears; buy, redeem, withdraw_seller_funds, swap_night now execute locally.

The wallet's private state (secretNonce + purchases) is stored encrypted in Convex's walletVaults table exactly like browser wallets, keyed from the agent seed — Convex cannot link the row to you or to the wallet.


Troubleshooting

| Symptom | Fix | |---|---| | karbonity-mcp: command not found | npm install -g @eddalabs/karbonity-mcp with Node ≥ 20; check npm prefix -g/bin is on PATH. | | Tool returns "Not logged in" | karbonity-mcp login. | | whoami → authenticated: false or a "No auth provider" error | Backend setup step 2/3 not applied, or the token comes from a different Clerk instance than CLERK_FRONTEND_API_URL. | | Claude Code shows karbonity ✘ Failed to connect | Use karbonity-mcp desktop-config output (absolute paths) instead of a bare command; run that exact command from / — it must print nothing on stdout until it receives JSON. | | Server says "wallet found but KARBONITY_WALLET_PASSPHRASE is not set" | Expected without step C.3; wallet tools fall back to drafts. | | Server says "could not unlock the agent wallet" | Wrong passphrase (or a ${VAR} that the client never expanded). The server keeps running — only wallet tools degrade to drafts. | | Login page says redirect URI mismatch | Add http://127.0.0.1:44831/callback to the Clerk OAuth app. | | Windows Desktop: server never connects | Run the wsl.exe … line from PowerShell; if it prints an error, fix the distro name or path. The proof server (pnpm ps) must also run inside WSL. |

Commands

karbonity-mcp login | logout | whoami | doctor | version
karbonity-mcp desktop-config [--windows] [--with-passphrase]
karbonity-mcp wallet init | import <words…> | show
karbonity-mcp serve                      # MCP over stdio (launched by Claude)
karbonity-mcp init [--convex-site URL] [--site URL] [--contract HEX] [--proof-server URL] [--issuer URL] [--client-id ID]
                   [--blockfrost-project-id ID] [--indexer URL] [--indexer-ws URL] [--node URL]

Releasing (maintainers)

Published as @eddalabs/karbonity-mcp (Preview) and @eddalabs/karbonity-mcp-preprod (Preprod) under the eddalabs npm org, from the same source. The release workflow renames the package and its command for Preprod and bakes the network in (KARBONITY_NETWORK → scripts/build.mjs). packages/mcp-core stays private: true — esbuild inlines it into dist/cli.js, so it is never resolved from the registry.

npm credentials (one-time). Publishing needs a token whose 2FA requirement is satisfied: either a granular access token created with Bypass two-factor authentication checked (Access Tokens → Generate New Token → Granular; permissions Read and write on the @eddalabs scope — granting access to the Organization is not enough, it only covers org settings), or a normal granular token combined with account 2FA set to "Authorization only" (Account settings → Two-factor authentication). Install it with npm config set //registry.npmjs.org/:_authToken npm_xxx — do not pass it to --otp, which expects a 6-digit code.

Release from CI (preferred). Bump version in packages/mcp-cli/package.json on main and promote it to the network branch. That's the whole release: when the merge lands on preview or preprod, .github/workflows/release-mcp-cli.yml asks npm whether that version of the network's package exists, and if not it builds, publishes, and tags the commit as a record:

| Branch | Package | Tag it creates | |---|---|---| | preview | @eddalabs/karbonity-mcp | mcp-cli-v<version> | | preprod | @eddalabs/karbonity-mcp-preprod | mcp-cli-preprod-v<version> |

Merges that don't bump the version, and re-runs, skip publishing. Nobody pushes tags by hand. Run workflow on a network branch (Actions tab) does the same check on demand, e.g. to retry after fixing a variable.

The deployment baked into the build comes from the repository variables the web deploy already uses, with the network's prefix <P>_ (PREPROD_ or PREVIEW_):

| Baked value | Repository variable | |---|---| | Convex site URL | <P>_VITE_CONVEX_SITE_URL | | contract address | <P>_VITE_CONTRACT_ADDRESS | | OAuth client id | <P>_VITE_MCP_OAUTH_CLIENT_ID | | OAuth issuer | decoded from <P>_VITE_CLERK_PUBLISHABLE_KEY (Clerk's Frontend API) | | web app URL (draft links) | <P>_SITE_URL, the only variable of its own |

<P>_KARBONITY_<NAME> (e.g. PREPROD_KARBONITY_OAUTH_ISSUER) overrides any of them, and Preview also still reads the older unprefixed KARBONITY_* variables.

The workflow fails if any value above is missing, and publishes through npm Trusted Publishing: set per package on npmjs.com (package → Settings → Trusted publisher → GitHub Actions, eddalabs / karbonity-gameplay / release-mcp-cli.yml), with no token stored anywhere. npm only offers that on a package that already exists, so a brand-new package's first version is published by hand (below), then Trusted Publishing is configured and CI takes over.

Each network's Clerk OAuth app needs the CLI's login redirect http://127.0.0.1:44831/callback.

Release manually (first version of a new package, or without CI). From a clone of this repo, on the network branch's commit. For Preprod, rename the package and give the build the deployment values the workflow would (same sources as the table above):

git fetch origin preprod && git checkout --detach origin/preprod
pnpm install
cd packages/mcp-cli
npm pkg delete bin && npm pkg set name=@eddalabs/karbonity-mcp-preprod bin.karbonity-mcp-preprod=dist/cli.js
export KARBONITY_NETWORK=preprod KARBONITY_CONVEX_SITE_URL=… KARBONITY_SITE_URL=… \
  KARBONITY_CONTRACT_ADDRESS=… KARBONITY_OAUTH_ISSUER=… KARBONITY_OAUTH_CLIENT_ID=…
npm login                     # once; npm asks for your 2FA code on publish
npm publish --access public
git checkout package.json

For Preview, skip the rename and KARBONITY_NETWORK (the repo already names the Preview package):

pnpm --filter @eddalabs/karbonity-mcp build
cd packages/mcp-cli
npm pack                      # inspect: dist/cli.js + dist/contract/**/keys, no src/
npm publish --access public   # ~66 MB; the registry document takes a few minutes to propagate

Notes: prepack runs the build, so npm publish never ships a stale bundle. Right after a first publish npm view/npm install can 404 for a few minutes while the CDN catches up — npm search and npm access list packages @eddalabs confirm it landed.