momo-ai 1.0.20 → 1.0.22
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/.claude/skills/algorithmic-art/LICENSE.txt +202 -0
- package/.claude/skills/algorithmic-art/SKILL.md +405 -0
- package/.claude/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/.claude/skills/algorithmic-art/templates/viewer.html +599 -0
- package/.claude/skills/r2mo-rad-lain/SKILL.md +101 -0
- package/.cursor/mcp.json +17 -0
- package/.obsidian/app.json +1 -0
- package/.obsidian/appearance.json +4 -0
- package/.obsidian/community-plugins.json +4 -0
- package/.obsidian/core-plugins.json +33 -0
- package/.obsidian/plugins/ai-agent/main.js +98495 -0
- package/.obsidian/plugins/ai-agent/manifest.json +11 -0
- package/.obsidian/plugins/ai-agent/styles.css +806 -0
- package/.obsidian/plugins/dataview/main.js +20876 -0
- package/.obsidian/plugins/dataview/manifest.json +11 -0
- package/.obsidian/plugins/dataview/styles.css +141 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
- package/.obsidian/plugins/templater-obsidian/main.js +45 -0
- package/.obsidian/plugins/templater-obsidian/manifest.json +11 -0
- package/.obsidian/plugins/templater-obsidian/styles.css +226 -0
- package/.obsidian/plugins/terminal/main.js +200 -0
- package/.obsidian/plugins/terminal/manifest.json +14 -0
- package/.obsidian/plugins/terminal/styles.css +32 -0
- package/.obsidian/themes/AnuPpuccin/manifest.json +7 -0
- package/.obsidian/themes/AnuPpuccin/theme.css +9080 -0
- package/.obsidian/themes/Things/manifest.json +7 -0
- package/.obsidian/themes/Things/theme.css +1628 -0
- package/.obsidian/workspace.json +196 -0
- package/.trae/skills/algorithmic-art/LICENSE.txt +202 -0
- package/.trae/skills/algorithmic-art/SKILL.md +405 -0
- package/.trae/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/.trae/skills/algorithmic-art/templates/viewer.html +599 -0
- package/.trae/skills/doc-coauthoring/SKILL.md +375 -0
- package/.trae/skills/frontend-design/LICENSE.txt +177 -0
- package/.trae/skills/frontend-design/SKILL.md +42 -0
- package/.trae/skills/r2mo-rad-lain/SKILL.md +101 -0
- package/README.md +12 -148
- package/docs/images/logo.jpeg +0 -0
- package/docs/images/r2mo-lain.png +0 -0
- package/install.sh +1 -0
- package/package.json +15 -11
- package/skills/r2mo-rad-domain/SKILL.md +70 -0
- package/skills/r2mo-rad-lain/SKILL.md +101 -0
- package/src/_mcp/skills-server.mjs +70 -0
- package/src/_skill/repositories.json +22 -0
- package/src/_template/LAIN/.obsidian/app.json +1 -0
- package/src/_template/LAIN/.obsidian/appearance.json +10 -0
- package/src/_template/LAIN/.obsidian/community-plugins.json +7 -0
- package/src/_template/LAIN/.obsidian/core-plugins.json +33 -0
- package/src/_template/LAIN/.obsidian/plugins/dataview/main.js +20876 -0
- package/src/_template/LAIN/.obsidian/plugins/dataview/manifest.json +11 -0
- package/src/_template/LAIN/.obsidian/plugins/dataview/styles.css +141 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/data.json +815 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/main.js +153 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/manifest.json +11 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-kanban/styles.css +1 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/main.js +7732 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/manifest.json +10 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-plantuml/styles.css +38 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/main.js +504 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +12 -0
- package/src/_template/LAIN/.obsidian/plugins/obsidian-tasks-plugin/styles.css +1 -0
- package/src/_template/LAIN/.obsidian/snippets/body-font.css +27 -0
- package/src/_template/LAIN/.obsidian/themes/Primary/manifest.json +9 -0
- package/src/_template/LAIN/.obsidian/themes/Primary/theme.css +3878 -0
- package/src/_template/LAIN/.obsidian/themes/Retro Windows/manifest.json +7 -0
- package/src/_template/LAIN/.obsidian/themes/Retro Windows/theme.css +582 -0
- package/src/_template/LAIN/.obsidian/themes/RetroOS 98/manifest.json +9 -0
- package/src/_template/LAIN/.obsidian/themes/RetroOS 98/theme.css +2566 -0
- package/src/_template/LAIN/.obsidian/types.json +28 -0
- package/src/_template/LAIN/.obsidian/workspace.json +184 -0
- package/src/_template/LAIN/AGENTS.md +170 -16
- package/src/_template/R2MO/domain-enhance.md +10 -0
- package/src/commander/app.json +13 -0
- package/src/commander/apply.json +13 -0
- package/src/commander/ask.json +6 -0
- package/src/commander/docs.json +13 -0
- package/src/commander/domain.json +19 -0
- package/src/commander/help.json +5 -0
- package/src/commander/init.json +1 -1
- package/src/commander/mcp.json +13 -0
- package/src/commander/mmr0.json +6 -0
- package/src/commander/mmr2.json +6 -0
- package/src/commander/open.json +8 -2
- package/src/executor/executeApp.js +133 -0
- package/src/executor/executeApply.js +611 -0
- package/src/executor/executeAsk.js +274 -0
- package/src/executor/executeDocs.js +498 -0
- package/src/executor/executeDomain.js +293 -0
- package/src/executor/executeEnv.js +48 -38
- package/src/executor/executeHelp.js +77 -16
- package/src/executor/executeInit.js +176 -346
- package/src/executor/executeMcp.js +363 -0
- package/src/executor/executeMmr0.js +488 -0
- package/src/executor/executeMmr2.js +880 -0
- package/src/executor/executeOpen.js +144 -125
- package/src/executor/index.js +17 -39
- package/src/momo.js +2 -1
- package/src/python/r2mo_proto.py +418 -0
- package/src/python/r2mo_proto_database.py +369 -0
- package/src/python/r2mo_proto_domain.py +458 -0
- package/src/utils/momo-args.js +39 -0
- package/src/utils/momo-file-utils.js +75 -0
- package/src/utils/momo-menu.js +84 -0
- package/src/_template/LAIN/.momo/advanced/actor.md +0 -42
- package/src/_template/LAIN/.momo/advanced/refer.json +0 -46
- package/src/_template/LAIN/.momo/scripts/submodule-clean.sh +0 -56
- package/src/_template/LAIN/changes/proposal.md +0 -39
- package/src/_template/LAIN/changes/tasks/task-detail.md +0 -45
- package/src/_template/LAIN/changes/tasks.md +0 -49
- package/src/_template/LAIN/execute/admin-n-f-dashboard.md +0 -53
- package/src/_template/LAIN/execute/admin-n-f-form.md +0 -51
- package/src/_template/LAIN/execute/admin-n-f-home.md +0 -49
- package/src/_template/LAIN/execute/admin-n-f-list.md +0 -52
- package/src/_template/LAIN/execute/admin-n-f-login.md +0 -56
- package/src/_template/LAIN/specification/project-model.md +0 -13
- package/src/_template/LAIN/specification/project.md +0 -73
- package/src/_template/LAIN/specification/requirement.md +0 -25
- package/src/commander/actor.json +0 -12
- package/src/commander/actors.json +0 -6
- package/src/commander/add.json +0 -12
- package/src/commander/agent.json +0 -12
- package/src/commander/agentcfg.json +0 -5
- package/src/commander/archive.json +0 -12
- package/src/commander/commit.json +0 -12
- package/src/commander/console.json +0 -7
- package/src/commander/lain.json +0 -7
- package/src/commander/list.json +0 -7
- package/src/commander/plan.json +0 -12
- package/src/commander/project.json +0 -12
- package/src/commander/pull.json +0 -6
- package/src/commander/push.json +0 -6
- package/src/commander/repo.json +0 -18
- package/src/commander/run.json +0 -18
- package/src/commander/show.json +0 -12
- package/src/commander/tasks.json +0 -18
- package/src/commander/unlock.json +0 -6
- package/src/commander/validate.json +0 -12
- package/src/executor/executeActor.js +0 -133
- package/src/executor/executeActors.js +0 -58
- package/src/executor/executeAdd.js +0 -307
- package/src/executor/executeAgent.js +0 -299
- package/src/executor/executeAgentCfg.js +0 -210
- package/src/executor/executeArchive.js +0 -124
- package/src/executor/executeCommit.js +0 -202
- package/src/executor/executeConsole.js +0 -142
- package/src/executor/executeList.js +0 -133
- package/src/executor/executePlan.js +0 -164
- package/src/executor/executeProject.js +0 -313
- package/src/executor/executePull.js +0 -127
- package/src/executor/executePush.js +0 -243
- package/src/executor/executeRepo.js +0 -238
- package/src/executor/executeRun.js +0 -644
- package/src/executor/executeShow.js +0 -164
- package/src/executor/executeTasks.js +0 -384
- package/src/executor/executeUnlock.js +0 -110
- package/src/executor/executeValidate.js +0 -210
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
const Ec = require('../epic');
|
|
6
|
+
|
|
7
|
+
// 源 MCP 脚本路径
|
|
8
|
+
const SOURCE_MCP_SCRIPT = path.join(__dirname, '../_mcp/skills-server.mjs');
|
|
9
|
+
|
|
10
|
+
// 必需的依赖包
|
|
11
|
+
const REQUIRED_DEPS = ['@modelcontextprotocol/sdk', 'zod', 'front-matter', 'chokidar'];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 检查依赖是否已安装
|
|
15
|
+
*/
|
|
16
|
+
const _checkDependencies = () => {
|
|
17
|
+
const missing = [];
|
|
18
|
+
const projectRoot = path.join(__dirname, '../..');
|
|
19
|
+
for (const dep of REQUIRED_DEPS) {
|
|
20
|
+
const depPath = path.join(projectRoot, 'node_modules', dep);
|
|
21
|
+
if (!fs.existsSync(depPath)) {
|
|
22
|
+
missing.push(dep);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { installed: missing.length === 0, missing };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 显示依赖安装命令
|
|
30
|
+
*/
|
|
31
|
+
const _showInstallCommand = (missing) => {
|
|
32
|
+
console.log('');
|
|
33
|
+
Ec.error('❌ 缺少必要依赖,请先安装:');
|
|
34
|
+
console.log(` npm install ${missing.join(' ')}`.cyan);
|
|
35
|
+
console.log('');
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 生成 MCP 脚本内容
|
|
40
|
+
*/
|
|
41
|
+
const _getMcpScriptContent = () => {
|
|
42
|
+
return `#!/usr/bin/env node
|
|
43
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
44
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
45
|
+
import { z } from "zod";
|
|
46
|
+
import fs from "fs/promises";
|
|
47
|
+
import fsSync from "fs";
|
|
48
|
+
import path from "path";
|
|
49
|
+
import fm from "front-matter";
|
|
50
|
+
import os from "os";
|
|
51
|
+
|
|
52
|
+
const GLOBAL_SKILLS_DIR = process.env.MOMO_GLOBAL_SKILLS_DIR || path.join(os.homedir(), '.claude', 'skills');
|
|
53
|
+
const PROJECT_SKILLS_DIR = process.env.MOMO_PROJECT_SKILLS_DIR || path.join(process.cwd(), '.claude', 'skills');
|
|
54
|
+
|
|
55
|
+
const server = new McpServer({ name: "MomoSkills", version: "2.0.0" });
|
|
56
|
+
|
|
57
|
+
async function parseSkillFile(filePath) {
|
|
58
|
+
try {
|
|
59
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
60
|
+
const parsed = fm(content);
|
|
61
|
+
return { attributes: parsed.attributes, body: parsed.body };
|
|
62
|
+
} catch (err) { return null; }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function scanAndRegister(dir, source) {
|
|
66
|
+
if (!fsSync.existsSync(dir)) return;
|
|
67
|
+
try {
|
|
68
|
+
const items = await fs.readdir(dir);
|
|
69
|
+
for (const item of items) {
|
|
70
|
+
const skillDir = path.join(dir, item);
|
|
71
|
+
try {
|
|
72
|
+
if ((await fs.stat(skillDir)).isDirectory()) {
|
|
73
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
74
|
+
if (fsSync.existsSync(skillFile)) {
|
|
75
|
+
await registerTool(item, skillFile, source);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch(e){}
|
|
79
|
+
}
|
|
80
|
+
} catch(e) {}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function registerTool(folderName, filePath, source) {
|
|
84
|
+
try {
|
|
85
|
+
const parsed = await parseSkillFile(filePath);
|
|
86
|
+
if(!parsed || !parsed.attributes) return;
|
|
87
|
+
const attr = parsed.attributes;
|
|
88
|
+
const toolName = attr.name || folderName;
|
|
89
|
+
|
|
90
|
+
const argsSchema = {};
|
|
91
|
+
if (Array.isArray(attr.arguments)) {
|
|
92
|
+
attr.arguments.forEach(arg => {
|
|
93
|
+
argsSchema[arg.name] = z.string().describe(arg.description || "");
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
server.tool(toolName, attr.description || "No desc", argsSchema, async (args) => {
|
|
98
|
+
let res = parsed.body;
|
|
99
|
+
for (const [k, v] of Object.entries(args)) res = res.replace(new RegExp(\`{{\\\${k}}}\`, 'g'), v);
|
|
100
|
+
return { content: [{ type: "text", text: res }] };
|
|
101
|
+
});
|
|
102
|
+
} catch(e) { console.error(e); }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function main() {
|
|
106
|
+
await scanAndRegister(PROJECT_SKILLS_DIR, 'project');
|
|
107
|
+
await scanAndRegister(GLOBAL_SKILLS_DIR, 'global');
|
|
108
|
+
const transport = new StdioServerTransport();
|
|
109
|
+
await server.connect(transport);
|
|
110
|
+
}
|
|
111
|
+
main().catch(err => { console.error(err); process.exit(1); });
|
|
112
|
+
`;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 确保源 MCP 脚本存在
|
|
117
|
+
*/
|
|
118
|
+
const _ensureSourceScript = () => {
|
|
119
|
+
const mcpDir = path.dirname(SOURCE_MCP_SCRIPT);
|
|
120
|
+
if (!fs.existsSync(mcpDir)) {
|
|
121
|
+
fs.mkdirSync(mcpDir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
fs.writeFileSync(SOURCE_MCP_SCRIPT, _getMcpScriptContent());
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 拷贝 MCP 脚本到项目目录
|
|
128
|
+
* @param {string} projectDir 项目目录
|
|
129
|
+
* @returns {string} 目标脚本路径
|
|
130
|
+
*/
|
|
131
|
+
const _copyMcpScriptToProject = (projectDir) => {
|
|
132
|
+
const targetDir = path.join(projectDir, '.r2mo', 'mcpserver');
|
|
133
|
+
const targetScript = path.join(targetDir, 'skills-server.mjs');
|
|
134
|
+
|
|
135
|
+
// 创建目录
|
|
136
|
+
if (!fs.existsSync(targetDir)) {
|
|
137
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
138
|
+
Ec.waiting(`创建目录: ${targetDir}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 拷贝脚本
|
|
142
|
+
const content = _getMcpScriptContent();
|
|
143
|
+
fs.writeFileSync(targetScript, content);
|
|
144
|
+
Ec.waiting(`✓ MCP 脚本已拷贝到: ${targetScript}`);
|
|
145
|
+
|
|
146
|
+
return targetScript;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 更新 .cursor/mcp.json 配置
|
|
151
|
+
* @param {string} projectDir 项目目录
|
|
152
|
+
* @param {string} mcpScriptPath MCP 脚本路径
|
|
153
|
+
* @param {string} skillsDir 技能目录路径
|
|
154
|
+
*/
|
|
155
|
+
const _updateMcpConfig = (projectDir, mcpScriptPath, skillsDir) => {
|
|
156
|
+
const cursorDir = path.join(projectDir, '.cursor');
|
|
157
|
+
const mcpConfigPath = path.join(cursorDir, 'mcp.json');
|
|
158
|
+
|
|
159
|
+
// 确保 .cursor 目录存在
|
|
160
|
+
if (!fs.existsSync(cursorDir)) {
|
|
161
|
+
fs.mkdirSync(cursorDir, { recursive: true });
|
|
162
|
+
Ec.waiting(`创建目录: ${cursorDir}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 读取现有配置或创建新配置
|
|
166
|
+
let config = { mcpServers: {} };
|
|
167
|
+
|
|
168
|
+
if (fs.existsSync(mcpConfigPath)) {
|
|
169
|
+
try {
|
|
170
|
+
const content = fs.readFileSync(mcpConfigPath, 'utf8');
|
|
171
|
+
config = JSON.parse(content);
|
|
172
|
+
if (!config.mcpServers) {
|
|
173
|
+
config.mcpServers = {};
|
|
174
|
+
}
|
|
175
|
+
Ec.waiting(`读取现有配置: ${mcpConfigPath}`);
|
|
176
|
+
} catch (e) {
|
|
177
|
+
Ec.warn(`配置文件解析失败,将创建新配置`);
|
|
178
|
+
config = { mcpServers: {} };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 添加/更新 momo-skills 配置
|
|
183
|
+
config.mcpServers['momo-skills'] = {
|
|
184
|
+
command: 'node',
|
|
185
|
+
args: [mcpScriptPath],
|
|
186
|
+
env: {
|
|
187
|
+
NODE_ENV: 'production',
|
|
188
|
+
MOMO_PROJECT_SKILLS_DIR: skillsDir,
|
|
189
|
+
MOMO_GLOBAL_SKILLS_DIR: path.join(os.homedir(), '.claude', 'skills')
|
|
190
|
+
},
|
|
191
|
+
disabled: false,
|
|
192
|
+
alwaysAllow: []
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// 写入配置
|
|
196
|
+
fs.writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2));
|
|
197
|
+
Ec.info(`✓ MCP 配置已更新: ${mcpConfigPath}`);
|
|
198
|
+
|
|
199
|
+
return mcpConfigPath;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 确保 .r2mo/mcpserver 在 .gitignore 中
|
|
204
|
+
* @param {string} projectDir 项目目录
|
|
205
|
+
*/
|
|
206
|
+
const _ensureGitIgnore = (projectDir) => {
|
|
207
|
+
const gitignorePath = path.join(projectDir, '.gitignore');
|
|
208
|
+
const ignoreEntry = '.r2mo/mcpserver';
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
let content = '';
|
|
212
|
+
if (fs.existsSync(gitignorePath)) {
|
|
213
|
+
content = fs.readFileSync(gitignorePath, 'utf8');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const lines = content.split('\n');
|
|
217
|
+
const hasEntry = lines.some(line => line.trim() === ignoreEntry);
|
|
218
|
+
|
|
219
|
+
if (!hasEntry) {
|
|
220
|
+
const newContent = content.endsWith('\n') || content === ''
|
|
221
|
+
? content + ignoreEntry + '\n'
|
|
222
|
+
: content + '\n' + ignoreEntry + '\n';
|
|
223
|
+
fs.writeFileSync(gitignorePath, newContent);
|
|
224
|
+
Ec.waiting(`已将 ${ignoreEntry} 添加到 .gitignore`);
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
Ec.warn(`更新 .gitignore 失败: ${error.message}`);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 在 .r2mo/mcpserver 目录中安装依赖
|
|
233
|
+
* @param {string} projectDir 项目目录
|
|
234
|
+
*/
|
|
235
|
+
const _installDependencies = (projectDir) => {
|
|
236
|
+
const mcpServerDir = path.join(projectDir, '.r2mo', 'mcpserver');
|
|
237
|
+
|
|
238
|
+
// 确保目录存在
|
|
239
|
+
if (!fs.existsSync(mcpServerDir)) {
|
|
240
|
+
fs.mkdirSync(mcpServerDir, { recursive: true });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// 检查是否存在 package.json,不存在则创建
|
|
244
|
+
const packageJsonPath = path.join(mcpServerDir, 'package.json');
|
|
245
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
246
|
+
const packageJson = {
|
|
247
|
+
name: 'momo-mcp-server',
|
|
248
|
+
version: '1.0.0',
|
|
249
|
+
type: 'module',
|
|
250
|
+
dependencies: {
|
|
251
|
+
'@modelcontextprotocol/sdk': '^1.0.0',
|
|
252
|
+
'front-matter': '^4.0.3'
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
256
|
+
Ec.waiting(`创建 package.json: ${packageJsonPath}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 执行 npm install
|
|
260
|
+
try {
|
|
261
|
+
Ec.waiting('正在安装 MCP 依赖...');
|
|
262
|
+
execSync('npm install @modelcontextprotocol/sdk front-matter', {
|
|
263
|
+
cwd: mcpServerDir,
|
|
264
|
+
stdio: 'inherit'
|
|
265
|
+
});
|
|
266
|
+
Ec.info('✓ MCP 依赖安装完成');
|
|
267
|
+
} catch (error) {
|
|
268
|
+
Ec.warn(`⚠ 依赖安装失败: ${error.message}`);
|
|
269
|
+
Ec.warn(' 请手动执行: cd .r2mo/mcpserver && npm install @modelcontextprotocol/sdk front-matter');
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
module.exports = async (options) => {
|
|
274
|
+
try {
|
|
275
|
+
const projectDir = process.cwd();
|
|
276
|
+
const skillsDir = path.join(projectDir, '.claude', 'skills');
|
|
277
|
+
|
|
278
|
+
// 1. 检查依赖
|
|
279
|
+
Ec.waiting('正在检查依赖...');
|
|
280
|
+
const { installed, missing } = _checkDependencies();
|
|
281
|
+
|
|
282
|
+
if (!installed) {
|
|
283
|
+
_showInstallCommand(missing);
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
Ec.info('✓ 所有依赖已安装');
|
|
287
|
+
|
|
288
|
+
// 2. 确保源脚本存在
|
|
289
|
+
_ensureSourceScript();
|
|
290
|
+
|
|
291
|
+
// 3. 拷贝 MCP 脚本到项目
|
|
292
|
+
console.log('');
|
|
293
|
+
const mcpScriptPath = _copyMcpScriptToProject(projectDir);
|
|
294
|
+
|
|
295
|
+
// 4. 更新 .cursor/mcp.json
|
|
296
|
+
console.log('');
|
|
297
|
+
const mcpConfigPath = _updateMcpConfig(projectDir, mcpScriptPath, skillsDir);
|
|
298
|
+
|
|
299
|
+
// 5. 更新 .gitignore
|
|
300
|
+
_ensureGitIgnore(projectDir);
|
|
301
|
+
|
|
302
|
+
// 6. 安装 MCP 依赖
|
|
303
|
+
console.log('');
|
|
304
|
+
_installDependencies(projectDir);
|
|
305
|
+
|
|
306
|
+
// 7. 显示结果
|
|
307
|
+
// 将项目目录内的绝对路径转换为 {ROOT} 相对路径
|
|
308
|
+
const formatPath = (absPath) => {
|
|
309
|
+
if (absPath.startsWith(projectDir)) {
|
|
310
|
+
return absPath.replace(projectDir, '{ROOT}');
|
|
311
|
+
}
|
|
312
|
+
return absPath;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const globalSkillsPath = path.join(os.homedir(), '.claude', 'skills');
|
|
316
|
+
|
|
317
|
+
console.log('');
|
|
318
|
+
console.log('─'.repeat(60));
|
|
319
|
+
console.log(' MCP Skills Server 配置完成'.green);
|
|
320
|
+
console.log('─'.repeat(60));
|
|
321
|
+
console.log(` 脚本位置: ${formatPath(mcpScriptPath)}`);
|
|
322
|
+
console.log(` 配置文件: ${formatPath(mcpConfigPath)}`);
|
|
323
|
+
console.log(` 项目技能: ${formatPath(skillsDir)}`);
|
|
324
|
+
console.log(` 全局技能: ${globalSkillsPath}`);
|
|
325
|
+
console.log('─'.repeat(60));
|
|
326
|
+
console.log('');
|
|
327
|
+
console.log(` {ROOT} = 当前目录`.gray);
|
|
328
|
+
console.log('');
|
|
329
|
+
|
|
330
|
+
// 8. 读取并打印 mcp.json 内容,复制到剪切板
|
|
331
|
+
try {
|
|
332
|
+
const mcpConfigContent = fs.readFileSync(mcpConfigPath, 'utf8');
|
|
333
|
+
const mcpConfigJson = JSON.parse(mcpConfigContent);
|
|
334
|
+
const formattedJson = JSON.stringify(mcpConfigJson, null, 2);
|
|
335
|
+
|
|
336
|
+
console.log('─'.repeat(60));
|
|
337
|
+
console.log(' MCP 配置文件内容'.green);
|
|
338
|
+
console.log('─'.repeat(60));
|
|
339
|
+
console.log(formattedJson);
|
|
340
|
+
console.log('─'.repeat(60));
|
|
341
|
+
console.log('');
|
|
342
|
+
|
|
343
|
+
// 复制到剪切板
|
|
344
|
+
try {
|
|
345
|
+
await Ec.outCopy(formattedJson);
|
|
346
|
+
Ec.info('✓ 配置内容已复制到剪切板');
|
|
347
|
+
} catch (copyError) {
|
|
348
|
+
Ec.warn(`⚠ 复制到剪切板失败: ${copyError.message}`);
|
|
349
|
+
Ec.warn(' 请手动复制上述配置内容');
|
|
350
|
+
}
|
|
351
|
+
} catch (readError) {
|
|
352
|
+
Ec.warn(`⚠ 读取配置文件失败: ${readError.message}`);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
console.log('');
|
|
356
|
+
Ec.info('🎉 配置完成!重启 Cursor 后生效');
|
|
357
|
+
|
|
358
|
+
process.exit(0);
|
|
359
|
+
} catch (error) {
|
|
360
|
+
Ec.error(`❌ 执行失败: ${error.message}`);
|
|
361
|
+
process.exit(1);
|
|
362
|
+
}
|
|
363
|
+
};
|