About Bunny Tools
Bunny Tools is an MCP server in the RAG category: the CLI Bunny.net never shipped — 60 commands across Storage, CDN, DNS, Stream, Edge Scripting, plus a built-in MCP server for AI agents (Claude Code, Claude Desktop).
The repository has 1 stars and 0 forks.
Install
claude mcp add bunny-tools -- npx -y bunny-toolsnpx -y bunny-toolsThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Bunny Tools
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
Bunny CLI and MCP Server
Package: bunny-tools · Binary: bunny · Node: ≥20
Why bunny-tools
Bunny.net is a great CDN/storage/DNS/streaming platform but managing it from the terminal was DIY territory. bunny-tools fixes that with one binary covering Storage, CDN, DNS, Stream, and Edge Scripting - and a built-in MCP server so AI agents can drive every command:
bunny deployfor static sites. Familiar ergonomics if you've usedfirebase deploy- walk public dir → SHA-cached diff → parallel upload → CDN purge, in one command.bunny.jsonis your single source of truth. Versioned in git. Every command honors it. JSON Schema published atunpkg.com/bunny-tools/schema/bunny.schema.json.- AI-native via MCP. AI agents see the same surface you do - no separate plugin per agent.
bunny install mcpregisters it with Claude Code in one shot. - Verified end-to-end. 185 unit tests + nightly drift detection against a real Bunny account. We catch Bunny API changes before they break your deploys.
Install
As a CLI
npm install -g bunny-tools
As an MCP server (recommended for AI workflows)
For Claude Code:
claude mcp add bunny-tools npx -y bunny-tools mcp
For Claude Desktop, add to claude_desktop_config.json:
{
"mcpServers": {
"bunny-tools": {
"command": "npx",
"args": ["-y", "bunny-tools", "mcp"]
}
}
}
Once installed, any Claude session can use 15 high-level tools (bunny.deploy, bunny.purge, zone/dns CRUD) plus 3 resources (bunny://manifest, bunny://agents, bunny://config/current) without needing prior context. See MCP server below for the full tool surface.
Quickstart
bunny init # interactive: auth + feature picker + bunny.json
bunny deploy --dry-run # preview
bunny deploy # storage sync + CDN purge
bunny init walks you through:
- Bunny account API key (skipped if already in env or keychain)
- Feature multi-select - Storage+CDN, DNS, Stream, Magic Containers, Edge Scripting
- Per-feature config (e.g. for Storage+CDN: public dir, storage zone, password, pull zone, purge strategy)
Non-interactive form for CI:
bunny init --non-interactive --features=storage \
--api-key=$BUNNY_API_KEY \
--storage-zone=my-app \
--storage-password=$BUNNY_STORAGE_PASSWORD \
--pull-zone=12345
Add --ci to also generate .github/workflows/bunny-deploy.yml for GitHub Actions.
Quickstart for AI agents
With the MCP server installed (see Install), Claude Code and Claude Desktop can drive every command. Drop into any project and try:
| What you say | What happens |
|---|---|
| "Use bunny-tools to set up CI/CD for this project" | Runs bunny init, writes .github/workflows/deploy.yml using the official action, and lists the secrets you need to add |
| "Deploy this site to Bunny" | Reads existing bunny.json, runs bunny deploy (with dry-run preview first) |
| "Purge the CDN cache for tag release-2026-04" | Calls bunny.purge with tag:release-2026-04 |
| "Show me what's on my Bunny account" | Calls bunny.whoami + lists reachable zone counts |
| "Add an A record for www → 1.2.3.4 on my Bunny DNS zone for example.com" | Resolves the zone id, calls bunny.dns_record_add |
For best results in a new project, drop a 2-line hint into the project's CLAUDE.md:
## Deploy
This project uses bunny-tools. Run `bunny init` for first-time setup, then `bunny deploy`.
This anchors Claude to bunny-tools for that project's deploy work.
Setup & Auth
| Command | Description |
|---|---|
bunny init |
Interactive setup - auth + feature picker + bunny.json |
bunny configure |
Walkthrough - store credentials in a named profile |
bunny configure list |
List all credential profiles + scopes (masked) |
bunny configure switch <name> |
Set the active profile |
bunny configure remove <name> [scope] |
Remove a profile, or a single scope inside one |
bunny use [alias] |
Switch active alias from .bunnyrc (or list aliases) |
bunny whoami |
Show current account context + reachable zone counts |
bunny docs [topic] |
Open Bunny.net docs in browser |
Example
bunny configure --profile=staging
bunny configure switch staging
Deploy & Purge
| Command | Description |
|---|---|
bunny deploy |
Sync public dir to storage zone and purge CDN cache |
bunny purge <target> |
Purge by URL, tag:<name>, or pullzone:<id> |
Example
bunny deploy --dry-run
bunny purge tag:release-2026-05
Storage (file operations)
| Command | Description |
|---|---|
bunny storage upload <local> <remote> |
Upload a single file to the active zone |
bunny storage download <remote> <local> |
Download a single file from a zone |
bunny storage list [path] |
List a storage-zone path |
bunny storage delete <path> |
Delete a file or path (use --recursive for dirs) |
bunny storage sync <local-dir> |
Mirror local dir to zone - SHA-cached diff, parallel upload |
Example
bunny storage sync ./dist --zone=my-app
Storage Zones
| Command | Description |
|---|---|
bunny storagezone list |
List storage zones |
bunny storagezone get <id|name> |
Get a storage zone |
bunny storagezone create <name> |
Create a storage zone |
bunny storagezone update <id> --body=<json> |
Update a storage zone (raw JSON body) |
bunny storagezone delete <id> |
Delete a storage zone |
Pull Zones (CDN)
Tip:
bunny cdn ...works everywherebunny pullzone ...does - Bunny's dashboard calls these "CDN", so the alias is there for muscle memory. Canonical name follows Bunny's API (pullzone).
| Command | Description |
|---|---|
bunny pullzone list (or bunny cdn list) |
List pull zones |
bunny pullzone get <id> |
Get a pull zone |
bunny pullzone create <name> |
Create a pull zone |
bunny pullzone update <id> --body=<json> |
Update a pull zone (raw JSON body) |
bunny pullzone delete <id> |
Delete a pull zone |
bunny pullzone edgerule list <id> |
List edge rules on a pull zone |
bunny pullzone edgerule add <id> --rule=<json> |
Add an edge rule (raw JSON rule) |
bunny pullzone edgerule delete <id> <rule-id> |
Delete an edge rule |
bunny pullzone hostname list <id> |
List custom hostnames linked to a pull zone |
bunny pullzone hostname add <id> <hostname> |
Link hostname + provision Let's Encrypt cert + ForceSSL. Idempotent. --no-force-ssl opts out of HTTP→HTTPS redirect |
bunny pullzone hostname remove <id> <hostname> |
Unlink a custom hostname |
Example
bunny cdn edgerule list 12345
# Wire DNS to a pull zone (2 steps - `add` does link + cert + ForceSSL
# in one idempotent call; the DNS record points at the wired-up PZ):
bunny pullzone hostname add 5780316 example.com # ~2-90s
bunny dns record add 783181 PULLZONE @ --pull-zone=5780316
# Or do everything in one shot via the atomic Connect Domain command:
bunny domain connect 5780316 example.com --dns-zone=783181
DNS
| Command | Description |
|---|---|
bunny dns list |
List DNS zones |
bunny dns get <id|domain> |
Get a DNS zone |
bunny dns create <domain> |
Create a DNS zone |
bunny dns delete <id> |
Delete a DNS zone |
bunny dns record list <zone> |
List records on a zone |
bunny dns record add <zone> <type> <name> <value> |
Add a record (positional args) |
bunny dns record update <zone> <record-id> --body=<json> |
Update a record |
bunny dns record delete <zone> <record-id> |
Delete a record |
Supported record types: standard A, AAAA, CNAME, TXT, MX, SRV, CAA, NS plus Bunny routing types REDIRECT, PULLZONE, PTR, SCRIPT. PULLZONE and SCRIPT need --link-name=<id> (the linked pull zone / script id). For PULLZONE you can use the convenience flag --pull-zone=<id> instead and the CLI will fill in both the value and link-name from the pull zone's metadata. (FLATTEN is documented in Bunny's OpenAPI spec but the live API rejects it; dropped from supported types - re-add when Bunny enables it server-side.)
Examples
# Standard A record
bunny dns record add 783181 A www 1.2.3.4 --ttl=300
# Redirect www → https://example.com
bunny dns record add 783181 REDIRECT www https://example.com
# Wire DNS to a pull zone - auto-fills value + link-name
bunny dns record add 783181 PULLZONE "" --pull-zone=5780316
# Or raw form if you already know the pz name
bunny dns record add 783181 PULLZONE "" my-pz-name --link-name=5780316
Stream
| Command | Description |
|---|---|
bunny stream library list |
List Stream libraries |
bunny stream library create <name> |
Create a Stream library |
bunny stream library delete <id> |
Delete a Stream library |
bunny stream video list <library> |
List videos in a library |
bunny stream video upload <library> <file> |
Upload a video to a library |
bunny stream video delete <library> <video-id> |
Delete a video |
Example
bunny stream video upload 42 ./demo.mp4 --title="My demo"
Magic Containers
| Command | Description |
|---|---|
bunny containers app list |
List container apps |
bunny containers app delete <id> |
Delete a container app |
containers app createis deferred to v0.2 - Bunny's v3 schema requiresruntimeType+containerTemplates[]+autoScalingwhich the current CLI surface doesn't yet model. Manage creation via the Bunny dashboard for now.
Edge Scripting
| Command | Description |
|---|---|
bunny scripting list |
List edge scripts |
bunny scripting deploy <name> --code=<file> |
Create or update a script (dual-mode) |
bunny scripting delete <id> |
Delete a script |
Example
bunny scripting deploy my-router --code=./worker.js
Discovery & AI
| Command | Description |
|---|---|
bunny manifest --pretty |
Full registry as JSON (machine-readable surface) |
bunny manifest --names |
One command name per line - handy for shell completion |
bunny <any-command> --help-json |
Help for any command as JSON |
bunny mcp |
Boot MCP stdio server (15 tools, 3 resources) |
See AGENTS.md for AI-agent guidance.
Global flags
Apply to any command:
| Flag | Effect |
|---|---|
-c, --config <path> |
Override bunny.json location |
--cwd <dir> |
Run as if launched from this directory |
-e, --env <alias> |
One-shot .bunnyrc alias |
-p, --profile <name> |
One-shot credential profile |
Example
bunny --profile=staging deploy
Configuration
bunny.json (per-project, git-tracked):
{
"$schema": "https://unpkg.com/bunny-tools/schema/bunny.schema.json",
"deploy": {
"publicDir": "dist",
"ignore": ["bunny.json", ".bunnyrc", "**/.*", "**/node_modules/**"],
"storageZone": "my-app",
"region": "ny",
"concurrency": 8,
"pullZones": [{ "id": 12345, "purge": "all" }]
}
}
.bunnyrc (per-developer aliases, gitignored):
{
"default": "prod",
"aliases": {
"prod": { "storageZone": "my-app", "pullZones": [12345] },
"staging": { "storageZone": "my-app-stg", "pullZones": [12346] }
}
}
Multi-account profiles (~/.config/bunny-tools/credentials.json):
{
"active": "default",
"profiles": {
"default": { "account": "...", "storage:my-app": "..." },
"staging": { "account": "...", "storage:my-app-stg": "..." }
}
}
Switch the active profile with bunny configure switch <name>, or one-shot with bunny --profile=<name> <cmd> or BUNNY_PROFILE=<name>.
Auth model
Four credential scopes (all use the AccessKey HTTP header):
account- Account API keystorage:<zone>- Storage zone password (per zone)stream:<lib>- Stream library API key (per library)database:<name>- Database access key
Resolver chain (per call site): --flag → scoped env (e.g. BUNNY_STORAGE_PASSWORD_MY_APP) → generic env (BUNNY_STORAGE_PASSWORD) → OS keychain (<profile>:<scope> keys) → ~/.config/bunny-tools/credentials.json → interactive prompt.
GitHub Actions
bunny init --ci generates a workflow that uses npm-install + bunny deploy:
- name: Install bunny-tools
run: npm install -g bunny-tools
- name: Deploy
env:
BUNNY_API_KEY: ${{ secrets.BUNNY_API_KEY }}
BUNNY_STORAGE_PASSWORD_MY_APP: ${{ secrets.BUNNY_STORAGE_PASSWORD_MY_APP }}
run: bunny deploy
A composite action wrapper (bytekcorp/bunny-tools-deploy-action@v1) is on the v0.2 roadmap for tighter ergonomics. The npm-install form above is the canonical path for v0.1.
MCP server (AI integration)
Install steps are at the top under Install → As an MCP server. Once configured, the server exposes:
Tools (15): bunny.deploy, bunny.purge, bunny.init, bunny.manifest, bunny.whoami, storage zone CRUD, pull zone CRUD, DNS zone + record CRUD, plus bunny.run as an escape hatch for any CLI invocation.
Resources (3):
bunny://manifest- full command registry as JSONbunny://agents- AGENTS.md (workflows, gotchas, conventions for AI agents)bunny://config/current- resolved config frombunny.json+ active alias
Cross-project usage. With the MCP server installed, drop a 2-line hint into any new project's CLAUDE.md to anchor Claude to bunny-tools for that project:
## Deploy
This project uses bunny-tools. Run `bunny init` for first-time setup, then `bunny deploy`. See `bunny manifest --pretty` for the full command surface.
Development
git clone https://github.com/bytekcorp/bunny-tools
cd bunny-tools
npm ci
npm run build
npm test
npm run dev -- manifest --pretty
For end-to-end testing against a real Bunny account (drift detection), see docs/e2e-testing.md.
For release instructions, see docs/deployment-guide.md.
FAQ
Is this the official Bunny.net CLI?
No. bunny-tools is a community CLI. Bunny.net publishes @bunny.net/cli, which focuses on Databases, Magic Containers, and Edge Scripts. bunny-tools covers a different surface (Storage, CDN, DNS, Stream, Edge Scripting) and ships an MCP server for AI agents.
Why the binary name bunny?
Short and matches the brand. Note that @bunny.net/cli also installs a bunny binary, so installing both globally will collide - pick one or use npx for the other.
Can I use this in CI?
Yes. bunny init --ci generates a .github/workflows/bunny-deploy.yml. All commands honor BUNNY_API_KEY and per-zone scoped env vars.
Does it work without Node.js? Currently npm-only (Node 20+). A standalone binary is on the v0.2 roadmap.
License
MIT - see LICENSE.
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.