{
  "manifest_version": "1",
  "slug": "mcp-server",
  "title": "Remote MCP server",
  "headline": "Host a remote MCP server",
  "description": "Host a remote MCP server on an exe.dev VM: Streamable HTTP over HTTPS, private behind exe.dev login, OAuth for claude.ai and ChatGPT, SQLite on disk.",
  "category": "ai-agents",
  "tags": [
    "mcp server",
    "remote mcp server",
    "host mcp server",
    "streamable http",
    "mcp oauth",
    "claude connector",
    "chatgpt connector",
    "mcp-proxy",
    "stdio to http",
    "python mcp sdk"
  ],
  "url": "https://exe.dev/deploy/mcp-server",
  "markdown_url": "https://exe-staging.dev/deploy/mcp-server.md",
  "upstream": {
    "website": "https://modelcontextprotocol.io",
    "source": "https://github.com/modelcontextprotocol/python-sdk",
    "docs": "https://modelcontextprotocol.io/docs/develop/build-server",
    "license": "MIT"
  },
  "example_vm_name": "my-mcp-server",
  "time": "10 minutes",
  "stack": [
    {
      "name": "Your MCP server",
      "detail": "the notes starter (official Python SDK), your repository, or stdio servers behind mcp-proxy, as `mcp-server.service`",
      "port": 8000,
      "data": "~/mcp-server"
    },
    {
      "name": "SQLite",
      "detail": "the starter's notes, full-text searchable",
      "data": "~/data"
    },
    {
      "name": "mcp-gate (optional)",
      "detail": "OAuth via exe.dev login, for claude.ai and ChatGPT; takes port 8000 and moves the server to 8001",
      "port": 8000,
      "data": "~/data/mcp-gate.db"
    },
    {
      "name": "Nightly backup",
      "detail": "a systemd timer; keeps two weeks",
      "data": "~/backups"
    }
  ],
  "access": [
    {
      "url": "https://my-mcp-server.exe.xyz/mcp",
      "who": "private",
      "what": "the MCP endpoint, for you and agents with a VM token"
    },
    {
      "url": "http://notes.int.exe.xyz/mcp",
      "who": "private",
      "what": "the same, for agents on your other VMs (VM-to-VM integration)"
    },
    {
      "url": "https://my-mcp-server.exe.xyz/mcp",
      "who": "public",
      "what": "with mcp-gate only: OAuth sign-in for claude.ai, ChatGPT, and their apps"
    }
  ],
  "inputs": [
    {
      "name": "SERVER",
      "description": "`new` for the notes starter; a GitHub repository (owner/name or URL) with an MCP server; or a stdio server's command (`npx -y @modelcontextprotocol/server-filesystem@2 ~/shared`) or Claude Desktop config"
    }
  ],
  "delivers": [
    "An MCP server on Streamable HTTP at `https://my-mcp-server.exe.xyz/mcp` (`/servers/\u003cname\u003e/mcp` for stdio servers) as `mcp-server.service`, restarted on failure and reboot: the starter, your repository, or stdio servers behind mcp-proxy.",
    "Private behind exe.dev: clients send a VM token in one header, and your server reads the caller from `X-ExeDev-Email` with no auth code.",
    "`~/bin/mcp-check`, a small client that lists the tools and calls one, run against the server as exe.dev's proxy reaches it.",
    "Code, `~/data`, and settings backed up nightly to `~/backups`, with a restore checked in a scratch directory."
  ],
  "owner_runs_after": [
    "ssh exe.dev ssh-key generate-api-key --vm=my-mcp-server --label=mcp-clients --exp=90d",
    "claude mcp add --transport http --scope user notes https://my-mcp-server.exe.xyz/mcp --header \"X-Exedev-Authorization: Bearer exe1.paste-yours-here\"   # or the name and URL Shelley gave you"
  ],
  "deployable": true,
  "deploy": {
    "new_vm_url": "https://exe-staging.dev/new?prompt=SERVER%3D%3Cfill-this-in%3E%0A%0ASet%20up%20Remote%20MCP%20server%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Fmcp-server.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20SERVER%3A%20%60new%60%20for%20the%20notes%20starter%3B%20a%20GitHub%20repository%20%28owner%2Fname%20or%20URL%29%20with%20an%20MCP%20server%3B%20or%20a%20stdio%20server%27s%20command%20%28%60npx%20-y%20%40modelcontextprotocol%2Fserver-filesystem%402%20~%2Fshared%60%29%20or%20Claude%20Desktop%20config%0AAsk%20me%20for%20any%20that%20still%20say%20%3Cfill-this-in%3E%20before%20you%20need%20them.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-mcp-server.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-mcp-server.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20An%20MCP%20server%20on%20Streamable%20HTTP%20at%20%60https%3A%2F%2Fmy-mcp-server.exe.xyz%2Fmcp%60%20%28%60%2Fservers%2F%3Cname%3E%2Fmcp%60%20for%20stdio%20servers%29%20as%20%60mcp-server.service%60%2C%20restarted%20on%20failure%20and%20reboot%3A%20the%20starter%2C%20your%20repository%2C%20or%20stdio%20servers%20behind%20mcp-proxy.%0A-%20Private%20behind%20exe.dev%3A%20clients%20send%20a%20VM%20token%20in%20one%20header%2C%20and%20your%20server%20reads%20the%20caller%20from%20%60X-ExeDev-Email%60%20with%20no%20auth%20code.%0A-%20%60~%2Fbin%2Fmcp-check%60%2C%20a%20small%20client%20that%20lists%20the%20tools%20and%20calls%20one%2C%20run%20against%20the%20server%20as%20exe.dev%27s%20proxy%20reaches%20it.%0A-%20Code%2C%20%60~%2Fdata%60%2C%20and%20settings%20backed%20up%20nightly%20to%20%60~%2Fbackups%60%2C%20with%20a%20restore%20checked%20in%20a%20scratch%20directory.%0A%0ARead%20the%20whole%20recipe%2C%20closed%20details%20included%2C%20and%20follow%20%22Set%20up%20by%0Ahand%22%20in%20order%2C%20skipping%20VM%20creation%3B%20the%20walkthrough%20above%20it%20is%20for%0Athe%20owner.%20Ask%20for%20SERVER%20first%20if%20it%20says%20%3Cfill-this-in%3E.%20For%20%60new%60%2C%0Abuild%20the%20starter%20exactly%20as%20written%3B%20for%20a%20repository%2C%20follow%20%22Or%3A%20a%0Aserver%20from%20a%20repository%22%3B%20for%20a%20stdio%20server%20or%20Claude%20Desktop%20config%2C%0A%22Or%3A%20stdio%20servers%22.%20Ask%20the%20owner%20for%20any%20secret%20a%20server%20needs%20and%20put%0Ait%20in%20~%2Fmcp-server.env%2C%20never%20in%20servers.json%20or%20the%20unit.%20If%20a%20private%0Arepository%20won%27t%20clone%2C%20give%20the%20owner%20the%20%60integrations%20add%20github%60%0Acommand%20with%20this%20VM%27s%20name%20and%20wait.%0ASet%20up%20mcp-gate%20only%20if%20the%20owner%20asks%20for%20claude.ai%2C%20ChatGPT%2C%20or%20their%0Aapps%2C%20following%20%22Connect%20claude.ai%20and%20ChatGPT%22%20on%20the%20VM%3B%20don%27t%20make%0Athe%20VM%20public%2C%20but%20give%20the%20owner%20the%20%60share%20set-public%60%20command.%0ADelete%20notes%20you%20save%20while%20checking.%20Don%27t%20reboot%20or%20restore%20over%20live%0Adata%3A%20test%20the%20backup%20in%20a%20scratch%20directory%20as%20written.%20The%20VM%20can%27t%0Aopen%20its%20own%20https%3A%2F%2F%3Cvm%3E.exe.xyz%3B%20%22Check%20it%22%20goes%20through%20localhost.%0AEnd%20with%20each%20MCP%20URL%2C%20a%20short%20name%20and%20the%20tools%20for%20each%2C%20and%0Aanything%20you%20adapted%20or%20the%20owner%20should%20change.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open%20and%20these%20commands%2C%20which%20only%20I%20can%20run%2C%20from%20my%20own%20computer%20%28with%20this%20VM%27s%20name%20in%20them%29%3A%0A%20%20ssh%20exe.dev%20ssh-key%20generate-api-key%20--vm%3Dmy-mcp-server%20--label%3Dmcp-clients%20--exp%3D90d%0A%20%20claude%20mcp%20add%20--transport%20http%20--scope%20user%20notes%20https%3A%2F%2Fmy-mcp-server.exe.xyz%2Fmcp%20--header%20%22X-Exedev-Authorization%3A%20Bearer%20exe1.paste-yours-here%22%20%20%20%23%20or%20the%20name%20and%20URL%20Shelley%20gave%20you%0A",
    "terminal": "curl -fsSL https://exe-staging.dev/deploy/mcp-server/prompt.txt | ssh exe.dev new --prompt=/dev/stdin",
    "prompt": "SERVER=\u003cfill-this-in\u003e\n\nSet up Remote MCP server on this VM by following the exe.dev recipe at https://exe-staging.dev/deploy/mcp-server.md from top to bottom.\n\nThe values at the top of this message are mine:\n- SERVER: `new` for the notes starter; a GitHub repository (owner/name or URL) with an MCP server; or a stdio server's command (`npx -y @modelcontextprotocol/server-filesystem@2 ~/shared`) or Claude Desktop config\nAsk me for any that still say \u003cfill-this-in\u003e before you need them.\n\nThe recipe's example VM name is my-mcp-server. This VM's name is the output of `hostname`: use it wherever the recipe writes my-mcp-server. Skip the step that creates the VM; you are on it.\n\nYou are done when all of these are true. Check each one yourself:\n- An MCP server on Streamable HTTP at `https://my-mcp-server.exe.xyz/mcp` (`/servers/\u003cname\u003e/mcp` for stdio servers) as `mcp-server.service`, restarted on failure and reboot: the starter, your repository, or stdio servers behind mcp-proxy.\n- Private behind exe.dev: clients send a VM token in one header, and your server reads the caller from `X-ExeDev-Email` with no auth code.\n- `~/bin/mcp-check`, a small client that lists the tools and calls one, run against the server as exe.dev's proxy reaches it.\n- Code, `~/data`, and settings backed up nightly to `~/backups`, with a restore checked in a scratch directory.\n\nRead the whole recipe, closed details included, and follow \"Set up by\nhand\" in order, skipping VM creation; the walkthrough above it is for\nthe owner. Ask for SERVER first if it says \u003cfill-this-in\u003e. For `new`,\nbuild the starter exactly as written; for a repository, follow \"Or: a\nserver from a repository\"; for a stdio server or Claude Desktop config,\n\"Or: stdio servers\". Ask the owner for any secret a server needs and put\nit in ~/mcp-server.env, never in servers.json or the unit. If a private\nrepository won't clone, give the owner the `integrations add github`\ncommand with this VM's name and wait.\nSet up mcp-gate only if the owner asks for claude.ai, ChatGPT, or their\napps, following \"Connect claude.ai and ChatGPT\" on the VM; don't make\nthe VM public, but give the owner the `share set-public` command.\nDelete notes you save while checking. Don't reboot or restore over live\ndata: test the backup in a scratch directory as written. The VM can't\nopen its own https://\u003cvm\u003e.exe.xyz; \"Check it\" goes through localhost.\nEnd with each MCP URL, a short name and the tools for each, and\nanything you adapted or the owner should change.\n\nFinish 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):\n  ssh exe.dev ssh-key generate-api-key --vm=my-mcp-server --label=mcp-clients --exp=90d\n  claude mcp add --transport http --scope user notes https://my-mcp-server.exe.xyz/mcp --header \"X-Exedev-Authorization: Bearer exe1.paste-yours-here\"   # or the name and URL Shelley gave you\n",
    "prompt_url": "https://exe-staging.dev/deploy/mcp-server/prompt.txt"
  },
  "updated": "2026-10-23",
  "related": [
    "claude-code",
    "codex",
    "fastapi",
    "agents",
    "openclaw",
    "opencode"
  ],
  "alternatives": [
    "Cloudflare Workers",
    "Vercel",
    "Fly.io",
    "Railway"
  ],
  "files": [
    "https://exe-staging.dev/deploy/mcp-server/check.py",
    "https://exe-staging.dev/deploy/mcp-server/mcp-gate.py",
    "https://exe-staging.dev/deploy/mcp-server/server.py"
  ]
}
