The deploy is red. The agent is staring at a fresh prompt: “The latest deploy of tinylink-web is failing. Can you take a look?” From here you do almost nothing - the plugin does the work.
1. Watch the diagnosis unfold
A typical session walks through four phases. Yours will vary in wording, not in structure.
Phase 1: orient
Loading skill: render-debug.
Step 1/4 - figure out what's failing.
Calling render -> list_services()...-> found tinylink-web (web_service, oregon)
Calling render -> list_deploys(serviceId="web-srv-ghi789", limit=3)...-> dep_001 status=live 5h ago-> dep_002 status=build_failed 2m ago commit=4f8a2bThe agent uses MCP to ground itself in real state - not what it thinks your services are, but what they actually are right now.
Phase 2: read the failure
Step 2/4 - inspect the failed deploy.
Calling render -> get_deploy(deployId="dep_002")...-> status=build_failed-> finishedAt=2026-05-21T20:34:11Z-> commit.message="feat: tighten uvicorn binding (do not merge)"
Calling render -> get_deploy_logs(deployId="dep_002", tail=200)...-> INFO: Uvicorn running on http://127.0.0.1:10000-> INFO: Application startup complete.-> ==> No open ports detected, continuing to scan...-> ==> Detected service running on port 10000 - unreachable (only listening on 127.0.0.1)-> ==> Timed out-> ==> Exited with status 1This is where MCP earns its keep - the agent isn’t speculating about why the deploy failed, it’s reading the actual log lines from the failed run.
Phase 3: diagnose
Step 3/4 - root cause.
The skill render-debug pattern-matches this on the canonical Renderport-binding failure. Two pieces of evidence:
- 'Uvicorn running on http://127.0.0.1:10000' - 'No open ports detected ... only listening on 127.0.0.1'
The container starts, the app starts, but the proxy can't reach itbecause uvicorn is bound to the loopback interface only. Render'sload balancer connects from outside the container.
Checking the commit diff to confirm:
Calling render -> get_commit_diff(commit="4f8a2b")...-> startCommand: uvicorn main:app --host 0.0.0.0 --port $PORT-> +startCommand: uvicorn main:app --port $PORT
Confirmed. The fix is to restore `--host 0.0.0.0`.The skill bundles this canonical pattern - along with about a dozen others (missing env var, OOM, dependency install failure, healthcheck wrong path, etc.) - so the agent doesn’t have to reinvent it from logs alone.
Phase 4: fix and ship
Step 4/4 - apply the fix.
Editing render.yaml... startCommand: uvicorn main:app --host 0.0.0.0 --port $PORTHook: render.yaml validated, no errors.
Committing and pushing... git add render.yaml git commit -m "fix: bind uvicorn to 0.0.0.0 so Render's proxy can reach it" git push
Calling render -> watch_deploy(serviceId="web-srv-ghi789")...-> build_in_progress ...-> update_in_progress ...-> live /healthz returning 200
Fixed. Root cause: the previous commit removed --host 0.0.0.0 from theuvicorn start command, leaving the app bound to the loopback interface.Restored it. Deploy is green.That’s the whole thing. Four MCP tool calls, one skill, one one-line diff. Total wall-clock, not counting build time: about a minute.
2. The canonical port-binding rule
This failure mode is so common it’s worth memorizing. Reveal the rule when you’ve talked the agent through the fix:
Show hint
A web service on Render must bind to 0.0.0.0 (all interfaces) on the port given by the $PORT environment variable.
- Binding to
127.0.0.1works locally but fails on Render with “No open ports detected.” - Binding to a hardcoded port like
8000may also fail - Render assigns$PORTdynamically; in production it’s typically10000, but never bet on a specific value. - Frameworks vary. The flag is
--hostfor uvicorn/hypercorn,-b 0.0.0.0:$PORTfor gunicorn,app.listen(process.env.PORT, "0.0.0.0")for Express.
The plugin’s render-platform.mdc rule encodes this so the agent doesn’t drift on it between sessions.
3. Confirm the fix from outside
Once the agent says “live,” verify yourself instead of taking its word for it:
$curl https://tinylink-web.onrender.com/healthz{"status":"ok"}$curl -X POST https://tinylink-web.onrender.com/links -H 'Content-Type: application/json' -d '{"url":"https://github.com/render-oss/skills"}'{"slug":"a9X2Zk"}$curl -I https://tinylink-web.onrender.com/a9X2ZkHTTP/2 307location: https://github.com/render-oss/skills
The 307 means the redirect path is healthy end-to-end - web service -> Postgres -> response.
4. Why this is more than a one-trick pony
The pattern you just watched generalizes. render-debug knows about:
- Missing or misnamed env vars (the agent reads them from
get_serviceand compares against what your code references) - Out-of-memory kills (it reads metrics over MCP and correlates with the deploy timeline)
- Healthcheck path mismatches (compares
healthCheckPathin your Blueprint to the routes in your code) - Dependency-install failures (parses build logs for known package-manager error signatures)
- Database connection issues (cross-checks
DATABASE_URLplumbing against the Blueprint and the code)
For each, the playbook is the same: read live state via MCP, pattern-match on logs and metrics, propose a fix, apply it, watch the redeploy.
What you learned
- Asked the agent a vague question ("the deploy is failing") - it grounded itself in real state with MCP
- Watched render-debug walk through orient -> read logs -> diagnose -> fix in four MCP tool calls
- Saw the agent pattern-match the 'no open ports detected' failure against the canonical Render port-binding rule
- Restored the fix in one diff, redeployed automatically, and verified from outside