Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

AppCrane

NPM · APPCRANE-MCP · SCANNED SEP 25

Deploy and manage apps on your own AppCrane instance, the self-hosted PaaS for AI-built apps.

Available components

+3 this week 75 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security98
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 31 of 95 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency45
Schema Quality & AI Usability67
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 13973 tokens (~245/item across 57 items; 57 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management60
  • Stability observed for 18 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage94
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 83% of tool parameters carry a description.Partial
Tool Safety75
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • 0 of 5 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "appcrane_deploy" implies "deploy" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
  • An AI judge read all 57 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the AppCrane MCP server?

AppCrane runs locally as an npm package, launched with npx -y appcrane-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · appcrane-mcp

# add to Claude Code
claude mcp add gitayg-appcrane -- npx -y appcrane-mcp
// .cursor/mcp.json
{
  "mcpServers": {
    "gitayg-appcrane": {
      "command": "npx",
      "args": [
        "-y",
        "appcrane-mcp"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "gitayg-appcrane": {
      "command": "npx",
      "args": [
        "-y",
        "appcrane-mcp"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add gitayg-appcrane -- npx -y appcrane-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "gitayg-appcrane": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "appcrane-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add gitayg-appcrane --command npx --arg -y --arg appcrane-mcp
# ~/.hermes/config.yaml
mcp_servers:
  gitayg-appcrane:
    command: "npx"
    args: ["-y", "appcrane-mcp"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "gitayg-appcrane": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "appcrane-mcp"
      ]
    }
  }
}
# add to Vellum
assistant mcp add gitayg-appcrane -t stdio -c npx -a -y appcrane-mcp
// mcp.json
{
  "mcpServers": {
    "gitayg-appcrane": {
      "command": "npx",
      "args": [
        "-y",
        "appcrane-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 25 Sept 26 +1
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 23 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 50 to 53. That category is still filling its 30-day observation window: 15 days of observed history at the previous scan, 16 at this one. The score rises as the window fills, whether or not the server changes.

  • 20 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

  • 18 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 33 to 37. That category is still filling its 30-day observation window: 10 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

  • 16 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

  • 14 Sept 26 +4
    • Stability: unverified → 0.23 ▲ functional
  • 8 Sept 26 +15
    • Malware scan: unverified → pass ▲ security
  • 7 Sept 26 51

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 25 Sept 2026 · Analysed npm/appcrane-mcp@1.0.0

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem npm

Background: How many MCP packages publish verified provenance →

Dependencies 95 packages
Packages resolved 95
Stale 31
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 57 exposed · ~13,973 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
appcrane_approve_access_request ~90

Approve a pending access request: grants the requester access to the app at `role` (default "user") and marks the enhancement_request as done. Verifies the request is actually an access request before acting. App-admin / owner / global admin required.

NameTypeReqDescription
request_idintegeryesenhancement_requests.id from appcrane_list_access_requests
rolestring––

No output schema declared.

No examples provided.

appcrane_cat ~103

Print the contents of a file inside a running app container. Read-only; bound to safe roots (/app and /data only). Refuses files larger than 256KB; truncate by reading the first N bytes via path tricks if you need a tail.

NameTypeReqDescription
pathstringyesAbsolute path inside the container, must start with /app or /data
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_check_resource_limits ~229

Which containers are NOT running with the CPU/RAM limits AppCrane has configured for them? Compares every app row against the limits actually in force on its container and reports only the mismatches. `--memory` and `--cpus` are `docker run` flags, so changing a limit rewrites the database and nothing else until the container is RECREATED — a container created before the limit was set keeps running without it, and every other AppCrane surface reports the CONFIGURED number, so the two are indistinguishable without this. `memory state=not_applied` means NO limit at all: that container can take the whole host, and on a host with no swap that ends as a global OOM kill of whatever the kernel judges largest. Answers `applied: null` (unknown) rather than guessing when Docker cannot be read. ADMIN ONLY.

NameTypeReqDescription
include_okboolean–Also list containers whose limits ARE applied. Default false — the point is the exceptions.
slugstring–Check one app instead of the whole fleet.

No output schema declared.

No examples provided.

appcrane_cp ~287

Copy/upload a file straight into the app's persistent /data volume on the host (aliases: appcrane_upload, appcrane_set_data_blob) — single hop, no container round-trip, no GitHub round-trip, no inline size ceiling. The bytes land at /data/apps/<slug>/<env>/shared/data/<path>, which is the SAME path the running container sees mounted as /data/<path>. Right tool for multi-MB datasets, large fixtures, or anything where appcrane_push_to_managed_app's tool-arg ceiling would force chunking. Returns the SHA-256 + byte count of what was stored so the caller can verify integrity. App-admin or owner of the app required. NEVER returns secrets in the response. Path must be repo-relative, no `..`, no leading slash.

NameTypeReqDescription
contentstringyesThe data to write. utf-8 string or base64-encoded bytes depending on encoding.
encodingstring–Defaults to utf-8. Use base64 for binary blobs.
pathstringyesPath within /data, e.g. "datasets/threats.json" or "cache/build.tar.gz". No leading slash, no "..".
slugstringyesApp slug.
stagestring–Which env's /data volume to write to. Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_create_app ~697

Register a new app in AppCrane, either from a GitHub repository or from a prebuilt container image. Use this only after the user has explicitly confirmed they want to onboard a new app and told you which source to use — a real github URL, or an image reference for source_type='image'. Allocates ports, creates the data directories, configures Caddy routing, and starts health checks. After this returns, call appcrane_set_secret to set any required secrets, then appcrane_deploy to ship the first build. For an image app there is nothing to build: the deploy pulls image_ref and starts it, so also pass container_port and health_path unless the image happens to match AppCrane's own 3000 + /api/health defaults. Requires the create-apps permission (global admins, or any role a platform admin granted at Settings → Roles).

NameTypeReqDescription
branchstring–Branch to track. Default: main
container_portinteger–Port the image listens on inside the container. Omit only if the image really listens on 3000 (what an AppCrane-built image does); a third-party image usually does not — odoo is 8069, nginx is 80. Ge…
descriptionstring––
domainstring–Optional custom domain. If omitted, the app lives under CRANE_DOMAIN/<slug>/.
github_tokenstring–GitHub PAT for private repos. Stored encrypted; only used to clone.
github_urlstring–GitHub repo URL, e.g. https://github.com/me/mysite. Required unless source_type is 'image'.
health_pathstring–HTTP path AppCrane health-checks. Omit only if the image serves /api/health (the AppCrane-built default). A stock image will not, and a health check against a 404 marks a working app unhealthy.
image_refstring–Prebuilt container image to run instead of building from source, e.g. "odoo:19" or "ghcr.io/owner/app@sha256:<64 hex>". Sets source_type='image'. The reference MUST name a version: a bare name ("odoo…
max_cpu_percentnumber–Per-container CPU cap. Default: 50.
max_ram_mbnumber–Per-container memory cap. Default: 512.
namestringyesDisplay name (shown in dashboard)
slugstringyesURL-safe identifier — lowercase letters, digits, dashes; must start with a letter or digit. Lives at /<slug>/.
source_typestring–'github' (default) clones and builds a repo; 'image' runs a prebuilt image and never builds. Implied when image_ref is passed.

No output schema declared.

No examples provided.

appcrane_create_app_role ~242

Define a new role for an app to enforce itself — the vocabulary side of app-defined roles. This does NOT grant AppCrane privileges of any kind, and it does NOT give anyone the role: use appcrane_set_user_app_roles for that. To change who may deploy / read env / delete, you want appcrane_grant_app_access, not this tool. key is what the app's code compares against and is immutable once created; it must match /^[a-z][a-z0-9_-]{0,31}$/ and may not be one of the AppCrane-reserved words (owner, admin, user, viewer, none, platform_admin). label is the human name shown in the dashboard. An app may define at most 16 roles. Owner or admin of the app required.

NameTypeReqDescription
descriptionstring–Optional. What the app lets this role do.
keystringyesMachine key the app matches on, e.g. "approver". Lowercase, immutable.
labelstringyesHuman-readable name, e.g. "Budget approver"
slugstringyes–

No output schema declared.

No examples provided.

appcrane_create_managed_app ~324

Create a new app using AppCrane's GitHub service-account — the platform creates a repo on the configured org/user, owns it, and the agent works against it through github_* tools without the end user ever needing their own PAT. Use this when the user does not have a GitHub account or does not want to deal with GitHub at all. Requires the platform admin to have configured the service-account in Settings → GitHub. Returns the same shape as appcrane_create_app, plus the auto-created repo metadata. IDEMPOTENT RECOVERY: if the slug already exists as a managed app but its AMC_ repo was never created (a half-created app from an earlier failure — push then returns REPO_NOT_FOUND), calling this again re-provisions the missing repo and returns { repaired: true } instead of erroring. So if a create attempt half-failed, just call it again with the same slug. Owner-or-admin to repair an existing one.

NameTypeReqDescription
branchstring–Default branch for the new repo. Defaults to "main".
descriptionstring–Optional. Used as both app description and repo description.
domainstring–Optional custom domain.
max_cpu_percentnumber–Per-container CPU cap. Default: 50.
max_ram_mbnumber–Per-container memory cap. Default: 512.
namestringyesDisplay name (human-readable)
slugstringyesURL slug, lowercase-alphanumeric-with-dashes. Becomes the repo name.

No output schema declared.

No examples provided.

appcrane_deny_access_request ~84

Deny a pending access request: marks the enhancement_request as done WITHOUT granting access. Optionally appends a reason to the original message so the requester (and the audit trail) sees why. App-admin / owner / global admin required.

NameTypeReqDescription
reasonstring–Optional. Appended to the request message.
request_idintegeryes–

No output schema declared.

No examples provided.

appcrane_deploy ~169

Trigger a deployment — this IS how you "update an env to the latest". For github and managed apps it pulls the latest commit from the app's configured branch on GitHub (server-side, using the app's stored credentials — you do NOT need your own github token or to push/upload anything), builds a fresh Docker image, and swaps in a new container. Use it whenever the user says things like "update sandbox to the latest", "deploy the newest version", "pull my latest github changes", or "redeploy". Returns a deployment ID; use appcrane_get_logs to monitor progress. Defaults to sandbox; production requires explicit confirmation from the user.

NameTypeReqDescription
slugstringyesApp slug to deploy
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_deploy_artifact ~325

Deploy a release from an uploaded BUNDLE instead of from git. For an app with no GitHub repo, and the fallback when the repo path is unavailable — an expired service-account PAT blocks every managed-repo write, and this route does not touch GitHub at all. Two steps: (1) upload the bundle with `curl -F file=@dist.zip -H "X-API-Key: <your dhk_mcp_ key>" https://<host>/api/files/staged` — your MCP key IS allowed on that endpoint; it returns { token, sha256, size_bytes }. (2) Call this tool with that token. Accepts .zip, .tar.gz, .tgz, up to the staged-file limit. The release is identified by a SHA-256 AppCrane computes over the bytes, recorded as commit_hash "sha256:<digest>"; the tool re-hashes the staged bytes and refuses if they no longer match what was staged. Returns that digest — compare it against the one you computed locally. Deploys to sandbox unless env=production.

NameTypeReqDescription
commit_messagestring–Optional release note, shown in the deploy history
commit_shastring–Optional git SHA from the machine that BUILT the bundle. Recorded as context only — it is not verified and does not become the release identity.
slugstringyesTarget app slug
stagestring–Target stage (legacy alias: env).
tokenstringyesToken returned by POST /api/files/staged

No output schema declared.

No examples provided.

appcrane_get_app ~241

Get detailed info for a single app: URLs, current versions per environment, recent deployments, and health state. Use this when the user asks "what's the status of <app>", "is <app> deployed", or after a deploy to confirm what landed. Returns 404-equivalent error if the slug doesn't exist or the caller has no access. config.auth_mode tells you whether the app gets identity at all: `authenticated` means routes go through forward_auth and arrive at the container with X-AppCrane-* headers; `headless` means forward_auth is skipped for the whole app and those headers NEVER arrive. Check it first when debugging "my app sees no identity headers", but note it is per-APP, not per-request: an `authenticated` app can still have auth_bypass_paths prefixes that skip forward_auth, and a custom domain is never gated either. The request itself is authoritative — the app can read X-AppCrane-Auth-Mode (authenticated / headless / bypass), which AppCrane stamps on every route it proxies.

NameTypeReqDescription
slugstringyesApp slug, e.g. "mysite"

No output schema declared.

No examples provided.

appcrane_get_app_ingress ~328

Read HOW an app is reachable. ingress_type is `http` (default — every request goes through Caddy: TLS, AppCrane SSO/forward_auth, X-AppCrane-* identity headers, security headers, access logs), `tcp` (the container port is published DIRECTLY on the host at public_port, with Caddy not in the path at all — for apps that do not speak HTTP, e.g. a forward/CONNECT proxy handing back a raw tunnel), or `dual` (v2.45.0 — BOTH at once: an ordinary HTTP control plane still served through Caddy on container port 3000 with every Caddy control intact, PLUS a raw data plane published at 0.0.0.0:<public_port> -> <data_plane_port>, a DIFFERENT port inside the same container, with none of them). For a dual app the two planes have different security properties and the answer to "is this app behind AppCrane auth" is different for each — read `exposure.control_plane` and `exposure.data_plane` rather than the enum. Read this before debugging "why does my app see no identity headers" or "what port do clients connect to". IMPORTANT — this is NOT auth_mode: auth_mode=`headless` still goes through Caddy and only skips forward_auth, so it keeps TLS, security headers and request logging; a published port under `tcp` or `dual` keeps NONE of that. Requires access to the app.

NameTypeReqDescription
slugstringyesApp slug.

No output schema declared.

No examples provided.

appcrane_get_backup_status ~158

Is off-site backup actually working? Reports the scheduled S3/R2 backup config together with a verdict — `configured`, `enabled`, `healthy`, when it last ran and what is missing — so "are we backed up" is one call rather than an inference from raw settings. The backup covers the SQLite database (apps, users, settings, encrypted env vars), .env, icons and appdata, uploaded nightly as one zip. NEVER returns the secret access key; `has_secret` reports only whether one is stored. Read the `summary` first: a config can be fully populated and still not be running (enabled=false), and it can be enabled and failing every night (see last_error). PLATFORM ADMIN ONLY.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

appcrane_get_deploy_log ~210

Read the deploy/build log for a specific deployment — the output that came out of clone / npm install / docker build / health-validate, BEFORE the container started running. This is what you want when a deploy fails fast (1-2 second failures are almost always pre-build errors that never reach the runtime container, so appcrane_get_logs has nothing to show). Pass a deployment_id from appcrane_deploy / appcrane_get_app.recent_deployments, OR omit it and pass slug+env to get the latest deployment's log.

NameTypeReqDescription
deployment_idinteger–Specific deployment id. Preferred — unambiguous.
slugstring–App slug. Required when deployment_id is not given.
stagestring–Required when deployment_id is not given. Target stage (legacy alias: env).
tailinteger–Return only the last N lines. Defaults to 500; full log can be many KB on a long build.

No output schema declared.

No examples provided.

appcrane_get_guide ~165

Fetch the latest AppCrane playbook on a given topic. Use this at the START of any non-trivial workflow so you operate on the current authoritative guidance, not on whatever you remember from a past session. Topics: "onboarding" = the full new-app onboarding playbook (paths a/b/c/d, health-endpoint contract, common pitfalls). "operations" = the comprehensive agent operations guide (deploy, env, logs, rollback, every appcrane_* tool). "email" = how a hosted app sends email through AppCrane (the /api/service/email endpoint, env vars, recipient rules). Topic defaults to "onboarding" if omitted. Returns markdown.

NameTypeReqDescription
topicstring–Which guide to fetch. Default: onboarding.

No output schema declared.

No examples provided.

appcrane_get_health ~139

Fetch the deployed app's health endpoint server-side, bypassing AppCrane's auth proxy. Use this to validate that a deploy actually landed the expected version, or to check if the app is responding. AppCrane hits the app's configured health endpoint (default /api/health) on the internal port directly — no Caddy, no SSO redirect — and returns the response status + body. Defaults to sandbox; pass stage="production" only when the user asks about prod.

NameTypeReqDescription
slugstringyesApp slug, e.g. "mysite"
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_get_logs ~164

Get recent runtime logs from a running app container (docker logs). Use this for runtime issues — once the container is up. Returns the most recent N lines (default 100, max 1000). Pass search to filter to lines containing a substring (case-insensitive). NOT the right tool for fast deploy failures (1-2 second exits, "no such container" errors): those happen during clone / npm install / docker build / health-validate, BEFORE any container exists. Use appcrane_get_deploy_log for that.

NameTypeReqDescription
linesnumber––
searchstring–Filter to lines containing this substring (case-insensitive)
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_get_secret ~196

List an app's secrets (encrypted env vars) with their values MASKED — safe to show in chat. For each key you get: is_set, length, a short preview (last 3 chars, rest masked; fully masked for short values), a sha256 `fingerprint` (compare two envs or detect a changed value without seeing it), and updated_at. This is what you want for "is X set?", "did the key change?", "which vars exist?". Does NOT return plaintext — a secret never lands in the transcript. To read one actual value, use appcrane_reveal_secret with a specific key. Defaults to sandbox; pass env="production" only when the user explicitly says production. App-admin or AppCrane admin only.

NameTypeReqDescription
slugstringyesApp slug, e.g. "mysite"
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_grant_app_access ~115

Grant a user access to an app at a specific per-app role. `user` accepts a numeric user id, an email, or a username — first match wins. role defaults to "user". Idempotent: existing rows are upgraded/downgraded to the new role. App-admin or owner of the app required (or global admin).

NameTypeReqDescription
rolestring––
slugstringyes–
userstringyesUser id (numeric string), email, or username

No output schema declared.

No examples provided.

appcrane_list_access_requests ~84

List pending access requests — enhancement_requests rows whose message starts with "Access request for app …" (the portal's Request-access button posts these). With slug, scopes to one app; without, returns access requests across every app the caller can administer. App-admin / owner / global admin required.

NameTypeReqDescription
slugstring–Optional. Limit to one app.

No output schema declared.

No examples provided.

appcrane_list_app_members ~85

List every user who has access to an app, with their per-app role (owner / admin / user / viewer / none). Use this before granting or revoking to see who is already in. Returns email + name + role for each member. App-admin or owner of the app required (or global admin / platform_admin).

NameTypeReqDescription
slugstringyes–

No output schema declared.

No examples provided.

appcrane_list_app_roles ~194

List the roles an app defines FOR ITSELF (approver, auditor, reviewer — whatever that app invented). Any member sees the roles and how many hold each; an owner or admin also gets `members`, the roster of who holds what. These are NOT AppCrane permissions: they grant nothing on the platform and are only handed to the app, in the X-AppCrane-App-Roles request header and in /api/me's app_roles array, for the app's own code to enforce. For AppCrane's own per-app tier — owner/admin/user/viewer, i.e. who may deploy, read env vars, or delete the app — use appcrane_list_app_members instead. Call this before creating a role (to avoid duplicating one) or before setting a user's roles (to see the valid keys). Requires being assigned to the app.

NameTypeReqDescription
slugstringyes–

No output schema declared.

No examples provided.

appcrane_list_apps ~91

List all AppCrane apps the current user has access to. Each app includes slug, name, description, urls (production + sandbox), and the version currently live in each environment. Call this first when the user asks about "my apps", "what apps exist", or before doing anything app-specific. Non-admin users see only their assigned apps; admins (admin or platform_admin) see everything.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

appcrane_list_cron ~120

List the scheduled jobs declared in an app's deployhub.json `cron` array (after the most recent deploy). Each entry includes the cron schedule, the command, when it last ran, the exit code, and the tail of the last run's stdout/stderr. Use to verify a job was registered, debug a missing run, or read the recent log. App-admin or owner.

NameTypeReqDescription
slugstringyes–
stagestring–Optional — omit to list both envs. Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_list_releases ~111

List the deploy/release history for an app + env, newest first — each release is id, version, commit, status (live / rolled_back / failed / pending), who deployed it, and when. Use this to see what is live and to pick a target for appcrane_rollback. App access required.

NameTypeReqDescription
limitinteger–Max rows (default 10).
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_list_requests ~161

List enhancement requests filed against an app via the AppCrane intake form. Use this when the user asks "what should I work on?", "what's queued for X?", or wants to pick up tickets. Returns id, message, app_slug, submitter, and bucket. Buckets: triage (unclaimed), in_progress (someone is working on it), shipped (merged + deployed), validated (requester confirmed). Filter by bucket="triage" to find work to pick up.

NameTypeReqDescription
bucketstring–Filter to one bucket. Most useful: "triage" for unclaimed work.
limitnumber––
slugstring–Filter by app slug. Omit to see across all accessible apps.

No output schema declared.

No examples provided.

appcrane_ls ~102

List files inside a running app container at a specific path. Use to verify what actually got built / what files made it into the deployed image. Read-only; bound to safe roots (/app and /data only). Returns the directory listing as text.

NameTypeReqDescription
pathstring–Absolute path inside the container, must start with /app or /data
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_managed_assemble ~266

Finish a chunked upload started with appcrane_managed_push_chunk: concatenate all parts of a `session` in order, verify the whole, and commit the assembled file to the managed app's AMC_<slug> repo as a single commit. Fails if any part is missing. If you pass `sha256` (hex SHA-256 of the ENTIRE original file's bytes), the server verifies the reassembled bytes against it and refuses to commit on mismatch — always pass it for large or binary files. On success the staged parts are deleted. Returns the commit sha plus the committed file's sha256 and byte length.

NameTypeReqDescription
branchstring–Target branch. Defaults to the app's branch / repo default.
messagestring–Commit message. Defaults to "chore: update <path>".
pathstringyesThe destination path; must match what the parts were staged with.
sessionstringyesThe upload id you used for appcrane_managed_push_chunk.
sha256string–Optional hex SHA-256 of the whole original file. If given, the reassembled bytes are verified against it before committing.
slugstringyesManaged app slug (repo AMC_<slug>).

No output schema declared.

No examples provided.

appcrane_managed_patch ~336

Edit an existing text file in a managed app's AMC_<slug> repo by applying a unified diff, entirely over MCP — you emit only the changed hunks, not the whole file. Ideal for small edits to a large file (avoids re-emitting the whole thing, which is where inline truncation comes from). The server fetches the current file, applies your `unified_diff`, and commits the result as a single commit. The diff must be a standard unified diff (as from `git diff` / `diff -u`): `@@ -old,len +new,len @@` hunk headers, lines prefixed with " " (context), "-" (remove), "+" (add). Include a few context lines around each change. Hunks are matched by CONTENT (not just line numbers), so small line drift is tolerated — but if a hunk's context does not match the current file, the whole patch is rejected and nothing is committed (re-read the file and regenerate the diff). Only single-file diffs are supported; the target is `path`, not the diff's ---/+++ headers.

NameTypeReqDescription
branchstring–Target branch. Defaults to the app's branch / repo default.
messagestring–Commit message. Defaults to "chore: patch <path>".
pathstringyesRepo-relative path of the file to patch (no leading slash, no "..").
slugstringyesManaged app slug (repo AMC_<slug>).
unified_diffstringyesA standard unified diff to apply to the current contents of `path`.

No output schema declared.

No examples provided.

appcrane_managed_push_chunk ~446

Stage ONE part of a large file for a managed app, entirely over MCP (no HTTP upload). Use this + appcrane_managed_assemble when a file is too large to emit reliably inline via appcrane_push_to_managed_app (roughly >64 KB of code). Workflow: pick an opaque `session` id (any unique string, e.g. "app.tsx-1"), split the file into N parts, and call this once per part with part=1..N and of=N. The parts are held server-side keyed by (session, part); appcrane_managed_assemble then concatenates them in order, verifies the whole, and commits. Split on any boundary you like (byte or line) — assemble concatenates the decoded bytes verbatim, so the split points do not need to be newlines. Keep each part small (≤ ~48 KB of content) so inline emission stays reliable. encoding defaults to "utf-8"; use "base64" for binary. If you provide `sha256` (hex SHA-256 of THIS part's decoded bytes), the server verifies it on arrival and rejects a corrupted part immediately. Re-sending the same (session, part) overwrites it, so a failed part is safe to retry.

NameTypeReqDescription
contentstringyesThis part's bytes, encoded per `encoding`.
encodingstring–Defaults to utf-8. Use base64 for binary files.
ofintegeryesTotal number of parts. Must be identical across every part of a session.
partintegeryes1-based part number.
pathstringyesRepo-relative destination path (no leading slash, no ".."). Must be identical across every part of a session.
sessionstringyesOpaque upload id grouping the parts. Any unique string; reuse the same value for every part of one file.
sha256string–Optional hex SHA-256 of this part's decoded bytes. If given, the server verifies it and rejects a mismatch.
slugstringyesManaged app slug (repo AMC_<slug>).

No output schema declared.

No examples provided.

appcrane_memory_budget ~243

Does the sum of every app's CONFIGURED memory ceiling fit in this host's RAM? Adds up the per-container `--memory` limits AppCrane has on file and compares the total against total host memory. THESE ARE CONFIGURED CEILINGS, NOT MEASURED USAGE: a report of "25 GB committed on a 7.6 GB host" does NOT mean the host is using 25 GB, and must never be relayed as one — it means the limits promise more than the host can deliver if the containers ever ask for it at once. Nothing here reads a running container; for what is actually in force on the containers use appcrane_check_resource_limits, and for live consumption read the host. Over-commitment is normal and is not by itself a fault (containers idle far below their ceilings) — it matters because it means there is no headroom guarantee, so a correlated event such as a post-reboot cold start, when every container loads at once, is resolved by the kernel's global OOM killer. Counts both stages of every app, which is exactly what a cold start brings up. ADMIN ONLY.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

appcrane_platform_policy ~266

Read or set the two platform-wide policy levers, and list the apps currently in violation. `ban_public_apps` refuses visibility=public on every write path; `mandate_security_scans` reports every app without a completed scan in the last 48h. Both default OFF, so an upgrade enforces nothing until an admin turns one on. Call with no arguments to read the current policy plus violations; pass either boolean to change it. POLICY IS NOT RETROACTIVE: turning a lever on refuses the NEXT write and REPORTS what is already in violation — it does not reach into the database and change existing apps, and the violations it lists keep working exactly as they did. That is deliberate: silently making live public apps private would break their URLs with no warning to their owners and no record of what changed, so the list exists for an admin to work through deliberately. Never describe enabling a lever as having fixed the apps it reports; nothing about them has changed. PLATFORM ADMIN ONLY.

NameTypeReqDescription
ban_public_appsboolean–Refuse visibility=public everywhere. Existing public apps keep serving and are reported as violations.
mandate_security_scansboolean–Report every app with no completed dependency scan in the last 48h (two missed daily runs).

No output schema declared.

No examples provided.

appcrane_promote ~102

Promote the current live SANDBOX release to production — the gated sandbox→prod path. Refuses unless sandbox is live AND currently healthy (you do not ship a broken sandbox to prod), and the promoted prod release is health-checked with auto-revert. For github apps this rebuilds production from the EXACT sandbox commit; for managed/upload apps it copies the exact tested sandbox release. Owner-only (or global admin).

NameTypeReqDescription
slugstringyes–

No output schema declared.

No examples provided.

appcrane_push_staged_file ~249

Move a previously-staged file into a running container at a path under /app or /data. THE WAY TO GET LARGE BINARIES (DMGs, datasets, bundles) into a container when they're too big to inline through appcrane_cp. Two steps: (1) upload the bytes with a plain multipart POST to `curl -F file=@local.dmg -H "X-API-Key: <your dhk_mcp_ key>" https://<host>/api/files/staged` — your MCP key IS allowed on this endpoint (v2.10.6+); it returns { token, sha256, size_bytes }. (2) Call this tool with that token and a dest path. The container must be running. Path is validated (no "..", must start with /app or /data). The staged blob is deleted on success.

NameTypeReqDescription
deststringyesAbsolute container path under /app or /data — destination file or directory
slugstringyesTarget app slug
stagestring–Target stage (legacy alias: env).
tokenstringyesToken returned by POST /api/files/staged

No output schema declared.

No examples provided.

appcrane_push_to_managed_app ~432

Push a batch of files to a managed app's AMC_<slug> repo, authenticated server-side via AppCrane's service-account credential. Use this — NOT github_push_files — for managed apps, because github_* tools authenticate with the caller's personal PAT, which has zero access to the service account's repos. Multiple files become a single commit. files: [{ path, content, encoding? }] where encoding defaults to "utf-8" (use "base64" for binaries like icons). Requires the app to already exist via appcrane_create_managed_app. v2.7.22: response now includes per-file `sha256` (hex) and decoded `bytes` length so you can verify integrity — compute the SHA-256 of the bytes you sent, compare to the server's echo, and fail loudly if they differ. Essential for binary files where inline-string truncation or trailing-byte issues would otherwise produce a silently-broken commit. v2.10.7: for a large CODE file, do NOT inline it — upload the bytes over HTTP and commit by token. (1) `curl -F file=@big.js -H "X-API-Key: <your dhk_mcp_ key>" https://<host>/api/files/staged` returns { token, sha256, size_bytes }. (2) Pass that file as { path, staged_token } instead of { path, content }. The server reads the staged bytes and commits them verbatim, so 100+ KB sources push reliably without the model having to emit the content (which is where inline truncation comes from). Per file, provide exactly one of content or staged_token. Staged tokens are owner-scoped and expiring.

NameTypeReqDescription
branchstring–Target branch. Defaults to the repo's default branch (usually "main").
filesarrayyes–
messagestring–Commit message. Defaults to "chore: scaffolding for <slug>".
slugstringyesManaged app slug. Repo name resolved as AMC_<slug>.

No output schema declared.

No examples provided.

appcrane_rename_app ~229

Rename an app's slug. The slug is its URL, its container name and its data directory, so this changes all three — but it is NOT destructive: deploy history, env vars, ports, per-app roles and grants are keyed on the app id, not the slug, and survive untouched. The old slug is kept as a redirect unless redirect=false. Platform admin. Use this instead of recreating an app under a new name, which is what loses the history. To free a slug held by an app you no longer want, rename THAT app out of the way with redirect=false rather than deleting it — deleting clears the database rows but leaves data/apps/<slug> on disk, and the rename then refuses because the directory is still there.

NameTypeReqDescription
new_slugstringyesNew slug: lowercase letters, digits and dashes, starting with a letter or digit.
redirectboolean–Keep the old slug redirecting to the new one. Pass false when you are freeing the old slug for another app to take.
slugstringyesCurrent app slug.

No output schema declared.

No examples provided.

appcrane_reveal_secret ~197

Reveal the PLAINTEXT of ONE secret by key. Use ONLY when the user explicitly needs the actual value — it will appear in this conversation transcript, so treat the transcript as sensitive afterward (and consider rotating the secret if the transcript may be stored/shared). For checking whether a var is set, comparing values, or seeing what exists, use appcrane_get_secret (masked) instead — do NOT reveal just to inspect config. Single key only — it never dumps the whole env. Every reveal is audit-logged. Defaults to sandbox; env="production" only when the user explicitly asks. App-admin or AppCrane admin only.

NameTypeReqDescription
keystringyesExact env var name to reveal (e.g. "RESEND_API_KEY"). One key per call.
slugstringyesApp slug, e.g. "mysite"
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_revoke_app_access ~79

Remove a user's access from an app entirely. Idempotent: returns ok even if the user had no access. App-admin or owner of the app required (or global admin). Refuses to remove the only remaining owner.

NameTypeReqDescription
slugstringyes–
userstringyesUser id, email, or username

No output schema declared.

No examples provided.

appcrane_rollback ~146

Roll an env back to a prior release. Pass deployment_id (from appcrane_list_releases) to target a specific release, or omit it to roll back to the immediately previous one. Re-runs that release from its recorded build (re-uses the cached per-commit image — no rebuild when it is still retained) and health-checks it. Records a NEW deployment and marks the previous live one rolled_back. Owner-only (or global admin).

NameTypeReqDescription
deployment_idinteger–Target release id. Omit to roll back to the previous release.
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_run_backup_now ~117

Run the off-site backup immediately and report what was uploaded. Use this to PROVE a new configuration works instead of waiting for the nightly run to fail quietly — it exercises the real credentials, the real bucket and the real upload path, and records the result in last_run / last_error exactly as the scheduled job does. Works whether or not the schedule is enabled, so a configuration can be verified before turning it on. Uploads a zip of the SQLite database, .env, icons and appdata. PLATFORM ADMIN ONLY.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

appcrane_run_cron_now ~159

Trigger a scheduled cron job RIGHT NOW, regardless of its schedule. Useful for "I want to test my daily rebuild without waiting until midnight" or "rerun yesterday's failed job." Runs the same `docker exec` the tick loop would, against the app's container; updates last_run_at / last_exit_code / last_log just like a scheduled run. Returns the exit code and last-log tail. App-admin or owner. Idempotent: if the job is already running (mutex held), reports it and skips rather than overlapping.

NameTypeReqDescription
namestringyesJob name from deployhub.json `cron[].name`.
slugstringyes–
stagestring–Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_scan_app ~275

Scan one app's dependencies against OSV right now and record the result, instead of waiting for its next deploy or the nightly run. Use it after fixing a lockfile to confirm a finding is gone, or on an app whose last result was `skipped` or `error` to find out what it actually contains. REPORT ONLY — it records a row and feeds the daily digest; it never blocks, fails or rolls back anything, and running it cannot disturb the app. It does not throw on a failed scan either: an unreachable OSV or a missing lockfile comes back as `ok: false` with status `error` or `skipped`, meaning the app was NOT scanned and is NOT known to be clean. `ok: true` with status `findings` is the opposite case — the scan worked and found something. Reads the LIVE release through the same `current` symlink the running container was built from. Defaults to the PRODUCTION stage: most AppCrane tools default to sandbox, but the code an advisory applies to is the code that is serving. ADMIN ONLY.

NameTypeReqDescription
slugstringyesApp to scan.
stagestring–Stage to scan. Defaults to production — that is the deployed code an advisory applies to. Target stage (legacy alias: env).

No output schema declared.

No examples provided.

appcrane_scan_report ~489

Which hosted apps have known-vulnerable dependencies? Reports the recorded CVE scan state for the whole fleet, or for one app with `slug`. REPORT ONLY: this scan has never blocked a deploy and cannot — the apps belong to other teams who did not choose the control, so findings are recorded and mailed and the deploy proceeds either way. Never relay a finding as a deploy failure. READ `status` BEFORE READING COUNTS. It is four-valued: `ok` (scanned, nothing found) and `findings` (scanned, something found) are results; `skipped` (no lockfile AppCrane can read) and `error` (OSV unreachable, unparseable lockfile) mean the app was NOT SCANNED, as does having no scan row at all. Those two carry no findings for the same reason an unopened box is empty, and an agent that reports such an app as clean has stated the opposite of what is known — "no vulnerabilities found" is only ever true of an app whose status is `ok`. `assurance` (none / partial / complete), `unscanned_count` and `unscanned_by_status` say how much of the fleet the numbers actually cover; read them before the findings. EVERY FINDING CARRIES `ecosystem` AND `fixed` beside `name`, `version` and `ids`. `fixed` is the version that resolves those advisories, or null when OSV PUBLISHED NO FIXED VERSION — a null means there is nothing to upgrade to yet, NEVER that no fix is needed and never that AppCrane did not look, so a null-`fixed` finding is not a harmless one. `manifests_scanned` says WHICH manifests were actually read, because coverage is per manifest and not per app: one scan row reads ONE manifest — the ecosystem named on it — so an app whose Go service was never read appears here beside its scanned npm frontend with an empty findings list, and that emptiness is evidence about the frontend only. Scans run at deploy AND daily, and the daily run is the one that matters, because it catches an advisory published against code that was already deployed and has not changed since. ADMIN ONLY.

NameTypeReqDescription
slugstring–Report one app (both stages) instead of the whole fleet.

No output schema declared.

No examples provided.

appcrane_set_app_icon ~196

Set the tile icon for an app (shown on the Dashboard, the Launcher cards, the Manage table, and the frame topbar). Accepts a base64-encoded image in PNG / SVG / WEBP / JPEG / GIF. For repo-tracked icons prefer committing public/icon.png to the repo — AppCrane picks it up automatically on each deploy. Use this MCP tool when the icon needs to change without a redeploy, or when the source isn't in the repo. Replaces any existing icon. App-admin or owner required (or global admin).

NameTypeReqDescription
base64stringyesBase64-encoded image payload. May or may not include the data URL prefix (data:image/png;base64,…) — both work. Max 500 KB decoded.
formatstringyesImage format. Determines the on-disk file extension (icon.<format>).
slugstringyesApp slug.

No output schema declared.

No examples provided.

appcrane_set_app_ingress ~1,266

Switch an app between HTTP ingress, raw TCP ingress and dual (both), and choose its public host port. PLATFORM ADMIN ONLY — this is not an owner self-service field like auth_mode. ingress_type=`tcp` publishes 0.0.0.0:<public_port> -> the container in ADDITION to the loopback publish every app has, so clients connect straight to the host and Caddy never sees the traffic: no forward_auth/SSO, no identity headers, no per-request audit, no rate limiting, no security headers, no TLS from AppCrane. Every control AppCrane has assumes Caddy is the only door; this adds a second one the platform does not control, and the app then owns authentication completely. Do NOT reach for this to make an app reachable without login — that is auth_mode=`headless`, which still goes through Caddy and keeps TLS, security headers and logging. Use `tcp` ONLY when the app does not speak HTTP at all (a forward/CONNECT proxy tunnels raw bytes; no reverse proxy can express that). ingress_type=`dual` (v2.45.0) is for an app that is BOTH: its HTTP control plane keeps being served through Caddy on container port 3000 with every control intact (and stays the plane its health check probes), while a SECOND listener inside the same container — data_plane_port, which is REQUIRED and must not be 3000 — is published raw at 0.0.0.0:<public_port> with none of them. Setting data_plane_port to 3000 is refused: that would republish the ordinary HTTP origin Caddy fronts, unauthenticated and unaudited, which is the exact surface Caddy is in the path to protect. Omit public_port to keep the existing allocation, or to have the lowest free port in 31000-31999 allocated — a dedicated band so the operator firewalls one predictable block; an explicitly NAMED port may be anything in 1024-65535, because clients are configured with a port by hand or by MDM and a number like 8080 is often not the platform's to choose. Naming a port outside the auto band is legal and safe — the guards that matter (the WHATWG blocked list,…

NameTypeReqDescription
data_plane_portinteger|null–CONTAINER port the raw publish targets, 1024-65535. REQUIRED with ingress_type='dual'. On any other type the only accepted value is null, which DROPS a data plane the app still has pinned — required…
ingress_typestringyeshttp = through Caddy (default). tcp = the container port is published on the host, with no AppCrane authentication in front of it. dual = both — the HTTP control plane stays behind Caddy on container…
public_portinteger–HOST port to publish. Only valid with ingress_type='tcp' or 'dual'. Omit to keep the port the app already holds, or to have one allocated from 31000-31999; name one explicitly and it may be anything…
sandbox_public_portinteger|null–HOST port to publish for the SANDBOX container, so a raw data plane can be exercised before it goes live. Opt-in and independent of public_port — omit it and sandbox publishes nothing, exactly as bef…
slugstringyesApp slug.

No output schema declared.

No examples provided.

appcrane_set_app_meta ~646

Set an app's category, visibility, auth_mode, and/or auth_bypass_paths — the owner self-service fields (same controls the dashboard Launcher exposes to owners). Owner of the app (or global admin) required. visibility is one of public / private / hidden. auth_mode is `authenticated` (default — all routes go through AppCrane SSO) or `headless` (the app bypasses forward_auth ENTIRELY and is reachable without identity — right tool for telemetry ingest, public webhooks, status pages; the app's own server is responsible for any payload-level authn). A headless app is still served BY CADDY over HTTP — TLS, security headers and access logging all still apply; it is not a raw port. An app that does not speak HTTP at all needs ingress_type='tcp', and an app that speaks HTTP AND needs a second raw port for non-HTTP clients needs ingress_type='dual' (both via appcrane_set_app_ingress, platform admin only) — different and far more exposed things. auth_bypass_paths (v2.7.27+) is an array of path prefixes (e.g. ["/ws/local-runner"]) that bypass SSO on this app only — narrower than headless mode; the app authenticates those paths itself (e.g. token in query string). The platform strips incoming X-AppCrane-* headers on bypass paths (forgery defense intact) and suppresses access logging for them (token-in-query never sits in log storage). Owners may only assign an EXISTING category; creating a brand-new category is reserved for global admins. For powerful fields (github_url, branch, token, source_type, resource limits) use appcrane_update_app (admin only).

NameTypeReqDescription
auth_bypass_pathsarray–v2.7.27: array of path prefixes (e.g. ["/ws/local-runner"]) that bypass SSO forward_auth on this app. Requests under these prefixes reach the container with NO X-AppCrane-* identity headers — the app…
auth_modestring–authenticated = AppCrane SSO + per-app role checks; headless = NO auth at the proxy (the entire app is reachable by anyone on the internet).
categorystring–Category/tag. Owners must pick one already in use; pass empty string to clear.
domainstring–v2.10.0: custom domain (e.g. "raise.glick.run") that serves this app at the ROOT of that domain with NO AppCrane SSO and NO topbar — the app does its own auth. Maps to production. Requires the domain…
slugstringyesApp slug.
visibilitystring–public = anyone; private = assigned users; hidden = not discoverable.

No output schema declared.

No examples provided.

appcrane_set_backup_config ~401

Configure the scheduled off-site (S3 / S3-compatible, e.g. Cloudflare R2) backup. Every field is optional — only what you pass is changed. Enabling is REFUSED unless bucket, access_key_id and a stored secret are all present, because an enabled-but-unconfigured backup fails silently every night while every status surface reads "enabled", which is worse than being plainly off. SECURITY: `secret_access_key` is write-only — AppCrane encrypts it and never returns it — but passing it here means the plaintext value travels through this conversation and whatever logs it. Prefer Settings → Backup in the dashboard for the secret itself, and use this tool for the rest. PLATFORM ADMIN ONLY: this names the destination a copy of every secret on the platform is written to, so pointing it at the wrong bucket is an exfiltration path, not a misconfiguration.

NameTypeReqDescription
access_key_idstring–Access key id. Not a secret on its own; stored in the clear.
bucketstring–Destination bucket name.
enabledboolean–Turn the nightly schedule on or off. Refused with enabled=true unless bucket, access_key_id and a stored secret all exist.
endpointstring–Custom S3 endpoint for a non-AWS provider (Cloudflare R2, MinIO). Leave empty for AWS.
hourinteger–Hour of day (server local time) to run. Default 3.
prefixstring–Key prefix inside the bucket, e.g. "appcrane/". Optional.
regionstring–Region, e.g. us-east-1. Defaults to us-east-1.
secret_access_keystring–Secret access key. Write-only: encrypted at rest, never returned by any read surface. NOTE: passing it here puts the plaintext in this conversation — the dashboard is the better place for it.

No output schema declared.

No examples provided.

appcrane_set_request_status ~106

Move a request through the lifecycle: triage → in_progress → shipped → validated. Use this when the user says "I'll take #42" (set to in_progress), after merging a PR (set to shipped), or after confirming a fix works (set to validated). Validated requests are considered closed. Requires app-admin or AppCrane admin role.

NameTypeReqDescription
bucketstringyesTarget bucket.
idnumberyesRequest id (the # column).

No output schema declared.

No examples provided.

appcrane_set_secret ~137

Set or update a secret (an encrypted environment variable injected into the app). Encrypted at rest; only the running app process can read the plaintext. Defaults to sandbox; require explicit stage="production" only when the user asks. App-admin or AppCrane admin only. Respects the caller's mcp_app_scope.

NameTypeReqDescription
keystringyesEnv var name. Letters, digits, underscores; must not start with a digit.
slugstringyes–
stagestring–Target stage (legacy alias: env).
valuestringyesThe value to store (will be encrypted server-side).

No output schema declared.

No examples provided.

appcrane_set_user_app_roles ~230

Set which app-defined roles a user holds on one app. Replaces their whole set: keys omitted from the list are removed, and keys: [] clears every role they hold. This changes only what the app itself enforces — it does NOT change the user's AppCrane per-app tier, so it can neither grant nor remove deploy / env / delete power. Use appcrane_grant_app_access for that. Every key must already be defined on this app (appcrane_create_app_role) and the user must already have access to the app (appcrane_grant_app_access) — a role on a non-member is unenforceable, since the app never sees them. The result is what the app receives in X-AppCrane-App-Roles on the user's next request. Owner or admin of the app required.

NameTypeReqDescription
keysarrayyesThe COMPLETE set of app-defined role keys this user should hold. [] removes all of them.
slugstringyes–
userstringyesUser id (numeric string), email, or username

No output schema declared.

No examples provided.

Common questions

What is the AppCrane MCP server?

AppCrane is an MCP server listed in the public MCP registry as io.github.gitayg/appcrane. Deploy and manage apps on your own AppCrane instance, the self-hosted PaaS for AI-built apps. This page covers its npm package (appcrane-mcp).

Is the AppCrane MCP server safe to use?

AppCrane scores 75 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 25 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the AppCrane MCP server expose?

AppCrane exposes 57 tools: appcrane_list_apps, appcrane_get_app, appcrane_top_apps, appcrane_top_users, appcrane_get_health, and 52 more. Their descriptions and schemas cost roughly 13,973 tokens of context every time the server is loaded.

Is the AppCrane MCP server still maintained?

AppCrane is still listed as active in the MCP registry. We last reached this channel on 25 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the AppCrane MCP server under?

AppCrane declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.