JetDeploy runs a remote MCP server at https://jetdeploy.com/mcp. An agent connected to it gets one tool per API operation: it can create the App, add the database, wire the environment variables, follow the deploy and read the logs. This article covers the part that decides whether that goes well: what to allow the agent, what to put in the prompt, and how to check its work.
The examples use Claude Code, which also has a terminal and can push the code itself. The same flow works from Codex, GitHub Copilot in VS Code and Cursor. Claude and ChatGPT in the browser do everything except the push, and hand you the command instead.
1 Connect
Pick your client:
# Claude Code, then run /mcp inside it to sign in
claude mcp add --transport http jetdeploy https://jetdeploy.com/mcp
# Codex, which opens the JetDeploy login by itself
codex mcp add jetdeploy --url https://jetdeploy.com/mcpFor Cursor, in .cursor/mcp.json:
{"mcpServers": {"jetdeploy": {"url": "https://jetdeploy.com/mcp"}}}For GitHub Copilot in VS Code, in .vscode/mcp.json:
{"servers": {"jetdeploy": {"type": "http", "url": "https://jetdeploy.com/mcp"}}}In claude.ai, add https://jetdeploy.com/mcp under Settings › Connectors › Add custom connector. In ChatGPT, turn on developer mode and add it as a server with OAuth. The AI Agents page has every client with copy buttons.
2 Choose what the agent may do
The consent page decides what the connection can do, and it can be narrower than what you can do in the Console:
| Scope | Lets the agent | Secrets |
|---|---|---|
read, always granted | read organizations, Apps, services, domains, logs and metrics | all null |
write | create, change, deploy and delete; push code with a git credential of its own | readable |
exec, only with write | run commands inside running processes with exec_in_pod | readable |
A sensible start:
Exploring or debugging a live App: read only. The agent reads logs and metrics and cannot change anything. Environment values and service passwords come back as null.
Setting up a new App: read and write.
Running one-off commands, such as a manual migration or a data fix: add exec, and only for as long as you need it.
A call outside the granted scopes is refused with 403 insufficient_scope, and the agent is told to reconnect with the missing permission. Nothing happens silently.
3 Write a prompt the agent can act on
"Deploy this app" works, but the agent then has to guess the port, the database and the migration command. It reads the repository, and it can still guess wrong. A prompt that answers those questions up front gets a correct first deploy:
Put this Django app in production on JetDeploy, organization "Acme".
- App name: acme-shop, branch main.
- It needs PostgreSQL, 10 GiB. Set DATABASE_URL from its credentials.
- gunicorn listens on 0.0.0.0:8080 (see the Dockerfile); one external process "web".
- Pre-deploy script: python manage.py migrate --noinput
- SECRET_KEY: generate a random one. ALLOWED_HOSTS: the App's default host.
Push when everything is set, then follow the deploy and show me the result.The details worth stating, and why:
Organization, if you belong to more than one. Tools take it as an argument.
Name. App and service names are unique across all of JetDeploy, not just your account, and the name becomes the default host.
Port and process layout, since JetDeploy sets no PORT variable and a worker needs its own process.
Pre-deploy script. It has to be in place before the push, because the push starts the deploy.
4 What the agent does
With the prompt above, the tool calls follow the same order as the API:
create_appwith the name and branch. The answer carries the App id andgit_remote_with_token.create_servicefor PostgreSQL, thenget_serviceuntil its status isready.update_envswithDATABASE_URL,SECRET_KEYandALLOWED_HOSTS.update_appwith the pre-deploy script.create_podforweb, port8080, external.git pushfrom the terminal togit_remote_with_token. This starts the build.get_operationwithwait_secondsuntil the deploy finishes, andget_app_deploy_logsfor the build output.
5 Check the result
Ask the agent to show you, rather than trusting a summary:
- the operation status and
commitfromget_operation; - the last lines of the logs from
get_app_logs, filtered toerrorandwarn; - the App's
url, which you open yourself.
Log reads over MCP are pages, not live streams. For a long answer, the agent keeps paging with next_cursor. When a deploy fails, the error_message of the operation names the step and the cause, and the agent can read the matching logs. When a deploy fails explains what each failure means.
Guardrails that are already there
Destroying needs the exact name. destroy_app and destroy_service require confirm_name to match, or they are refused.
The agent cannot revoke connections. list_connections is a tool; revoking is not. You revoke from Integrations › AI Agents & MCP in the Console, and the agent stops at once, git credential included.
Token regeneration and payment methods are not tools either.
A second deploy, apply or rollback tool call while an operation runs on the same App is refused with 409 operation_pending, so the agent is told to wait instead of starting another one. A git push is not a tool call: each push with a new commit queues its own deploy behind the running one.
Prompts for day two
Once the App runs, the same connection covers everyday work:
Why did the last deploy of acme-shop fail? Show me the relevant log lines.
Add a Redis with 512 MiB for sessions and set REDIS_URL on acme-shop.
Attach www.acme.example to acme-shop and tell me which DNS records to create.
Roll acme-shop back to the release before the last deploy.Next step
Connect your agent from the AI Agents page, or read the MCP section of the docs for the full tool list and how large answers are paged. Agents that work over plain HTTP instead of MCP can start from llms.txt, which describes the same steps as API calls.