KellerKev/smcp
GitHub: KellerKev/smcp
SMCP 为模型上下文协议(MCP)增加身份验证、逐消息加密和多智能体协调能力,使 MCP 工具能够安全地跨网络和智能体间运行。
Stars: 0 | Forks: 0
# SMCP — 安全模型上下文协议
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://modelcontextprotocol.io/)
## 🎬 演示:运行中的多智能体商业智能

*CrewAI + SMCP 编排多个 AI 智能体,利用本地 Ollama 模型、DuckDB 和安全的多智能体协调,基于
电子商务、SaaS 和物联网数据生成商业智能报告。*
## 🚀 什么是 SMCP
[MCP](https://modelcontextprotocol.io/) 是为 AI 模型提供工具的绝佳方式,但它是为
**本地、可信的传输**(单台机器上的 stdio)而构建的。**SMCP 完全保留 MCP 的工具模型,
并将其封装在安全 + 协调层中**,因此相同的工具可以*跨机器*和
*在智能体之间*工作:
- 🔒 **身份验证** — `api_key` → JWT 会话,带有可选的非对称 (RS256) 模式,因此
服务器签发令牌,客户端可以验证但无法伪造
- 🔐 **加密** — 经过身份验证的单条消息负载加密;使用 ECDH 密钥交换实现
具有前向保密性的会话密钥
- 🛡️ **默认故障关闭** — 服务器/客户端拒绝使用空的、弱的或
公开已知的密钥启动;拒绝向非环回主机进行明文传输
- 🔁 **重放保护** — 签名的消息带有 freshness 时间窗口,并且只能被接受一次
- 🤝 **多智能体 (A2A)** — 智能体间的发现和编排,支持串行或并行
- 🔌 **连接器** — 经过强化的 DuckDB 和文件系统集成,用于构建工具
- ✅ **兼容 MCP** — 安全是可选的;标准的 MCP 工具继续工作
选择适合的姿态 — 从用于本地测试的简单 API 密钥到
带有审计追踪的单条消息加密(请参阅下方的[安全模式](#-security-modes))。
## 📚 文档
### 架构与设计
- [**架构概述**](docs/ARCHITECTURE_OVERVIEW.md) - 完整的系统架构、数据流和设计模式
- [**演示架构**](docs/DEMO_ARCHITECTURES.md) - 每个演示的详细步骤流程解析
- [**MCP 与 SMCP 对比**](docs/MCP_SMCP_COMPARISON.md) - 标准 MCP 与 SMCP 的全面比较
- [**用例**](docs/USE_CASES.md) - 实际应用和实施场景
### 技术指南
- [**AI SQL 生成指南**](docs/AI_SQL_GENERATION_GUIDE.md) - 使用 LLM 生成 SQL 查询
- [**连接器开发指南**](docs/CONNECTOR_DEVELOPMENT_GUIDE.md) - 构建自定义连接器
- [**CrewAI 集成**](docs/CREWAI_SMCP_INTEGRATION.md) - 将 CrewAI 与 SMCP 集成
## ✨ 关键特性
### 🔐 安全模式
根据部署进行选择 — 相同的工具,根据需要提供更强的安全姿态:
- **简单** — API 密钥身份验证 → JWT 会话(本地/开发)
- **基础** — JWT 会话;依赖 TLS (`wss://`) 进行传输安全
- **加密** — ECDH 密钥交换 + 经过身份验证的单条消息负载加密
- **企业** — 针对外部身份提供商的 OAuth2 client-credentials(JWKS 或
固定的静态公钥),并进行完整的令牌验证
无论处于何种模式,安全层都是**故障关闭**的:`SMCPConfig.validate()` 会拒绝空的、
过短的、占位符或公开已知的密钥,并且如果验证失败,`SMCPServer` 和 `SMCPClient` 都会拒绝
启动。
### 🔑 非对称令牌 (RS256)
默认情况下,JWT 使用共享密钥 (HS256) 签名 — 这在单一信任域内是没有问题的。对于
多方部署,请设置 `jwt_algorithm="RS256"` 并使用服务器持有的私钥和客户端
公钥:服务器生成令牌,客户端验证它们,而客户端**无法伪造自己的令牌**。
### 🏢 外部 IdP OAuth2(企业模式)
企业模式验证来自外部身份提供商的 OAuth2 访问令牌。它**故障关闭**:
需要 `oauth2.audience`、`oauth2.issuer` 和一个密钥源(`oauth2.jwks_url` **或**
`oauth2.local_public_key_path`),令牌使用固定为
RS256 的算法进行验证,并要求包含 `exp`/`iat`/`aud`/`iss`,对 IdP 的调用强制使用带有证书
验证的 HTTPS(可以通过 `oauth2.ca_cert_path` 固定 CA 证书包),并且自动处理 JWKS 密钥
轮换。由针对模拟 OIDC 提供商(令牌
endpoint + JWKS)运行的端到端测试套件覆盖,包括错误的受众、错误的签发者、过期的、
`alg=none`、HS/RS 混淆以及密钥轮换等情况。
### 🤖 智能体到智能体 (A2A) 系统
- 多智能体任务编排
- 动态智能体发现
- 并行和串行工作流
- 每个工具的授权(令牌范围授权给特定工具,而不是所有工具)
### 🔌 原生连接器
- **DuckDB**:高性能分析查询。默认**关闭**文件系统/网络访问,
在 DuckDB 引擎级别强制执行(`enable_external_access`);过滤原始 SQL 中的
文件/网络/扩展访问,验证标识符,并将批准的文件加载限制在
已配置的目录中。使用 `allow_raw_file_sql` 显式选择启用原始文件 SQL。
- **文件系统**:安全的本地存储,具有符号链接安全的路径包含功能,在
读取/删除/列表(不仅仅是写入)上强制执行扩展名白名单,以及读取/写入大小上限。
- **可扩展**:易于添加自定义连接器。
### 🏗️ 技术特性
- 通过 TOML/YAML/ENV 进行配置,具有严格的优先级顺序
- 日志和监控示例
- 连接上限、单客户端速率限制和由服务器强制执行的消息大小限制
## 📦 安装
### 前置条件
- Python 3.11+
- [Pixi](https://pixi.sh) 包管理器
- [Ollama](https://ollama.ai)(用于演示中的 AI 功能)
- Docker(仅用于 MindsDB 集成示例)
### 快速开始
1. **克隆代码库**:
```
git clone https://github.com/KellerKev/smcp.git
cd smcp
```
2. **使用 pixi 安装依赖**:
```
# 如果你还没有安装 pixi,请先安装
curl -fsSL https://pixi.sh/install.sh | bash
# 核心环境(快速)
pixi install
# 可选:重量级集成(CrewAI + MindsDB SDK)
pixi install -e integrations
```
3. **设置 Ollama 并为演示拉取一个小型模型**:
```
# 安装 Ollama,然后:
ollama serve &
# 示例默认使用一个轻量、快速的模型:
ollama pull llama3.2:1b
```
示例/测试模型是可配置的 — 设置 `SMCP_DEMO_MODEL` 以使用不同的模型:
```
export SMCP_DEMO_MODEL="qwen2.5-coder:7b-instruct-q4_K_M"
```
4. **(可选)用于 MCP-bridge / ML 示例的 MindsDB**:
```
docker run -d --name smcp-mindsdb -p 47334:47334 -p 47337:47337 mindsdb/mindsdb
# 等待直到健康,然后验证:
curl http://localhost:47334/api/status
```
📚 **完整安装指南**:有关详细说明,请参阅 [SETUP_GUIDE.md](SETUP_GUIDE.md)。
## 🧪 测试
```
# 完整的 pytest 套件(security、connectors 和端到端 server/client)
pixi run test
# 仅 crypto 互操作向量
pixi run test-interop
```
该套件涵盖了配置验证、移除旧的演示后门、重放/过期
拒绝、单工具授权、JWT 签发者/受众/过期时间、RS256 仅验证客户端、TLS
强制执行、DuckDB 注入/路径限制以及文件系统遍历/大小上限。
external-IdP OAuth2 流程针对模拟 OIDC 提供商进行了端到端测试。
服务器/客户端端到端测试在环回地址上启动真实的服务器和客户端(如果 Ollama 或演示模型不可用,基于 Ollama 的
测试会自动跳过)。
## 🎯 快速演示
示例脚本会自动生成强大的、基于机器的演示密钥(缓存在
被 git 忽略的 `examples/.demo_secrets.json` 中),因此服务器和客户端可以在强化的
验证下互操作,而代码库中没有任何密钥。
### 1. 服务器 + 客户端端到端
```
# 终端 1
pixi run example-server
# 终端 2
pixi run example-client
```
执行 handshake → auth → capability discovery → 工具调用,加上实时的 Ollama 调用。
### 2. DuckDB 分析
```
pixi run python tools/generate_sample_data.py # writes sample_data/
pixi run duckdb-example
```
加载数万行数据,让模型从业务问题中生成 SQL,通过
SMCP DuckDB 连接器执行它,并分析结果。
### 3. 完整系统展示
```
pixi run python examples/showcase_complete_system.py
```
### 4. 多智能体报告生成 (CrewAI)
```
pixi run -e integrations crewai-report-demo
```
针对本地 Ollama 运行数据分析师 → 业务分析师 → 报告撰写者 → 质量审查员智能体
,并将执行报告写入 `./crewai_reports/`。
### 5. MindsDB 集成(需要上述的 MindsDB 容器)
```
pixi run python examples/basic/basic_a2a_mcp_sample.py
pixi run python examples/mindsdb_integration_example.py
```
## 🏃 运行服务器并连接客户端
### 服务器
```
# 生成一个带有全新强 secrets 的 config,然后启动:
pixi run create-config
pixi run server
```
### 客户端(库)
```
import secrets
from smcp_client import SMCPClient
from smcp_config import SMCPConfig
# Secrets 是必需的,并且必须与 server 的匹配(shared-secret 模式)。
# 对于弱/空值,server 拒绝启动,且 client 拒绝连接。
config = SMCPConfig(
mode="basic",
server_url="ws://localhost:8765",
api_key=secrets.token_urlsafe(32),
secret_key=secrets.token_urlsafe(32),
jwt_secret=secrets.token_urlsafe(32),
kdf_salt=secrets.token_urlsafe(16),
)
config.security.allow_insecure_transit = True # loopback only; use wss:// in production
client = SMCPClient(config)
await client.connect()
capabilities = client.list_capabilities()
result = await client.invoke_tool("calculator", operation="add", a=15, b=27)
await client.disconnect()
```
## 📁 项目结构
```
smcp/
├── smcp_*.py # Core SMCP modules
├── connectors/ # Native connector implementations
│ ├── smcp_duckdb_connector.py
│ └── smcp_filesystem_connector.py
├── examples/ # Demo applications
│ ├── _demo_support.py # Shared strong-secret helper for the demos
│ ├── basic/ # Basic (JWT) mode examples
│ ├── encrypted/ # Encrypted mode examples
│ └── *.py # Integration examples
├── tests/ # Pytest suite (security, connectors, e2e)
├── tools/ # Utility scripts (sample data, key generation)
├── docs/ # Documentation
└── pixi.toml # Environments and tasks
```
## 🔧 配置
SMCP 按以下优先级顺序合并配置(优先级从高到低):CLI 参数 → 环境变量 → 配置文件 →
默认值。必须提供密钥;如果缺失或太弱,应用程序将故障关闭。
### 环境变量
```
export SCP_API_KEY="$(python -c 'import secrets;print(secrets.token_urlsafe(32))')"
export SCP_SECRET_KEY="$(python -c 'import secrets;print(secrets.token_urlsafe(32))')"
export SCP_JWT_SECRET="$(python -c 'import secrets;print(secrets.token_urlsafe(32))')"
export SCP_KDF_SALT="$(python -c 'import secrets;print(secrets.token_urlsafe(16))')"
export SCP_MODE="basic"
```
完整列表请参见 [.env.example](.env.example)。在联邦中的各节点之间共享 `SCP_SECRET_KEY` / `SCP_JWT_SECRET` /
`SCP_KDF_SALT`。
### TOML
```
pixi run create-config # writes scp_config.toml with fresh strong secrets
```
## 🛡️ 安全说明
1. **密钥** — 32 个字符以上的随机 `secret_key`/`jwt_secret`,16 个字符以上的 `kdf_salt`;永远不要提交它们。
`validate()` 会拒绝空/过短/占位符/已知值。
2. **传输** — 设置 `security.tls_enabled=True`(带上证书/密钥)并在
生产环境中使用 `wss://`/`https://`。明文仅允许用于环回地址,且仅在
设置了 `security.allow_insecure_transit` 时允许。
3. **令牌** — 当客户端不应该能够
生成自己的令牌时,使用 `jwt_algorithm="RS256"`(服务器私钥,客户端公钥)。
4. **连接器** — 除非你需要主机文件/网络
访问权限,否则保持 DuckDB 的 `enable_external_access=False`,并设置 `data_dir` 以限制
文件操作。
## 🤝 MCP 兼容性
SMCP 保持了 MCP 工具模型的完整;安全层是附加的。标准的 MCP 工具继续
工作,并且 [MCP bridge](smcp_mcp_bridge.py) 将 SMCP 连接到外部 MCP 服务器(除非
目标是环回地址,否则拒绝通过明文发送凭据)。
## 📄 许可证
该项目基于 MIT 许可证授权。
## 🚦 状态
- ✅ **核心 SMCP**:经过安全强化并由测试覆盖(106 项测试)
- ✅ **基础/加密模式**:经过安全强化,由测试覆盖
- 🚧 **A2A 系统**:带有单工具授权的工作原型(localhost 模拟)
- ✅ **DuckDB / 文件系统连接器**:经过强化,默认故障关闭,由测试覆盖
- ✅ **CrewAI 集成**:可运行的演示(在 `integrations` 环境中)
- ✅ **MindsDB 集成**:可运行的演示(需要 MindsDB 容器)
- ✅ **企业 / OAuth2 模式**:external-IdP 令牌验证,经过强化并由测试覆盖
(JWKS + 静态密钥),已针对模拟 OIDC 提供商进行验证
- 🚧 **联合身份验证**:带有 RS256 仅验证支持和
测试套件的绑定 audience/issuer 的令牌;默认为共享的 HS256 密钥(对于多方信任,请使用 RS256)
**想要探索 MCP 安全概念?** 请从上方的[快速演示](#-quick-demo)开始。
标签:AI风险缓解, Python, 人工智能, 多智能体, 无后门, 模型上下文协议, 用户模式Hook绕过, 请求拦截, 逆向工具, 通信安全