Back to blog
Deployment • 8 min read

Deploy an MCP Server to Render

Deploy a generated MCP server to Render with native Node or Python runtimes, Docker for PHP and Java, a render.yaml blueprint, and secret environment variables.

Render is a platform-as-a-service for web services, workers, cron jobs, and managed data. It builds from a Git repository on every push and gives each web service an HTTPS URL ending in onrender.com.

For an MCP server, the deployment is straightforward: bind the generated server to Render's port on 0.0.0.0, add a blueprint that describes the build and start commands, and supply upstream credentials as environment variables. The MCP endpoint ends up at /mcp.

Prerequisites

  • A generated bundle for your chosen runtime.
  • A GitHub, GitLab, or Bitbucket repository connected to Render.
  • A Render account. The Free plan is enough to try the deployment.

Render sets a PORT environment variable for every web service, with a default of 10000. Your process must listen on 0.0.0.0, not localhost.

1. Bind the server to Render's port

TypeScript and Python are supported by Render's native runtimes. Make two small changes to the TypeScript entry point so the process listens on all interfaces and honors PORT.

src/server.ts
// Before
port: { type: 'string', default: '3000' },
serve({ fetch: app.fetch, port, hostname: '127.0.0.1' }, () => {

// After
port: { type: 'string', default: process.env.PORT ?? '3000' },
serve({ fetch: app.fetch, port, hostname: '0.0.0.0' }, () => {

Then make npm start use the HTTP transport instead of stdio.

package.json
"scripts": {
  "build": "tsc",
  "start": "node dist/server.js --http",
  "dev": "tsx watch src/server.ts"
}

Python needs no source edits. Pass --host 0.0.0.0 and --port $PORT in the start command. PHP and Java use Render's Docker runtime with a Dockerfile; the ones in the Cloud Run guide already read $PORT and bind to all interfaces.

2. Add a Render blueprint

Commit a render.yaml file at the bundle root. Render reads it when you create a Blueprint and provisions the service with the build command, start command, plan, and environment variables.

render.yaml (TypeScript)
services:
  - type: web
    name: my-mcp-server
    runtime: node
    plan: free
    buildCommand: npm install && npm run build
    startCommand: npm start
    envVars:
      - key: MCP_AUTH_API_TOKEN
        sync: false

The Python version uses the same shape with a different runtime and commands.

render.yaml (Python)
services:
  - type: web
    name: my-mcp-server
    runtime: python
    plan: free
    buildCommand: pip install -r requirements.txt
    startCommand: python server.py --transport streamable-http --host 0.0.0.0 --port $PORT
    envVars:
      - key: MCP_AUTH_API_TOKEN
        sync: false

Blueprint vs. dashboard: if you prefer not to commit a blueprint, create the web service in the Render Dashboard instead and enter the same build command, start command, and environment variables by hand. The blueprint keeps the configuration in version control.

3. Deploy from Git

Push the updated bundle, including render.yaml, to your connected repository. In the Render Dashboard, create a new Blueprint and select the repository and branch.

terminal
git add .
git commit -m "Add MCP server Render blueprint"
git push

Render prompts for the value of every environment variable marked sync: false, then starts the first build. Each later push to the linked branch triggers a new deploy automatically.

If you already have a web service, add the same values under the service's Environment settings and trigger a manual deploy.

4. Add the upstream credentials

The bundle README lists the variable names produced from your API security schemes. They are prefixed with MCP_AUTH_. Add one entry for each scheme rather than putting a token in the repository.

Render environment variables are injected into the process, so the generated process.env lookups work unchanged. Mark secrets with sync: false in the blueprint, or add them directly in the service's Environment tab.

Do not commit secrets: keep the token out of render.yaml. The sync: false value means Render asks for the value in the dashboard instead of reading it from Git.

5. Verify the endpoint

Wait for the deploy to finish, then open the service URL. It follows this shape, and the MCP endpoint is the URL plus /mcp:

https://my-mcp-server.onrender.com/mcp

Connect an MCP client that supports Streamable HTTP and call a read-only tool. Render's Logs tab shows build failures, startup errors, and missing environment variables. The default health check is a TCP probe, so no special health route is required.

PHP and Java with Docker

Render's native runtimes do not include PHP or Java, so select the Docker runtime for those bundles. The Dockerfiles from the Cloud Run guide work on Render because they already read $PORT.

render.yaml (Docker)
services:
  - type: web
    name: my-mcp-server
    runtime: docker
    plan: free
    dockerfilePath: ./Dockerfile
    envVars:
      - key: MCP_AUTH_API_TOKEN
        sync: false

Render sets PORT to 10000 by default, so the container must not hard-code 8080. The linked Dockerfiles use ${PORT:-8080} for exactly this reason.

Free plan caveats

  • Spin-down after inactivity. A Free web service sleeps after 15 minutes without traffic and takes about a minute to wake. That interrupts idle MCP sessions and adds latency to the first request.
  • Ephemeral filesystem. Files written by the process are lost on every restart, redeploy, or spin-down. The PHP bundle's file-based session store is not durable on Render Free.
  • One instance and no disks. Free services cannot scale beyond one instance or attach persistent storage.
  • Monthly limits. Each workspace gets 750 Free instance hours per month, plus bandwidth and build pipeline allowances. Exceeding them can suspend Free services.

Use a paid instance for production traffic, or keep the Free plan for testing and demos.

Operational notes

  • Secure the URL. Every web service is publicly reachable at its onrender.com subdomain. Upstream credentials are protected, but the MCP endpoint has no built-in authentication. Add an authorizer or a gateway before sharing it.
  • Streaming connections. Render supports long-lived HTTP responses, but Free spin-down and restarts will terminate them. Clients should reconnect and retry tool calls.
  • Health checks. The default TCP check confirms the process is listening. If you add an HTTP health path, make it return 2xx; the MCP endpoint itself may reject plain browser requests.
  • Redeploy on spec changes. Regenerate the bundle, reapply the port and start-command changes, commit, and push. Render rebuilds automatically.
  • Config changes redeploy. Updating environment variables or build settings can trigger a new deploy, so expect a short interruption on Free instances.

Next steps

Render is the simplest option when your MCP server is Node or Python and you want Git-based deploys with a managed HTTPS endpoint. Compare it with Google Cloud Run, AWS App Runner, Railway, Fly.io, Vercel, and Cloudflare Workers. A side-by-side comparison of the deployment options is available in Where to Deploy Your MCP Server.

Need a bundle to deploy? Start with From OpenAPI to a Running MCP Server.

Need a bundle to deploy?

Import a spec and generate an MCP server in TypeScript, Python, Java, or PHP.

Upload Spec