Render Tutorials
Build and host a full-featured, secure MCP server on Render

What you'll build

⏱ 5 min

The Model Context Protocol (MCP) gives LLM agents a standard way to call your tools, read your resources, and reuse your prompts. The protocol is straightforward; the hard part is everything around it: authentication, transport, persistence, observability, and keeping the whole thing online.

By the end of this tutorial, you’ll have a production-shaped MCP server running on Render that any MCP-capable client (Claude Desktop, Cursor, the Codex CLI, or the MCP Inspector) can connect to.

You start from Render’s official mcp-server-typescript template - a one-click-deployable MCP server with Streamable HTTP transport, a hello tool, bearer-token auth, and a working render.yaml. The tutorial’s value-add is everything you bolt on top of it: proper OAuth, Postgres, rate limiting, structured logs, and the operational habits that keep it running.

Before you start

You’ll need:

The MCP server docs, the Blueprint spec, and the Postgres docs are good companions when you wire each piece in.

You’re not shipping a toy. The server you’ll build covers the pieces real MCP deployments need:

  • Streamable HTTP transport so any modern MCP client can connect over the public internet, not just stdio on the same machine.
  • OAuth-based auth so each caller is a real, revocable identity - no shared bearer tokens checked into config files.
  • A Postgres-backed tool that does something genuinely useful (a small note-taking surface), wired over Render’s private network.
  • Rate limiting and structured logging so one bad client can’t drown the others, and you can actually debug what happened.
  • A health check and a Blueprint so deploys are reproducible and Render can keep the service healthy.

What you won’t need to figure out

Render handles the boring-but-load-bearing parts:

  • Free, auto-renewing TLS on a public URL.
  • Zero-downtime deploys when you push to main.
  • A managed Postgres database reachable over the private network - no public exposure.
  • Logs, metrics, and shell access from the dashboard.

That lets the tutorial stay focused on the MCP-specific decisions: transport choice, auth flow, tool design, and how to validate the server end-to-end.

Roadmap

Here’s the path from a templated starting point to a deployed, authenticated, persistent MCP server:

  1. Fork Render’s MCP template - clone it, run it locally, optionally deploy the unmodified version first so you’ve seen the green path.
  2. Add your first real tool and resource - a notes.create tool and a notes://recent resource backed by an in-memory store, registered alongside the template’s hello.
  3. Add Postgres locally with Docker, then wire the same code to Render’s managed Postgres over the private network.
  4. Replace the template’s bearer token with OAuth 2.1 - the flow MCP clients expect for multi-user remote servers.
  5. Add rate limiting, structured logs, and a real health check so the service is observable and resilient.
  6. Extend the template’s render.yaml to provision Postgres, wire OAuth env vars, and lock down the deploy.
  7. Connect a real client - point Claude Desktop (or the MCP Inspector) at your live URL and watch your tool execute.
  8. Harden and iterate - durable OAuth storage, per-user data scoping, secrets rotation, and what to monitor in week one.
flowchart LR
  client["MCP client<br/>(Claude / Cursor / Inspector)"]
  edge["Render web service<br/>(public HTTPS + OAuth)"]
  app["MCP server<br/>(TypeScript SDK)"]
  db[("Render Postgres<br/>(private network)")]

  client -->|"Streamable HTTP + Bearer"| edge
  edge --> app
  app -->|"private DNS"| db

The public surface is exactly one URL with TLS and OAuth in front of it. Everything else - Postgres, internal env vars, deploy artifacts - stays on Render’s private network.

Why does this tutorial use OAuth instead of a shared bearer token for the MCP server?

What you learned

  • MCP standardizes how agents call tools and read resources - the hard part is the production envelope around it
  • You'll ship a TypeScript MCP server with OAuth, Postgres, rate limiting, and structured logs
  • Render provides TLS, zero-downtime deploys, private networking, and managed Postgres so you can focus on MCP itself
  • Public surface is one OAuth-protected HTTPS URL; everything else stays private