Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
คำอธิบายจากผู้ทำ (ภาษาอังกฤษตามต้นฉบับ)
Leased dev environments — every server dies when its AI session ends.
สามเรื่องนี้ไม่รวมเป็นคะแนนเดียว เพราะความเห็น การวัด และความนิยม เป็นคนละเรื่องกัน
ตัวนี้ยังไม่ได้เรียบเรียงเป็นภาษาไทย ด้านล่างคือข้อเท็จจริงที่เราอ่านจาก registry
เลือกโปรแกรม AI ที่คุณใช้ แล้วคัดลอกค่าตั้งไปวาง
ต้องเตรียมก่อน
คุณใช้แอปไหน
เลือกแอปด้านบน เราจำไว้ให้ ครั้งหน้าปุ่มจะขึ้นว่า “ติดตั้งลง …”
เปิด Claude Desktop → Settings → Developer → Edit Config แล้ววางค่านี้ในไฟล์ claude_desktop_config.json
{
"mcpServers": {
"rentctl": {
"command": "uvx",
"args": [
"rentctl"
]
}
}
}พิมพ์คำสั่งนี้ใน Terminal
claude mcp add rentctl -- uvx rentctlวางในไฟล์ .cursor/mcp.json ของโปรเจกต์ หรือ ~/.cursor/mcp.json
{
"mcpServers": {
"rentctl": {
"command": "uvx",
"args": [
"rentctl"
]
}
}
}เบราว์เซอร์จะถามก่อนเปิดแอป จากนั้นแอปแสดงค่าตั้งให้ตรวจแล้วกดยืนยัน ช่อง key เว้นว่างไว้ให้คุณใส่เอง
วางในไฟล์ .vscode/mcp.json ของโปรเจกต์
{
"servers": {
"rentctl": {
"type": "stdio",
"command": "uvx",
"args": [
"rentctl"
]
}
}
}เบราว์เซอร์จะถามก่อนเปิดแอป จากนั้นแอปแสดงค่าตั้งให้ตรวจแล้วกดยืนยัน ช่อง key เว้นว่างไว้ให้คุณใส่เอง
ตัวนี้รันในเครื่องคุณ แต่ ChatGPT ต่อได้เฉพาะ server บนอินเทอร์เน็ต ลองเลือกแอปอื่น
ตัวเลือกเก็บในคุกกี้บนเครื่องนี้ ไม่ต้องมีบัญชี
ค่าตั้งนี้สร้างจากข้อมูลใน registry ของผู้ทำ ถ้าไม่ตรงกับ README ให้เชื่อ README
รันในเครื่องคุณ รายการเครื่องมือจะขึ้นในแอป AI หลังติดตั้ง
เราตรวจจากข้อมูลที่ใครก็เปิดดูได้ ยังไม่ได้อ่านโค้ด ข้อที่ไม่เกี่ยวกับตัวนี้ไม่นับในตัวหาร · ตรวจเมื่อ 7 พ.ย. 2569
ชื่อใน registry ยืนยันด้วยบัญชี GitHub Michael-Drake ซึ่งเป็นเจ้าของ repo
ยังไม่ได้อ่านข้อมูล repo จาก GitHub
ยังไม่ได้อ่านข้อมูล repo จาก GitHub
ตัวนี้รันบนเครื่องคุณ ไม่มี endpoint บนอินเทอร์เน็ต
ตัวนี้รันบนเครื่อง ใช้ค่าที่ตั้งในเครื่องแทน
รันในเครื่องคุณ เราอ่านรายการเครื่องมือได้เฉพาะตัวที่มี endpoint บนอินเทอร์เน็ต
เทียบกับทุก server ที่ยังใช้งานในหมวดนี้ทั้งทะเบียน ดาวนับเฉพาะเมื่อผู้ลงทะเบียนเป็นเจ้าของ repo
จากการตรวจเบื้องต้นของเรา ผ่าน 1 จาก 1 ข้อที่ตรวจได้ เรายังไม่ได้อ่านโค้ด ก่อนใส่กุญแจหรือ token ให้ดูว่า server ขอสิทธิ์อะไร และเลือกกุญแจที่ทำได้เท่าที่จำเป็น
registry ไม่ได้ระบุว่าต้องใช้กุญแจ แต่บางตัวจะขอให้ล็อกอินตอนใช้ครั้งแรก
รันบนเครื่องของคุณ โปรแกรม AI จะเปิด server ขึ้นมาเองเมื่อใช้ ข้อมูลไม่ต้องผ่านเซิร์ฟเวอร์ของผู้ทำ (ยกเว้นตัวที่ไปเรียกบริการออนไลน์ต่อ)
repo บน GitHub มีการแก้โค้ดล่าสุด – และส่งรุ่นล่าสุด (1.2.0) เข้า registry 38 วันที่ผ่านมา
โปรแกรมที่รองรับ MCP เช่น Claude Desktop, Claude Code, Cursor และ VS Code ตัวนี้ต้องมี Python (uv) ในเครื่องด้วย
ในหมวดเดียวกันมี Spec Driven Development, Remote Desktop Commander, Detailing Manager
server หมวดเดียวกันจากผู้ทำคนอื่น เรียงตามดาว
อ่านการ์ด:★ ดาว GitHubiสามเสา: รีวิว · ผลตรวจ · การใช้งานiอัปเดต = วันที่ส่งรุ่นล่าสุดเข้า registryi
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Connect your auto detailing studio's tasks, cars, clients and revenue to Claude or ChatGPT.
ส่วนนี้คัดจาก repo ของผู้ทำตามต้นฉบับ PopNx MCP ไม่ได้ตรวจหรือรับรองเนื้อหา ตัด HTML รูปภาพ และสคริปต์ออกแล้ว ลิงก์จะพาออกนอกเว็บ
A dev server should never outlive the work that needed it.
rentctl *rents* dev environments to your AI coding sessions. Every environment is a lease: it dies when the session ends, when the lease expires, or when you say so — whichever comes first. Cleanup is owned by code, not by an agent remembering to clean up.
Ships as both a CLI (rent) and an MCP server, so an agent can start and stop environments through tools instead of shelling out to a raw npm run dev it will forget about.
An AI coding session starts a dev server. Then the session ends — crashes, is closed, or just moves on — and the server keeps running. By Friday there are six of them, three are on ports you've forgotten, and one is quietly serving stale code that makes a bug look unreproducible.
Telling the agent to clean up doesn't fix this, because the failure mode *is* the agent not doing what it was told. rentctl makes the cleanup structural: the environment has an expiry, and something other than the agent enforces it.
uv tool install rentctl # or: pipx install rentctl, or: pip install rentctl
Requires Python 3.12+. macOS and Linux. There is no Windows support and no Windows claim — POSIX sessions are the safety-critical mechanism here, and they have no tested Windows equivalent yet.
Upgrading from 1.0.x? Drain first. Run rent down --all in each project before you upgrade, then restart your agent sessions so their MCP servers load the new version. Skipping it is safe but degraded: a 1.0.x environment keeps working under 1.1 — rent up renews it, and rent down and rent sweep stop it by its whole session — but a 1.0.x watchdog still running from before the upgrade enforces its expiry with the old code, which can miss a child that outlived its shell.
A framework-free server, so nothing but Python is involved. In a scratch repo:
mkdir hello && cd hello && git init -q
cat > rentctl.toml <<'EOF' [project] name = "hello" runner = "process"
[profiles.default] cmd = 'python3 -m http.server --bind 127.0.0.1 "$PORT"' cwd = "." port_env = "PORT" EOF rent init
init shows you exactly what it will run and waits for an explicit yes:
Enroll project 'hello' (runner: process)
source: /home/you/hello port block: 6200-6209
rentctl will run these commands on your behalf: [default] command: python3 -m http.server --bind 127.0.0.1 "$PORT" in: /home/you/hello port via $PORT
Approve and enroll? [y/N] y
Your block will differ — blocks are drawn from 5100 upward, lowest free first. Then:
$ rent up hello
{ "ok": true, "project": "hello", … "url": "http://localhost:6200", "port": 6200, … "lease_expires": "2026-09-28T15:50:21.327166-05:00", "already_running": false, "state": "running", "supervisor_pid": 24202, … "readiness": "answered" }
$ rent ls # one row: hello, port 6200, "state": "running", "healthy": true $ curl -sI http://localhost:6200/ HTTP/1.0 200 OK
$ rent down --all --cwd . --reason session-end # what the SessionEnd hook runs { "ok": true, … "downed": [ { "project": "hello", …, "port": 6200, "was_running": true, "stopped": null, "pending": true, "state": "stopping", "detail": "supervisor 24202 is completing cleanup; rent ls shows the outcome" } ] }
$ curl -sI http://localhost:6200/ || echo gone gone
(Output trimmed where marked ….) That last step is the whole product: in an enrolled Claude Code or Gemini CLI session you never type rent down — the session ending does. The hook doesn't wait for the server to die; it asks, and the environment's supervisor finishes the job (see How cleanup actually happens). rent down hello, typed by hand, waits and answers "stopped": true. rent events --summary afterwards shows the teardown and which cleanup layer did it.
If something doesn't behave, see Troubleshooting.
A project describes itself in a rentctl.toml at its repo root (a devctl.toml left over from before the rename is still read, so nothing needs renaming to keep working):
[project]
name = "myapp" # lowercase, no separators — it is used as a filename runner = "process"
[profiles.default] cmd = 'npm run dev -- --port "$PORT" --strictPort' cwd = "frontend" # repo-relative, never absolute port_env = "PORT" # rentctl sets this in the child's environment
Then, from the repo:
rent init
init shows you the exact command it will run, asks you to approve it, claims a block of ports for the project, registers the MCP server, installs the cleanup hooks (unless the Claude Code plugin already supplies them), and adds a short rule to CLAUDE.md / GEMINI.md telling agents to start servers through rentctl rather than by hand. Nobody else has to edit anything.
There is no port field. Ports are drawn when a server starts, not written down in a tracked file — so two checkouts of the same repo get different ports instead of fighting, and a config file can't hand out a number the allocator never heard of. Each project owns a contiguous block of 10 ports.
rent up myapp # start (or renew) — prints the URL and the port
rent down myapp # stop it; waits up to 15 s (--wait SECONDS, --wait 0 = don't wait) rent down --all --cwd . # stop everything leased to this directory rent ls # every environment on this machine, with its state rent sweep # reconcile: stop what's expired or dead rent events --summary # what happened, and which cleanup layer did it rent sync # re-approve a changed rentctl.toml rent doctor # are the shims, registry and hooks actually working? rent report-kill myapp --note "…" # "you killed something I was using"
report-kill exists because rentctl cannot tell, on its own, whether a teardown was unwanted — a kill you asked for and a kill you regret look identical from the inside. The report lands in the same append-only log as everything else and is matched to the teardown it disputes, so an unwanted kill becomes a fact on the record rather than an anecdote.
Leases default to 120 minutes and are capped at 480. rent up on a live lease renews it rather than starting a second server.
| Client | How it is wired | Session-end cleanup |
|---|---|---|
| Claude Code | the plugin (guide), or rent init (.mcp.json + .claude/settings.local.json) | Yes — SessionEnd releases the session's claim (rent down --all --cwd … --reason session-end); SessionStart runs rent sweep |
| Codex | the plugin (guide) | Yes, once you trust the plugin's hooks (/hooks) — the same hooks; until then, expiry and sweep |
| Gemini CLI | rent init (.gemini/settings.json), when Gemini is used in the project or installed | Yes — same hooks, scoped by $GEMINI_PROJECT_DIR |
| Any other MCP client | register rent-mcp yourself | No — lease expiry and sweep only |
| A plain shell | rent | No — lease expiry and sweep only |
"Expiry and sweep only" still guarantees the server dies — just at the end of its lease (120 minutes by default), not when you close the window.
Plugin-only installs need the CLI too. The plugin (Claude Code or Codex) calls the rent and rent-mcp you installed with uv tool install rentctl; it does not bundle them, and it deliberately does not fetch its own copy — a second, different rentctl acting on the same leases is worse than none. Without rent on PATH, session-end cleanup is off: every session then starts with a warning saying so and naming the install command. Install the package first, then run rent doctor, which reports whether each project's hooks come from the plugin, from settings.local.json, or from both.
From the MCP Registry, a client runs uvx rentctl@ : the rentctl executable is the MCP server, the same as rent-mcp (typed in a terminal it waits for a client on stdin). That gives you the tools with expiry-and-sweep cleanup only — the hooks come from the plugin or rent init. rent --version says which version you are running.
Every environment has its own supervisor: a small rentctl process that starts your command inside a POSIX session it owns and stays until that whole session — the command, its children, and anything they spawned — has been checked and found empty. The lease is written before the command starts, so there is no moment when something is running that rentctl has no record of.
Every stop, whatever asked for it, is the same: SIGTERM to every process in the session, SIGTERM to anything forked while it shuts down, SIGKILL to each process still there after 10 s, then a final scan. A child that ignores SIGTERM, or that outlived the shell that launched it, is stopped with the rest.
Four independent layers decide *when*, so no single failure leaves an orphan:
rent down.SessionEnd hook releases that session's claim on everything leased to that directory. The server stops if no other session still holds a claim.rent sweep (which the hooks also run at session start) and rent ls clean up what the first three missed, including an environment whose supervisor was killed.What `rent down` tells you is what the lease says, in one of three shapes:
"stopped": true — the session was scanned empty and the lease removed."stopped": false, "state": "cleanup_incomplete", "survivors": [...] — something could not be stopped (a child that switched user with sudo, say). The lease is kept, so the survivors stay named and the port stays out of the draw; the supervisor keeps retrying (5 s, 15 s, 60 s, then every minute), rent down retries at once, and rent up refuses with CLEANUP_INCOMPLETE until it clears."stopped": null, "pending": true — the stop was accepted and is still running; rent ls shows how it ended. This is "ok": true: the supervisor finishes regardless.rent down waits up to 15 s for the first two (--wait SECONDS; --wait 0 returns at once). The MCP tool env_down takes the same wait as wait_s — 15 s by default, 60 s at most.
Session end returns fast; cleanup finishes in the background. Claude Code gives a plugin's SessionEnd hook about 1.5 s. So the hook's rent down --all --reason session-end doesn't wait: it records a stop for every lease that no other session still holds, wakes each supervisor, and returns pending. The supervisors don't need the session to finish. A lease with no living supervisor is handed to a detached recovery process rather than stopped halfway.
A crashed session is cleaned up by layers 3 and 4, not 2. If the session dies without firing its hook, its server keeps running until the lease expires — up to the full lease length. Shorter leases (rent up myapp --lease-minutes 30) shorten that window. A sweep does not stop a live, unexpired lease; it cannot tell a crashed session from one that is still working.
If a supervisor is killed, recovery waits for the next command. The server keeps serving. The next rent ls, sweep, up or down notices, marks the lease unsupervised, and records supervisor_lost; it is not killed early. At its expiry the next of those commands stops it, and rent down stops it now. Nothing notices at the moment the supervisor dies, because nothing else is running to notice.
There is no daemon. Th
ตัดมาแค่ช่วงต้น อ่านต่อใน repo