@lovinka/deployik-mcp
v1.2.0
Published
MCP server for Deployik — drive projects, deployments, secrets, and domains from any MCP-aware AI.
Maintainers
Readme
@lovinka/deployik-mcp
MCP server for Deployik. Lets any MCP-aware AI drive Deployik end-to-end — create apps, spin up environments, deploy services, set variables, debug failed builds, manage domains + protection — without touching the dashboard.
Deployik's model is App → Environments × Services: an app owns N services (deployable build-config members) and N environments (a git branch pinned to a name); a deployment is a cell of that matrix. Tools take ids primarily (app_id, environment_id, project_id for a service) with name-based convenience (app, environment, service) resolved within the app.
Install (one-shot, no JSON editing)
npx -y @lovinka/deployik-mcp installPrompts for your Deployik URL and Personal Access Token, then:
- Registers the
deployikMCP server in~/.claude.json(Claude Code) and the Claude Desktop config (if installed) so every project + every window can use it. - Copies the Deployik how-to recipes into
~/.claude/skills/deployik-howto/so/skillssurfaces them. - Backs up any pre-existing config to
<path>.bak.<timestamp>before merging.
Restart Claude Code / Claude Desktop afterwards.
Scopes
# Global (recommended) — once installed, available everywhere
npx -y @lovinka/deployik-mcp install --global
# Local — writes <cwd>/.mcp.json + <cwd>/.claude/skills/
# MCP only fires when Claude is opened in this folder
npx -y @lovinka/deployik-mcp install --localNon-interactive
npx -y @lovinka/deployik-mcp install \
--yes \
--url=https://deployik.example.com \
--token=dpk_xxxOr set DEPLOYIK_URL / DEPLOYIK_TOKEN env vars and pass --yes.
Granular subcommands
| Command | What it does |
|---|---|
| install | MCP registration + skill files (default) |
| install --daemon | Long-lived launchd daemon — one HTTP process for every Claude window (macOS only, see below) |
| install-mcp | MCP registration only |
| install-skill | Skill files only |
| uninstall | Removes the deployik MCP entry from every Claude config |
| uninstall --daemon | Stops + removes the launchd daemon and clears the HTTP entry from Claude configs |
| daemon | Runs the HTTP daemon in the foreground (for testing) |
| doctor | Read-only diagnosis: build vs npm version, daemon health, Claude config entry shapes, stray per-session processes, API connectivity. Exit 1 on failures |
| update | Refreshes the installed launchd daemon runtime to this build (reuses the plist's URL/token/port, restarts the service). Never rewrites Claude configs |
Daemon mode (one process, every Claude window)
By default each Claude Code window spawns its own stdio child for every configured MCP. After a few open windows you can easily have 10+ idle node processes eating ~100 MB each. The daemon mode collapses this to a single long-lived HTTP MCP server bound to 127.0.0.1:8788.
npx -y @lovinka/deployik-mcp install --daemon --token=dpk_xxxWhat it does:
- Writes a launchd plist at
~/Library/LaunchAgents/com.lovinka.deployik-mcp.plistwithKeepAlive=true,RunAtLoad=true, andDEPLOYIK_URL/DEPLOYIK_TOKENinEnvironmentVariables(file mode 0600 — token only readable by your user). - Stages the runtime into
~/.deployik-mcp/runtime/so launchd can read it on every macOS regardless of TCC (Transparency, Consent, Control) restrictions on~/Documents,~/Desktop, etc. - Runs
launchctl bootstrap gui/$UID <plist>to start the daemon immediately. - Rewrites the
deployikentry in~/.claude.json(and the Claude Desktop config) from a stdio command to{ "type": "http", "url": "http://127.0.0.1:8788/mcp" }.
After install, restart any open Claude windows so they pick up the HTTP entry. From then on, opening N windows still uses one daemon process.
Tools that need the client's filesystem (init_in_repo, show_binding) are skipped in HTTP mode since the daemon has no per-repo context. Project resolution still works via explicit project_id / slug / single-project workspace.
Logs: ~/Library/Logs/deployik-mcp.{out,err}.log.
To go back to per-window stdio: npx -y @lovinka/deployik-mcp uninstall --daemon, then re-run install without --daemon.
Linux note: launchd is macOS-only. On Linux, run the daemon under
systemd --userpointing atnode <prefix>/lib/node_modules/@lovinka/deployik-mcp/dist/daemon.jsand add the matching HTTP entry to your client config manually.
Manual install (if you prefer to edit JSON yourself)
{
"mcpServers": {
"deployik": {
"command": "npx",
"args": ["-y", "@lovinka/deployik-mcp"],
"env": {
"DEPLOYIK_URL": "https://deployik.example.com",
"DEPLOYIK_TOKEN": "dpk_..."
}
}
}
}Get a token at Account → Access tokens in Deployik. The token is shown once on creation; copy it then. For a VPN-only deployment, point DEPLOYIK_URL at any reachable host (http://10.x.x.x:8080, https://deployik.internal, etc.).
What it does
- Apps —
list_apps(each row carries an environment rollup — counts by status, so the 897-env Prospector app costs one row),get_app(services + environments),create_app(bind a GitHub repo; optionally seedservices+ aninitial_environmentin one call),create_service(add a build-config member to an existing app — becomes an enabled cell in every active env),update_app(rename / toggledeploy_ordered/auto_previews_enabled),delete_app. - Environments — full lifecycle:
list_environments,get_environment,create_environment(app, name, branch, kind?, service_ids?),repin_environment(branch),delete_environment,set_environment_service(enabled)(matrix cell toggle), plus deploys:deploy_environment/deploy_environment_and_wait(all enabled cells) anddeploy_service(one cell). - Variables — app-scoped, one store with a
kind(env|secret):list_variables,set_variable,bulk_set_variables,delete_variable. Scope each key app-wide, to oneenvironment_id, topreview_defaults(inherited by auto-previews), and/or to one service.NEXT_PUBLIC_*is allowed only as an env var. - Domains / protection / deployments — per environment (
list_domains/add_domain/verify_domain/update_domain/delete_domain;get_protection/set_protectionper env, optionally per service);list_deployments(app + env/service filters),get_deployment,get_deploy_logs,get_deploy_screenshot. - Prospector auto-preview flow (driven by eve-ai-layer over MCP):
create_environment→deploy_environment_and_wait→get_deploy_screenshot→set_protectionreplaces the oldcreate_project+deploy_projectflow end-to-end. - Workflow shortcuts —
wait_for_deployment,debug_failed_deployment,tail_latest_logs,whats_broken(freshest failure across apps),whats_my_url(an env's live URL),init_in_repo/show_binding. - Service-level tools (postgres sidecars, volumes, analytics, email, auto-build) remain scoped to a service (
project_id). - Bundled knowledge — Deployik's how-to recipes ship as MCP prompts, plus
list_recipes,get_recipe(topic), andfind_help(question)which routes free-form English to the right recipe. - Repo binding — first call inside a git repo whose
originuniquely matches one app auto-writes.deployik.json(committed) and gitignores the private.deployik/directory. Self-healing.gitignore. - Tiered safety — destructive operations require
confirm: true; production-touching operations also requireconfirm_name. Every destructive call is logged to.deployik/audit.log.
Local development
cd mcp
bun install
bun run build
bun run inspect # opens MCP Inspector against the local binaryTest against a local Deployik dev server with DEPLOYIK_URL=http://127.0.0.1:8080 and a dev-mode PAT.
Files written on the host
Project ↔ repo state is split into two layers — public (commit it) and private (gitignored, per developer):
<repo-root>/
├── .deployik.json PUBLIC, commit this. Just { project, workspace, $schema }.
│ Teammates pulling your repo immediately know which
│ Deployik project this folder deploys to.
└── .deployik/ PRIVATE. Auto-added to .gitignore (and re-added on every
MCP call if a teammate clobbers the .gitignore line).
├── cache.json Project + dashboard group list (1h TTL).
├── token Optional token fallback (mode 0600) — only used if
DEPLOYIK_TOKEN env var is unset.
└── audit.log Append-only ledger of destructive calls (secret values
redacted automatically).Automatic binding: the first time you run any tool inside a git repo whose
origin remote uniquely matches one Deployik project, the MCP writes
.deployik.json silently — no explicit setup needed. If multiple projects
deploy the same repo (monorepos with several Deployik apps), the MCP returns a
friendly "which one?" with the candidate slugs.
Manual binding (also fine): "deployik bind this repo to acme-app" → the
AI calls init_in_repo({ project: "acme-app" }) and writes .deployik.json.
