MCP Write Gate

io.github.goran-revops由 GitHub 帳號 goran-revops 發布v0.2.0更新於 Oct 24, 2026

Sits in front of any MCP server. Reads pass, writes are checked against your lists.

已驗證STDIO僅桌面開發者工具安全與監控

概覽

AI 產生的概覽

置於任何 MCP 伺服器之前的寫入閘道,讓 AI 代理自由讀取,但每次寫入都先依你的名單檢查後才放行或拒絕。

可以做什麼
代理連上閘道而非真實伺服器,看到相同的工具名稱與輸入,呼叫時由閘道決定放行或拒絕。讀取直接通過;寫入會比對名單,涉及客戶、進行中交易或禁止聯絡對象時拒絕並告知原因。可設定寫入預設放行或等待人工核准,並限制對同一對象的聯絡頻率。唯讀模式下所有寫入一律拒絕,讀取須經伺服器標記或人工確認才放行。真實 API 金鑰留在閘道資料夾,並從回傳內容中移除;每次呼叫都寫入可偵測竄改的日誌。
適用情境
當你讓 AI 代理透過 MCP 連接真實的業務系統(如電子郵件、CRM、Slack),並希望有一道代理無法繞過的寫入規則時使用。也適合想以唯讀模式搭配完整權限 API 金鑰、讓代理只能查看不能修改的情境。
執行需求
需 Python 3.10 以上,以 pip 或 uvx 安裝並在本機執行。需建立閘道資料夾,內含規則檔、名單檔與存放真實伺服器 API 金鑰的 keys.env。遠端伺服器以 URL 加入,使用 OAuth 的伺服器需人工登入一次。
安裝前請注意
閘道會保管真實伺服器的完整權限 API 金鑰,代理若可讀取閘道資料夾或以同一系統使用者執行程式碼,就能取得金鑰直接呼叫 API,建議以獨立容器隔離。它只檢查呼叫的對象與動作,不檢查訊息內容,也看不到加密內容或純記錄 ID 中的目標。它只控制代理送往伺服器的呼叫,後方只應放置信任的伺服器。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 MCP Write Gate,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

mcp-write-gate

mcp-write-gate sits between an AI agent and the tools it uses through MCP, such as email, a CRM, Smartlead, or Slack. The agent can read freely, but every write is checked before it goes out, and anything aimed at a customer, an open deal, or anyone else on your lists is refused before it reaches the tool.

I built it for GTM and ops teams who connect an agent like Claude Code to their real systems and want a rule the agent cannot argue its way around. The most common setup is read-only mode: you connect Smartlead, HubSpot, or Salesforce with a full-scope API key, and the agent can look at everything but change nothing.

+---------------+               +------------------+                  +-------------------+|   AI agent    |   tool call   |  mcp-write-gate  |  allowed calls   |  Real MCP server  || (Claude Code, | ------------> |                  | ---------------> | (HubSpot, Gmail,  ||  Cursor, ...) | <------------ |                  | <--------------- |  Smartlead, ...)  |+---------------+  the result,  +--------+---------+     results      +-------------------+                   or why it             |                   was refused           v                          +-----------------------------+                          |  read          ->  forward  |                          |  write, safe   ->  forward  |                          |  write, listed ->  refuse   |                          |  write, unsure ->  hold     |                          |  read-only     ->  refuse   |                          |  every call    ->  log      |                          +-----------------------------+

How it works

The agent connects to mcp-write-gate instead of the real server and sees the same tools, with the same names and inputs. When it calls one, the gate decides what happens. A read goes straight through. A write is checked against your lists, and if it touches a customer, an open deal, or anyone marked do not contact, it is refused and the agent is told why. Nothing reaches the tool. A write to someone who is on no list goes through by default, or waits for a person to approve it if you prefer. You can also cap how often one person is contacted, for example one email per week, and on a read-only server every write is refused no matter what the key allows.

The agent never holds the real API key. The key stays in the gate's own folder, and the gate strips it from anything the server sends back. Every call, allowed or refused, goes into a log that shows if anyone edits it later.

Quick start

You need Python 3.10 or newer.

bash
pip install mcp-write-gatemcp-write-gate initmcp-write-gate add mail -- npx -y your-mail-mcp-server

init creates the gate folder in your user folder, away from your projects. It holds gate.json with the rules and the servers, a starter list in lists/off-limits.csv, keys.env for the real servers' API keys, and the log.

add starts the real server once, reads its tools, and guesses which ones read and which ones write. It prints each guess along with a block for your agent's MCP config. Look over the guesses, then paste that block where the real server's entry used to be. In Claude Code it is one command:

bash
claude mcp add mail -- mcp-write-gate serve mail --config "<gate folder>/gate.json"

