Set up Render
This walkthrough stands up Tapestry’s backend on Render — the services your projects connect to via .mcp.json. In self-host you run this once for your own deployment. See Platform dependencies for what’s needed.
Estimated time: 20–40 minutes for first provisioning, mostly waiting on builds.
What you’ll provision
Section titled “What you’ll provision”The Render side hosts five Python web services plus one Postgres instance plus one cron, declared in render.yaml (the platform’s Blueprint file). The Blueprint is the source of truth — Render reads it and provisions everything declaratively.
| Resource | Purpose | Source |
|---|---|---|
postgres (managed Postgres) | Backing store for memory records, project registry, candidate registry | render.yaml |
memory-mcp (web service) | The Memory MCP — memory_read/write/recall/list/search/delete over HTTP + MCP | services/agent-context/ |
architecture-registry | Candidate + Architecture registry endpoints | services/architecture-registry/ |
policy-service | Promotion policy evaluator | services/policy/ |
project-registry | Project + repo + machine registration | services/project-registry/ |
self-observer (cron) | 6-hour scan that interprets signals into candidates | services/self-observer/ |
Prerequisites
Section titled “Prerequisites”- A Render account (free tier is enough to start; the your own deployment may need a paid plan once traffic grows — see Render’s pricing)
- A GitHub account that can read
your deployment repo(the public repo holding the Blueprint) - A Grafana Cloud account with OTel credentials in hand — see Set up Grafana Cloud + OTel first; the Render services need
OTEL_EXPORTER_OTLP_*env vars at provisioning time
Step 1 — Sign up + sign in
Section titled “Step 1 — Sign up + sign in”- Open render.com and create an account if you don’t have one. The Render docs’ Getting Started page covers the basics.
- After signup, you land at dashboard.render.com. Bookmark it — every later step happens here.
Step 2 — Connect the GitHub repo
Section titled “Step 2 — Connect the GitHub repo”Render reads the Blueprint directly from a connected GitHub repo. You need to authorize Render to access your deployment repo.
- In the dashboard, click your profile (top-right) → Account Settings → GitHub → Configure.
- Authorize Render against
Lizo-RoadTown(your fork, or the upstream if you’re the upstream owner).
If you’re standing up your own deployment, fork the platform repo (Lizo-RoadTown/tapestry) first and edit the render.yaml service names if you want a different namespace.
Step 3 — Validate the Blueprint locally (optional but recommended)
Section titled “Step 3 — Validate the Blueprint locally (optional but recommended)”Render provides a CLI for Blueprint validation. Per the Blueprint spec, the command (requires CLI v2.7.0+):
brew install render # or: curl -fsSL https://render.com/download-cli/linux | shrender loginrender validate render.yamlIf the file is valid, the command exits 0. If not, it prints the schema errors so you can fix them before pushing.
Step 4 — Provision the Blueprint
Section titled “Step 4 — Provision the Blueprint”- In the Render dashboard, click New (top-right) → Blueprint. Render’s Infrastructure as Code page documents this workflow.
- Select the connected
your deployment reporepo. - Render reads
render.yamlat the repo root and previews what it will create — five web services + one Postgres + one cron, matching the table above. - Click Apply.
Render builds each service in parallel. First builds take 3–8 minutes per service (the Postgres comes up faster, services have to install pip dependencies). Subsequent deploys are incremental.
Step 5 — Set the required env vars
Section titled “Step 5 — Set the required env vars”The Blueprint declares which env vars each service needs but does not set their values (secrets are operator-supplied). Per the render.yaml comments, you need to set these in the dashboard.
Shared across services — loom-shared-secrets env group
Section titled “Shared across services — loom-shared-secrets env group”-
In the dashboard, click Environment Groups (left sidebar) → New Environment Group → name it
loom-shared-secrets. -
Add these key-value pairs:
Key Source OTEL_EXPORTER_OTLP_ENDPOINTfrom Grafana Cloud setup OTEL_EXPORTER_OTLP_HEADERSfrom Grafana Cloud setup LOOM_JWT_PUBLIC_KEYRSA public key (PEM) — every service verifies tokens with it -
Attach the env group to each web service: open the service → Environment → Link Environment Group → select
loom-shared-secrets.
Per-service secrets
Section titled “Per-service secrets”A few keys must be set on individual services (not shared):
| Service | Key | Purpose |
|---|---|---|
memory-mcp | LOOM_JWT_PRIVATE_KEY | RSA private key — only this service signs tokens |
loom-project-observatory (if deployed) | GRAFANA_CLOUD_API_URL | Server-side Grafana query endpoint |
loom-project-observatory (if deployed) | GRAFANA_CLOUD_API_TOKEN | Auth for the query endpoint |
Set these per-service: open the service → Environment → Add Environment Variable.
Step 6 — Verify deployment
Section titled “Step 6 — Verify deployment”Each service must show Live in the dashboard. Then check the health endpoints (every Python service in services/*/main.py exposes /health):
curl https://your-memory-host.example.com/healthcurl https://your-registry-host.example.com/healthcurl https://your-policy-host.example.com/healthcurl https://your-project-registry-host.example.com/healthEach should return {"status": "ok", "service": "<name>"}.
For the cron, open self-observer in the dashboard and check the Logs tab. The first run executes within 6 hours of deployment (or you can manually trigger it via Manual Deploy → Trigger Job).
Step 7 — Confirm the Memory MCP is reachable
Section titled “Step 7 — Confirm the Memory MCP is reachable”From a Claude Code session in any test project:
-
Create or update the project’s
.mcp.json:{"mcpServers": {"loom-memory": {"transport": {"type": "http","url": "https://your-memory-host.example.com/mcp/memory/"}}}} -
Restart Claude Code.
-
In a session, call
memory_list— should return without error.
If you see MCP UNREACHABLE: HTTP 404, the service is still cold-starting (free-tier services sleep after 15 minutes of no traffic). Wait 30–60 seconds and retry. If persistent, see Memory troubleshoot.
Cost notes
Section titled “Cost notes”Render’s free tier covers small projects but the platform’s services have constraints:
- Free-tier web services sleep after 15 minutes idle (~60s cold-start when traffic resumes). For the Memory MCP this is a real UX cost — every fresh session hits a cold start. You typically upgrade
memory-mcpto a paid plan (starter or above) once consumers are active. - Managed Postgres has its own pricing tiers; the free tier is fine for early use.
- The cron schedule (every 6h) is well within free-tier limits.
See Render pricing for current rates.
Operator-only actions that need the dashboard (not the MCP)
Section titled “Operator-only actions that need the dashboard (not the MCP)”Some Render operations are NOT available via the Render MCP — only the dashboard:
- Plan changes (free → starter etc.) — operator does in dashboard
- Service deletion — operator does in dashboard
- Cron deletion — operator does in dashboard
This is by design; the Render MCP only supports updates that don’t change billing state. See feedback_render_mcp_cannot_change_service_plan_must_use_dashboard in the operator’s memory for the full list.
Related
Section titled “Related”- Set up Grafana Cloud + OTel — do this first; Render needs the OTel env vars during provisioning
- Set up Vercel — for the frontend (docs site + Observatory cockpit)
- Platform dependencies — what each external service does
- Memory, Registry, Observer — the Systems pages for the components deployed here
render.yaml— the actual Blueprint file- Render docs — Blueprint spec
- Render docs — Infrastructure as Code