Skip to content

Self-host Executor, the open-source MCP gateway

Add your tools once; every agent reaches them through one private MCP URL.

Deploy on exe.dev

Shelley handles the setup. About 10 minutes.

Prefer a terminal?
curl -fsSL https://exe.dev/deploy/executor/prompt.txt | ssh exe.dev new --prompt=/dev/stdin

Executor is an open-source gateway between your agents and your tools. You add MCP servers, OpenAPI and GraphQL APIs, and accounts such as Gmail or GitHub to it once; it keeps their credentials and asks before risky calls. Every agent then connects to one MCP endpoint and finds the tool it needs by searching, instead of loading hundreds of tool definitions into its context. Executor 2, in beta, goes further: an agent can write new tools for you, with storage, schedules and webhooks, and they keep running on the server.

A VM makes a good home for it: always on, with HTTPS and a disk for the catalog and credentials. exe.dev's proxy keeps it private, which matters more than usual here. Executor 2 has no admin password to preset: the first person to finish its setup page owns the server. Behind your exe.dev login, that can only be you.

What you get#

  • Executor 2 at https://my-executor.exe.xyz, in Docker, restarted on failure and after a reboot.
  • Its database, generated keys and your apps' code in ~/executor/data.
  • An owner account that only you can create, because the setup page is behind your exe.dev login.
  • One MCP endpoint, /mcp, that Claude Code, Codex, Shelley and other agents share.
  • A backup and update procedure for the data directory.
What's running, and where
Private https://my-executor.exe.xyz/ the dashboard, behind your exe.dev login and your Executor account
Private https://my-executor.exe.xyz/mcp the MCP endpoint; agents send an exe.dev VM token and an Executor token
my-executor.exe.xyz exe.dev VM
Executor 2 (beta) ghcr.io/usefulsoftwareco/executor-selfhost:2.0.0-beta.34 in Docker Compose: dashboard, MCP endpoint and app runtime :8000~/executor/data

Deploy with Shelley#

Click Deploy and Shelley will set up Executor on a new VM, then check that it works. No config-file wrangling required.

Prefer a terminal?
curl -fsSL \
  https://exe.dev/deploy/executor/prompt.txt \
  | ssh exe.dev new --prompt=/dev/stdin

When it's done, run this on your computer (only you can):

ssh exe.dev ssh-key generate-api-key --vm=my-executor --label=executor-agents --exp=90d
What Shelley is told
Set up Executor on this VM by following the exe.dev recipe at https://exe.dev/deploy/executor.md from top to bottom.

The recipe's example VM name is my-executor. This VM's name is the output of `hostname`: use it wherever the recipe writes my-executor. Skip the step that creates the VM; you are on it.

You are done when all of these are true. Check each one yourself:
- Executor 2 at `https://my-executor.exe.xyz`, in Docker, restarted on failure and after a reboot.
- Its database, generated keys and your apps' code in `~/executor/data`.
- An owner account that only you can create, because the setup page is behind your exe.dev login.
- One MCP endpoint, `/mcp`, that Claude Code, Codex, Shelley and other agents share.
- A backup and update procedure for the data directory.

Read the whole recipe, closed details included, and follow "Set up by
hand" in order, skipping VM creation; the walkthrough above it is for
the owner. Use the pinned image tag as written. Never make the VM public:
the first person to finish Executor's setup page becomes its owner, and
that must be the owner. Don't set EXECUTOR_APPS_ALLOW_PRIVATE_FETCH unless
the owner asks. On an existing VM, ask before replacing anything on port
8000. The VM can't reach its own https://<vm>.exe.xyz, so checks use
localhost. Finish by sending the owner to https://<vm>.exe.xyz/ to create
their account, then to "Add your tools" and "Connect your agents", with the
`ssh-key generate-api-key` command to run on their computer.

Finish with the URLs I should open and these commands, which only I can run, from my own computer (with this VM's name in them):
  ssh exe.dev ssh-key generate-api-key --vm=my-executor --label=executor-agents --exp=90d

Also at /deploy/executor/prompt.txt. The recipe it follows is /deploy/executor.md.

Add your tools#

Open https://my-executor.exe.xyz/ and create your account: an organization name, your name, an email and a password. Skip Connect your accounts for now.

On Apps, choose Add app:

  • From an MCP server takes a remote MCP server's URL. Try https://mcp.deepwiki.com/mcp: Executor finds its three tools and makes an app of them. Servers that need a sign-in use OAuth, from the app's Accounts tab.
  • Browse app catalog lists ready-made apps such as Gmail, GitHub, Linear and Stripe. Some need an OAuth client of your own; give the provider https://my-executor.exe.xyz/api/oauth/callback as its redirect URL.
  • From scratch gives you a prompt for your agent, which then writes the app: for an OpenAPI or GraphQL API, a service with an API key, or a tool of your own.

Each app is TypeScript code you can read on its Source tab. Apps made from an MCP server ask for your approval before any tool the server marks as destructive; edit that rule there.

Connect your agents#

Each agent sends two headers:

  • X-Exedev-Authorization: Bearer exe1.…, a VM token that gets it through exe.dev's proxy, which removes it before Executor sees the request.
  • Authorization: Bearer exp_…, an Executor personal access token.

Make the VM token on your computer (--exp sets when it expires):

ssh exe.dev ssh-key generate-api-key --vm=my-executor --label=executor-agents --exp=90d

For the Executor token, open your avatar menu → Account settings → Tokens → Create token, name it after the agent, and limit it to your organization. It's shown once. Below, replace exe1.paste-yours-here and exp_paste-yours-here with yours.

Claude Code, on your computer or a VM like the one in Claude Code on exe.dev:

claude mcp add --transport http --scope user executor https://my-executor.exe.xyz/mcp \
  --header "X-Exedev-Authorization: Bearer exe1.paste-yours-here" \
  --header "Authorization: Bearer exp_paste-yours-here"
claude mcp list

Expect executor: https://my-executor.exe.xyz/mcp (HTTP) - ✔ Connected.

Codex, on your computer or a Codex VM, in ~/.codex/config.toml:

[mcp_servers.executor]
url = "https://my-executor.exe.xyz/mcp"
http_headers = { "X-Exedev-Authorization" = "Bearer exe1.paste-yours-here", "Authorization" = "Bearer exp_paste-yours-here" }

Shelley, on any of your VMs:

shelley mcp add executor -d "Executor: my apps and tools" \
  -H "X-Exedev-Authorization: Bearer exe1.paste-yours-here" \
  -H "Authorization: Bearer exp_paste-yours-here" \
  https://my-executor.exe.xyz/mcp
shelley mcp call executor.search query=deepwiki

Other clients: any MCP client that speaks Streamable HTTP and can send headers works the same way. An agent on the Executor VM itself can skip the VM token and use http://localhost:8000/mcp.

Tip

For agents on your other exe.dev VMs, a VM-to-VM integration can add both headers at exe.dev's edge, so no token is stored on the agent's VM. On your computer, for an agent on my-hermes-agent: ssh exe.dev integrations add http-proxy --name executor-hermes --target https://my-executor.exe.xyz/ --peer --bearer exp_paste-yours-here --attach vm:my-hermes-agent. The agent's URL is then https://executor-hermes.int.exe.xyz/mcp, with no headers.

Try it#

Ask your agent:

Use executor to find out how the UsefulSoftwareCo/executor repository is structured.

It searches Executor's catalog, finds the DeepWiki tools, and calls one. The six tools an agent sees are always the same (search, describe, call, execute, resume, skills); the apps behind them are what you add. To have an agent add one:

Use executor to add an app for the Linear API.

When a call needs your approval, the agent shows you the request and passes on your answer.

Keys off the VM#

API keys you give Executor stay in its encrypted database, not in your agents. To keep some off the VM entirely, use an exe.dev integration: exe.dev holds the secret and adds it at its edge when the VM calls https://<name>.int.exe.xyz. Executor's app sandbox refuses private addresses, which these are, until you allow them in ~/executor/compose.yaml, under environment:

      EXECUTOR_APPS_ALLOW_PRIVATE_FETCH: "true"

Then run docker compose up -d in ~/executor, and ask your agent for an app that calls https://<name>.int.exe.xyz with no credentials.

Warning

This applies to every app, not just one: any app can then reach every integration attached to the VM and services on the VM itself. Allow it only if you read the apps your agents write.

Cloud agents#

claude.ai, ChatGPT, and agents running in their makers' clouds can't send an exe.dev token, so they can reach only a public VM. Executor then is the only lock, and a real one: /mcp refuses requests without a token, and clients sign in with OAuth in your browser, which needs your Executor password and your approval. Create your account first, then, on your computer:

ssh exe.dev share set-public my-executor

Add https://my-executor.exe.xyz/mcp to the app as a custom connector and sign in. Claude Code (/mcp) and Codex (codex mcp login executor) can sign in the same way. OAuth connections can also be limited to some apps: on Connections, make a connection and use its MCP URL.

Warning

Public means Executor's sign-in page faces the internet. Use a strong password, approve only connections you just started, and go back with ssh exe.dev share set-private my-executor when you're done.

The nuts and bolts#

Happy with what Shelley set up? Stop here. Below are the steps it followed, and maintenance for later.

Set up by hand

Create the VM#

On your computer (pick another name if my-executor is taken):

ssh exe.dev new --name=my-executor
ssh my-executor.exe.xyz

Everything else runs on the VM.

Run Executor#

Executor's official image listens on port 4400; Compose publishes it on 8000, where exe.dev's proxy sends https://<vm>.exe.xyz/. BETTER_AUTH_URL must be exactly that address, or sign-in fails. The catalog feed fills Browse app catalog, and DO_NOT_TRACK turns off the anonymous usage events that released images send by default:

mkdir -p ~/executor && cd ~/executor
echo "BETTER_AUTH_URL=https://$(hostname).exe.xyz" > .env
cat > compose.yaml <<'EOF'
services:
  executor:
    image: ghcr.io/usefulsoftwareco/executor-selfhost:2.0.0-beta.34
    init: true
    restart: unless-stopped
    ports:
      - "8000:4400"
    environment:
      BETTER_AUTH_URL: ${BETTER_AUTH_URL}
      EXECUTOR_CATALOG_URL: https://catalog.executor.sh/index.json
      DO_NOT_TRACK: "1"
    volumes:
      - ./data:/app/data
    stop_grace_period: 30s
EOF
sudo systemctl enable --now docker.service
docker compose up -d

On first start, Executor creates its database and two keys, auth-secret.key and encryption.key, in ~/executor/data.

Check it#

until curl -fsS http://localhost:8000/health; do sleep 2; done; echo
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:8000/mcp

Expect {"status":"ok"}, then 401: the MCP endpoint wants a token. Then open https://my-executor.exe.xyz/ and create your account, as in Add your tools.

Back up and restore

Everything is in ~/executor/data: the database, both key files, and your apps' code. Stop Executor for a consistent copy:

cd ~/executor
docker compose stop
(umask 077; tar -czf - data compose.yaml .env > ~/executor-$(date -u +%Y%m%d).tar.gz)
docker compose start

The archive holds the keys, so it's readable only by you. Copy it off the VM too. To restore one:

cd ~/executor
docker compose stop
rm -rf data
tar -xzf ~/executor-20261031.tar.gz -C ~/executor
docker compose start

A backup without the key files can't be opened.

Update

Back up first. Then change the tag in ~/executor/compose.yaml to the newest release (2.0.0-beta.35, for example) and recreate the container:

cd ~/executor
docker compose pull && docker compose up -d

Executor migrates its data on startup. To follow every beta without editing the file, use the beta tag instead.

Troubleshooting
  • Sign-in loops or fails: BETTER_AUTH_URL in ~/executor/.env isn't exactly https://<vm>.exe.xyz. Fix it and docker compose up -d.
  • An agent gets 401: without X-Exedev-Authorization, exe.dev refuses it; with it, Executor wants Authorization: Bearer exp_…. Check both, the Bearer before each, and that neither has expired.
  • "Could not reach this MCP server": Executor fetches the URL from the VM. Check it from there with curl -i <url>.
  • Logs: docker compose -f ~/executor/compose.yaml logs --tail 100.

Frequently asked questions#

Executor 1 or Executor 2?

This page runs Executor 2, which is in beta and is what executor.sh and its docs now describe: apps with tools, skills, storage, schedules and webhooks. The 1.x line (1.6.11 on Oct 22, 2026) is still the latest image tag and npm release, with its own data format; 2.0 doesn't upgrade a 1.x install in place. Betas come out almost daily, so the page pins one tag.

What does it cost?

Executor is MIT-licensed and runs no model of its own, so just your VM plan. Your agents' model use bills wherever those agents run.

Who can reach it?

exe.dev's proxy lets in only you (signed in) and holders of a VM token for this VM, then Executor wants its own sign-in or token. A leaked Executor token is useless without a VM token, and the reverse.

Where are my API keys and OAuth tokens kept?

In Executor's database on the VM, encrypted with encryption.key in the same data directory. Agents get tools, never the credentials behind them. Back up the whole directory: without the key files, Executor won't start.

Does it phone home?

Released images send anonymous usage events (counts, timings, error types; never tool inputs, outputs or credentials) to the Executor team by default. This page turns that off with DO_NOT_TRACK: "1" in compose.yaml; remove the line to send them.

Can claude.ai or ChatGPT use it?

Only if the VM is public, since they connect from their makers' servers. See Cloud agents.

Updated Oct 31, 2026 · tested end to end Oct 31, 2026 · Markdown · manifest.json · Something wrong? Tell us