mcp-guarded-toolkit
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-guarded-toolkitlist all tables in the sample database"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-gatekeeper
一个基于 MCP(Model Context Protocol) 的本地工具服务:把一份示例数据库和一份公版文本库 开放成 6 个工具。其中「让模型自己写 SQL 查数据库」这条链路必须真的安全 —— 所以它配了三层 SQL 护栏、工具级 scope 鉴权、有界重写状态机和可复核的数字口径。
它的用途是技术验证:证明这套工程约束是可迁移的,而不是绑在某一份数据上的特例。
只用公开、可再分发的数据:示例库 + 公版中文文本(逐篇出处见 NOTICE.md)
不联网、不需要模型凭据就能跑完全部测试与自检(自检里靠词表的那几项会判
SKIP, 见「已知边界」——SKIP是「没查」,不是通过)报告里每个数字都能指出「脚本名 + 口径」,没有估计值
需要模型凭据的那条链路已经跑通(2026-09-18 的评测;2026-09-22 又在并发下重跑了一遍对账), 数字落盘在 RESULTS.md 第二节与 reports/ledger_under_concurrency.md
本仓库不放凭据(
.env也不放,理由见 BLOCKERS.md 卡点 1),所以直接重跑 需要凭据的脚本会一律报「未完成」(退出码 5 + 一份说明),不编数字。 本轮真跑通的那几次,凭据是以进程环境变量注入的,没落仓库盘
快速开始
# 1) 单元测试(零网络、零模型调用)
python -m pytest -q
# 2) 构建数据:示例库(.sql → .db)与文本库(切词 → 全文索引)
python experiments/01_build_db.py
python experiments/02_build_kb.py
# 3) 安全层与协议层:鉴权矩阵、护栏负例矩阵、真实 stdio 握手
python experiments/10_auth_test.py
python experiments/11_guardrail_test.py
python experiments/08_mcp_smoke.py
# 4) HTTP 入口与并发:真起服务、真 TCP 冒烟;以及并发度的实测读数
python experiments/30_http_smoke.py
python experiments/29_concurrency_bench.py
# 5) 一条命令回答「现在能不能交出去」
python tools/check.pypython tools/check.py 会依次跑单元测试、台账式自检、交付物核验、收尾自检,
退出码 = 卡在第几步(0 = 全部通过)。只想看它要跑什么:python tools/check.py --list。
起服务端
python -m mcp_server.server --check # 只做启动自检:注册的工具与 scope 表是否一致
python -m mcp_server.server # 真正拉起 stdio 服务端
python -m mcp_server.http_api --check # HTTP 侧的自检:路由名集合 == TOOL_SCOPES 键集合
python -m mcp_server.http_api # 拉起 HTTP 服务(默认 127.0.0.1:8000)
python -m mcp_server.http_api --port 0 # 由系统分配端口,启动行会打印真实端口stdio 服务端的 stdout 是协议通道,所以人话一律走 stderr —— 打印一行启动信息到
stdout 会让握手直接报 Invalid JSON(这个 bug 只有真实握手能抓到,见 PROGRESS.md 阶段 3)。
HTTP 侧沿用同一条规矩:人话走 stderr,端口也打在那儿([http] 监听 127.0.0.1:<port>)。
服务端自己先 bind 好 socket 再交给 uvicorn,所以端口是确定的,不存在「先探测空闲端口、
启动时被抢走」的竞态。
起好之后,/docs 是 OpenAPI 自动生成的交互文档,/openapi.json 是机器可读的那份。
Related MCP server: any-db-mcp
工具集
6 个工具、3 个 scope。scope 挂在工具上而不是「用户」上,所以换一个客户端、 换一次会话,权限判定都一样。
工具 | scope | 做什么 |
|
| 列出所有表和视图 |
|
| 看某张表的列与类型 |
|
| 执行一条只读查询(过三层护栏) |
|
| 自然语言提问 → 模型写 SQL → 护栏 → 执行 → 失败则重写 |
|
| 在公版文本库里检索段落,返回原文片段与偏移量 |
|
| 按偏移量取回原文 |
调用工具要带一个 JWT,令牌里带着 scope 列表:
from mcp_server import auth
token = auth.make_token("demo-user", scopes=["db:read", "kb:read"])ask_database 是唯一需要模型凭据的工具;其余 5 个不需要。
同一批工具的 HTTP 入口
mcp_server/http_api.py 把上面这 6 个工具挂成 HTTP 路由。路由是照着 auth.TOOL_SCOPES
现生成的(不是第二份工具清单),请求体就是那个工具的 kwargs(含 token),
响应体就是工具原本的返回值 —— 同一份业务逻辑,两个传输层。
方法 | 路径 | 说明 |
POST |
| 调一个工具;上表那 6 个名字各有一条路由 |
GET |
| 工具名 + 所需 scope 的清单 |
GET |
| 存活探针 |
GET |
| OpenAPI 交互文档(FastAPI 自带, |
状态码不是一刀切:拒绝 → 403(code 原样带回)、未知工具 → 404、参数绑不上 → 400,
被 SQL 护栏拦下的查询是 200 —— 那是业务结论(请求被正确执行并给出了结论),
报 4xx 会让「护栏工作正常」看起来像「调用失败」。完整映射见
mcp_server/http_api.py 的 status_for(),逐条断言在 tests/test_http_api.py。
并发调用走 mcp_server/concurrency.py:同步阻塞的工具函数一律 asyncio.to_thread
挪出事件循环,Semaphore 限并发,wait_for 超时降级成一条结果记录而不是拖垮整批。
为什么必须挪、以及不挪会怎样(实测并发度退化成 1),见 reports/concurrency.md。
目录结构
mcp_server/ 服务端与全部纯逻辑(可 import,因此可单测)
auth.py JWT 签发/校验/guard(),工具级 scope 表
guardrails.py 三层 SQL 护栏
db_tools.py 列表 / 结构 / 查询
kb_tools.py 检索 / 取原文
t2sql_core.py 自然语言转 SQL 的状态机(有界重写)
cost.py 用量账本(JSONL 只追加,金额允许为空)
dispatch.py 名字 → 工具函数的派发器(HTTP 层的唯一入口)
http_api.py FastAPI 入口:路由由 TOOL_SCOPES 现生成
concurrency.py asyncio 并发层:限流 + 超时降级 + 阻塞调用挪出事件循环
selfcheck.py 仓库卫生扫描口径(词表、范围、掩码)
verify_kit.py 退出码台账与判定
deliverable_kit.py 交付物核验 G1~G8
experiments/ 可重跑的入口脚本(全部幂等)
29_concurrency_bench.py 三种跑法的实测并发度对照
30_http_smoke.py HTTP 入口冒烟(真进程、真端口)
31_ledger_under_concurrency.py 并发下的账本对账(需要模型凭据)
tests/ 单元测试:零网络、零模型调用
tools/check.py 守门链
data/ 公开数据(示例库 .sql + 公版文本 + 出处清单)
reports/ 全部实测产物落盘
docs/ 设计说明数据与许可
示例数据库:Chinook(MIT),随仓库分发
.sql源文件,由脚本构建成数据库文本库:40 篇公版中文文本,逐篇的标题、作者、原文地址、许可与 sha256 见 NOTICE.md
构建产物(数据库文件、全文索引)不入库,由
experiments/01_build_db.py与experiments/02_build_kb.py确定性重建
怎么证明它是对的
四层,从细到粗:
谁 | 管什么 |
| 某个函数对不对 |
每个入口脚本的实际退出码对不对得上声明 | |
文档里写的和仓库里对不对得上 | |
发布前 9 项红线,逐项报命中数 |
三条原则写在 docs/design.md 里,这里只列结论:
每一项检查都要能红。 只证明「会绿」的检查,一个永远返回
PASS的假实现也能通过。「未完成」必须交证据。 需要模型凭据的脚本以退出码 5 结束,同时留下写清卡在哪一步的 「未完成」说明和
BLOCKERS.md里对应的最小动作。三件缺一,判失败 —— 没有落盘、没有解法的「未完成」,和「忘了跑」长得一模一样。报告不能成为它自己报告的污染。 自检报告要写出「在哪里命中了什么」, 而写出来的那一刻,报告自己就带上了那个词。处置方式见
docs/design.md第 4.4 节。
当前的完成状态
部分 | 状态 |
数据构建、鉴权、三层护栏、MCP 握手、知识库检索 | 已完成,有实测报告 |
自然语言转 SQL( | 已跑通一次(2026-09-18):配好凭据后四条链路全部跑完并落盘,数字见 RESULTS.md 第二节。凭据不在仓库里,所以 clone 后要自配一份才能重跑(见 BLOCKERS.md 卡点 1) |
噪声带与配对统计 | 同上那次运行里跑完:尺子有正负控,数字见 RESULTS.md 第二节 |
HTTP 入口(FastAPI) | 已完成:6 条工具路由 + |
asyncio 并发层 | 已完成:限流、超时降级、阻塞调用挪出事件循环。实测并发度(不是设定值):串行 1 / 天真 gather 1 / 正确并发 6,见 reports/concurrency.md |
并发下的账本一致性 | 已完成(2026-09-22,凭据以环境变量注入):并发批与串行批各 12 题,账本新增行数都等于实际调用次数 12,见 reports/ledger_under_concurrency.md |
真实跑出来的数字见 RESULTS.md;每个数字都注明了脚本与口径。
已知边界
卫生扫描用的词表按设计不在仓库里:那张「不许出现的名字 / 数字 / 术语」表 放在仓库外面(
MCP_TOOLKIT_WORDLIST指向的.py,没设就找仓库同级目录的mcp-guarded-toolkit-wordlist.py)。把它放进仓库等于在仓库里再造一份那些字面量 —— 那正是这个仓库修掉的那座「明文桥」。代价写清楚:clone 下来跑自检时, 靠词表的那几项判SKIP(没查,不是通过),所以python tools/check.py在没有词表的机器上停在「未完成」,不会全绿。这不是失败,但也不是通过。第一次跑之前要构建数据:
data/下的示例库与全文索引是构建产物、不入库, 所以 clone 下来直接跑闸门会停在「示例库还没构建」,先跑「快速开始」第 2 步 那两条命令(不需要联网)。不联网:数据随仓库分发;只有「重新抓语料」这一个脚本需要网络,且它是可选的。
护栏不是形式化证明:三层护栏(文本校验 / 只读连接 / 引擎级 authorizer) 挡的是「写不进数据库」,不是「SQL 一定正确」。
experiments/11_guardrail_test.py列了 41 条负例,那 41 条之外没测过的写法是未知的。交付物核验 G4 的强度有限:它查「文档里的
--flag在源码里出现过」, 不保证argparse真的注册了那个参数。本机现在没有模型凭据,所以那四条需要模型的命令不能重跑 —— 它们会以退出码 5 结束, 并写出「未完成」声明。已经跑通的那一次(2026-09-18)数字在 RESULTS.md 第二节, 是实测,不是 0,也不是任何估计值。(本机能拿到凭据与「工作区里没有
.env」这条发布自检 互斥,所以两者不可能同时成立,见 BLOCKERS.md 卡点 1。)
设计取舍与代价逐条记在 DECISIONS.md,整体思路见 docs/design.md。
This server cannot be deployed
Maintenance
Related MCP Connectors
Text-to-SQL MCP server: read-only queries on PostgreSQL, MySQL and SQL Server with your real schema
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA production-grade MCP server designed for multi-tenant, authenticated, and observable AI agent systems, enabling secure tool execution across heterogeneous data sources.66MIT
- AlicenseAqualityDmaintenanceA multi-database MCP server that enables LLMs to safely interact with MySQL, PostgreSQL, SQLite, and others through a unified tool interface, with permission modes and schema resources.107 npm53MIT
- FlicenseNot gradedqualityDmaintenanceA custom MCP server with 6 utility tools (file search, file reading, math calculation, JSON formatting, time query, system info) that demonstrates MCP protocol workflow and integrates with LangChain agents.-
- AlicenseBqualityBmaintenanceA universal MCP server enabling AI assistants to query and manage six database engines (Postgres, Redis, Elasticsearch, MySQL, MongoDB, LDAP) through 113+ tools with read-only safety and fault tolerance.10017 npm82MIT