@hatchbox/hatchbox-mcp
v0.8.2
Published
MCP server that wraps the Hatchbox /api/v1 API
Readme
hatchbox-mcp
An MCP server that wraps Hatchbox's /api/v1 API, so an LLM agent can inspect and operate your Hatchbox apps, domains, databases, and servers.
It also ships a Claude Code skill, migrate-from-heroku, which uses those tools to take a Rails app from Heroku to Hatchbox. See Migrating from Heroku.
Tools
One tool per operation, each with a readOnlyHint or destructiveHint annotation, grouped by resource:
| Resource | Read | Write |
|---|---|---|
| Accounts | hatchbox_list_accounts, hatchbox_get_account, hatchbox_list_account_apps, hatchbox_list_account_clusters, hatchbox_list_account_database_clusters, hatchbox_list_account_git_providers | — |
| User | hatchbox_get_me | — |
| Apps | hatchbox_get_app | hatchbox_create_app, hatchbox_update_app, hatchbox_rename_app, hatchbox_enable_app_maintenance, hatchbox_disable_app_maintenance, hatchbox_restart_app, hatchbox_deploy_app, hatchbox_enable_app_auto_deploy, hatchbox_disable_app_auto_deploy |
| Domains | hatchbox_list_domains, hatchbox_get_domain | hatchbox_create_domain, hatchbox_update_domain, hatchbox_delete_domain |
| Env vars | — | hatchbox_create_env_vars, hatchbox_update_env_vars, hatchbox_delete_env_vars |
| Processes | hatchbox_list_processes, hatchbox_get_process | hatchbox_create_process, hatchbox_update_process, hatchbox_delete_process, hatchbox_enable_process, hatchbox_disable_process, hatchbox_restart_process |
| Cron jobs | hatchbox_list_cron_jobs, hatchbox_get_cron_job | hatchbox_create_cron_job, hatchbox_update_cron_job, hatchbox_delete_cron_job |
| Databases | hatchbox_list_app_databases, hatchbox_get_app_database, hatchbox_list_cluster_databases, hatchbox_get_cluster_database | hatchbox_create_database, hatchbox_update_database, hatchbox_attach_database, hatchbox_detach_database |
| Clusters | hatchbox_get_cluster (embeds servers) | — |
| Servers | hatchbox_list_servers, hatchbox_get_server | hatchbox_provision_server, hatchbox_reboot_server |
| Firewall rules | hatchbox_list_firewall_rules, hatchbox_get_firewall_rule | hatchbox_create_firewall_rule, hatchbox_delete_firewall_rule |
| Backups | hatchbox_get_latest_backup, hatchbox_get_backup_configuration | hatchbox_create_backup, hatchbox_test_backup_connection, hatchbox_update_backup_configuration, hatchbox_disable_backups |
| Logs | hatchbox_list_app_logs, hatchbox_get_log | — |
hatchbox_restart_app, hatchbox_deploy_app, hatchbox_rename_app, hatchbox_create_backup, hatchbox_test_backup_connection, hatchbox_update_backup_configuration, hatchbox_disable_backups, hatchbox_provision_server, hatchbox_reboot_server, hatchbox_create_process, hatchbox_update_process, hatchbox_delete_process, hatchbox_enable_process, hatchbox_disable_process, hatchbox_create_firewall_rule, and hatchbox_delete_firewall_rule are asynchronous: they return a log id (as log_id, except hatchbox_delete_process, hatchbox_delete_firewall_rule, and hatchbox_rename_app, which return it as id) you follow up on with hatchbox_get_log until state is completed/failed/aborted. hatchbox_enable_process/hatchbox_disable_process return no log id when the process was already in that state (a no-op).
hatchbox_enable_app_maintenance/hatchbox_disable_app_maintenance are not async in this sense: they return the updated app record immediately (maintenance: true/false). The Caddy config reload that actually flips the served page happens on the app's servers in the background, with no log id to poll.
hatchbox_list_app_logs and hatchbox_list_firewall_rules are paginated: they return { logs, pagination } / { firewall_rules, pagination } respectively, where pagination carries current_page/total_pages/total_count/page_limit. limit defaults to and is capped at 100 server-side.
hatchbox_delete_firewall_rule fails with a 422 if the rule is one Hatchbox manages itself (SSH, and 80/443 on web servers) — check the removable field from hatchbox_list_firewall_rules/hatchbox_get_firewall_rule before attempting to delete a rule.
hatchbox_update_app rejects the name field entirely (422) — renaming moves the app's directory and rewrites server config, so it's handled separately by hatchbox_rename_app, which also 422s if the new name is unchanged, blank, contains characters other than letters/numbers/hyphens/underscores, or is already taken by another app in the same cluster.
Setup
Get an API token. Log into your Hatchbox web app, go to
/api_tokens→ New API Token, name it, and copy the revealed token value.Add it to your MCP client config. No install step needed —
npxfetches and runs the package on demand.Claude Code:
claude mcp add hatchbox -- npx -y @hatchbox/hatchbox-mcpThen set
HATCHBOX_API_TOKENfor that server (seeclaude mcp add --helpfor passing env vars, or edit.mcp.jsondirectly).Claude Desktop (
claude_desktop_config.json):{ "mcpServers": { "hatchbox": { "command": "npx", "args": ["-y", "@hatchbox/hatchbox-mcp"], "env": { "HATCHBOX_API_TOKEN": "your-token-here" } } } }
Migrating from Heroku
The migrate-from-heroku skill moves one Rails app from Heroku to Hatchbox in Claude Code. It
plans before it changes anything and waits for your approval, then creates your app, databases,
env vars and cron jobs on Hatchbox, rehearses the deploy and data transfer, and finally cuts over.
Your Heroku app is left intact throughout, so you can always roll back.
Install and run
- Install or update Claude Code to the latest version
- Make sure your Hatchbox account has an active subscription
- Create an API token at https://hatchbox.io/api_tokens
- Add
export HATCHBOX_API_TOKEN=<your token>to your shell profile (e.g.~/.zshrc) - Install the Heroku CLI, run
heroku login, and confirm withheroku auth:whoami - Install
jq(brew install jq) - In the Hatchbox dashboard, connect GitHub and grant it access to the repo of the Rails app you're migrating
- In the Hatchbox dashboard, add your SSH public key so you can
ssh deploy@<server-ip>— the database restore runs from a shell on the server - In the Hatchbox dashboard, create a cluster in the region closest to your Heroku app's region
- In that cluster, create a server with the
webandpostgresqlroles, plusredisif you use Sidekiq or Redis,workerfor any non-web Procfile entries, andcronif you use Heroku Scheduler — wait until it shows active - Open a new terminal window so it picks up
HATCHBOX_API_TOKEN, then start Claude Code from there - Run
/plugin marketplace add hatchboxio/hatchbox-mcp - Run
/plugin install hatchbox@hatchbox - Quit and restart Claude Code, again from a terminal that has the token
- Run
/mcpand confirmhatchboxis connected; if it isn't, reconnect it there - Ask Claude to call
hatchbox_get_meand confirm it returns your user cdinto the Rails app's repo and make suregit statusis clean- Ask Claude to run the
migrate-from-herokuskill on your Heroku app, giving it the Heroku app name - Answer what it stops to ask for: your Heroku Scheduler jobs, approval of the generated
MIGRATION.md, your app's<hashid>.hatchboxapp.comhostname from the dashboard, fresh credentials for any add-ons you're re-signing up for, and the output of the database restore commands you run on the server - Stop after Phase 6 unless you have a custom domain you control and are prepared for a real cutover — Phase 7 has not been tested yet
- Report anything that was wrong, confusing, or needed a workaround at https://github.com/hatchboxio/hatchbox-mcp/issues, noting which phase it happened in
Updating
- Run
/plugin marketplace update hatchbox - Run
/plugin update hatchbox@hatchbox - Restart Claude Code
Using a different MCP client? Configure the server directly as described in Setup — the skill itself is Claude Code only.
Development
To work on hatchbox-mcp itself rather than just using it:
git clone [email protected]:hatchboxio/hatchbox-mcp.git
cd hatchbox-mcp
npm install
npm run dev # run directly from src/ via tsx, no build step
npm run build # compile to build/
npm start # run the compiled build/index.js
npm test # run the test suiteTo point an MCP client at your local build instead of the published package, use node with an absolute path in place of the npx command above:
{
"command": "node",
"args": ["/absolute/path/to/hatchbox-mcp/build/index.js"]
}For local development against bin/dev, HATCHBOX_BASE_URL is typically http://app.lvh.me:3000/api/v1.
Notes
- The token has no scoping — it's effectively full access as the owning user, gated only by that user's account/subscription status. Treat it like a password.
- Every endpoint is subscription-gated (402) except account discovery — a lapsed/never-paid account can't use the API.
