
Orangerail
io.github.KimHyeongRae0由 GitHub 帳號 KimHyeongRae0 發布v0.1.4更新於 Oct 24, 2026
Turns your Prisma schema into typed MCP tools, with destructive writes gated behind human approval
概覽
依現有 Prisma schema 產生具型別的 MCP 伺服器,讓助理依物件讀寫資料,並把破壞性寫入置於人工核准之後。
- 可以做什麼
- 讀取物件:為每個 Prisma 模型提供依 id 的 get 與分頁 list,篩選條件僅限已宣告欄位,不支援自由查詢、聯表或彙總。寫入物件:每個寫入操作對應一個具型別驗證的動作,輸入依你的欄位定義驗證。處理核准:標記為需要核准的破壞性動作會被攔下並暫存,只有人工核准後 check_approval 才會執行。檢視治理狀況:studio 指令顯示物件、關聯及哪些動作被攔下,status 指令報告待核准項目與稽核鏈狀態。
- 適用情境
- 當助理需要透過 Prisma schema 存取資料庫,而你希望以固定、可讀的工具介面取代 SQL 時使用,特別適合無人值守執行、刪除等破壞性寫入應等待人工決定的情境。
- 執行需求
- 本機 Node.js 專案,且包含 prisma/schema.prisma 檔案。安裝 orangerail 命令列工具以及 orangerail-core 與 zod 執行階段套件,執行 orangerail init 產生伺服器,並提供 DATABASE_URL 指向產生動作所存取的資料庫。需要與產生程式碼相容的 Prisma 用戶端版本。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Orangerail,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
Give your agent your database. Don't give it SQL.
[npm] [CI] [node] [published with provenance] [license]
Quickstart · Commands · What it does not govern · Against a rules file · Examples · Docs
orangerail init on a three-model Prisma schema, then a real tools/list against the server it
generated. Sixteen tools: a get and a list per object, one action per write, and
check_approval. Nothing on that list takes a query. The three locks are --gate delete, which
is a default you change in one line, not a verdict.
A rules file cannot do this. It can ask the agent not to run a query. It cannot take the tool off the list — and we measured what the difference is worth, including the four claims that died when we did.
orangerail reads the schema you already have and generates the agent's surface from it.
orangerail init turns a prisma/schema.prisma into an MCP server: a get and a list per
object, one action per write with a zod input schema, and nothing else — no execute_sql, and
nothing on the tool list that takes a query. It is a scanner and a code generator, with no LLM
calls and no API keys. Writes you are happy to have run unattended run unattended. The ones you are
not carry policy: { approval: 'required' }, which stops the call and turns it into an approval a
person can act on later — including a person who is not you, after the conversation that produced
it has ended.
Bounded is not safe, and this README will not pretend otherwise. A generated surface buys a reach that is finite and legible, not a claim that nothing harmful is inside it. You declared the verbs, so a destructive verb you declared is a verb the agent can call.
One precondition decides whether any of this is worth installing: orangerail governs only its own tools. If the agent also has a shell with credentials or a second database MCP server, it can go around the rail — see what orangerail does not govern.
Pre-release and installable: 0.1.5 on npm — orangerail (the CLI) plus orangerail-core,
orangerail-mcp, orangerail-docs-gen and orangerail-studio. The API will move before 1.0, and
Status has the one upgrade note that matters.
See your whole domain as a map
One command, and the surface init generates is a map you can read.
Every object, how they relate, and every write action an agent can reach. Hover a table to light up its relations and actions; click one to read the policy that governs it.
Crisper version:
assets/studio-map.mp4— the same run at full resolution. One real run on a sample commerce domain,--gate delete. The locks are not annotations added for the video: they are what the studio draws from your ontology, which is why nine actions carry one and eighteen do not.
Be exact about what that is worth. The relations come from ontology/_links.mjs, which init
derives from your Prisma relations, so Customer_list's description reads List Customer records. Relations: has many Order. The agent is told that a Customer has many Orders. It still cannot
follow the edge: no traversal tool, no join, no aggregate, and Customer_list refuses a filter that
reaches into Order. Knowing the shape of a domain and being able to query across it are different
things, and only the first one is here.
Quickstart
Seven steps, every output verbatim from one recorded run. The reasoning behind each one — and the failure each prevents — is in Quickstart, annotated; requirements and the Prisma 7 caveat are the first thing on that page.
1. Install orangerail into the project you are about to scan.
2. Scan your project, in a repo with a prisma/schema.prisma.
3. Install the runtime the generated code loads.
4. Give the generated actions a database to reach.
Already have a database? Do not
db pushover it — adopting orangerail against an existing database.
5. Point your agent host at it. Drop this in your project root as .mcp.json:
Other hosts, the claude mcp add one-liner, and running from source:
wire it into your agent host.
6. Record the governance baseline — and commit it. ontology/ is yours to edit, so the one
line that disarms the whole flow is one careless deletion away and a re-scan cannot notice. The
posture is compared against a recorded file instead.
Commit orangerail.governance.json. Its whole value is that a pull request removing an
approval gate shows "approval": "required" turning into null in its own diff, in front of a
reviewer, before CI runs at all.
7. Now leave. While you are gone the agent works the queue: the writes you left un-gated go through, and the deletion it was asked for stops. When you come back:
The agent's next check_approval is the first moment the row can change. Nothing ran before you
said so, and every step is on the hash chain. That whole sequence is what
tests/e2e/ONT-093-quickstart-runs-as-documented.sh
runs against this repository's own build on every regression pass.
Why the prompt is the wrong control
The thing stopping you from walking away is not that the agent does too much. It is that your
only control is a question it has to ask you. The twentieth prompt of the afternoon gets the same
click as the first, and the switch that ends the asking ships in the box — Claude Code's
bypassPermissions mode "skips permission prompts, except those forced by explicit ask rules",
per its own permissions reference. A boundary
re-established by a person on every call cannot hold once nobody is there.
The prompt is also the wrong shape. It asks about a tool — may this run Bash — and the risk you
carry is about your domain: stock edits are fine, order deletions are not, refunds under $50 need
nobody. That distinction does not exist at the tool level. It exists in your schema.
The run this is built for
One run of examples/unattended-queue — a real MCP client, no API
key, every line asserted. The video shows six of the twelve; the row numbers jump, so you can see
where.
A 15-item back-office queue on a commerce database, handed to an agent with the operator gone for the day and told not to ask for confirmation. Twelve items are ordinary reversible writes. Three are destructive: delete a cancelled order, delete a customer under an erasure request, delete a discontinued product. Scored from the database afterwards, not from what the agent said it did:
That is the metric this project is built around, and it is not "how much did we block". It is how much finished while nobody was watching, and what is waiting when you get back.
Two separable claims sit in that table and they are not equally well evidenced. That the twelve go
through and the three cannot is a property of the server, and it is reproducible on your
machine — examples/unattended-queue runs exactly that queue
through a real MCP client, deterministically, asserting every line. That a model chooses these
calls when handed the queue in prose needed a live agent driving a real host, and that half is a
measurement, not a reproduction: small numbers, enough to say the gate holds where it was tested
and not enough to be a rate.
Against the thing you would do instead
The comparison that matters is not a raw SQL server. It is a rules file: a well-written CLAUDE.md
naming the permitted tables and the forbidden ones, over a Postgres MCP server with full write
access. Same queue, same model, three clones.
It tied on compliance, and it kept tying — through adversarial rewrites, a fake prior approval, an instruction planted in a database row, and a much smaller model. On one axis it beat us. So this project does not argue that your agent will ignore your rules: across every run measured here, it followed them.
That is six runs. Enough to retire the claim that it would not, nowhere near enough to be a rate — zero failures in six bounds the tail near 39%, not near zero. Buying a real bound is expensive and it perishes on the next model release, which is the reason the row below is the one this project stakes itself on: what ten runs cannot prove.
The row that does not tie is the last one, and it is not about the agent's behaviour: a grant
travels with the session it was registered for, and a rules file travels with the machine account
it was written under. A global ~/.claude/CLAUDE.md closes most of that gap for a single developer
on one machine — if that is you, you may not need this. It stops closing at a CI runner, a
container, a service account, or a teammate's checkout, each of which gets the database credentials
anyway.
Every run, the axis where the rules file wins, and the limits of the measurement:
against the thing you would do instead.
examples/vs-a-rules-file executes both arms.
What the agent gets instead of execute_sql
Run orangerail init on a three-model Prisma schema (Order, OrderItem, Payment) and the
entire tool list is 16 entries: a get and a list per object, one action per write, and
check_approval. Nothing else, and nothing that takes a query.
Each action's input is a zod schema derived from your own columns, published in tools/list, so
updateProduct refuses a string where the column is an integer and says which field it was. Each
read is a findUnique by id or a paged findMany, whose filter is a closed set of predicates
over declared fields — enforced by the server before it reaches your resolver, not merely
advertised.
A fixed surface is a narrow one: no aggregation, no join, no free-form query, no DDL. A question it cannot express has to be answered somewhere else — all of it, and where enforcement actually lives, is in what orangerail does not govern.
See it stop an agent
One real run of examples/governed-writes through a real MCP
client. The destructive tool stays available rather than hidden, the agent cannot force it
through, and the row changes only after a human decided — in a separate terminal, at a
separate time, which is the part that makes leaving possible.
Declaring a rule the generator cannot derive
Everything above is generated. When a rule lives in your head rather than your schema — "never issue a coupon for a sold-out item" — you write it once, in TypeScript, and it joins the same surface:
That block is not an illustration — it is
packages/cli/test/readme-example.ts printed verbatim,
compiled by the repo typecheck and compared against this file on every run, so it cannot rot into
something that never compiled.
Status
orangerail init runs against your own project today, with no checkout of this repo, and the API
will move before 1.0. All five packages are published from
.github/workflows/release.yml over npm's Trusted Publishing,
so each one carries a provenance attestation naming the workflow and commit that built it; there is
no npm token in this repository.
Upgrade from 0.1.0 if you are on it. That release published a read filter to the agent and
never checked it, so a <Object>_list call could read an object type the server never exposed
(the mechanism). The fix
is in 0.1.2 and lives in orangerail-mcp, so upgrading the package applies it with no re-run of
init. 0.1.2 also narrows what filter accepts and changes what a pending approval does across
the upgrade — both under Upgrading from 0.1.0 in the CHANGELOG.
Docs
- Commands — every command, what
--gatechooses, and how to narrow the surface to the tables you name. - Quickstart, annotated — the seven steps with the reasoning, the requirements, and the failure each step prevents.
- Wire it into your agent host — stdio,
.mcp.json, and running from source. - What orangerail does not govern — the preconditions, the missing capabilities, and where enforcement actually lives.
- What the audit log proves — the exact bar, why "tamper-evident" is not used, when a database-level audit is the better tool, and where to put the store.
- Against the thing you would do instead — the full rules-file comparison.
- How orangerail compares — against
--read-only, OpenAPI codegen, Prisma's own servers and Supabase's. - Adopting orangerail against an existing database —
prisma db pullonto a live database, and what Prisma 7 changes. - Also ask the host to prompt — the optional client-side prompt on un-gated writes.
- Troubleshooting — the readouts that report something is wrong with the install rather than with your policy.
- What we measured, and what died — every claim this project made or was tempted to make, and which ones survived being run. Four did not.
bench/— the fixtures behind that page, so you can disagree by reproducing rather than by arguing.- The MCP registry entry — what the listing is, and the step a hundred-character description cannot fit.
Examples
unattended-queue— the run at the top of this file, made reproducible. Deterministic, asserted, no API key.governed-writes— the same gate in isolation, one destructive call at a time.vs-a-rules-file— the rules-file comparison made runnable, both arms executed, including the column where the rules file wins.
Development
This repo is built under a deterministic 9-stage gate harness. Every change runs through
./scripts/verify.sh — language, structure, gate self-test, no-LLM,
templates, then typecheck / lint / test / build — and CI runs that script and nothing else, so a
green local run is a green build. A hard invariant: no LLM-inference SDK is ever bundled
(./scripts/check-no-llm.sh).
License
來源:README.md,提交 5514a2d
工具
0版本歷史
1- v0.1.4最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分