@yottameta/yotta-skills 0.1.2 → 0.2.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.
- package/CHANGELOG.md +22 -0
- package/README.md +8 -1
- package/README.zh-CN.md +8 -1
- package/SKILL.md +192 -119
- package/bin/yotta-skills.js +41 -2
- package/lib/skills-scan.js +318 -0
- package/package.json +3 -1
- package/references/install-flow.md +68 -68
- package/references/orchestration.md +72 -0
- package/references/skill-list.md +40 -40
- package/references/tutorial.md +106 -106
- package/scripts/yotta-skills-mcp.py +245 -0
- package/skills.json +9 -9
package/references/tutorial.md
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
# 元阁中文教程(新手全流程)
|
|
2
|
-
|
|
3
|
-
> 配套技能:元阁 yotta-skills(全家技能一键安装 CLI,依赖 Node.js 18+ / npm / 系统 tar)。
|
|
4
|
-
> 目标:把元阁已发布的 22 个 `yotta-*` 技能一次装进指定智能体或目录,并学会预览、更新、
|
|
5
|
-
> 锁版本与常见排查。
|
|
6
|
-
|
|
7
|
-
## 1. 教程目标与前置
|
|
8
|
-
|
|
9
|
-
- 学会 `--list` / `install` / `update` / `--dry-run` / `--pin` / `--force` 的用法;
|
|
10
|
-
- 理解版本策略(range 与 --pin)与幂等行为;
|
|
11
|
-
- 掌握元信装前摘要的开关与配置;
|
|
12
|
-
- 前置:Node.js 18+、npm、系统 tar(Windows 10+ 自带);网络可访问 npm 注册表
|
|
13
|
-
(国内可配置镜像或代理)。
|
|
14
|
-
|
|
15
|
-
## 2. 查看全家清单
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx -y @yottameta/yotta-skills --list
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
输出 22 个技能:slug / 中文名 / 包名与版本范围 / 清单版本 / 一句话说明。
|
|
22
|
-
确认某个技能在不在清单里,可加技能名过滤:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npx -y @yottameta/yotta-skills --list yotta-memory
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## 3. 安装全家到智能体
|
|
29
|
-
|
|
30
|
-
推荐用 `--agent` 装到指定智能体默认用户级目录(如 Codex):
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npx -y @yottameta/yotta-skills install --agent codex
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
支持 17 个智能体键名:`claude` / `cursor` / `codex` / `gemini` / `goose` / `amp` /
|
|
37
|
-
`opencode` / `windsurf` / `workbuddy` / `kiro` / `trae` / `trae-cn` / `qwen` / `comate` /
|
|
38
|
-
`codebuddy` / `kimi` / `agents`。未收录的智能体用 `--dir` 指到它的技能目录。
|
|
39
|
-
|
|
40
|
-
## 4. 安装到任意目录
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npx -y @yottameta/yotta-skills install --dir ~/my-skills
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
每个技能落在 `<dir>/<slug>`(如 `~/my-skills/yotta-memory/`)。
|
|
47
|
-
只装个别技能:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
npx -y @yottameta/yotta-skills install yotta-memory yotta-verify --dir ~/my-skills
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## 5. 更新已装技能
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
npx -y @yottameta/yotta-skills update --agent codex
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
- 缺失的技能 → 补装;版本不一致的技能 → 按当前版本策略重装;
|
|
60
|
-
- 已是最新的技能显示「已是最新」并跳过(幂等)。
|
|
61
|
-
|
|
62
|
-
## 6. 安装前预览
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
npx -y @yottameta/yotta-skills --dry-run
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
dry-run 只打印将要执行的清单(含目标与版本策略),不联网、不写任何文件。
|
|
69
|
-
|
|
70
|
-
## 7. 版本策略:range 与 --pin
|
|
71
|
-
|
|
72
|
-
- 默认 range:按同 major 最新 patch(如 `0.x`),维护性更新随最新;
|
|
73
|
-
- 想完全可复现 → 加 `--pin` 锁死清单精确版本:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
npx -y @yottameta/yotta-skills install --agent codex --pin
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## 8. 强制重装与跳过元信摘要
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npx -y @yottameta/yotta-skills install --agent codex --force # 已是最新也重装
|
|
83
|
-
npx -y @yottameta/yotta-skills install --agent codex --skip-scan # 跳过装前摘要
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
元信(yotta-verify)已安装时默认会对每个待装技能输出装前摘要(verdict + 计数),仅提示
|
|
87
|
-
不拦截;verdict 为 DO NOT INSTALL 时会提示人工复核。
|
|
88
|
-
|
|
89
|
-
## 9. 验证安装结果
|
|
90
|
-
|
|
91
|
-
- 看安装汇总:成功 N / 跳过 N / 失败 N;
|
|
92
|
-
- 抽查技能目录:`ls ~/.codex/skills/yotta-memory/SKILL.md`;
|
|
93
|
-
- 复核版本:每个技能 SKILL.md 的 frontmatter `version` 应与 `--list` 一致(这也是幂等
|
|
94
|
-
判断的依据)。
|
|
95
|
-
|
|
96
|
-
## 10. 常见问题
|
|
97
|
-
|
|
98
|
-
- **npmmirror 全新包 404**:镜像同步有延迟。设置环境变量 `YOTTA_SKILLS_NPM_FLAGS` 为
|
|
99
|
-
`--registry=https://registry.npmjs.org/`(国内需代理)再执行,或等待镜像缓存后重试。
|
|
100
|
-
- **`--agent` 报未收录**:改用 `--dir` 指到该智能体的技能目录(`.agents/skills` 不是
|
|
101
|
-
通用目录)。
|
|
102
|
-
- **某技能安装失败**:汇总报告给出失败原因;可单装该技能排查:
|
|
103
|
-
`install <slug> --dir <path>`。
|
|
104
|
-
- **目标未指定**:当前目录没有项目级技能目录时报错(退出码 4),加 `--agent` 或
|
|
105
|
-
`--dir`。
|
|
106
|
-
- **已有旧版本**:默认按 range 覆盖升级到最新 patch;`--pin` 则锁定清单版本。
|
|
1
|
+
# 元阁中文教程(新手全流程)
|
|
2
|
+
|
|
3
|
+
> 配套技能:元阁 yotta-skills(全家技能一键安装 CLI,依赖 Node.js 18+ / npm / 系统 tar)。
|
|
4
|
+
> 目标:把元阁已发布的 22 个 `yotta-*` 技能一次装进指定智能体或目录,并学会预览、更新、
|
|
5
|
+
> 锁版本与常见排查。
|
|
6
|
+
|
|
7
|
+
## 1. 教程目标与前置
|
|
8
|
+
|
|
9
|
+
- 学会 `--list` / `install` / `update` / `--dry-run` / `--pin` / `--force` 的用法;
|
|
10
|
+
- 理解版本策略(range 与 --pin)与幂等行为;
|
|
11
|
+
- 掌握元信装前摘要的开关与配置;
|
|
12
|
+
- 前置:Node.js 18+、npm、系统 tar(Windows 10+ 自带);网络可访问 npm 注册表
|
|
13
|
+
(国内可配置镜像或代理)。
|
|
14
|
+
|
|
15
|
+
## 2. 查看全家清单
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx -y @yottameta/yotta-skills --list
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
输出 22 个技能:slug / 中文名 / 包名与版本范围 / 清单版本 / 一句话说明。
|
|
22
|
+
确认某个技能在不在清单里,可加技能名过滤:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx -y @yottameta/yotta-skills --list yotta-memory
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 3. 安装全家到智能体
|
|
29
|
+
|
|
30
|
+
推荐用 `--agent` 装到指定智能体默认用户级目录(如 Codex):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx -y @yottameta/yotta-skills install --agent codex
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
支持 17 个智能体键名:`claude` / `cursor` / `codex` / `gemini` / `goose` / `amp` /
|
|
37
|
+
`opencode` / `windsurf` / `workbuddy` / `kiro` / `trae` / `trae-cn` / `qwen` / `comate` /
|
|
38
|
+
`codebuddy` / `kimi` / `agents`。未收录的智能体用 `--dir` 指到它的技能目录。
|
|
39
|
+
|
|
40
|
+
## 4. 安装到任意目录
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx -y @yottameta/yotta-skills install --dir ~/my-skills
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
每个技能落在 `<dir>/<slug>`(如 `~/my-skills/yotta-memory/`)。
|
|
47
|
+
只装个别技能:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx -y @yottameta/yotta-skills install yotta-memory yotta-verify --dir ~/my-skills
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 5. 更新已装技能
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx -y @yottameta/yotta-skills update --agent codex
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- 缺失的技能 → 补装;版本不一致的技能 → 按当前版本策略重装;
|
|
60
|
+
- 已是最新的技能显示「已是最新」并跳过(幂等)。
|
|
61
|
+
|
|
62
|
+
## 6. 安装前预览
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx -y @yottameta/yotta-skills --dry-run
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
dry-run 只打印将要执行的清单(含目标与版本策略),不联网、不写任何文件。
|
|
69
|
+
|
|
70
|
+
## 7. 版本策略:range 与 --pin
|
|
71
|
+
|
|
72
|
+
- 默认 range:按同 major 最新 patch(如 `0.x`),维护性更新随最新;
|
|
73
|
+
- 想完全可复现 → 加 `--pin` 锁死清单精确版本:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx -y @yottameta/yotta-skills install --agent codex --pin
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 8. 强制重装与跳过元信摘要
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx -y @yottameta/yotta-skills install --agent codex --force # 已是最新也重装
|
|
83
|
+
npx -y @yottameta/yotta-skills install --agent codex --skip-scan # 跳过装前摘要
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
元信(yotta-verify)已安装时默认会对每个待装技能输出装前摘要(verdict + 计数),仅提示
|
|
87
|
+
不拦截;verdict 为 DO NOT INSTALL 时会提示人工复核。
|
|
88
|
+
|
|
89
|
+
## 9. 验证安装结果
|
|
90
|
+
|
|
91
|
+
- 看安装汇总:成功 N / 跳过 N / 失败 N;
|
|
92
|
+
- 抽查技能目录:`ls ~/.codex/skills/yotta-memory/SKILL.md`;
|
|
93
|
+
- 复核版本:每个技能 SKILL.md 的 frontmatter `version` 应与 `--list` 一致(这也是幂等
|
|
94
|
+
判断的依据)。
|
|
95
|
+
|
|
96
|
+
## 10. 常见问题
|
|
97
|
+
|
|
98
|
+
- **npmmirror 全新包 404**:镜像同步有延迟。设置环境变量 `YOTTA_SKILLS_NPM_FLAGS` 为
|
|
99
|
+
`--registry=https://registry.npmjs.org/`(国内需代理)再执行,或等待镜像缓存后重试。
|
|
100
|
+
- **`--agent` 报未收录**:改用 `--dir` 指到该智能体的技能目录(`.agents/skills` 不是
|
|
101
|
+
通用目录)。
|
|
102
|
+
- **某技能安装失败**:汇总报告给出失败原因;可单装该技能排查:
|
|
103
|
+
`install <slug> --dir <path>`。
|
|
104
|
+
- **目标未指定**:当前目录没有项目级技能目录时报错(退出码 4),加 `--agent` 或
|
|
105
|
+
`--dir`。
|
|
106
|
+
- **已有旧版本**:默认按 range 覆盖升级到最新 patch;`--pin` 则锁定清单版本。
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""yotta-skills-mcp.py — 元阁(yotta-skills)技能盘点 MCP server。
|
|
4
|
+
|
|
5
|
+
stdio MCP server(JSON-RPC 2.0,换行分隔),把元阁技能扫描核心暴露为 MCP 工具:
|
|
6
|
+
list_installed_skills 盘点本机已装技能(读本地注册表;未生成则先扫描一次)
|
|
7
|
+
describe_skill 查看单个技能详情(slug / 版本 / 功能 / 来源)
|
|
8
|
+
reindex 强制重新扫描并更新注册表
|
|
9
|
+
|
|
10
|
+
自包含原则:扫描由元阁自带核心(bin/yotta-skills.js --inventory)完成,
|
|
11
|
+
不依赖任何元技能;数据只写本机 ~/.yottaskills/registry.json,不出本机。
|
|
12
|
+
|
|
13
|
+
运行:python scripts/yotta-skills-mcp.py
|
|
14
|
+
MCP 客户端配置:
|
|
15
|
+
{"mcpServers":{"yotta-skills":{"command":"python",
|
|
16
|
+
"args":["<绝对路径>/scripts/yotta-skills-mcp.py"]}}}
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import shutil
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
VERSION = "0.2.0"
|
|
27
|
+
TOOL_NAME = "yotta-skills"
|
|
28
|
+
CN_NAME = "元阁"
|
|
29
|
+
MCP_PROTOCOL = "2025-03-26"
|
|
30
|
+
SERVERS = {TOOL_NAME: {"name": TOOL_NAME, "cn": CN_NAME, "version": VERSION}}
|
|
31
|
+
|
|
32
|
+
_HERE = Path(__file__).resolve().parent
|
|
33
|
+
BIN_JS = (_HERE.parent / "bin" / "yotta-skills.js").resolve()
|
|
34
|
+
REGISTRY_FILE = Path(os.path.expanduser("~/.yottaskills/registry.json"))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _tool_error(message, extra=None):
|
|
38
|
+
payload = {"error": message}
|
|
39
|
+
if extra:
|
|
40
|
+
payload.update(extra)
|
|
41
|
+
return {"content": [{"type": "text", "text": json.dumps(payload, ensure_ascii=False, indent=2)}],
|
|
42
|
+
"isError": True}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _tool_spec(name, description, properties, required=None):
|
|
46
|
+
return {
|
|
47
|
+
"name": name,
|
|
48
|
+
"description": description,
|
|
49
|
+
"inputSchema": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"properties": properties,
|
|
52
|
+
**({"required": required} if required else {}),
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _run_cli(args):
|
|
58
|
+
"""运行元阁 CLI(Node),返回 stdout 文本;失败抛 RuntimeError。"""
|
|
59
|
+
node = shutil.which("node")
|
|
60
|
+
if not node:
|
|
61
|
+
raise RuntimeError("未找到 node 可执行文件(元阁 CLI 依赖 Node.js 18+)")
|
|
62
|
+
proc = subprocess.run(
|
|
63
|
+
[node, str(BIN_JS)] + args,
|
|
64
|
+
capture_output=True, text=True, encoding="utf-8",
|
|
65
|
+
timeout=120,
|
|
66
|
+
)
|
|
67
|
+
if proc.returncode != 0:
|
|
68
|
+
raise RuntimeError("yotta-skills CLI 失败(exit %s):%s" % (proc.returncode, (proc.stderr or proc.stdout).strip()[:500]))
|
|
69
|
+
return proc.stdout
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _read_registry():
|
|
73
|
+
if not REGISTRY_FILE.is_file():
|
|
74
|
+
return None
|
|
75
|
+
try:
|
|
76
|
+
return json.loads(REGISTRY_FILE.read_text(encoding="utf-8"))
|
|
77
|
+
except Exception: # noqa: BLE001
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _ensure_registry():
|
|
82
|
+
"""注册表不存在时先扫描生成一次;返回注册表 dict。"""
|
|
83
|
+
reg = _read_registry()
|
|
84
|
+
if reg is not None:
|
|
85
|
+
return reg
|
|
86
|
+
_run_cli(["--inventory"])
|
|
87
|
+
reg = _read_registry()
|
|
88
|
+
if reg is None:
|
|
89
|
+
raise RuntimeError("技能注册表生成失败(~/.yottaskills/registry.json)")
|
|
90
|
+
return reg
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _skills_list(registry):
|
|
94
|
+
return sorted(
|
|
95
|
+
[s for s in registry.get("skills", {}).values() if s.get("status") != "gone"],
|
|
96
|
+
key=lambda s: s.get("slug", ""),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _tool_list(arguments): # noqa: ARG001
|
|
101
|
+
registry = _ensure_registry()
|
|
102
|
+
skills = _skills_list(registry)
|
|
103
|
+
payload = {
|
|
104
|
+
"count": len(skills),
|
|
105
|
+
"registry": str(REGISTRY_FILE),
|
|
106
|
+
"skills": skills,
|
|
107
|
+
}
|
|
108
|
+
return {"content": [{"type": "text", "text": json.dumps(payload, ensure_ascii=False, indent=2)}],
|
|
109
|
+
"isError": False}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _tool_describe(arguments):
|
|
113
|
+
slug = str(arguments.get("slug") or "").strip()
|
|
114
|
+
if not slug:
|
|
115
|
+
return _tool_error("describe_skill 需要 slug 参数")
|
|
116
|
+
registry = _ensure_registry()
|
|
117
|
+
skill = registry.get("skills", {}).get(slug)
|
|
118
|
+
if not skill or skill.get("status") == "gone":
|
|
119
|
+
return _tool_error("未找到技能: %s" % slug)
|
|
120
|
+
payload = {"skill": skill}
|
|
121
|
+
return {"content": [{"type": "text", "text": json.dumps(payload, ensure_ascii=False, indent=2)}],
|
|
122
|
+
"isError": False}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _tool_reindex(arguments): # noqa: ARG001
|
|
126
|
+
stdout = _run_cli(["--inventory", "--json"])
|
|
127
|
+
try:
|
|
128
|
+
data = json.loads(stdout)
|
|
129
|
+
except json.JSONDecodeError as e:
|
|
130
|
+
return _tool_error("reindex 输出解析失败:%s" % e)
|
|
131
|
+
payload = {
|
|
132
|
+
"count": len(data.get("skills", [])),
|
|
133
|
+
"changes": data.get("changes"),
|
|
134
|
+
"errors": data.get("errors"),
|
|
135
|
+
"registry": str(REGISTRY_FILE),
|
|
136
|
+
}
|
|
137
|
+
return {"content": [{"type": "text", "text": json.dumps(payload, ensure_ascii=False, indent=2)}],
|
|
138
|
+
"isError": False}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
TOOL_HANDLERS = {
|
|
142
|
+
"list_installed_skills": _tool_list,
|
|
143
|
+
"describe_skill": _tool_describe,
|
|
144
|
+
"reindex": _tool_reindex,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def mcp_tools():
|
|
149
|
+
return [
|
|
150
|
+
_tool_spec(
|
|
151
|
+
"list_installed_skills",
|
|
152
|
+
"盘点本机已装技能:返回技能列表(slug / 版本 / 功能一句话 / 来源)。"
|
|
153
|
+
"读本地注册表 ~/.yottaskills/registry.json;未生成则先扫描一次。"
|
|
154
|
+
"扫描由元阁自带核心完成,不依赖任何其他技能。数据不出本机。",
|
|
155
|
+
{},
|
|
156
|
+
[],
|
|
157
|
+
),
|
|
158
|
+
_tool_spec(
|
|
159
|
+
"describe_skill",
|
|
160
|
+
"查看单个技能的详情(slug / 版本 / 功能 / 来源目录)。",
|
|
161
|
+
{"slug": {"type": "string", "description": "技能 slug(如 yotta-memory)"}},
|
|
162
|
+
["slug"],
|
|
163
|
+
),
|
|
164
|
+
_tool_spec(
|
|
165
|
+
"reindex",
|
|
166
|
+
"强制重新扫描所有技能目录并更新本地注册表,返回本次变化(新增 / 更新 / 消失)。",
|
|
167
|
+
{},
|
|
168
|
+
[],
|
|
169
|
+
),
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def handle_message(msg):
|
|
174
|
+
"""处理一行 JSON-RPC 消息,返回响应 dict;通知返回 None。"""
|
|
175
|
+
if not isinstance(msg, dict) or msg.get("jsonrpc") != "2.0":
|
|
176
|
+
rid = msg.get("id") if isinstance(msg, dict) else None
|
|
177
|
+
return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32600, "message": "invalid request"}}
|
|
178
|
+
method = msg.get("method")
|
|
179
|
+
rid = msg.get("id")
|
|
180
|
+
if rid is None: # JSON-RPC 通知(无 id)不响应
|
|
181
|
+
return None
|
|
182
|
+
if method is None:
|
|
183
|
+
return None
|
|
184
|
+
params = msg.get("params") or {}
|
|
185
|
+
|
|
186
|
+
if method == "initialize":
|
|
187
|
+
return {
|
|
188
|
+
"jsonrpc": "2.0", "id": rid,
|
|
189
|
+
"result": {
|
|
190
|
+
"protocolVersion": MCP_PROTOCOL,
|
|
191
|
+
"capabilities": {"tools": {}},
|
|
192
|
+
"serverInfo": {"name": TOOL_NAME, "version": VERSION},
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
if method == "ping":
|
|
196
|
+
return {"jsonrpc": "2.0", "id": rid, "result": {}}
|
|
197
|
+
if method == "tools/list":
|
|
198
|
+
return {"jsonrpc": "2.0", "id": rid, "result": {"tools": mcp_tools()}}
|
|
199
|
+
if method == "tools/call":
|
|
200
|
+
name = params.get("name")
|
|
201
|
+
arguments = params.get("arguments") or {}
|
|
202
|
+
handler = TOOL_HANDLERS.get(name)
|
|
203
|
+
if not handler:
|
|
204
|
+
return {
|
|
205
|
+
"jsonrpc": "2.0", "id": rid,
|
|
206
|
+
"result": {"content": [{"type": "text", "text": "未知工具: %s" % name}], "isError": True},
|
|
207
|
+
}
|
|
208
|
+
try:
|
|
209
|
+
return {"jsonrpc": "2.0", "id": rid, "result": handler(arguments)}
|
|
210
|
+
except Exception as e: # noqa: BLE001
|
|
211
|
+
return {
|
|
212
|
+
"jsonrpc": "2.0", "id": rid,
|
|
213
|
+
"result": {"content": [{"type": "text", "text": "工具执行异常:%s" % e}], "isError": True},
|
|
214
|
+
}
|
|
215
|
+
return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32601, "message": "Method not found: " + str(method)}}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def main():
|
|
219
|
+
"""stdio 主循环:读行 -> JSON-RPC -> 响应行。"""
|
|
220
|
+
try:
|
|
221
|
+
sys.stdin.reconfigure(encoding="utf-8")
|
|
222
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
223
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
224
|
+
except Exception: # noqa: BLE001
|
|
225
|
+
pass
|
|
226
|
+
for line in sys.stdin:
|
|
227
|
+
line = line.strip()
|
|
228
|
+
if not line:
|
|
229
|
+
continue
|
|
230
|
+
try:
|
|
231
|
+
msg = json.loads(line)
|
|
232
|
+
except json.JSONDecodeError:
|
|
233
|
+
sys.stdout.write(json.dumps(
|
|
234
|
+
{"jsonrpc": "2.0", "id": None, "error": {"code": -32700, "message": "parse error"}},
|
|
235
|
+
ensure_ascii=False) + "\n")
|
|
236
|
+
sys.stdout.flush()
|
|
237
|
+
continue
|
|
238
|
+
resp = handle_message(msg)
|
|
239
|
+
if resp is not None:
|
|
240
|
+
sys.stdout.write(json.dumps(resp, ensure_ascii=False) + "\n")
|
|
241
|
+
sys.stdout.flush()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
main()
|
package/skills.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": 1,
|
|
3
|
-
"updated": "2026-08-
|
|
3
|
+
"updated": "2026-08-30",
|
|
4
4
|
"note": "清单同步要求:每次技能发布新版本后,按 YottaSkills 技能登记表更新本文件(登记表为内部台账,不随包分发)。",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"name": "元序",
|
|
23
23
|
"pkg": "@yottameta/yotta-workflow",
|
|
24
24
|
"version": "0.2.6",
|
|
25
|
-
"desc": "
|
|
25
|
+
"desc": "跨会话/跨项目通用工作流协议(状态就近存)"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"slug": "yotta-memory",
|
|
29
29
|
"name": "元忆",
|
|
30
30
|
"pkg": "@yottameta/yotta-memory",
|
|
31
|
-
"version": "0.8.
|
|
31
|
+
"version": "0.8.5",
|
|
32
32
|
"desc": "有权限边界的文件式智能体记忆(FACT/PREF/BOUND/COMMIT)"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
@@ -36,20 +36,20 @@
|
|
|
36
36
|
"name": "元习",
|
|
37
37
|
"pkg": "@yottameta/yotta-learn",
|
|
38
38
|
"version": "0.1.4",
|
|
39
|
-
"desc": "
|
|
39
|
+
"desc": "学习沉淀 CLI:错误/纠正/洞见沉淀为 .learnings/ 条目"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"slug": "yotta-security-audit",
|
|
43
43
|
"name": "元安",
|
|
44
44
|
"pkg": "@yottameta/yotta-security-audit",
|
|
45
|
-
"version": "0.
|
|
45
|
+
"version": "0.2.2",
|
|
46
46
|
"desc": "安全扫描引擎:13 类检测器 + 系统安全基线"
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"slug": "yotta-vetter",
|
|
50
50
|
"name": "元审",
|
|
51
51
|
"pkg": "@yottameta/yotta-vetter",
|
|
52
|
-
"version": "0.
|
|
52
|
+
"version": "0.2.3",
|
|
53
53
|
"desc": "安全审查协议:四阶段 review + SAFE TO INSTALL 判定"
|
|
54
54
|
},
|
|
55
55
|
{
|
|
@@ -84,14 +84,14 @@
|
|
|
84
84
|
"slug": "yotta-security-testing",
|
|
85
85
|
"name": "元测",
|
|
86
86
|
"pkg": "@yottameta/yotta-security-testing",
|
|
87
|
-
"version": "0.
|
|
87
|
+
"version": "0.2.4",
|
|
88
88
|
"desc": "有纪律的 AI 安全测试方法论 + Scope Guard 五道防线"
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"slug": "yotta-agent-hardening",
|
|
92
92
|
"name": "元安全",
|
|
93
93
|
"pkg": "@yottameta/yotta-agent-hardening",
|
|
94
|
-
"version": "0.
|
|
94
|
+
"version": "0.2.4",
|
|
95
95
|
"desc": "防御向 AI 智能体自身安全加固(配置面静态扫描三域)"
|
|
96
96
|
},
|
|
97
97
|
{
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"slug": "yotta-verify",
|
|
155
155
|
"name": "元信",
|
|
156
156
|
"pkg": "@yottameta/yotta-verify",
|
|
157
|
-
"version": "0.
|
|
157
|
+
"version": "0.2.2",
|
|
158
158
|
"desc": "装前安全扫描器 + audited 徽章(prompt injection + 危险模式)"
|
|
159
159
|
}
|
|
160
160
|
]
|