Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
คำอธิบายจากผู้ทำ (ภาษาอังกฤษตามต้นฉบับ)
Read-only decision table over ACH return codes: 17 codes, 5 decisions, rule shown.
สามเรื่องนี้ไม่รวมเป็นคะแนนเดียว เพราะความเห็น การวัด และความนิยม เป็นคนละเรื่องกัน
ตัวนี้ยังไม่ได้เรียบเรียงเป็นภาษาไทย ด้านล่างคือข้อเท็จจริงที่เราอ่านจาก registry
เลือกโปรแกรม AI ที่คุณใช้ แล้วคัดลอกค่าตั้งไปวาง
ต้องเตรียมก่อน
คุณใช้แอปไหน
เลือกแอปด้านบน เราจำไว้ให้ ครั้งหน้าปุ่มจะขึ้นว่า “ติดตั้งลง …”
เปิด Claude Desktop → Settings → Developer → Edit Config แล้ววางค่านี้ในไฟล์ claude_desktop_config.json
{
"mcpServers": {
"paypilot-ach-returns": {
"command": "uvx",
"args": [
"paypilot-ach-returns-mcp"
]
}
}
}พิมพ์คำสั่งนี้ใน Terminal
claude mcp add paypilot-ach-returns -- uvx paypilot-ach-returns-mcpวางในไฟล์ .cursor/mcp.json ของโปรเจกต์ หรือ ~/.cursor/mcp.json
{
"mcpServers": {
"paypilot-ach-returns": {
"command": "uvx",
"args": [
"paypilot-ach-returns-mcp"
]
}
}
}เบราว์เซอร์จะถามก่อนเปิดแอป จากนั้นแอปแสดงค่าตั้งให้ตรวจแล้วกดยืนยัน ช่อง key เว้นว่างไว้ให้คุณใส่เอง
วางในไฟล์ .vscode/mcp.json ของโปรเจกต์
{
"servers": {
"paypilot-ach-returns": {
"type": "stdio",
"command": "uvx",
"args": [
"paypilot-ach-returns-mcp"
]
}
}
}เบราว์เซอร์จะถามก่อนเปิดแอป จากนั้นแอปแสดงค่าตั้งให้ตรวจแล้วกดยืนยัน ช่อง key เว้นว่างไว้ให้คุณใส่เอง
ตัวนี้รันในเครื่องคุณ แต่ ChatGPT ต่อได้เฉพาะ server บนอินเทอร์เน็ต ลองเลือกแอปอื่น
ตัวเลือกเก็บในคุกกี้บนเครื่องนี้ ไม่ต้องมีบัญชี
ค่าตั้งนี้สร้างจากข้อมูลใน registry ของผู้ทำ ถ้าไม่ตรงกับ README ให้เชื่อ README
รันในเครื่องคุณ รายการเครื่องมือจะขึ้นในแอป AI หลังติดตั้ง
เราตรวจจากข้อมูลที่ใครก็เปิดดูได้ ยังไม่ได้อ่านโค้ด ข้อที่ไม่เกี่ยวกับตัวนี้ไม่นับในตัวหาร · ตรวจเมื่อ 6 พ.ย. 2569
ชื่อใน registry ยืนยันด้วยบัญชี GitHub IvanSFlowGit ซึ่งเป็นเจ้าของ repo
ยังไม่ได้อ่านข้อมูล repo จาก GitHub
ยังไม่ได้อ่านข้อมูล repo จาก GitHub
ตัวนี้รันบนเครื่องคุณ ไม่มี endpoint บนอินเทอร์เน็ต
ตัวนี้รันบนเครื่อง ใช้ค่าที่ตั้งในเครื่องแทน
รันในเครื่องคุณ เราอ่านรายการเครื่องมือได้เฉพาะตัวที่มี endpoint บนอินเทอร์เน็ต
เทียบกับทุก server ที่ยังใช้งานในหมวดนี้ทั้งทะเบียน ดาวนับเฉพาะเมื่อผู้ลงทะเบียนเป็นเจ้าของ repo
จากการตรวจเบื้องต้นของเรา ผ่าน 1 จาก 1 ข้อที่ตรวจได้ เรายังไม่ได้อ่านโค้ด ก่อนใส่กุญแจหรือ token ให้ดูว่า server ขอสิทธิ์อะไร และเลือกกุญแจที่ทำได้เท่าที่จำเป็น
registry ไม่ได้ระบุว่าต้องใช้กุญแจ แต่บางตัวจะขอให้ล็อกอินตอนใช้ครั้งแรก
รันบนเครื่องของคุณ โปรแกรม AI จะเปิด server ขึ้นมาเองเมื่อใช้ ข้อมูลไม่ต้องผ่านเซิร์ฟเวอร์ของผู้ทำ (ยกเว้นตัวที่ไปเรียกบริการออนไลน์ต่อ)
repo บน GitHub มีการแก้โค้ดล่าสุด – และส่งรุ่นล่าสุด (0.1.1) เข้า registry 4 วันที่ผ่านมา
โปรแกรมที่รองรับ MCP เช่น Claude Desktop, Claude Code, Cursor และ VS Code ตัวนี้ต้องมี Python (uv) ในเครื่องด้วย
ในหมวดเดียวกันมี Spec Driven Development, Remote Desktop Commander, Zoo MCP
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.
An MCP server that provides access to the Zoo API for various CAD operations and tools.
ส่วนนี้คัดจาก repo ของผู้ทำตามต้นฉบับ PopNx MCP ไม่ได้ตรวจหรือรับรองเนื้อหา ตัด HTML รูปภาพ และสคริปต์ออกแล้ว ลิงก์จะพาออกนอกเว็บ
An AI dunning agent that recovers failed subscription payments.
[Live demo -> paypilot.fly.dev](https://paypilot.fly.dev/) - try it in the browser, no setup or API key required.
When a recurring charge fails, most of that revenue is recoverable - the customer didn't *decide* to churn, their card just expired or a payment bounced. PayPilot turns each invoice.payment_failed event into a grounded, on-brand recovery action: it diagnoses *why* the payment failed, picks the right retry strategy for that reason, and drafts a warm, one-click dunning email - all in a single API call.
It's built as a small, readable LangGraph agent with retrieval-augmented generation (RAG) over a dunning playbook, exposed through a FastAPI endpoint. The whole thing runs its test suite with no API key and no network.
A failed-payment event flows through a seven-node LangGraph StateGraph. Each node enriches a shared, typed RecoveryState and hands it to the next:
flowchart LR
A[retrieve_context] --> R[assess_risk] R --> B[diagnose_reason] B --> C[choose_strategy] C --> S[schedule_retry] S --> D[draft_message] D --> E[finalize] E --> F([END])
| Node | What it does |
|---|---|
retrieve_context | Loads the customer record and pulls relevant snippets from the dunning playbook via the RAG retriever. |
assess_risk | Deterministic (no LLM): scores churn risk (low/medium/high) from the dunning attempt number and the customer's recent failure streak. |
diagnose_reason | Committed template by default, LLM only with PAYPILOT_LLM_DRAFT=1: a 1-2 sentence, playbook-grounded diagnosis of *why* the payment failed, reflecting the churn risk. |
choose_strategy | Deterministic (no LLM): maps the failure code to a fixed action + retry cadence, then tightens it when churn risk is high. Stable and unit-testable. |
schedule_retry | Deterministic (no LLM): turns the cadence into a concrete next_retry_at UTC time, ready to hand to a scheduler. |
draft_message | Committed template by default, LLM only with PAYPILOT_LLM_DRAFT=1: a short, warm dunning email with one clear call to action. |
finalize | Assembles the {diagnosis, risk, strategy, schedule, message, impact} response payload. |
The recovery quality depends on dunning best-practice - retry timing, tone, when to offer a grace period. Rather than bake that into prompts, PayPilot keeps it in an editable knowledge source (data/playbook.md) that the retriever feeds into the diagnosis and drafting nodes.
Which retriever depends on configuration, and it is worth being precise about this. With OPENAI_API_KEY set, app/ingest.py builds a FAISS index over the playbook using OpenAI embeddings (k=3). With no key - which is how the public demo runs - it falls back to a lexical keyword retriever, so no FAISS index and no embedding call is involved in anything a visitor sees.
And the playbook only changes the output on the LLM path. On the default zero-inference path the committed templates are rendered as-is and retrieved context is not consulted, so editing playbook.md changes nothing until PAYPILOT_LLM_DRAFT=1 is set. Playbook edits are input to the build-time generation step, not to every request.
choose_strategy is intentionally *not* an LLM call. Retry cadence and the chosen action come from a fixed rules table (app/decision.py) keyed on the failure code, which comes from Stripe, Recharge, Chargebee or Loop:
| Failure code | Retry in | Action | Tone |
|---|---|---|---|
card_expired | ~1 day | request card update | Friendly, routine |
insufficient_funds | ~3 days | wait and retry | Soft, no pressure |
generic_decline | ~2 days | retry and verify | Calm, helpful |
issuer_do_not_retry | never | request new payment method | Plain, no blame |
card_details_invalid | never | request card update | Plain, no blame |
direct_debit_not_retried | never | request manual payment | Plain, no blame |
retries_exhausted | never | request new payment method | Plain, no blame |
The LLM writes the *message*; the *policy* stays predictable.
irreversible-reach maps which model-produced values in an agent can reach an action that cannot be undone. Its PayPilot manifest marks sending an email as PayPilot's only irreversible action, with deterministic guards in front of it; remove those guards and it fails. A manifest describes code, it does not test it.
assess_risk reads the dunning attempt number and the customer's recent payment history (from data/customers.json) and buckets churn risk. When it's high - a third attempt, or a run of recent failures - choose_strategy tightens the retry cadence and marks the strategy escalated, the diagnosis calls out the urgency, and impact discounts the recovery odds for a customer who keeps bouncing. So the agent reasons about *history*, not just the single event in front of it.
# 1. Install
python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt
cp .env.example .env # then add your OPENAI_API_KEY
PAYPILOT_TENANT=demo uvicorn app.api:app --reload
curl -s http://localhost:8000/payment-failed \
-H 'Content-Type: application/json' \ -d '{ "customer_id": "cust_001", "amount": 1499.0, "currency": "usd", "failure_code": "card_expired", "attempt": 1 }' | jq
{
"diagnosis": "The card on file for Acme Robotics has expired, so the Scale renewal couldn't be charged; ...", "risk": { "attempt": 1, "prior_failures": 0, "churn_risk": "low", "escalate": false }, "strategy": { "action": "request_card_update", "retry_in_days": 1, "offer": "...", "escalated": false }, "schedule": { "retry_in_days": 1, "next_retry_at": "2026-07-02T09:00:00+00:00", "retry_on": "2026-07-02", "timezone": "UTC" }, "message": "Hello Acme Robotics, we tried to renew your Scale plan but the card we have on file has expired ...", "impact": { "amount_at_risk": 1499.0, "currency": "USD", "recovery_likelihood": 0.7, "expected_recovered": 1049.3, "annual_value_at_risk": 17988.0, "churn_risk": "low" } }
GET /health returns {"status": "ok"} for liveness checks. The full response schema (typed with pydantic) is browsable at /docs.
The endpoint is rate limited per client IP, and the response payload is a typed RecoveryResponse (diagnosis, risk, strategy, schedule, message, impact), so the contract shows up precisely in the OpenAPI docs.
POST /payment-failed/batch runs a whole billing run (up to 50 events) in one call and adds a portfolio aggregate - total at risk, total expected recovered, and how many accounts are high churn risk. GET /portfolio-impact rolls that up across the demo customers and powers the recoverable-revenue headline on the landing page.
Status: no client traffic reaches this deployment, so no merchant's live Stripe delivery has either. The handler is exercised offline by tests/test_stripe.py.
POST /webhooks/stripe accepts a real Stripe invoice.payment_failed event. It verifies the Stripe-Signature header (HMAC-SHA256) when STRIPE_WEBHOOK_SECRET is set, acknowledges other event types with a 200 so Stripe won't retry, maps Stripe decline codes (expired_card, insufficient_funds, ...) to PayPilot's failure codes, and runs the recovery graph. Point a webhook (or stripe trigger invoice.payment_failed) at it; add metadata.paypilot_customer_id to resolve a demo customer.
Status: this deployment carries no client traffic, so no merchant's live Recharge delivery has reached it. The handler is exercised offline by tests/test_recharge.py.
POST /webhooks/recharge accepts Recharge charge/failed and charge/max_retries_reached deliveries for Shopify subscription stores. It checks X-Recharge-Hmac-Sha256 against RECHARGE_CLIENT_SECRET the way Recharge documents it, and maps every one of Recharge's 109 published error types to a PayPilot failure code (the full table). Recharge runs its own retries, so when it will retry, its retry_date is reported as the schedule with source="recharge" and no customer email is drafted (message_suppressed: "recharge_retry_scheduled"). Errors that are not a payment problem the customer can fix (inventory, shipping, tax, test mode) and error types PayPilot does not recognise are acknowledged and not run, so no customer gets an email about them.
A merchant comes on in three steps. They create an API token and copy the API Client Secret from their Recharge admin; the secret goes on the deployment as RECHARGE_CLIENT_SECRET; then RECHARGE_API_TOKEN=... python scripts/recharge_register_webhooks.py --apply registers both webhooks against this deployment (dry run without --apply, and safe to re-run).
The webhook is idempotent on the Stripe event id, so a retried delivery replays the stored result instead of re-running the graph. POST /payment-failed and /batch accept an optional Idempotency-Key header for the same guarantee. Every response carries X-Process-Time and X-Request-ID headers, emits a structured JSON access log, and 429s include Retry-After. GET /metrics (admin token required) returns a JSON snapshot (request counts by status, average latency, recoveries run, total expected recovered). Batches roll up per currency, so a mixed USD/EUR/GBP billing run stays correct (aggregate.by_currency).
For discovery, the app also serves /robots.txt, /sitemap.xml, and an /llms.txt summary for AI answer engines, and the landing page ships SoftwareApplication + FAQPage JSON-LD.
PayPilot does not stop at drafting. It records what failed, what it sent, and what happened next, so "we recovered X" is a figure you can audit rather than a claim.
invoice.payment_failed -> record -> strategy -> portal link -> email
| invoice.paid / payment_succeeded -> recovered <---------------+ customer.subscription.deleted -> churned
Per-invoice state machine: failed -> messaged -> clicked -> recovered | churned | exhausted. Illegal moves raise rather than silently overwrite, so the dashboard can never contradict revenue it already reported. Amounts are stored in integer minor units with a currency code. Floats appear only at the presentation edge, never in storage or arithmetic.
State only advances to `messaged` on a real send. A dry run, a suppr
ตัดมาแค่ช่วงต้น อ่านต่อใน repo