Remote servers are added by URL, with their keys kept in keys.env and referred to as ${NAME}. A server that uses OAuth needs one sign-in by a person, and after that the gate refreshes the tokens itself:

bash
mcp-write-gate add crm --url https://mcp.example.com/mcp --header 'Authorization: Bearer ${CRM_TOKEN}'mcp-write-gate add crm --url https://mcp.example.com/mcp --oauthmcp-write-gate login crm

Before you rely on a rule, you can test it without sending anything:

bash
mcp-write-gate check mail send_email --args '{"to": ["[email protected]"]}'

Read-only mode

bash
mcp-write-gate add smartlead --preset read-only --url 'https://mcp.smartlead.ai/sse?user_api_key=${SMARTLEAD_KEY}'mcp-write-gate reads smartleadmcp-write-gate confirm smartlead get_campaigns get_campaign_stats

In read-only mode every write is refused, and no list, mode, or approval can change that. A read passes only when it is vouched for, either because the server marks the tool as read-only and its name reads like a read, or because a person confirmed it with mcp-write-gate confirm. mcp-write-gate reads lists every read and who vouched for it.

The gate does not take the server's word for everything. A tool called delete_campaign that the server labels read-only is still treated as a write. If the server changes a tool after you confirmed it, the tool is refused until you confirm it again. A read that tries to change something through its arguments, such as an HTTP DELETE, a SQL statement that writes, or a GraphQL mutation, is refused as well.

That makes it safe to put a full-scope key behind the gate, as long as four things hold:

  1. The gate is the agent's only way to reach that tool.
  2. The agent cannot read the gate folder or run code as the gate's user, because then it could find the key and call the API directly. docs/security.md describes three ways to prevent that, the strongest being a separate container.
  3. You checked each read before confirming it. Generic tools like call_api or run_query need extra care, because a vendor API that deletes on a GET looks like a read.
  4. The key still has the narrowest scopes the vendor offers. The gate is a second lock, so keep the first one too.

Lists

Lists are plain CSV, TXT, or JSON files in the lists/ folder, so you can export them from your CRM or keep them by hand. Every file is read, and a change takes effect on the next call.

csv
target,status,noteexample.com,customer,paying account[email protected],open_deal,in a live deal[email protected],allow,partner contact inside a customer#sales-internal,blocked,chat channel the agent must not post in*/contracts/*,blocked,signed contracts stay untouched

A domain covers all its subdomains, and an email row also covers the same mailbox written with a +tag or with Gmail's dots. When two rows match, the more specific one wins, which is how [email protected],allow can sit inside a customer's domain. A status the gate does not recognize counts as a refusal, so a typo cannot open the gate. If the truth lives in your CRM instead of a file, the gate can run a lookup command for anything that is on no list, as described in docs/configuration.md.

Tested with real servers

ServerWhat was tested
SmartleadAll 170 tools sorted into reads and writes. Replying to a lead, starting a campaign, and forwarding an email were refused and never sent, confirmed reads passed through, and the API key never reached the agent.
HubSpotReads passed through to HubSpot. Creating records and logging engagements were refused and never sent.
GmailAll 23 tools sorted. Drafts, labels, spam, and trash are treated as writes.
SalesforceAll 74 tools sorted. Deploys, permission changes, and Apex tests are writes, and queries are reads.
NotionAll 24 tools sorted. Creating, editing, moving, and deleting pages are writes, and retrieving is a read.
MCP filesystem and everything serversFile paths as targets, resources, prompts, completions, and long-running calls.

I also ran it with Claude Code as the agent. Without the gate, Claude sent the email it was asked to send. With the gate in read-only mode, the email was never sent, and the log showed the refusal.

What it does not protect against

The gate checks who and what a call touches, not what a message says, so a customer's name in the body of an email to someone else is not caught. It cannot see targets hidden in encrypted payloads, custom binary formats, or a bare record id like contact 123. For ids you can add a lookup command, and for the rest you can set that tool to refuse anyone who is not on a list. It cannot stop an agent that runs code as the same OS user as the gate, which is why the Dockerfile runs the gate in its own container. And it only controls what the agent sends to a server, so put only servers you trust behind it.

Learn more

docs/configuration.md covers every setting in gate.json: targets, presets, rate limits, the lookup command, held calls and the approval page, serving over HTTP, and the full command list. docs/security.md explains how to keep the gate out of the agent's reach, where the secrets live, how the log shows tampering, and what the attack tests cover.

Running the tests

bash
pip install -e ".[dev]"pytest

The tests start a real MCP server behind the gate and talk to it with the official MCP client, over stdio and over HTTP.

License

MIT

來源:README.md,提交 ded1dc1

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.2.0最新Sep 26, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分