@selfhost.dev/mcp-server
v0.4.1
Published
MCP server for SelfHost.dev - provision managed databases and deploy apps (PaaS) via natural language
Maintainers
Readme
SelfHost MCP Server
The SelfHost cloud platform, one sentence away inside your AI coding assistant. Spin up production databases, ship apps straight from GitHub, wire up domains and environment variables, and watch builds stream live, all in plain English without ever leaving your editor.
SelfHost pairs the power of production-grade managed databases with the effortless, deploy-from-GitHub simplicity of a modern app platform. This Model Context Protocol server puts the whole thing at your fingertips.
Two products, one server:
- Projects - your apps, shipped. Connect a GitHub repo, click deploy, and it's live: auto-detected builds (Nixpacks, Dockerfile, Docker Compose, or static), auto-deploy on every push, live streaming build logs, environment variables, custom domains, pause and resume to scale to zero, and databases right inside the project. The ease of Railway, Render, and Vercel, with nothing to manage.
- Managed Databases - production-grade database hosting, your way. PostgreSQL, MySQL, and MongoDB on AWS, or Postgres on Hetzner, in our cloud or your own account (BYOC), with backups, point-in-time recovery, autoscaling, alerting, and connection pooling.
Works with Claude Code, Cursor, Windsurf, Cline, and any MCP-compatible client.
Quick Start
Prerequisites
- A SelfHost.dev account
- Node.js 18+ or Bun
Install
Claude Code:
# Using npm (Node.js)
claude mcp add selfhost -- npx @selfhost.dev/mcp-server
# Using Bun
claude mcp add selfhost -- bunx @selfhost.dev/mcp-serverCursor / Windsurf / Other MCP clients:
Add to your MCP configuration file:
{
"mcpServers": {
"selfhost": {
"command": "npx",
"args": ["@selfhost.dev/mcp-server"]
}
}
}Or with Bun:
{
"mcpServers": {
"selfhost": {
"command": "bunx",
"args": ["@selfhost.dev/mcp-server"]
}
}
}That's it. The server handles authentication, token refresh, and everything else automatically.
First Run
On first use, the MCP server opens your browser to sign in via SelfHost's console. After you authorize, credentials are saved locally (~/.selfhost/credentials.json) and auto-refreshed - you won't need to sign in again.
You: "Show me my databases"
Claude: Authenticates → fetches your orgs → selects org → lists instances
→ Shows you a summary of all your running databasesWhat Can You Do?
Talk to both products in plain English.
Ship and run apps with Projects
Connect a repo, deploy, and it's live - SelfHost takes your code from GitHub to a running app.
| You say | What happens | |---------|-------------| | "Create a project and deploy my GitHub repo into it" | Provisions the project, waits until it's ready, auto-detects the build, and deploys the repo | | "Deploy the main branch of my-org/api" | Creates the deployment, triggers the build, and streams live logs until it's running | | "Turn on auto-deploy so every push ships" | Enables auto-deploy; future pushes to the branch redeploy automatically | | "Add a private Postgres database to my project" | Provisions a Postgres database inside the project, with the credentials and visibility you choose | | "Spin up Supabase in this project" | Deploys the Supabase template alongside your app | | "Set DATABASE_URL on my app and redeploy" | Updates the env var (without wiping the others) and rolls out the change | | "Point app.example.com at my deployment" | Attaches the custom domain and returns the exact DNS records to add, then verifies them | | "Show me the build logs for the last deploy" | Streams the build and container logs for that run | | "Pause my staging app so I stop paying for it" | Pauses the deployment (scales to zero); resume instantly when you need it | | "Roll back to the last working deploy" | Re-deploys the commit from the previous successful run | | "Notify my team channel when a deploy fails" | Binds a notification channel to the app's deploy outcomes |
Manage database infrastructure with Managed Databases
Production-grade, standalone database hosting.
| You say | What happens | |---------|-------------| | "Spin up a Postgres 18 instance in us-east-1" | Walks you through config, shows cost estimate, provisions it | | "Stop my staging database" | Finds the instance, confirms with you, stops it | | "Set up a CPU alert at 80% on my prod DB" | Creates an alert rule with email notification | | "Show me the backups for my main instance" | Lists all backups with sizes and timestamps | | "Fork my production database for testing" | Creates an independent clone with a new password | | "What's my estimated monthly cost for an r6i.xlarge with 500GB gp3?" | Calculates itemized cost breakdown | | "Tune shared_buffers on my instance" | Previews defaults, applies the override, syncs to replicas | | "Enable PgBouncer on my prod DB with 200 max clients" | Configures connection pooling, clients connect on port 6432 | | "Add a read-only database user for the reporting app" | Creates a DBMS-level credential with the right grants | | "Restore my prod database to 14:30 yesterday into a new instance" | Sets up a point-in-time recovery from WAL + base backups | | "Scale my instance to r6i.2xlarge and 1TB" | Issues a manual scale, polls the resize event | | "Auto-stop my staging DB at 7pm weekdays" | Creates a scheduled scaling policy with start/stop times | | "Upgrade my org to the Pro plan" | Confirms billing state, creates or changes the subscription | | "Spin up a Postgres instance on Hetzner in Helsinki" | Confirms provider, walks through Hetzner location + server type, provisions on Hetzner Cloud | | "What cloud providers can I use?" | Lists AWS and Hetzner with their capabilities so you can pick |
Safety Built In
Destructive operations (delete, stop, reboot) require explicit confirmation. The server will always ask before proceeding - you'll never accidentally delete a production database.
Features
151 tools across 22 modules
Every tool maps to a real API endpoint. No mock data, no shortcuts.
Authentication & Users
Automatic browser-based sign-in with Firebase. Tokens refresh transparently.
| Tool | Description |
|------|-------------|
| create_or_login_user | Create account or sign in |
| get_current_user | Your profile, admin status, org membership |
| get_my_memberships | List your orgs and pending invitations |
| select_organization | Switch org context (sets rate limits based on billing plan) |
| get_invite_credits | Check remaining platform invite credits |
| send_platform_invite | Invite someone to join SelfHost |
| list_my_platform_invites | See invitations you've sent |
| reauthenticate | Sign out and sign in again (switch accounts) |
Organizations & Team Management
Multi-tenant - everything is scoped to your org.
| Tool | Description |
|------|-------------|
| list_organizations | All orgs you belong to |
| create_organization | Create a new org (you become owner, get 5 invite credits) |
| get_organization | Org details and billing plan |
| update_organization | Change name, description, or IAM role |
| delete_organization | Soft-delete org and all related resources |
| list_members | See team members and their roles |
| remove_member | Remove a member (owner/admin only) |
| invite_to_org | Send org invitation with role assignment |
| list_org_invitations | Pending invitations |
| cancel_invitation | Revoke a pending invitation |
| get_my_invitations | Invitations sent to you |
| list_activity_logs | Audit trail of all actions in the org |
Cloud Credentials
Bring your own AWS account (BYOC) or use SelfHost's managed infrastructure.
| Tool | Description |
|------|-------------|
| list_credentials | List cloud credentials (secrets never exposed) |
| add_credential | Add AWS access keys or IAM role |
| update_credential | Rotate keys or update metadata |
| delete_credential | Remove a credential (with confirmation) |
| set_default_credential | Set as default for the org |
| get_aws_account_info | AWS account ID and free tier status |
Networking
VPCs, subnets, and security groups. Optional - auto-created during provisioning if not specified.
| Tool | Description |
|------|-------------|
| list_vpcs | List VPCs in a region (grouped by public/private) |
| create_vpc | Create VPC with internet gateway and subnets |
| delete_vpc | Remove VPC and associated resources (with confirmation) |
| list_subnets | List subnets in a region |
| create_subnet | Create subnet in a VPC |
| list_security_groups | List security groups |
| create_security_group | Create SG with inbound rules |
| update_security_group | Replace inbound rules on a security group |
Database Instances
The core feature. Full lifecycle management for PostgreSQL, MySQL, and MongoDB.
| Tool | Description |
|------|-------------|
| list_regions | Available AWS regions |
| get_instance_types_for_region | EC2 types with specs and hourly pricing |
| list_storage_types | EBS volume types with pricing |
| estimate_instance_cost | Itemized monthly cost breakdown before provisioning |
| create_instance | Provision a new database (guided flow with cost confirmation) |
| list_instances | All instances grouped by master + replicas |
| get_instance | Detailed instance info with latest metrics |
| update_instance | Change config, resize, toggle multi-AZ, update CIDR ranges |
| stop_instance | Stop instances (with confirmation) |
| start_instance | Start stopped instances |
| reboot_instance | Reboot instances (with confirmation) |
| delete_instance | Delete instances with optional final snapshot (with confirmation) |
| fork_instance | Clone a database into a new independent instance |
| refresh_instance_group | Refresh cached state for a master + replica group |
PostgreSQL Configuration
Tune database parameters with calculated defaults per instance type.
| Tool | Description |
|------|-------------|
| preview_pg_config | See calculated defaults for an instance type (before creating) |
| get_pg_config | Current config with defaults, overrides, and effective values |
| update_pg_config | Apply overrides (auto-syncs to replicas, set null to revert) |
Backups & Snapshots
Automated backups with DLM policies and manual EBS snapshots.
| Tool | Description |
|------|-------------|
| list_backups | List all backups (syncs with AWS) |
| create_backup | Create S3 file backup or AWS backup job |
| delete_backup | Delete backup and AWS snapshot (with confirmation) |
| list_backup_policies | List DLM lifecycle policies |
| create_backup_policy | Create automated backup schedule |
| update_backup_policy | Enable/disable or modify schedule |
| delete_backup_policy | Remove policy (with confirmation) |
| list_snapshots | List EBS snapshots in a region |
| get_snapshot | Snapshot details |
| delete_snapshot | Delete EBS snapshot (with confirmation) |
| create_snapshot | Create EBS snapshot from instance volume |
Alerts & Notifications
Monitor your databases and get notified when things go wrong.
| Tool | Description |
|------|-------------|
| list_alert_rules | Active alert rules |
| create_alert_rule | Create rule (CPU, memory, disk, replication lag, etc.) |
| get_alert_rule | Rule details |
| update_alert_rule | Modify thresholds or notification channels |
| delete_alert_rule | Delete rule and all instances (with confirmation) |
| list_alert_instances | Fired/pending/resolved alerts (paginated) |
| get_alert_instance | Alert instance details |
| acknowledge_alert | Acknowledge a firing alert |
| resolve_alert | Manually resolve an alert |
| list_notification_channels | Email notification endpoints |
| create_notification_channel | Add email channel |
| update_notification_channel | Modify channel config |
| delete_notification_channel | Remove channel (with confirmation) |
| test_notification_channel | Send test notification |
Connection Pooling (PgBouncer)
PostgreSQL-only. Reduces connection overhead for high-concurrency workloads. Clients connect on port 6432 once enabled.
| Tool | Description |
|------|-------------|
| get_pgbouncer | Get current pooling config (or null if never configured) |
| enable_pgbouncer | Enable pooling with pool mode, max client conn, pool sizes |
| reconfigure_pgbouncer | Apply new settings on an enabled instance (PATCH-style) |
| disable_pgbouncer | Drain pool and disable (with confirmation) |
Database Users
DBMS-level credentials - distinct from the SelfHost platform login. Use for apps and people that need their own DB user.
| Tool | Description |
|------|-------------|
| list_database_users | List users with role, status, target DB, expiry metadata |
| create_database_user | Create user with role (read_only / read_write / admin) and optional connection limit + password expiry |
| update_database_user | Change role, connection limit, or password expiry |
| delete_database_user | Soft-delete user (with confirmation) - drops active connections |
| rotate_database_user_password | Rotate password (with confirmation) - new value shown once |
Scaling
Manual one-off resize plus auto-scaling policies (reactive metric-based, scheduled cron, and auto start/stop).
| Tool | Description |
|------|-------------|
| scale_instance | Manual resize - change instance type, volume type, size, IOPS, throughput |
| list_scaling_policies | List policies, optionally filtered to one instance |
| create_scaling_policy | Create policy - reactive metric breach, scheduled cron, or auto start/stop schedule |
| update_scaling_policy | Modify thresholds, schedule, or action details |
| delete_scaling_policy | Remove a policy (with confirmation) |
Point-in-Time Recovery (PITR)
PostgreSQL-only, Pro+. Continuous WAL archiving to S3 + restore to any second within the retention window. Restore creates a brand-new instance - the source is untouched.
| Tool | Description |
|------|-------------|
| get_pitr | Current config + restore window (oldest / latest restorable moments) |
| enable_pitr | Set up WAL archiving to an S3 bucket with retention days |
| configure_pitr | Toggle between enabled (resume) and disabled (pause) |
| retry_pitr | Retry after an error state (e.g. fix IAM, then retry) |
| trigger_pitr_base_backup | Run a one-off base backup now |
| list_pitr_base_backups | List historical base backups with status + timestamps |
| restore_pitr | Restore to a target time into a new instance (with confirmation) |
Billing & Subscriptions
Subscription lifecycle and payment-method linking. All endpoints scoped to the active org.
| Tool | Description |
|------|-------------|
| get_subscription | Get current subscription (404 = no subscription, on Free) |
| create_subscription | Start a paid subscription (plan goes pending → active via Razorpay webhook) |
| change_subscription | Upgrade or downgrade plan (downgrades scheduled at cycle end) |
| cancel_subscription | Cancel - keeps access until cycle end (with confirmation) |
| link_billing_payment_method | Initiate Razorpay link - returns short URL to open in browser |
| update_billing_contact | Update billing phone / tax ID / country / state for invoices |
Hetzner Cloud (Postgres-only)
Provisioning on Hetzner Cloud as an alternative to AWS. Currently provision / get / status / delete only - no start / stop / reboot / update / scaling / PITR / pooling yet. Call list_cloud_providers at the start of any create-database intent to surface both options to the user.
| Tool | Description |
|------|-------------|
| list_cloud_providers | List available cloud providers (AWS, Hetzner) with capabilities + the create tool to use for each |
| list_hetzner_locations | Hetzner datacenter locations (fsn1, nbg1, hel1, ash, sin) with country + continent |
| list_hetzner_server_types | Hetzner server types (cpx11-cpx51) with vCPU / RAM / local disk |
| create_hetzner_instance | Provision a Postgres instance on Hetzner Cloud (region, server type, storage size, HA toggle, CIDR allowlist) |
| get_hetzner_instance | Fetch a Hetzner instance's full details by PID |
| get_hetzner_instance_status | Poll provisioning progress (per-step status: network → firewall → ssh_key → server → volume → load_balancer → ansible → finalize) |
| delete_hetzner_instance | Tear down a Hetzner instance and all associated resources (with confirmation) |
PaaS - Projects (app containers)
A project is a per-app container: a provisioned server + Coolify install + wildcard DNS that deployments, databases, and services attach to. Creation is async (~2-5 min) - poll get_project until status is active before deploying into it.
| Tool | Description |
|------|-------------|
| list_projects | List projects in the org (pid, name, status, public_ip, domain) |
| get_project | Get one project; poll this for provisioning progress (active / failed) |
| create_project | Create a project and start async provisioning (returns status pending) |
| update_project | Rename / re-describe a project |
| delete_project | Tear down the server and everything in the project (with confirmation; blocked while provisioning or with running deployments) |
| get_project_metrics | Time-series server + database + deployment metrics from the monitoring agent (start_date/end_date) |
PaaS - Deployments (GitHub apps)
A deployment is an app built from a GitHub repo, living inside an active project. Build/run history is returned inline on the deployment.
| Tool | Description |
|------|-------------|
| list_deployments | List apps in the org, each with inline build runs (newest 50) |
| get_deployment | Get one app + runs; poll this for deploy/run progress |
| create_deployment | Deploy a GitHub repo into a project (repo_url, branch, build_pack, port, env_vars, …) |
| update_deployment | Pause/resume, toggle auto-deploy, set ignore_paths / max preview deployments |
| update_deployment_build_config | Change build_pack / base_directory / port / dockerfile / env_vars |
| delete_deployment | Remove the app and its Coolify resources (with confirmation) |
| trigger_deploy | Manually deploy the current branch (new run) |
| get_deployment_logs | Current application/container logs |
| get_deployment_health | Reachability of the deploy URL + attached domains |
| get_run_logs | Full build + container logs for one run (poll until terminal) |
| redeploy_run | Re-run a build from the same commit |
| rollback_run | Re-deploy the commit from a prior successful run |
PaaS - Custom Domains
| Tool | Description |
|------|-------------|
| add_deployment_domain | Attach a custom domain to a deployment (returns DNS records to add) |
| sync_deployment_domains | Set the full domain list for a deployment (set primary / remove several) |
| remove_deployment_domain | Remove one domain from a deployment |
| verify_custom_domain | Check DNS (TXT + CNAME) and advance verification → live HTTPS |
| list_custom_domains | List the org's custom-domain verification states |
PaaS - Environment Variables
| Tool | Description |
|------|-------------|
| list_env_vars | List a deployment's env vars (values returned in cleartext) |
| set_env_vars | Replace the entire env-var set (omitted keys are deleted) |
| merge_env_vars | Add/update env vars without deleting others (safe upsert) |
| delete_env_var | Remove one variable by key |
PaaS - GitHub
| Tool | Description |
|------|-------------|
| list_github_installations | Connected GitHub App installations + their accessible repos |
| list_repo_branches | Branches for a repo via an installation |
| detect_repo_config | Auto-detect build_pack / port / monorepo dirs / env-var hints for a repo |
| get_github_connect_url | Get a browser URL to connect GitHub (interactive; then re-list installations) |
PaaS - Project Databases
Postgres/Redis/MySQL/MongoDB provisioned inside a project (distinct from AWS/Hetzner managed instances).
| Tool | Description |
|------|-------------|
| list_project_databases | List databases attached to a project |
| create_project_database | Provision a Postgres/Redis/MySQL/MongoDB in a project (type-specific credentials) |
| delete_project_database | Delete a project database (exact name match + confirmation) |
PaaS - Project Services (templates)
| Tool | Description |
|------|-------------|
| list_project_services | List service-template instances (e.g. Supabase) in a project |
| create_project_service | Deploy a service template (currently supabase) into a project |
| delete_project_service | Delete a project service (exact name match + confirmation) |
PaaS - Deployment Notifications
| Tool | Description |
|------|-------------|
| list_deployment_notification_bindings | Channels notified on a deployment's deploy outcomes |
| bind_deployment_notification_channel | Notify an org channel (nchan_…) on deploy success/failure |
| unbind_deployment_notification_channel | Stop notifying a channel for a deployment |
Common Workflows
Deploy an app from GitHub (Projects)
You: "Deploy my-org/web to a new project"
Claude: Creates a project → polls until it's provisioned and active
→ detects the build config from the repo (build pack, port)
→ creates the deployment and triggers the first build
→ streams the build logs until the app is live
→ hands you the deploy URLThen: "add a private Postgres to it", "set my env vars", "point app.example.com at it", or "turn on auto-deploy" to round out the app.
Switch AWS Account (BYOC vs Platform-Managed)
You: "I want to use my own AWS account"
Claude: Lists your credentials → you pick one (or add new keys)
→ fetches VPCs in your chosen region → you pick a VPC
→ proceeds with instance creation using your accountSwitch Organization
If you belong to multiple orgs:
You: "Switch to my other org"
Claude: Calls get_my_memberships → shows your orgs
→ you pick one → calls select_organization
→ rate limits and context update to the new orgRe-authenticate (Switch Accounts)
If you need to sign in as a different user:
You: "Sign in with a different account"
Claude: Calls reauthenticate → clears stored credentials
→ opens browser for new login → saves new tokens
→ you're now signed in as the other userRestore from Backup
You: "Restore my prod database from yesterday's snapshot"
Claude: Lists snapshots → you pick one
→ creates a new instance with snapshot_id
→ shows you the new password (save it!)Rate Limiting
Rate limits are based on your org's billing plan and enforced per-user:
| Plan | Reads/min | Writes/min | Concurrent | |------|-----------|------------|------------| | Free | ~60 | ~20 | 3 | | Starter | ~150 | ~50 | 5 | | Pro | ~300 | ~120 | 10 | | Enterprise | ~600 | ~300 | Unlimited |
Reference data lookups (regions, instance types, storage types) are unlimited.
Configuration
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| API_URL | https://api.selfhost.dev | SelfHost API endpoint |
| CONSOLE_URL | https://console.selfhost.dev | SelfHost Console URL (for browser auth) |
| TIER | Auto-detected | Override rate limit tier (FREE, STARTER, PRO, ENTERPRISE, ADMIN) |
| FIREBASE_API_KEY | - | Skip browser auth (CI/headless) |
| FIREBASE_REFRESH_TOKEN | - | Skip browser auth (CI/headless) |
Local Development
Both API_URL and CONSOLE_URL are optional overrides - they default to the production endpoints when not set.
1. Local Rails API + Local Console
Using npx:
{
"mcpServers": {
"selfhost": {
"command": "npx",
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
"env": {
"API_URL": "http://localhost:3000",
"CONSOLE_URL": "http://localhost:54588"
}
}
}
}Using bun:
{
"mcpServers": {
"selfhost": {
"command": "bun",
"args": ["run", "/path/to/selfhost-mcp/src/index.ts"],
"env": {
"API_URL": "http://localhost:3000",
"CONSOLE_URL": "http://localhost:54588"
}
}
}
}2. Local Rails API + Production Console
{
"mcpServers": {
"selfhost": {
"command": "npx",
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
"env": {
"API_URL": "http://localhost:3000"
}
}
}
}3. Production Rails API + Local Console
{
"mcpServers": {
"selfhost": {
"command": "npx",
"args": ["tsx", "/path/to/selfhost-mcp/src/index.ts"],
"env": {
"CONSOLE_URL": "http://localhost:54588"
}
}
}
}Headless / CI Mode
Set FIREBASE_API_KEY and FIREBASE_REFRESH_TOKEN environment variables to skip the browser login flow. You can find these values in ~/.selfhost/credentials.json after your first browser login.
Security
- Credentials stored locally at
~/.selfhost/credentials.jsonwithchmod 0600(owner-only read/write) - JWT auto-refresh - tokens refresh 5 minutes before expiry, refresh tokens are rotated
- Sensitive fields stripped - passwords, AWS keys, tokens, and secrets are redacted from API responses
- Destructive operations gated - delete, stop, and reboot require explicit
confirm: true - No console.log - all logging goes to stderr to avoid corrupting the MCP JSON-RPC stream on stdout
