← Back to dashboard
renderhostingfresh

Render + Claude Code Integration Guide

What is Render?

The real model

Containerised, always-on services with persistent disks and managed Postgres.

Render fills the niche between "serverless" and "run your own k8s." Services run continuously (no scale-to-zero on paid tiers), keep WebSocket connections, and can attach persistent disks for state Postgres won't hold (uploads, SQLite). The managed Postgres is solid and isn't artificially limited like Heroku's. Background Workers are first-class — a worker is just a service with no port. Cron Jobs run on a schedule with full app context. For codeAmani, Render is the option when Vercel's serverless shape doesn't fit — Long-poll websockets, audio streaming agents, scheduled scrapers.

Five Render primitives

Long-running services with Heroku ergonomics and no vendor lockin.

Text
██████╗ ███████╗███╗   ██╗██████╗ ███████╗██████╗
██╔══██╗██╔════╝████╗  ██║██╔══██╗██╔════╝██╔══██╗
██████╔╝█████╗  ██╔██╗ ██║██║  ██║█████╗  ██████╔╝
██╔══██╗██╔══╝  ██║╚██╗██║██║  ██║██╔══╝  ██╔══██╗
██║  ██║███████╗██║ ╚████║██████╔╝███████╗██║  ██║
╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝╚═════╝ ╚══════╝╚═╝  ╚═╝

Render + Claude Code Integration Guide

Focus: Managing Render cloud infrastructure from Claude Code using the official Render MCP server and REST API automation.

Overview

Render is a unified cloud platform for deploying web services, APIs, static sites, cron jobs, and PostgreSQL databases. The official Render MCP server (GA since August 2025) exposes 20+ tools so Claude Code can inspect services, query databases, fetch logs, analyze metrics, and create new resources — all through natural language without leaving your session.

Here is the big picture — a single git push fans out into all of Render's service types, so you can reason about the whole platform at a glance:

Official Documentation


MCP Server Setup

Render hosts an official MCP server at https://mcp.render.com/mcp. Use your Render API key for authentication.

You are about to give Claude Code a direct line into your infrastructure — here is how a natural-language request flows through the MCP server to your live services:

Bash
# Add Render MCP to Claude Code (HTTP + Bearer token)
claude mcp add --transport http render \
  https://mcp.render.com/mcp \
  --header "Authorization: Bearer ${RENDER_API_KEY}"

.mcp.json Configuration

JSON
{
  "mcpServers": {
    "render": {
      "type": "http",
      "url": "https://mcp.render.com/mcp",
      "headers": {
        "Authorization": "Bearer ${RENDER_API_KEY}"
      }
    }
  }
}

Get your API key from: https://dashboard.render.com/u/settings → API Keys

Available MCP Tools (20+)

ToolDescription
list_servicesList all services (web, worker, cron, static)
get_serviceGet service details, URL, status
create_serviceCreate a new web service or worker
get_logsFetch runtime logs for a service
get_metricsGet CPU, memory, request metrics
list_databasesList PostgreSQL databases
run_queryExecute SQL on a Render Postgres DB
get_env_varsList environment variables
create_env_varAdd/update an environment variable
list_deploysList recent deployments
get_deployGet deploy status and logs

Note: The MCP server does not support triggering deploys or modifying scaling settings — use the REST API or Git push for those.


REST API Integration

Render doesn't have an official CLI, so direct API calls are the programmatic interface.

Get your services

Bash
curl https://api.render.com/v1/services \
  -H "Authorization: Bearer $RENDER_API_KEY" \
  -H "Content-Type: application/json" | jq '.[] | {id, name, status}'

Trigger a manual deploy

Bash
SERVICE_ID="srv-..."
curl -X POST "https://api.render.com/v1/services/$SERVICE_ID/deploys" \
  -H "Authorization: Bearer $RENDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"clearCache": "do_not_clear"}'

Create a web service (TypeScript)

TypeScript
const response = await fetch("https://api.render.com/v1/services", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RENDER_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    type: "web_service",
    name: "my-api",
    ownerId: "usr-...",
    serviceDetails: {
      env: "node",
      buildCommand: "npm ci",
      startCommand: "node dist/index.js",
      plan: "starter",
      region: "oregon",
      envSpecificDetails: {
        buildCommand: "npm run build",
      },
    },
    autoDeploy: "yes",
    repo: {
      url: "https://github.com/my-org/my-repo",
      branch: "main",
    },
  }),
});

const service = await response.json();
console.log("Created:", service.service.serviceDetails.url);

Python helper for Render API

Python
import os, requests

RENDER_API_KEY = os.environ["RENDER_API_KEY"]
BASE = "https://api.render.com/v1"
HEADERS = {"Authorization": f"Bearer {RENDER_API_KEY}", "Content-Type": "application/json"}

def get_services():
    return requests.get(f"{BASE}/services", headers=HEADERS).json()

