OpenSquilla MCP Gateway
by nhtqgm
README.md
# SquillaFlow MCP
[](https://www.python.org/)
[](https://github.com/modelcontextprotocol/python-sdk)
[](https://github.com/nhtqgm/squillaflow-mcp/actions/workflows/ci.yml)
[](LICENSE)
SquillaFlow MCP 是一个本机、通用、异步的 OpenSquilla 任务网关。任何标准 MCP Host 都可以提交文本、JSON 或文件任务,立即获得 `task_id`,再通过统一状态机等待、取消、续接和读取结果。
当前版本为 `0.4.0a1`。它面向真实集成测试,不应在完成目标环境 E2E 前标记为稳定版。
## 定位
- OpenSquilla 负责模型、工具、权限确认和实际执行。
- SquillaFlow 负责任务队列、幂等、恢复、调用方隔离、结果契约和 Artifact 托管。
- MCP Host 只需要标准 MCP,不依赖 Codex 私有协议;Codex 是优先验证的配置体验。
- sidecar 使用 stdio,本机用户自行安装并启动 OpenSquilla。
- 一次 OpenSquilla turn 对应一个 SquillaFlow task;续接会创建子 task 并复用父 task 的 session。
本仓库不包含 OpenSquilla Desktop、模型凭据、远程 SaaS、GUI/EXE、硬沙箱或跨实例分布式队列。
## 架构
```mermaid
flowchart LR
Host["MCP Host"] -->|"stdio MCP"| Server["SquillaFlow FastMCP Server"]
Server --> Tasks["TaskService"]
Tasks --> Queue[("SQLite queue + event trace")]
Tasks --> Store["Managed Artifact Store"]
Tasks --> Bridge["OpenSquilla Bridge"]
Bridge -->|"WebSocket RPC"| Gateway["OpenSquilla Gateway"]
Bridge -->|"same-origin HTTP"| Gateway
Gateway --> Runtime["Agent Runtime + Tools + Permissions"]
Server --> Legacy["0.4.x compatibility tools"]
Legacy --> Bridge
```
通用 task 数据与旧文献任务数据使用独立 Schema。`0.4.x` 保留原有 session Tools、文献 Tools、Python namespace 和旧 CLI 名称。
## 环境要求
- Python 3.12 或 3.13
- 一个正在运行的 OpenSquilla Gateway
- MCP Python SDK `>=1.27,<2`
已用 OpenSquilla `0.5.2 / protocol 3` 做真实文本与 Artifact E2E。实现根据 `hello-ok.features` 做能力检测,不锁死具体 patch 版本。
## 安装
Windows PowerShell:
```powershell
git clone https://github.com/nhtqgm/squillaflow-mcp.git
Set-Location squillaflow-mcp
py -3.12 -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
```
Linux/macOS:
```bash
git clone https://github.com/nhtqgm/squillaflow-mcp.git
cd squillaflow-mcp
python3.12 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
```
## 首次配置
OpenSquilla 默认地址为 `ws://localhost:18791/ws`。配置文件不会保存 Gateway Token,只保存读取 Token 的环境变量名称。
```powershell
.venv\Scripts\squillaflow-mcp.exe configure `
--gateway ws://127.0.0.1:18791/ws `
--allow-input-root D:\Projects
.venv\Scripts\squillaflow-mcp.exe doctor
```
配置位置遵循平台惯例:
- Windows: `%LOCALAPPDATA%\SquillaFlow\config\config.toml`
- macOS: `~/Library/Application Support/SquillaFlow/config.toml`
- Linux: `${XDG_CONFIG_HOME:-~/.config}/squillaflow/config.toml`
任务数据库与 Artifact Store 默认位于平台本机数据目录。可通过 `configure --data-dir` 或 `run --data-dir` 覆盖。
## 启动
```powershell
.venv\Scripts\squillaflow-mcp.exe run
```
也可以使用兼容入口:
```powershell
.venv\Scripts\opensquilla-mcp-gateway.exe run
.venv\Scripts\python.exe -m squillaflow_mcp run
.venv\Scripts\python.exe -m opensquilla_mcp_gateway run
```
多个 MCP Host 可以共享同一 `instance_name`。SQLite 事务、进程唯一 worker ID 和
lease 共同避免重复领取任务,并在整个 instance 范围内执行 worker 并发上限。
## MCP Host 配置
```json
{
"mcpServers": {
"squillaflow": {
"command": "C:\\path\\to\\venv\\Scripts\\squillaflow-mcp.exe",
"args": ["run"]
}
}
}
```
如 Gateway 使用 Token,只在 sidecar 进程环境中设置:
```powershell
$env:OPENSQUILLA_GATEWAY_TOKEN = "..."
```
stdio 是协议通道,业务日志不能写入 stdout。
## 通用 Task Tools
| Tool | 语义 |
| --- | --- |
| `task_start` | 幂等提交只读任务,立即返回 `task_id` |
| `task_start_mutating` | 提交显式启用的写任务;默认关闭 |
| `task_status` | 读取状态、phase、version、deadline 和错误 |
| `task_wait` | 从 `after_version` 长轮询下一次变化或终态 |
| `task_result` | 读取终态稳定结果 envelope |
| `task_cancel` | 幂等请求取消,并定向中止对应 OpenSquilla turn |
| `task_list` | 按状态、Profile、effect 分页列出当前调用方任务 |
| `task_pin` | 控制任务与 Artifact 的自动保留 |
| `task_delete` | 删除终态任务及不再共享的 Artifact |
Tools 成功时返回 `{"ok": true, ...}`;可预期失败返回:
```json
{
"ok": false,
"error": {
"code": "TASK_NOT_FOUND",
"message": "task does not exist or is not accessible",
"retryable": false,
"trace_id": "trc_...",
"details": {}
}
}
```
### TaskRequest
```json
{
"request": {
"instruction": "Compare the supplied JSON records and return the anomalies.",
"idempotency_key": "customer-42-audit-20260821",
"inputs": [
{"type": "json", "name": "records", "value": [{"id": 1, "total": 12.5}]},
{"type": "local_file", "path": "D:\\Projects\\rules.md"}
],
"constraints": ["Do not modify source files"],
"expected_output": {
"format": "json",
"json_schema": {
"type": "object",
"properties": {"anomalies": {"type": "array"}},
"required": ["anomalies"]
}
},
"timeout_seconds": 600,
"profile": "generic"
}
}
```
输入类型:
- `text`: 内联文本。
- `json`: 任意合法 JSON 值。
- `local_file`: 仅允许 `allowed_input_roots` 下的文件,导入后转为托管 Artifact。
- `artifact_ref`: 复用同一调用方已有的 `squillaflow://artifacts/...`。
输出格式:`text`、`markdown`、`json`、`artifact`、`mixed`。JSON 可附 Draft 2020-12 Schema;Artifact 可约束数量和 MIME。
`timeout_seconds` 是异常停滞核验窗口,不是任务总墙钟时长。任务真正开始执行以及收到事件、心跳或匹配的 OpenSquilla `active_task` 状态时都会滚动续期 `deadline_at`;排队等待不会耗尽执行窗口。窗口到期时 SquillaFlow 会先核验目标 turn 和持久化终态,正常执行中的 turn 不会被自动中断。只有目标 turn 不再活跃且没有成功终态、OpenSquilla 明确失败或用户取消时才会中止任务。
### 状态机
```text
queued -> running -> completed
|-> failed
|-> cancel_requested -> cancelled
queued -------------------------------> cancelled
```
`phase`(如 `sending`、`waiting`、`reconciling`)不是生命周期状态。每个变更增加单调 `version`,供 `task_wait` 使用。
### 续接
将终态父 task 传给 `continue_from_task_id`。子 task 使用新 `task_id`、独立结果和幂等键,但复用父 task 的 OpenSquilla session 与 agent alias。
### 恢复
- SQLite lease 与 heartbeat 负责进程异常后的重新领取。
- `sessions.send` 使用由 task id 派生的稳定 `client_message_id`。
- 一旦保存接受回执,恢复逻辑不会重复发送 turn。
- 恢复时按 OpenSquilla `turn_outcomes` 对账 `succeeded/failed/timeout/cancelled`。
- session stream seq 持久化;事件回放缺失时以 history 和 turn outcome 收尾。
## Artifact
小输入使用内联 base64;大输入先上传到 OpenSquilla `/api/v1/files/upload`。最多 10 个输入附件,总计 60 MiB,单文件与本地 Store 另受配置配额限制。
OpenSquilla 输出 Artifact 是 session-scoped。SquillaFlow 只从已配置 Gateway 的同源固定路径下载,校验声明的 size 与 SHA-256,再原子写入内容寻址 Store。不会跟随 Artifact 元数据中的任意 URL。
| Resource | 内容 |
| --- | --- |
| `squillaflow://profiles` | 内置 Profile 与 options Schema |
| `squillaflow://tasks/{task_id}` | 当前 task 状态 |
| `squillaflow://tasks/{task_id}/trace` | 脱敏状态事件 |
| `squillaflow://artifacts/{artifact_id}` | 校验后的本地 Artifact bytes |
## 权限与隔离
- `task_start` 声明 `read_only` effect。
- `task_start_mutating` 需要全局 `allow_mutating=true`,且 agent alias 的 `allowed_effects` 必须包含 `mutating`。
- 最终工具审批与系统权限仍由 OpenSquilla 执行;SquillaFlow 不冒充硬沙箱。
- 调用方 namespace 由本机 `installation_id` 与 MCP `clientInfo.name` 生成。任务、幂等键和 Artifact 均按 namespace 隔离。
- Gateway Token 只从配置指定的环境变量读取;HTTP 上传使用 Authorization header。
## Profiles
Profile 是内置、可选的任务提示与 options 校验层,不改变 9 个通用 Tools。
- `generic`: 默认,允许只读或经配置启用的写任务。
- `literature`: 文献搜索、综述和引用核验,只读;强调一手来源、DOI/稳定 URL、元数据证据和覆盖不确定性。
`0.4.x` 不提供公开第三方 Profile SDK。需要完全定制时,使用 `generic` 的 instruction、inputs、constraints 和 output contract。
## 兼容接口
以下旧接口在 `0.4.x` 保留:
- Session Tools: `conversations_list`、`session_create`、`session_resolve`、`messages_read`、`messages_send`、`events_wait`、`transcript_export`。
- 文献 Tools: `literature_search_start/status/result/refine/cancel/pin/delete`。
- Resources: `opensquilla://...` 与 `research://...`。
- Python package: `opensquilla_mcp_gateway`。
- CLI alias: `opensquilla-mcp-gateway`。
旧文献服务继续使用原数据库和环境变量,不会被通用 task Schema 自动改写。新工作流应优先使用 `task_start` 加 `profile="literature"`。
兼容文献接口中的 `deadline_seconds` 同样作为异常停滞核验窗口,并受管理员配置的研究 inactivity 上限约束;事件、心跳或匹配的 active-turn 状态会续期,不再以固定总墙钟时长截断正常检索轮次。
## 管理命令
```text
squillaflow-mcp configure 创建或更新 TOML 配置
squillaflow-mcp doctor 检查配置并读取 Gateway hello-ok
squillaflow-mcp migrate 初始化/迁移通用 task 数据库
squillaflow-mcp cleanup 清理过期且未固定的任务和 Artifact
squillaflow-mcp run 启动 stdio MCP sidecar
```
详细字段见 [docs/configuration.md](docs/configuration.md),Tool 契约见 [docs/task-api.md](docs/task-api.md),升级说明见 [docs/migration-0.4.md](docs/migration-0.4.md)。
## 开发与验证
```powershell
.venv\Scripts\python.exe -m ruff check src tests
.venv\Scripts\python.exe -m pytest -q
.venv\Scripts\python.exe -m build
```
测试覆盖 SQLite 幂等/租约、effect worker 隔离、调用方 namespace、文件根目录、Artifact 完整性、JSON Schema、续接、取消、恢复、Gateway HTTP/WS、官方 MCP stdio 协议和旧接口回归。
真实 OpenSquilla `0.5.2` E2E 已验证:
- 文本 task 完成并返回精确文本。
- 生成文件经 session-scoped HTTP 下载、size/SHA-256 校验、Store 托管后读回精确 bytes。
CI 在 Ubuntu、Windows、macOS 上测试 Python 3.12,并在 Ubuntu 上额外测试 Python 3.13;发行任务还构建 wheel/sdist、执行 metadata 检查和干净 wheel 安装 smoke。
## 当前限制
- 本机单节点 SQLite 队列,支持同一主机上的多个 MCP Host 共享 instance;不支持网络共享盘、多节点或跨 instance 队列。
- 只提供 stdio MCP Server,不提供远程多租户服务。
- 不自动安装或启动 OpenSquilla。
- 不提供 GUI/EXE。
- 调用方隔离依赖 MCP clientInfo,是本机命名空间边界,不是远程强身份认证。
- 旧出站 SSE Client 尚未支持通用认证 headers 或 Streamable HTTP。
## 版本对应
| 项目 | 版本 |
| --- | --- |
| SquillaFlow MCP | `0.4.0a1` |
| 已验证 OpenSquilla | `0.5.2 / protocol 3` |
| MCP Python SDK | `1.27.x`、`1.29.x` |
| Python | `3.12`、`3.13` |
## 来源与许可证
本仓库早期 MCP bridge 源自 OpenSquilla `v0.5.2` 相关模块,继续使用 [Apache License 2.0](LICENSE)。
- 上游仓库:[opensquilla/opensquilla](https://github.com/opensquilla/opensquilla)
- 固定参考提交:[`0624e20cf6aae4eb818211092956d3a1d611e97e`](https://github.com/opensquilla/opensquilla/commit/0624e20cf6aae4eb818211092956d3a1d611e97e)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues