agentseed-mcp 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/LICENSE +202 -0
  3. package/README.ja.md +320 -0
  4. package/README.md +318 -0
  5. package/README.zh.md +306 -0
  6. package/bin/cli.js +37 -0
  7. package/mcp.json +12 -0
  8. package/package.json +30 -0
  9. package/plugin.json +22 -0
  10. package/server/.agentseed/verification-log.jsonl +2 -0
  11. package/server/__pycache__/guard_cli.cpython-313.pyc +0 -0
  12. package/server/__pycache__/guard_engine.cpython-313.pyc +0 -0
  13. package/server/__pycache__/test_cli.cpython-313-pytest-9.1.1.pyc +0 -0
  14. package/server/__pycache__/test_cli.cpython-313.pyc +0 -0
  15. package/server/__pycache__/test_features.cpython-313-pytest-9.1.1.pyc +0 -0
  16. package/server/__pycache__/test_features.cpython-313.pyc +0 -0
  17. package/server/__pycache__/test_guard.cpython-313-pytest-9.1.1.pyc +0 -0
  18. package/server/__pycache__/test_guard.cpython-313.pyc +0 -0
  19. package/server/__pycache__/test_hook.cpython-313-pytest-9.1.1.pyc +0 -0
  20. package/server/__pycache__/test_hook.cpython-313.pyc +0 -0
  21. package/server/__pycache__/test_manifests.cpython-313-pytest-9.1.1.pyc +0 -0
  22. package/server/__pycache__/test_manifests.cpython-313.pyc +0 -0
  23. package/server/__pycache__/test_server.cpython-313-pytest-9.1.1.pyc +0 -0
  24. package/server/__pycache__/test_server.cpython-313.pyc +0 -0
  25. package/server/engine/__init__.py +64 -0
  26. package/server/engine/__pycache__/__init__.cpython-313.pyc +0 -0
  27. package/server/engine/__pycache__/audit.cpython-313.pyc +0 -0
  28. package/server/engine/__pycache__/config.cpython-313.pyc +0 -0
  29. package/server/engine/__pycache__/hallucination.cpython-313.pyc +0 -0
  30. package/server/engine/__pycache__/imports.cpython-313.pyc +0 -0
  31. package/server/engine/__pycache__/plugin.cpython-313.pyc +0 -0
  32. package/server/engine/__pycache__/sandbox.cpython-313.pyc +0 -0
  33. package/server/engine/__pycache__/schema.cpython-313.pyc +0 -0
  34. package/server/engine/__pycache__/symbols.cpython-313.pyc +0 -0
  35. package/server/engine/__pycache__/version.cpython-313.pyc +0 -0
  36. package/server/engine/audit.py +84 -0
  37. package/server/engine/config.py +131 -0
  38. package/server/engine/hallucination.py +254 -0
  39. package/server/engine/imports.py +136 -0
  40. package/server/engine/plugin.py +367 -0
  41. package/server/engine/sandbox.py +287 -0
  42. package/server/engine/schema.py +193 -0
  43. package/server/engine/symbols.py +984 -0
  44. package/server/engine/version.py +17 -0
  45. package/server/guard_cli.py +455 -0
  46. package/server/guard_engine.py +111 -0
  47. package/server/guard_hook.py +404 -0
  48. package/server/guard_server.py +472 -0
  49. package/server/requirements.txt +7 -0
  50. package/server/test_cli.py +132 -0
  51. package/server/test_features.py +426 -0
  52. package/server/test_guard.py +828 -0
  53. package/server/test_hook.py +331 -0
  54. package/server/test_manifests.py +70 -0
  55. package/server/test_server.py +247 -0
  56. package/skills/verify-before-code/SKILL.ja.md +116 -0
  57. package/skills/verify-before-code/SKILL.md +140 -0
  58. package/skills/verify-before-code/SKILL.zh.md +117 -0
  59. package/skills/verify-before-code/references/DEFAULT-NORMS.md +52 -0
  60. package/skills/verify-before-code/references/HALLUCINATION-PATTERNS.ja.md +121 -0
  61. package/skills/verify-before-code/references/HALLUCINATION-PATTERNS.md +166 -0
  62. package/skills/verify-before-code/references/HALLUCINATION-PATTERNS.zh.md +145 -0
  63. package/skills/verify-before-code/references/PROMPT-POOL.ja.md +248 -0
  64. package/skills/verify-before-code/references/PROMPT-POOL.md +282 -0
  65. package/skills/verify-before-code/references/PROMPT-POOL.zh.md +252 -0
  66. package/skills/verify-before-code/references/SDD-CONTRACT.ja.md +61 -0
  67. package/skills/verify-before-code/references/SDD-CONTRACT.md +66 -0
  68. package/skills/verify-before-code/references/SDD-CONTRACT.zh.md +58 -0
  69. package/skills/verify-before-code/references/VENDOR-SOLUTIONS.ja.md +62 -0
  70. package/skills/verify-before-code/references/VENDOR-SOLUTIONS.md +62 -0
  71. package/skills/verify-before-code/references/VENDOR-SOLUTIONS.zh.md +54 -0
  72. package/skills/verify-before-code/references/VERIFICATION-CHECKLIST.ja.md +68 -0
  73. package/skills/verify-before-code/references/VERIFICATION-CHECKLIST.md +73 -0
  74. package/skills/verify-before-code/references/VERIFICATION-CHECKLIST.zh.md +68 -0
  75. package/skills/verify-before-code/scripts/check.ps1 +52 -0
  76. package/skills/verify-before-code/scripts/check.sh +44 -0
package/README.zh.md ADDED
@@ -0,0 +1,306 @@
1
+ <div align="center">
2
+
3
+ <img src="docs/logo.png" width="96" alt="AgentSeed logo">
4
+
5
+ # AgentSeed
6
+
7
+ **AI 编码智能体的反幻觉闸门。**
8
+
9
+ AI 会编造不存在的 API,会不跑任何测试就说"全部通过",会自信地交付
10
+ 虚假代码。**AgentSeed 就是在"完成"之前拦截这一切的闸门**——一个零依赖插件,
11
+ 在任务被标记为"完成"之前先验证代码,让"完成"= **可观测事实**,而非自说自话。
12
+
13
+ [![License](https://img.shields.io/badge/license-Apache_2.0-green)](LICENSE)
14
+ [![Version](https://img.shields.io/badge/version-0.3.0-blue)](https://gitcode.com/badhope/AgentSeed/releases)
15
+ [![CI](https://github.com/Morningstar202604/AgentSeed/actions/workflows/ci.yml/badge.svg)](https://github.com/Morningstar202604/AgentSeed/actions/workflows/ci.yml)
16
+ [![Platforms](https://img.shields.io/badge/platform-Cursor%20%7C%20VS%20Code%20%7C%20Claude%20Code%20%7C%20Copilot-blue)](https://agent-plugins.org)
17
+
18
+ [English](./README.md) · **中文** · [日本語](./README.ja.md)
19
+
20
+ ⭐ **觉得有用?点个 Star——让更多开发者在上线幻觉代码之前找到护栏。**
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## 为什么你需要它
27
+
28
+ LLM 会幻觉——放到代码里就是**编造的 API、未定义的标识符、虚假的测试通过、
29
+ 自信的过度声明**:
30
+
31
+ - **15.1%** 的代码幻觉是调用不存在的、或从未导入的 API([arXiv:2404.00971](https://arxiv.org/abs/2404.00971))。
32
+ - **不足 10%** 的幻觉代码会挂掉测试——**约 90% 能溜过 CI**([arXiv:2404.00971](https://arxiv.org/abs/2404.00971))。
33
+ - **60%+** 的模型输出错误**表面上看不出来**(FAVA,[SoK](https://arxiv.org/abs/2502.18468))。
34
+
35
+ 纯提示词护栏是"软"的:模型可以嘴上答应验证、然后跳过。
36
+ **AgentSeed 把指令绑成一道"硬闸"**——证据来自真正运行的代码,而不是模型的自述。
37
+
38
+ ## 30 秒看懂 AgentSeed 是什么
39
+
40
+ 一个即插即用的 [Agent Plugins](https://agent-plugins.org) 1.0.0 插件
41
+ (Skill + MCP 服务器 + 可选的客户端 Hook + CI 门禁),兑现三个承诺:
42
+
43
+ | 承诺 | 如何兑现 |
44
+ | --- | --- |
45
+ | **🚫 不编造 API** | `verify_code` 用 **12+ 种语言**解析你的代码,标记任何"被调用却从未定义/导入"的符号 |
46
+ | **🚫 不假报"完成"** | `scan_hallucination` 拦截占位代码、过度声明与虚构内容(**中英双语**);`sandbox_run` 用真实执行证明运行时声明 |
47
+ | **🚫 不跳过验证** | Skill 约束流程、**客户端 Hook** 在 `Write`/`Edit` 落盘前拦截、`guard_cli gate` 用退出码在 CI 强制同一套规则 |
48
+
49
+ 它还填补了 1.0.0 规范故意留下的两个空白:
50
+
51
+ | Agent Plugins 1.0.0 的空白 | AgentSeed 的答案 |
52
+ | --- | --- |
53
+ | 没有强制机制(skill 可做可不做) | `verify-before-code` skill + 可选的**客户端强制 Hook**,让验证不可跳过 |
54
+ | 没有官方合规 linter | `check_plugin` 是**第一个严格的 1.0.0 linter**——而且 AgentSeed 通过了自己的 linter(`ok: true`) |
55
+
56
+ ## 看它现场抓幻觉
57
+
58
+ ```python
59
+ # 你的编码智能体刚刚"写完"这段——它调用了 magic_unknown(),
60
+ # 一个不存在、也从未导入的 API:
61
+
62
+ def f():
63
+ return magic_unknown() # ← 幻觉 API
64
+
65
+ # AgentSeed 在任务被标记为"完成"之前:
66
+ $ verify_code(source=..., language="python")
67
+ {
68
+ "language": "python",
69
+ "suspects": ["magic_unknown"] # ← 抓到,阻断
70
+ }
71
+ ```
72
+
73
+ ```text
74
+ # 智能体的"完成声明"也活不过这一关:
75
+ "The feature is production ready, all tests pass. Trust me."
76
+
77
+ $ scan_hallucination(source=...)
78
+ {
79
+ "hits": [
80
+ {"word": "all tests pass", "group": "oversold", "line": 1},
81
+ {"word": "production ready", "group": "oversold", "line": 1},
82
+ {"word": "trust me", "group": "oversold", "line": 1}
83
+ ],
84
+ "clean": false # ← 抓到,阻断
85
+ }
86
+ ```
87
+
88
+ 判定是**测出来的,不是吹出来的**:在固定种子的合成语料上(5 类缺陷、
89
+ 100 个缺陷模块 + 40 个干净模块),AgentSeed 得分
90
+ **precision 1.0 · recall 1.0**(tp=100, fp=0, fn=0)——并有回归测试锁定。
91
+ 方法与诚实边界见 [docs/BENCHMARK.md](./docs/BENCHMARK.md)。
92
+
93
+ ## 闸门如何工作
94
+
95
+ 1. **写码前** —— 加载 SDD 契约,用一句话陈述。
96
+ 2. **实现** —— 只写真代码:无占位、无编造 API。
97
+ 3. **说"完成"前** —— 跑 `verify_code` + `scan_hallucination`;运行时声明用
98
+ `sandbox_run` 实证;结构化输出用 `schema_validate` 校验。
99
+ 4. **语言审计** —— 完成报告必须附证据;禁用夸大词汇。
100
+ 5. 只有当**所有检查都通过**,任务才允许被标记为完成。
101
+
102
+ ## 快速开始
103
+
104
+ **方案 A —— 下载发布包(无需 git):**
105
+
106
+ ```bash
107
+ # 从 https://gitcode.com/badhope/AgentSeed/releases 取最新资产
108
+ # 或用安装器一键接入你的客户端:
109
+ bash install.sh --client auto --hooks # macOS / Linux
110
+ ./install.ps1 -Client auto -Hooks # Windows PowerShell
111
+ # --client: claude | opencode | cursor | manual
112
+ # --hooks / -Hooks: 同时注册 Claude Code 强制 Hook
113
+ ```
114
+
115
+ **方案 B —— 克隆:**
116
+
117
+ ```bash
118
+ git clone https://gitcode.com/badhope/AgentSeed.git
119
+ # 镜像:https://gitcode.com/badhope/AgentSeed · https://gitee.com/badhope/AgentSeed
120
+ ```
121
+
122
+ 1. 把 `AgentSeed/` 目录**丢进**任意支持 Agent Plugins 的客户端
123
+ (Cursor、VS Code、Claude Code、Copilot…)。无需构建、无需安装。
124
+ 2. 客户端从 `plugin.json` + `mcp.json` 自动发现 `verify-before-code` skill
125
+ 与 `agentseed` MCP 服务器。
126
+ 3. **完事。** 从此每个编码任务都被闸门约束:契约 → 实现 → 验证 → 证据。
127
+
128
+ 独立运行,或用人机同规的 CI 门禁:
129
+
130
+ ```bash
131
+ python3 server/guard_engine.py # 自检演示
132
+ python3 -m unittest discover -s server # 160+ 单元测试
133
+ python3 server/guard_cli.py gate --root . # CI 等价硬门禁
134
+ python3 server/guard_cli.py check . --ci # 仅插件合规
135
+ python3 server/guard_cli.py scan src/ --strict
136
+ ```
137
+
138
+ > **Windows 提示:** `mcp.json` 用 `python3` 启动服务器。很多 Windows 安装的
139
+ > 该别名是 Microsoft Store 占位程序;把 `command` 改成
140
+ > `["python", "server/guard_server.py"]` 或指向你的解释器绝对路径即可。
141
+
142
+ ## 8 个 MCP 工具
143
+
144
+ 零**必需**依赖——纯 Python 标准库;可选依赖把两个工具升级为行业标准引擎
145
+ (见下)。
146
+
147
+ | 工具 | 拦截什么 | 技术 |
148
+ | --- | --- | --- |
149
+ | `verify_code` | 编造的 API / 未定义符号 | Python AST + 配置驱动的通用词法扫描(12+ 语言) |
150
+ | `check_contract` | 违反书面规范 | requires/prohibits 契约校验 |
151
+ | `check_imports` | 幻觉包导入(slopsquatting 抢注) | stdlib + known_packages 白名单校验 |
152
+ | `scan_hallucination` | 占位代码、夸大声称、虚构内容 | 3 组 28+ 信号,中英双语 |
153
+ | `check_plugin` | 不合规的插件打包 | 严格 1.0.0 linter |
154
+ | `sandbox_run` | 什么都没跑就说"测试通过" | 确定性执行通道(有界内存输出) |
155
+ | `schema_validate` | 不合法的结构化输出 | JSON Schema 校验 |
156
+ | `record_verification` | 没有持久化证据链 | `PLUGIN_DATA` 下 JSONL 审计轨迹 |
157
+
158
+ ### 语言覆盖(诚实范围)
159
+
160
+ | 语言 | `verify_code` 分析 |
161
+ | --- | --- |
162
+ | Python | 完整 AST 作用域遍历(装 pyflakes 则合并),带行号 |
163
+ | TypeScript / JavaScript | 词法正则扫描(有明确记录的误报类别) |
164
+ | Go · Rust · Java · C · C++ · C# · PHP · Ruby · Kotlin · Swift | 配置驱动的通用词法扫描 |
165
+ | 任何其他语言 | 加一条 `LangSpec` 注册即可——无需改引擎 |
166
+
167
+ 诚实边界:属性调用(`obj.m()`)、宏、跨文件符号不分析;Ruby 无括号调用已支持。
168
+
169
+ 诚实边界:属性调用(`obj.m()`)、宏、跨文件符号不分析;Ruby 无括号调用已支持。
170
+
171
+ ### 真的能抓其他语言——实测为证
172
+
173
+ 同一规则适用于所有注册语言:只要「裸调用了从未定义的符号」,无论什么语法,都是幻觉:
174
+
175
+ ```python
176
+ # Go detect_undefined_symbols("func main() { process_data() }", "go") -> ["process_data"]
177
+ # Rust fn main() { let x = load_config() } -> ["load_config"]
178
+ # Java class A { void m() { connect_db() } } -> ["connect_db"]
179
+ # C int main() { ghost(); return 0; } -> ["ghost"]
180
+ # Kotlin fun main() { fetch_users() } -> ["fetch_users"]
181
+ # Swift func run() { connect() } -> ["connect"]
182
+ # Ruby def run; authenticate; end -> ["authenticate"]
183
+ # TypeScript function run() { connectDb() } -> ["connectDb"]
184
+ ```
185
+
186
+ 已实测 Go · Rust · Java · C · C++ · C# · PHP · Ruby · Kotlin · Swift ·
187
+ TypeScript——每种语言都能抓出自己的幻觉调用,且各语言干净代码**零误报**。
188
+
189
+
190
+ ## 客户端强制 Hook 模式
191
+
192
+ Skill 靠"劝",**Hook 在客户端边界"强制执行"**。把 AgentSeed 注册为
193
+ Claude Code hook,每个 `Write`/`Edit`/`MultiEdit` 都会自动被扫描——
194
+ 任何提示词都无法跳过:
195
+
196
+ ```bash
197
+ python3 server/guard_hook.py register --client claude # 幂等,合并进 settings
198
+ python3 server/guard_hook.py --file path/to/source.py # 直接扫描任意文件
199
+ ```
200
+
201
+ - **PreToolUse** 在内容落盘**之前**检查;阻断性发现退出码 `2`,智能体必须
202
+ 修复被标记的行。
203
+ - **PostToolUse** 对无内联内容的写路径再次检查落盘文件。
204
+ - **失败策略(诚实):** 基础设施问题(stdin 畸形、文件不可读)永不阻断
205
+ 工作——fail-open;只有真实的扫描发现才阻断。
206
+
207
+ ## 平台支持
208
+
209
+ | 客户端 | 状态 | 说明 |
210
+ | --- | --- | --- |
211
+ | Claude Code | ✅ 已验证 | skills + MCP + 可选强制 Hook |
212
+ | opencode | ✅ 已验证 | `~/.config/opencode/opencode.json` |
213
+ | Cursor | ⚪ 规范兼容* | 拷入项目;尚无稳定插件目录 |
214
+ | VS Code (+Copilot) | ⚪ 规范兼容* | MCP 支持逐步开放 |
215
+ | Cline / Windsurf | ⚪ 规范兼容* | stdio 服务器条目可直接映射 |
216
+
217
+ \* 诚实标注:格式与规范兼容、预期可用,但维护者尚未实测。你若验证成功,
218
+ 欢迎 PR 更新此表。
219
+
220
+ ## 可选依赖
221
+
222
+ ```bash
223
+ pip install -r server/requirements.txt
224
+ ```
225
+
226
+ | 扩展 | 升级效果 | 无它时 |
227
+ | --- | --- | --- |
228
+ | `jsonschema` | `schema_validate` → 完整 Draft 2020-12 | 内置子集校验器 |
229
+ | `pyflakes` | `verify_code` → pyflakes F821 分析 | 内置 AST 遍历 |
230
+ | `pyyaml` | SKILL.md frontmatter → 完整 YAML | 内置轻量解析器 |
231
+
232
+ ## 配置(`agentseed.config.json`)
233
+
234
+ | 键 | 作用 |
235
+ | --- | --- |
236
+ | `allowlist` | 扫描排除(替换内置测试惯用语清单) |
237
+ | `severities` | 按组覆盖严重度(`error` \| `warning` \| `info`) |
238
+ | `timeout` | 默认 `sandbox_run` 超时,秒(1–120) |
239
+ | `extra_tokens` | 运行时扩展幻觉词池 |
240
+ | `suppress_symbols` | `verify_code` 永不标记的名字(在 `suppressed` 中可见) |
241
+ | `known_packages` | `check_imports` 视为已知的包(stdlib + 常见包 + 本列表) |
242
+ | `sandbox_allowed_prefixes` | `sandbox_run` 可启动的**可执行文件白名单**;PATH 解析、分隔符边界强制(缺省=不限) |
243
+ | `sandbox_env` | `"inherit"` \| `"scrub"` —— `scrub` 在启动前剔除疑似凭据的环境变量 |
244
+
245
+ 未知键会在 stderr 告警——拼错的键绝不会被静默忽略。
246
+
247
+ > ⚠️ **安全提示:** `sandbox_run` 以你的用户权限执行真实进程。客户端必须将其
248
+ > 置于用户批准之后;共享/CI 环境请设置 `sandbox_allowed_prefixes`。命令会先经
249
+ > `PATH` 解析为绝对路径再执行,恶意 `cwd` 无法用植入的可执行文件冒充白名单
250
+ > 命令;未匹配/无法解析的命令不执行直接拒绝(退出码 -10)。
251
+
252
+ ## 兼容与优雅降级
253
+
254
+ | 宿主能力 | 得到什么 |
255
+ | --- | --- |
256
+ | 完整 Agent Plugins | 即插即用:skill + MCP 自动发现,`${PLUGIN_DATA}` 配置生效 |
257
+ | 支持 MCP 的客户端 | 注册即得全部 8 个工具 |
258
+ | 仅支持 skill 的客户端 | skill 流程;验证降级为 shell 调用 `guard_cli.py` |
259
+ | 纯终端 / CI | 带退出码的 CLI 门禁 |
260
+
261
+ ## 内置护栏库(EN / 中文 / 日本語)
262
+
263
+ `PROMPT-POOL`(20+ 条即贴即用的护栏提示)· `HALLUCINATION-PATTERNS`
264
+ (5 类失败模式目录)· `VERIFICATION-CHECKLIST`(可执行的收尾检查清单)·
265
+ `SDD-CONTRACT`(每个任务必须满足的契约)· `VENDOR-SOLUTIONS`
266
+ (厂商技术落地地图)。
267
+
268
+ ## 为什么选 AgentSeed 而非替代方案
269
+
270
+ | | 纯提示词护栏 skill | 静态 import linter(MCP) | **AgentSeed** |
271
+ | --- | --- | --- | --- |
272
+ | 触碰代码 | ❌ 仅提示 | ✅ import 图 | ✅ AST + 词法(12+ 语言) |
273
+ | 跑验证工具 | ❌ | lint 门禁 | ✅ 8 个 MCP 工具含沙箱 |
274
+ | 幻觉语言扫描 | ❌ | ❌ | ✅ stub/oversold/fabricated,中英双语 |
275
+ | 强制力 | 软(skill 文本) | CI 门禁 | **硬**:skill + MCP + hook + CLI 退出码 |
276
+ | 1.0.0 合规 linter | ❌ | ❌ | ✅ 首个 |
277
+
278
+ ## FAQ
279
+
280
+ **需要特定 LLM 吗?** 不需要——客户端无关、模型无关;闸门由 skill + MCP +
281
+ hook + CI 执行,与具体模型无关。
282
+
283
+ **零依赖?** 是的。MCP 服务器是纯 Python 标准库。
284
+
285
+ **能和现有的 AGENTS.md / CLAUDE.md 共存吗?** 能——它们是互补的。那些文件
286
+ 承载项目事实(散文、说服力);AgentSeed 承载行为契约与硬强制。
287
+
288
+ **怎么扩展到新语言?** 在 `server/engine/symbols.py` 加一条 `LangSpec` 注册
289
+ ——一份配置,零引擎改动。
290
+
291
+ ## 参与贡献
292
+
293
+ 欢迎 Issue、PR 与想法——或者为尚未收录的幻觉模式开一个 issue。
294
+ 详见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
295
+
296
+ ## 许可证
297
+
298
+ Apache-2.0 © AgentSeed。见 [LICENSE](./LICENSE)。
299
+
300
+ ---
301
+
302
+ <div align="center">
303
+
304
+ ⭐ **如果 AgentSeed 帮你拦下了要上线的幻觉代码,点个 Star——这是"护栏有用"最好的信号。**
305
+
306
+ </div>
package/bin/cli.js ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * agentseed-mcp launcher.
4
+ *
5
+ * The AgentSeed server itself is Python (stdlib-only). This shim exists so
6
+ * npm-based clients can spawn it the standard way:
7
+ *
8
+ * npx agentseed-mcp
9
+ *
10
+ * Requires Python 3.9+ on PATH (override with the PYTHON env var).
11
+ */
12
+ "use strict";
13
+
14
+ const { spawn } = require("child_process");
15
+ const path = require("path");
16
+
17
+ const py = process.env.PYTHON || (process.platform === "win32" ? "python" : "python3");
18
+ const server = path.join(__dirname, "..", "server", "guard_server.py");
19
+
20
+ const child = spawn(py, [server], { stdio: "inherit" });
21
+
22
+ child.on("error", (err) => {
23
+ if (err.code === "ENOENT") {
24
+ console.error(
25
+ `[agentseed-mcp] Python interpreter "${py}" not found on PATH.\n` +
26
+ `Install Python 3.9+ or set PYTHON=/path/to/python.`
27
+ );
28
+ process.exit(1);
29
+ }
30
+ throw err;
31
+ });
32
+
33
+ child.on("exit", (code) => process.exit(code == null ? 1 : code));
34
+
35
+ for (const sig of ["SIGINT", "SIGTERM"]) {
36
+ process.on(sig, () => child.kill(sig));
37
+ }
package/mcp.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
3
+ "mcpServers": {
4
+ "agentseed": {
5
+ "type": "stdio",
6
+ "command": "python3",
7
+ "args": ["server/guard_server.py"],
8
+ "cwd": "${PLUGIN_ROOT}",
9
+ "env": {}
10
+ }
11
+ }
12
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "agentseed-mcp",
3
+ "version": "0.3.0",
4
+ "description": "Anti-hallucination guardrails for AI coding agents: hybrid Skill + MCP server that forces spec-driven development and verifies code before it is marked done.",
5
+ "license": "Apache-2.0",
6
+ "mcpName": "io.gitcode.badhope/agentseed",
7
+ "bin": {
8
+ "agentseed-mcp": "bin/cli.js"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "server/",
13
+ "skills/",
14
+ "plugin.json",
15
+ "mcp.json",
16
+ "CHANGELOG.md",
17
+ "LICENSE"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://gitcode.com/badhope/AgentSeed.git"
22
+ },
23
+ "homepage": "https://gitcode.com/badhope/AgentSeed#readme",
24
+ "bugs": {
25
+ "url": "https://gitcode.com/badhope/AgentSeed/issues"
26
+ },
27
+ "engines": {
28
+ "node": ">=16"
29
+ }
30
+ }
package/plugin.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
+ "name": "agentseed",
4
+ "version": "0.3.0",
5
+ "description": "Guardrails for coding agents: a hybrid Agent Plugin (Skill + MCP Server) that forces spec-driven development and blocks hallucinated code before it is marked done. Built to the Agent Plugins 1.0.0 spec.",
6
+ "author": {
7
+ "name": "AgentSeed",
8
+ "url": "https://gitcode.com/badhope/AgentSeed"
9
+ },
10
+ "license": "Apache-2.0",
11
+ "keywords": [
12
+ "guardrail",
13
+ "anti-hallucination",
14
+ "spec-driven-development",
15
+ "code-verification",
16
+ "mcp",
17
+ "agent-plugins",
18
+ "coding-agent"
19
+ ],
20
+ "homepage": "https://gitcode.com/badhope/AgentSeed",
21
+ "repository": "https://gitcode.com/badhope/AgentSeed.git"
22
+ }
@@ -0,0 +1,2 @@
1
+ {"ts": "2026-08-26T13:56:04+00:00", "plugin_version": "0.1.1", "task": "protocol test", "checks": [{"tool": "manual", "status": "pass"}]}
2
+ {"ts": "2026-08-27T06:02:49+00:00", "plugin_version": "0.3.0", "task": "protocol test", "checks": [{"tool": "manual", "status": "pass"}]}
@@ -0,0 +1,64 @@
1
+ """AgentSeed guard engine — modular package.
2
+
3
+ Modules:
4
+ config — Config loading (load_config, config helpers)
5
+ symbols — Undefined symbol detection (detect_undefined_symbols)
6
+ hallucination — Hallucination word scanning (scan_hallucination_words)
7
+ plugin — Agent Plugins 1.0.0 conformance checker (check_plugin_conformance)
8
+ sandbox — Deterministic execution channel (sandbox_run)
9
+ schema — JSON Schema subset validator (schema_validate)
10
+
11
+ Public API only: internal helpers stay inside their modules.
12
+ """
13
+
14
+ from .audit import VALID_STATUSES, audit_path, record_verification
15
+ from .config import (
16
+ CONFIG_FILENAME,
17
+ KNOWN_CONFIG_KEYS,
18
+ SANDBOX_ENV_MODES,
19
+ VALID_GROUPS,
20
+ config_extra_tokens,
21
+ config_severities,
22
+ config_str_list,
23
+ load_config,
24
+ parse_timeout,
25
+ sandbox_env_mode,
26
+ unknown_config_keys,
27
+ )
28
+ from .hallucination import DEFAULT_ALLOWLIST, HALLUCINATION_WORDS, scan_hallucination_words
29
+ from .imports import check_imports
30
+ from .plugin import check_plugin_conformance
31
+ from .sandbox import build_env, kill_tree, resolve_executable, sandbox_run
32
+ from .schema import schema_validate
33
+ from .symbols import defined_symbols, detect_undefined_symbols
34
+ from .version import plugin_version
35
+
36
+ __all__ = [
37
+ "CONFIG_FILENAME",
38
+ "DEFAULT_ALLOWLIST",
39
+ "HALLUCINATION_WORDS",
40
+ "KNOWN_CONFIG_KEYS",
41
+ "SANDBOX_ENV_MODES",
42
+ "VALID_GROUPS",
43
+ "VALID_STATUSES",
44
+ "audit_path",
45
+ "build_env",
46
+ "check_plugin_conformance",
47
+ "check_imports",
48
+ "config_extra_tokens",
49
+ "config_severities",
50
+ "config_str_list",
51
+ "detect_undefined_symbols",
52
+ "defined_symbols",
53
+ "kill_tree",
54
+ "load_config",
55
+ "parse_timeout",
56
+ "plugin_version",
57
+ "record_verification",
58
+ "resolve_executable",
59
+ "sandbox_env_mode",
60
+ "sandbox_run",
61
+ "scan_hallucination_words",
62
+ "schema_validate",
63
+ "unknown_config_keys",
64
+ ]
@@ -0,0 +1,84 @@
1
+ """AgentSeed verification audit trail (P2-10).
2
+
3
+ The SDD contract requires a completion report with attached evidence, but
4
+ until now nothing persisted verification history. ``record_verification``
5
+ appends one JSONL line per call to
6
+
7
+ ${PLUGIN_DATA}/verification-log.jsonl (fallback: ./.agentseed/)
8
+
9
+ creating a tamper-evident-by-append audit trail agents (or CI) can cite.
10
+ Zero dependencies; stdlib only.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import os
17
+ import sys
18
+ from datetime import datetime, timezone
19
+
20
+ from .version import plugin_version
21
+
22
+ VALID_STATUSES = {"pass", "fail", "skipped"}
23
+
24
+
25
+ def audit_path(data_dir: str | None = None) -> str:
26
+ base = data_dir or os.environ.get("PLUGIN_DATA") or os.path.join(os.getcwd(), ".agentseed")
27
+ return os.path.join(base, "verification-log.jsonl")
28
+
29
+
30
+ def record_verification(
31
+ task: str,
32
+ checks: list[dict] | None = None,
33
+ summary: str | None = None,
34
+ data_dir: str | None = None,
35
+ ) -> dict:
36
+ """Append one verification record; returns {"ok", "path", "entries"}."""
37
+ if not isinstance(task, str) or not task.strip():
38
+ return {"ok": False, "error": "task must be a non-empty string", "path": "", "entries": 0}
39
+ clean_checks = []
40
+ for c in checks if isinstance(checks, list) else []:
41
+ if not isinstance(c, dict):
42
+ continue
43
+ status = c.get("status")
44
+ if status not in VALID_STATUSES:
45
+ continue
46
+ entry = {"tool": str(c.get("tool", "unknown")), "status": status}
47
+ if isinstance(c.get("summary"), str):
48
+ entry["summary"] = c["summary"]
49
+ clean_checks.append(entry)
50
+ path = audit_path(data_dir)
51
+ record = {
52
+ "ts": datetime.now(timezone.utc).isoformat(timespec="seconds"),
53
+ "plugin_version": plugin_version(),
54
+ "task": task,
55
+ "checks": clean_checks,
56
+ }
57
+ if isinstance(summary, str) and summary:
58
+ record["summary"] = summary
59
+ try:
60
+ os.makedirs(os.path.dirname(path), exist_ok=True)
61
+ with open(path, "a", encoding="utf-8") as fh:
62
+ fh.write(json.dumps(record, ensure_ascii=False) + "\n")
63
+ except OSError as exc:
64
+ return {"ok": False, "error": f"cannot write audit log: {exc}", "path": path, "entries": 0}
65
+ entries = 0
66
+ try:
67
+ with open(path, encoding="utf-8") as fh:
68
+ entries = sum(1 for line in fh if line.strip())
69
+ except OSError:
70
+ pass
71
+ return {"ok": True, "path": path, "entries": entries}
72
+
73
+
74
+ def main() -> int: # pragma: no cover - CLI convenience
75
+ args = sys.argv[1:]
76
+ if not args:
77
+ print(__doc__)
78
+ return 2
79
+ print(json.dumps(record_verification(args[0]), ensure_ascii=False, indent=2))
80
+ return 0
81
+
82
+
83
+ if __name__ == "__main__":
84
+ sys.exit(main())