def get_logs(service_id: str, limit: int = 100):
    return requests.get(
        f"{BASE}/services/{service_id}/logs",
        headers=HEADERS,
        params={"limit": limit},
    ).json()

def trigger_deploy(service_id: str):
    return requests.post(
        f"{BASE}/services/{service_id}/deploys",
        headers=HEADERS,
        json={"clearCache": "do_not_clear"},
    ).json()

render.yaml Blueprint (Infrastructure as Code)

A Blueprint (render.yaml at your repo root) is the single source of truth for an interconnected set of services, databases, and environment groups. Commit it to Git, connect the repo in the Dashboard, and Render provisions everything in one pass. By default Render re-syncs affected resources on every push to the linked branch, so you manage infra the same way you manage code — via PRs and git push.

A web service + managed Postgres + a shared env group, fully wired:

YAML
# render.yaml
services:
  - type: web
    name: amani-api
    runtime: node
    plan: starter
    region: oregon
    buildCommand: npm ci && npm run build
    startCommand: node dist/index.js
    autoDeployTrigger: commit
    envVarGroups:
      - amani-shared
    envVars:
      # Wire the DATABASE_URL straight from the managed database below
      - key: DATABASE_URL
        fromDatabase:
          name: amani-db
          property: connectionString
      # Prompt for this secret once during Blueprint creation (never stored in Git)
      - key: RENDER_API_KEY
        sync: false
      # Let Render generate a strong random secret
      - key: SESSION_SECRET
        generateValue: true

databases:
  - name: amani-db
    plan: basic-256mb
    databaseName: amani
    user: amani
    region: oregon
    postgresMajorVersion: "17"

envVarGroups:
  - name: amani-shared
    envVars:
      - key: NODE_ENV
        value: production
      - key: TZ
        value: Africa/Nairobi

Gotcha — sync overwrites, but never deletes. Dashboard edits to a Blueprint-managed resource are overwritten on the next sync if they conflict with the YAML, so make changes in render.yaml, not the UI. Conversely, removing a resource from the file does not delete it — syncing never deletes existing resources, so you must delete them manually in the Dashboard. Also never manage one resource from two Blueprints, and list all fields when importing an existing resource (omitted fields fall back to defaults that likely differ from your current setup).


Environment Variables

Bash
# Required
RENDER_API_KEY=rnd_...          # From dashboard.render.com → Settings → API Keys

# Your service variables (set via dashboard or API)
DATABASE_URL=postgresql://...
PORT=10000                       # Render injects PORT automatically

Set environment variables via API:

Bash
curl -X PUT "https://api.render.com/v1/services/$SERVICE_ID/env-vars" \
  -H "Authorization: Bearer $RENDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"key":"MY_VAR","value":"my-value"}]'

Automation Workflows

Claude Code Slash Command: Service Health Check

.claude/commands/render-health.md:

Markdown
Check the health of all Render services.

Use the Render MCP tool `list_services` to get all services and their status. 
For any service that is NOT "live", use `get_logs` to fetch recent logs and diagnose the issue.
Provide a summary table of service name, status, and any detected errors.

Usage: /project:render-health

GitHub Actions: Deploy after Tests Pass

YAML
# .github/workflows/render-deploy.yml
name: Deploy to Render
on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: npm ci && npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Render deploy
        env:
          RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
          SERVICE_ID: ${{ secrets.RENDER_SERVICE_ID }}
        run: |
          curl -X POST "https://api.render.com/v1/services/$SERVICE_ID/deploys" \
            -H "Authorization: Bearer $RENDER_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{"clearCache":"do_not_clear"}'

      - name: Wait for deploy and check status
        env:
          RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }}
          SERVICE_ID: ${{ secrets.RENDER_SERVICE_ID }}
        run: |
          for i in {1..20}; do
            status=$(curl -s "https://api.render.com/v1/services/$SERVICE_ID/deploys?limit=1" \
              -H "Authorization: Bearer $RENDER_API_KEY" | jq -r '.[0].deploy.status')
            echo "Status: $status"
            if [ "$status" = "live" ]; then echo "Deploy succeeded!"; exit 0; fi
            if [ "$status" = "deactivated" ]; then echo "Deploy failed!"; exit 1; fi
            sleep 15
          done
          echo "Timeout waiting for deploy"; exit 1

Common Use Cases

Use CaseApproach
Inspect failing serviceMCP get_logs + get_metrics
Query production DBMCP run_query on Postgres service
Create new serviceMCP create_service or REST API POST
Deploy on mergeGitHub Actions + REST API deploys endpoint
Env var managementMCP create_env_var or REST API PUT
Monitor resource usageMCP get_metrics

Troubleshooting

IssueFix
Service stuck in "building"Check get_logs for build errors
Port connection refusedEnsure app listens on process.env.PORT
503 on requestsService may be suspended (free tier)
Deploy not triggeringRender auto-deploys on git push — check webhook in dashboard
API key invalidGenerate a new key in dashboard → Settings → API Keys
Database connection failedCheck DATABASE_URL env var; allow external connections in DB settings