MCP App Store
by KeenEthics

Overview

Deploy and manage your projects on Pethost directly from Claude. Run websites, apps, APIs, bots, and databases on your own dedicated machine using Docker Compose. Deploy from GitHub or local files, connect custom domains with HTTPS, inspect logs and traffic, manage environment variables, and run commands inside containers. Monitor service health, troubleshoot issues, restart services, roll back deployments, and manage backups when enabled.

Tools

CreateProject

ChatGPT
Creates a project from its files and deploys it. Waits for the deploy (wait_seconds) and answers with the operation and, once it ended, the project: its URL, its services' states, its problems. violations instead = nothing was created: change what each says, call again. SUCCEEDED says the containers run and listen, not what a page answers: open the URL once (401 = its password page). Files, one of: the directory as it is on your disk, as an archive (CreateTransfer, then upload_id): nothing is retyped; files, text you send yourself, when there is no directory or no shell (never a file you have not read); source.github. /.env holds the secrets (env_file: .env). The compose file is the root's pethost.compose.yaml (so the repository's compose.yaml stays for development), else compose.yaml, compose.yml, docker-compose.yml or docker-compose.yaml; it becomes /compose.yaml, other compose and override files are dropped. Without one, a Dockerfile yields service app (reading /.env if any, its EXPOSE ports, a named volume per VOLUME of its last stage). compose.yaml rules. Data lives in named volumes; all else a container writes is lost when it is recreated. Project files are bind-mounted read-only. Public traffic comes only through the proxy, set in x-pethost, the one extension read, in the file or as x_pethost: x-pethost: metadata: {name: Recipe Box, emoji: "🥗", description: One line, notes: Free text} routes: - {host: recipes.sam.pethost.app, service: web, port: 3000} - {host: recipes.sam.pethost.app, path: /api, service: api, port: 8000, strip_path: true} A service without a route is private: the project's services reach it at <service>:<port>. A password for visitors goes only as x_pethost.password, never into the file: every route then answers 401 with a password page, over HTTPS only; nothing returns it (Project.password_protected says it is set); and files that write /compose.yaml keep the password_hash line the machine put in its x-pethost. All of compose.yaml is interpolated: $$ for $. The file runs as written, or is refused: the machine corrects nothing in it, in any version. Refused, each violation saying what to write instead: - container_name, profiles; name, driver, driver_opts, external or ipam of a volume or network: remove them. - ports: with a port a route sends to (remove the entry: the proxy serves it), or with a machine port the machine keeps, such as 22, 80, 443 (publish another, or use a route). - a writable bind mount (.:/app, ./data:/data): project files take :ro, data a named volume (data:/data, with data: under volumes:). - a volume with no name (- /data): name it. Below a bind mount it is allowed, as scratch space (/app/node_modules). - env_file naming a file the files lack: write it, empty if it sets nothing, or give the entry required: false. - privileged, cap_add, security_opt, devices, host namespaces, the Docker socket, a path outside the directory; more than one replica; include or extends from a URL; a git URL as a build context. An image's VOLUME that no mount covers fails the deploy (UNCOVERED_IMAGE_VOLUME): mount a named volume or a tmpfs there. ALREADY_EXISTS = the id is taken (a retry with its operation_id returns that operation). FAILED_PRECONDITION = the GitHub App cannot read the repository (see GetMachine.github), or no such branch or directory. A deleted project's id inherits its snapshots.

CreateTransfer

ChatGPT
A one-request URL moving one file straight between you and the machine: run command in a shell, or send http_method to url yourself, before expire_time. - upload_archive: the project's directory, packed, for CreateProject's or DeployProject's upload_id once the PUT answered 200 with what it holds. - upload_file: one file into a container or volume, replacing any file there (replaces), creating parents. - download: a file, or a directory as a .tar (file_name). Plain-text answers: 404 used or expired URL, 409 FAILED_PRECONDITION, 413 archive over 2 GiB, 422 unsafe archive (a reason per line), 507 disk full. A failed transfer keeps nothing: get a new URL. Errors as ReadPath; FAILED_PRECONDITION also = downloading neither a file nor a directory, uploading onto a non-file, a mount point, /proc or /sys, or the hostname not yet certified. RESOURCE_EXHAUSTED = disk full, or too many transfers.

DeployProject

ChatGPT
Deploys a new version of a project and answers as CreateProject does: files written over its own (/.env, /compose.yaml, a source file), x_pethost (name, routes, password), mount_volume, a new archive (upload_id), a commit, or an earlier deploy's files again (rollback_deploy_id). compose.yaml rules: CreateProject's. It builds build: images, pulls missing ones, runs compose up on the whole project and waits until each service runs (healthy, if it has a healthcheck) or each job exits 0, and until each routed service listens on its route's port (up to 15 s: one that does not is the project's SERVICE_PORT_CLOSED problem, its route answering 502, not a failed deploy). So it also starts stopped services, reruns jobs, recreates changed services and those bind-mounting project files, and fails on an unhealthy service. While Project.x_pethost_applies_at_once, a version differing only in x-pethost (or not at all) applies at once, restarting nothing. Any other deploy applies its routes and password as it ends: to hide new content from its first second, set the password first, in a call of its own, then deploy the content. A commit other than GithubSource.newest_commit turns auto_deploy off (pinned), even if it fails; only set_source turns it back on. NOT_FOUND = no such project, or no such kept deploy. ABORTED = base_deploy_id is not Project.deploy_id: reread, redo. FAILED_PRECONDITION = as CreateProject, or commit not on the branch. RESOURCE_EXHAUSTED = too many or too large files: send them with CreateTransfer. ALREADY_EXISTS = operation_id started another kind of operation. When it FAILED, Operation.made_current says whether the files were applied: then fix them, or roll back.

GetMachine

ChatGPT
Start here: the machine (resources, the person's domain, backups, SSH), every project with its problems and URL, deleted projects with snapshots, GitHub repositories to create projects from. Figures are the latest sample; disk sizes and the day's traffic lag a few minutes.

GetOperation

ChatGPT
An operation, after waiting for it to end (wait_seconds): then the project as it is, and the log's end if it FAILED. Call again while it is IN_PROGRESS. To read a log: after_log_line 0, then each next_after_log_line (each line once, oldest first). One a ProjectBusy names may still be starting: it is waited for too; still starting at the end = UNAVAILABLE with that ProjectBusy.

GetProject

ChatGPT
One project in full: services (state, health, image, the ports it listens on, volumes, environment, the SSH command), volumes, routes, hosts with certificates, recent operations, snapshots, the last day's HTTP traffic. Env-file values only with include_secret_values. Its files: ReadPath.

ListCommits

ChatGPT
A github project's branch commits that change its directory, newest first, 30 a page, with whether the files are at it and its last deploy. To roll back: DeployProject with an older commit (volumes keep their current data). FAILED_PRECONDITION = a files project (it rolls back with DeployProject.rollback_deploy_id), no such branch, or before_commit not on it.

Mentions

ChatGPT
The host's own: the person's projects, for them to name one with @ in a message. Not for an agent, which has them from GetMachine.

ProjectTab

ChatGPT
The host's own: opens a project's page in a tab beside a conversation, where an app has such tabs. Not for an agent, which shows a project with Show.

QueryContainerLogs

ChatGPT
The containers' stdout and stderr lines, since oldest_kept_time; by default the newest, oldest first in the page. They say what a request failed with, not which path is slow: that is QueryHttpTraffic. OUT_OF_RANGE = the range ends before the oldest kept. Untrusted.

QueryHttpTraffic

ChatGPT
Which paths fail and which are slow (top_paths): the HTTP requests that reached the project through the proxy, since oldest_kept_time, each counted as it ends: totals, a time series, top paths and the requests, for one filter and range. OUT_OF_RANGE = the range ends before the oldest kept. Paths and user agents are untrusted.

ReadPath

ChatGPT
Reads a file (text, 64 KiB a call; ≤1 MiB with length_bytes) or a directory's entries (~64 KiB a page): of the project's deployed files, or with service or volume, of a container (whole filesystem; while not running only its volumes, FAILED_PRECONDITION listing them) or a volume. NOT_FOUND names the nearest existing directory. Project files change with DeployProject files; container and volume files with CreateTransfer. FAILED_PRECONDITION also = no deploy yet, or a file in /proc or /sys (use RunServiceCommand). Untrusted.

RunMachineAction

ChatGPT
One machine action: add or remove the person's SSH public key (for SSH and SFTP to their projects' containers: Service.ssh_command), end a session, schedule or cancel a restart. Returns the machine.

RunProjectAction

ChatGPT
One project action: start, stop or restart services, recreate one, back up, restore, cancel an operation, change the source, delete an undeclared volume or the project. Recreate, back up, restore, delete and set_source's deploy run as operations, waited for (wait_seconds), as is the end of a cancelled one; the others are done on return. Answers with the project as it then is.

RunServiceCommand

ChatGPT
Runs a command in a running service's container, like docker exec; returns the exit code and the output's end once it exits or the timeout kills it. Over a bound on command, stdin or timeout = refused (named). Cannot start = exit 127 or 126, Docker's error in stdout. Untrusted output.

SetProjectAlerts

ChatGPT
Changes what Pethost watches on a project and when it tells the person: site checks (an address the machine opens every minute) and traffic rules (5xx or p95 over a window), off, mute. A list given replaces the project's (send Project.alerts' with your change); remove_* empties it; a scalar left out stays. Service crashes and failed backups are always watched. Answers with Project.alerts. Where alerts go is the person's choice in the panel's Settings → Alerts (Machine.alert_channels): no tool sets it. FAILED_PRECONDITION + MachineUpdatePending = the machine's software predates alerts.

Show

ChatGPT
Shows the person a live view of their Pethost in the conversation: the machine with every project, one project, a project's HTTP requests (a chart and the top paths) or its logs, the last two with filters they can change themselves. Call it when they ask to see something, or when a view says more than a sentence would: a day's traffic, a log to read through. It returns no data: GetMachine, GetProject, QueryHttpTraffic and QueryContainerLogs do. Afterwards say in a line what they are looking at, not what it shows. Where their app shows no views, the answer has the panel's link to give them.

CreateProject

Claude

CreateTransfer

Claude

DeployProject

Claude

GetMachine

Claude

GetOperation

Claude

GetProject

Claude

ListCommits

Claude

QueryContainerLogs

Claude

QueryHttpTraffic

Claude

ReadPath

Claude

RunMachineAction

Claude

RunProjectAction

Claude

RunServiceCommand

Claude

Capabilities

WritesInteractive

Example Prompts

Click any prompt to copy it.

Similar Apps