Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
DDD 架构 · MCP 工具管理平台。
启动 MySQL 8.0(首次创建数据卷时会执行 docs/init.sql):
docker compose -f docs/docker-compose.yml up -d安装后端依赖:
uv sync --extra dev安装并构建前端:
cd frontend
npm install
npm run build
cd ..启动 HTTP + MCP Streamable HTTP:
source .venv/bin/activate
python -m dd_arch.app.application如果没有激活虚拟环境,也可以直接通过 uv 调用:
uv run python -m dd_arch.app.application启动后主要入口:
/api 管理端 REST API
/mcp MCP Streamable HTTP
/ frontend/dist 静态前端停止 MySQL:
docker compose -f docs/docker-compose.yml down如需重新执行初始化 SQL,先删除数据卷:
docker compose -f docs/docker-compose.yml down -v
docker compose -f docs/docker-compose.yml up -d⚠️ 安全前提(RCE):本平台允许从 Web 提交并在服务器进程内执行任意 Python 代码,本质是远程代码执行。当前采用进程内 `exec`(最简,完全 RCE,无沙箱),仅适用于受信任的内网/单用户环境。编辑类接口必须置于受信任网络或加鉴权后再对外。命名空间预置的最小__builtins__不构成安全边界;沙箱隔离是预留扩展点(IToolExecutorPort可替换为受限/子进程实现)。
权威规格见 spec.md,执行进度见 progress.md。
项目采用轻量六边形架构,并额外保留通用类型层和启动层。工具来自数据库,不再有静态注册中心或工具目录。
+-------------+
| trigger | HTTP / MCP 入站适配
+------+------+
|
+------v------+
| api | DTO / 响应契约
+------+------+
|
+------v------+
| domain | 领域模型 / 领域服务 / 接口
+------^------+
|
+---------------+---------------+
| infrastructure | DB / Cache / Event / Metrics / Executor
+-------------------------------+
types 提供跨层共享的错误码、异常、响应和分页类型。
app 作为组合根装配所有层,并负责生命周期。核心约束:
domain 不依赖 FastAPI、SQLAlchemy、MCP、infrastructure 等外部技术;也不真正 exec 代码(编译执行是 IToolExecutorPort 的 infra 职责,domain 只定义接口)。domain service 中;trigger 只做协议适配、参数接收、响应包装。infrastructure 实现领域层定义的 repository/port 接口,不反向依赖 trigger。app 是唯一知道所有层实现细节的组合根,负责依赖注入、生命周期和挂载。.
├── resources/
│ └── application.yaml # 默认运行配置
├── docs/init.sql # MySQL schema
├── pyproject.toml # 项目依赖和构建配置
├── docs/spec.md # 项目权威规格
├── docs/progress.md # 执行进度
├── docs/step-*.md # 分步骤规格
├── tests/ # 自动化测试
├── frontend/ # Vue 管理端(含工具编辑器)
└── src/dd_arch/
├── types/ # 通用基础类型
├── api/ # HTTP/API 契约
├── domain/ # 领域核心(tooldef / invocation)
├── infrastructure/ # 外部技术实现(含 ToolExecutorPort)
├── trigger/ # HTTP/MCP 入站适配器
└── app/ # 组合根、启动入口和运行配置加载types/ 通用类型层这一层放跨层共享且不携带业务流程的基础类型,主要包括:
{code, info, data}。它可以被各层引用,但不主动依赖业务层或基础设施层。
api/ 契约层这一层描述管理端 API 的输入输出契约,主要包括:
api 层不处理业务流程,只定义 trigger 和 service 之间稳定的数据形状。
domain/ 领域层领域层是业务核心,不包含框架代码和数据库代码。
domain/
├── tooldef/ # 工具定义子域(Web 动态工具核心)
│ ├── model/ # ToolDefinitionAggregate / 参数与状态值对象 / 编译产物 VO
│ ├── adapter/repository/ # 工具定义、工具配置仓储接口
│ ├── adapter/port/ # 代码执行器端口接口(IToolExecutorPort)
│ └── service/ # 参数→JSON Schema、参数矫正等领域规则
└── invocation/ # 工具调用子域
├── model/ # 调用日志、调用事件、状态值对象
├── adapter/repository/ # 调用日志仓储接口
├── adapter/port/ # 事件发布、指标等端口接口
└── service/ # 调用日志和统计领域规则这一层解决的问题:
infrastructure/ 基础设施层基础设施层负责把领域接口落到具体技术实现。
infrastructure/
├── dao/ # SQLAlchemy 查询封装
│ └── po/ # ORM 持久化对象(tool_definition / tool_invocation_log)
├── adapter/
│ ├── repository/ # 领域 repository 的实现
│ └── port/ # 领域 port 的实现(含 ToolExecutorPort)
├── cache/ # 进程内 TTL 缓存
└── logging/ # 审计日志后台批量写入这一层解决的问题:
ToolExecutorPort):把工具的 code 串 compile+exec 到受控命名空间取出入口函数,按 name+sha256(code) 缓存编译产物,工具更新即 invalidate,按 is_async 分派。领域服务同时负责这些简单编排:
ctx 配置。def handler(...) 和 async def handler(...)。source='test' 日志、不发 MCP 调用事件。trigger/ 触发层触发层是入站适配器,负责把外部协议转换为用例调用。
trigger/
├── http/ # FastAPI 管理 API
└── mcp/ # 官方 MCP low-level server 和 Streamable HTTPHTTP 侧主要提供:
GET /api/status
GET /api/tools
GET /api/tools/{name}
POST /api/tools # 创建:code + parameters + is_async + tags + config
PUT /api/tools/{name} # 更新:同创建请求体
DELETE /api/tools/{name} # 删除
POST /api/tools/{name}/enable
POST /api/tools/{name}/disable
POST /api/tools/test # 草稿试跑(body 含 definition,不读/写库)
POST /api/tools/{name}/test # 已存工具试跑(绕过 ENABLED)
GET /api/logs
GET /api/logs/stats
GET /api/logs/{id}
DELETE /api/logs?before=ISO_DATETIMEMCP 侧主要提供:
tools/list:只暴露启用状态的工具。tools/call:把 MCP 调用转换为工具执行用例。/mcp。app/ 启动层启动层是组合根,负责把所有层连接起来。
app/
├── application.py # 进程启动入口,按配置选择 HTTP 或 stdio
├── container.py # dependency-injector 容器和 ApplicationContext
├── persistence.py # session/事务边界和仓储装配
└── config/ # YAML 配置加载、数据库/FastAPI/MCP 组件配置这一层解决的问题:
resources/application.yaml 和可选 resources/application-local.yaml。ToolExecutorPort)和 service。tool_definition 表),由 Web 端创建,不做工具目录自动发现。HTTP request
-> trigger/http controller
-> domain service / repository interface
-> infrastructure repository / dao / cache
-> Response{code, info, data}典型场景:
COMPILE_ERROR),写入后失效执行器缓存。ctx 可读取。MCP tools/call
-> trigger/mcp
-> 工具执行服务
-> 工具定义仓储查询(经缓存)
-> domain 检查工具状态
-> ToolExecutorPort 取/编译可调用对象(按 name+code 哈希缓存)
-> 按 is_async 分派执行(同步服务中封装 async handler)
-> 发布成功或失败领域事件
-> 审计日志订阅者入队
-> 文本结果返回 MCP client这条链路保证:
UNKNOWN_TOOL)。TOOL_DISABLED)。默认 MySQL schema 见 init.sql:
tool_definition
动态工具定义:code、is_async、tags_json、parameters_json、config_json、status
tool_invocation_log
工具调用日志、状态、耗时、错误、source(mcp/test)和创建时间开发和测试可使用 sqlite:///path/to/dev.db。生产默认配置使用 mysql+pymysql。
默认配置在 resources/application.yaml:
server:
host: 127.0.0.1
port: 8003
mcp:
transport: streamable-http
http-path: /mcp
frontend-dist: frontend/dist
database:
url: mysql+pymysql://root:[email protected]:3306/mcp_admin?charset=utf8mb4
pool-size: 20
max-overflow: 10本地敏感配置写入 resources/application-local.yaml,会覆盖默认配置,且已被 .gitignore 忽略。
本地敏感配置可写入 resources/application-local.yaml。例如开发时可使用 SQLite:
database:
url: sqlite:///./dev.db直接用模块方式启动服务,host、port、MCP transport 和路径都从 resources/application.yaml 读取:
python -m dd_arch开发前端时也可以单独启动 Vite:
cd frontend
npm run devVite 会把 /api 和 /mcp 代理到 http://127.0.0.1:8003。
def handler(...) 或 async def handler(...)(异步工具需勾选「Async」开关并与代码一致)。需要读取运行时配置时,在签名里加 ctx 参数(ctx.config 为该工具的 KV 配置)。COMPILE_ERROR)。info 并不落库。tools/list 即可见、tools/call 可调用。示例代码(同步):
def handler(a, b):
return a + b示例代码(异步):
import asyncio
async def handler(seconds):
await asyncio.sleep(seconds)
return f"slept {seconds}s"当前数据库主链路是同步的;HTTP/MCP 入口会把用例调用放入线程池执行。
运行后端测试:
uv run pytest运行前端类型检查和生产构建:
cd frontend
npm run build当前测试覆盖:
is_async 不符返回 COMPILE_ERROR、build_input_schema 与 coerce_arguments(字符串转型与必填校验)。COMPILE_ERROR 且不落库。ok=false, code=COMPILE_ERROR;已存工具试跑对 DRAFT/DISABLED 工具仍能执行;测试调用记 source='test' 且不计入 stats()。ToolFailedEvent;成功调用返回结果并经订阅者批量落库。async def handler + await asyncio.sleep(1) 通过线程池并发调用总耗时小于 5 秒。当前已完成的本地验证包括:
src/dd_arch 导入检查(全包可 import,无残留旧模块引用)。uv run pytest(18 项全绿)。frontend/npm run build(vue-tsc 类型检查 + vite 构建通过)。/api/status、/api/tools CRUD、/api/tools/test 草稿试跑和 enable(经 ASGI 实测)。~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.