debug-lessons-mcp 1.0.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/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # debug-lessons-mcp
2
+
3
+ 跨项目共享的踩坑案例 MCP 服务。所有本地 Claude Code 实例共享同一个 SQLite 数据库。
4
+
5
+ ## 快速开始
6
+
7
+ ```bash
8
+ npm install -g debug-lessons-mcp
9
+ debug-lessons-mcp setup
10
+ ```
11
+
12
+ 重启 Claude Code 后即可使用配套 slash commands。
13
+
14
+ ## 配套指令
15
+
16
+ | 指令 | 说明 |
17
+ |------|------|
18
+ | `/记录踩坑` | 引导式记录一条新的踩坑案例 |
19
+ | `/搜索踩坑` | 在案例库中搜索类似问题 |
20
+ | `/踩坑统计` | 查看案例统计概览和趋势 |
21
+ | `/浏览踩坑` | 按项目/分类/模型浏览案例列表 |
22
+
23
+ ## 手动配置
24
+
25
+ 如果需要手动配置 Claude Code,在 `~/.claude/mcp.json` 中添加:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "debug-lessons": {
31
+ "command": "debug-lessons-mcp",
32
+ "args": [],
33
+ "env": {
34
+ "DB_PATH": "~/.claude/debug-lessons-mcp/data/debug-lessons.db"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## CLI 命令
42
+
43
+ | 命令 | 说明 |
44
+ |------|------|
45
+ | `debug-lessons-mcp` | 启动 MCP Server(stdio 模式) |
46
+ | `debug-lessons-mcp setup` | 自动配置 mcp.json + 安装配套 skills |
47
+ | `debug-lessons-mcp install-skills` | 仅安装/更新配套 slash commands |
48
+
49
+ ## 工具列表
50
+
51
+ | 工具 | 说明 |
52
+ |------|------|
53
+ | `search_cases` | 全文搜索,当前项目案例加权 +50 优先 |
54
+ | `list_cases` | 按项目/分类/模型筛选,带分页 |
55
+ | `get_case` | 查看完整案例详情 |
56
+ | `add_case` | 新增案例(model_id 必填) |
57
+ | `update_case` | 编辑已有案例 |
58
+ | `delete_case` | 删除案例(需二次确认) |
59
+ | `get_stats` | 统计:总数、按模型/分类/项目分布、趋势 |
60
+ | `get_models` | 列出所有模型标识及案例数 |
61
+ | `migrate_from_json` | 从旧 JSON 批量导入 |
62
+
63
+ ## 数据迁移
64
+
65
+ 从旧版 `debug-lessons.json` 导入:
66
+
67
+ ```
68
+ migrate_from_json <json_路径> <项目标识> <模型标识>
69
+ ```
70
+
71
+ 示例:
72
+ ```
73
+ migrate_from_json /path/to/docs/debug-lessons.json sparx claude-opus-4-8
74
+ ```
75
+
76
+ ## 数据库位置
77
+
78
+ `~/.claude/debug-lessons-mcp/data/debug-lessons.db`
79
+
80
+ 可通过 `DB_PATH` 环境变量自定义路径。
81
+
82
+ ## 开发
83
+
84
+ ```bash
85
+ git clone https://github.com/MikkoAyaka/debug-lessons-mcp.git
86
+ cd debug-lessons-mcp
87
+ npm install
88
+ npm run build
89
+ ```
90
+
91
+ ## 更新与卸载
92
+
93
+ ```bash
94
+ # 更新
95
+ npm update -g debug-lessons-mcp
96
+
97
+ # 卸载
98
+ npm uninstall -g debug-lessons-mcp
99
+ # 手动删除 ~/.claude/mcp.json 中的 debug-lessons 条目
100
+ # 手动删除 ~/.claude/skills/ 中的 记录踩坑.md 等文件
101
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import { startServer } from "./index.js";
3
+ import { getHomeDir, getMcpConfigPath, getSkillsDir, getDefaultDataDir, } from "./utils.js";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ const PKG_VERSION = "1.0.0";
8
+ function printHelp() {
9
+ console.log(`
10
+ debug-lessons-mcp — 跨项目共享的踩坑案例 MCP 服务
11
+
12
+ 用法:
13
+ debug-lessons-mcp [命令]
14
+
15
+ 命令:
16
+ (无参数) 启动 MCP Server (stdio 模式),供 Claude Code 调用
17
+ setup 自动配置 Claude Code(mcp.json + 安装配套 skills)
18
+ install-skills 仅安装/更新配套 slash commands 到 ~/.claude/skills/
19
+ --help, -h 显示此帮助
20
+ --version, -v 显示版本号
21
+
22
+ 示例:
23
+ npm install -g debug-lessons-mcp # 全局安装
24
+ debug-lessons-mcp setup # 一键配置
25
+ `);
26
+ }
27
+ function installSkills() {
28
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
29
+ const pkgRoot = path.resolve(__dirname, "..");
30
+ const skillsSrc = path.join(pkgRoot, "skills");
31
+ const skillsDest = getSkillsDir();
32
+ if (!fs.existsSync(skillsSrc)) {
33
+ throw new Error("skills source dir not found: " + skillsSrc);
34
+ }
35
+ fs.mkdirSync(skillsDest, { recursive: true });
36
+ const installed = [];
37
+ const entries = fs.readdirSync(skillsSrc);
38
+ for (const entry of entries) {
39
+ if (entry.endsWith(".md")) {
40
+ const src = path.join(skillsSrc, entry);
41
+ const dest = path.join(skillsDest, entry);
42
+ fs.copyFileSync(src, dest);
43
+ installed.push(entry);
44
+ }
45
+ }
46
+ return { installed, targetDir: skillsDest };
47
+ }
48
+ function readMcpConfig() {
49
+ const configPath = getMcpConfigPath();
50
+ if (fs.existsSync(configPath)) {
51
+ try {
52
+ const content = fs.readFileSync(configPath, "utf-8");
53
+ const config = JSON.parse(content);
54
+ return { config, existed: true };
55
+ }
56
+ catch {
57
+ console.warn("Warning: failed to parse mcp.json, creating new config.");
58
+ return { config: {}, existed: true };
59
+ }
60
+ }
61
+ return { config: {}, existed: false };
62
+ }
63
+ function writeMcpConfig(config) {
64
+ const configPath = getMcpConfigPath();
65
+ const claudeDir = path.dirname(configPath);
66
+ fs.mkdirSync(claudeDir, { recursive: true });
67
+ const content = JSON.stringify(config, null, 2) + "\n";
68
+ fs.writeFileSync(configPath, content, "utf-8");
69
+ return configPath;
70
+ }
71
+ function buildServerEntry() {
72
+ const home = getHomeDir();
73
+ const dbPath = path.join(home, ".claude", "debug-lessons-mcp", "data", "debug-lessons.db");
74
+ return {
75
+ command: "debug-lessons-mcp",
76
+ args: [],
77
+ env: { DB_PATH: dbPath },
78
+ };
79
+ }
80
+ async function runSetup() {
81
+ console.log("Configuring debug-lessons MCP service...\n");
82
+ const { config, existed } = readMcpConfig();
83
+ const serverEntry = buildServerEntry();
84
+ if (!config.mcpServers) {
85
+ config.mcpServers = {};
86
+ }
87
+ config.mcpServers["debug-lessons"] = serverEntry;
88
+ const configPath = writeMcpConfig(config);
89
+ const action = existed ? "updated" : "created";
90
+ console.log("mcp.json " + action + " (debug-lessons entry)");
91
+ const dataDir = getDefaultDataDir();
92
+ fs.mkdirSync(dataDir, { recursive: true });
93
+ console.log("Data dir: " + dataDir);
94
+ console.log("");
95
+ await runInstallSkills();
96
+ const dbPath = path.join(dataDir, "debug-lessons.db");
97
+ console.log("");
98
+ console.log("Setup complete! Restart Claude Code and use /record-lesson to start.");
99
+ console.log("");
100
+ console.log(" mcp.json: " + configPath);
101
+ console.log(" Database: " + dbPath);
102
+ }
103
+ async function runInstallSkills() {
104
+ try {
105
+ const { installed, targetDir } = installSkills();
106
+ console.log("Skills installed (" + installed.length + " slash commands)");
107
+ for (const name of installed) {
108
+ const cmdName = name.replace(/\.md$/, "");
109
+ console.log(" - /" + cmdName);
110
+ }
111
+ console.log(" Location: " + targetDir);
112
+ }
113
+ catch (err) {
114
+ console.error("Skills install failed: " + err.message);
115
+ }
116
+ }
117
+ const command = process.argv[2];
118
+ async function main() {
119
+ switch (command) {
120
+ case undefined:
121
+ case "start":
122
+ await startServer();
123
+ break;
124
+ case "setup":
125
+ await runSetup();
126
+ break;
127
+ case "install-skills":
128
+ await runInstallSkills();
129
+ break;
130
+ case "--version":
131
+ case "-v":
132
+ console.log("debug-lessons-mcp v" + PKG_VERSION);
133
+ break;
134
+ case "--help":
135
+ case "-h":
136
+ printHelp();
137
+ break;
138
+ default:
139
+ console.error("Unknown command: " + command);
140
+ printHelp();
141
+ process.exit(1);
142
+ }
143
+ }
144
+ main().catch((err) => {
145
+ console.error("Fatal error:", err);
146
+ process.exit(1);
147
+ });
148
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,75 @@
1
+ import Database from "better-sqlite3";
2
+ export declare function getDb(): Database.Database;
3
+ export interface DebugCase {
4
+ id: number;
5
+ project_id: string;
6
+ project_path: string;
7
+ model_id: string;
8
+ model_name: string;
9
+ category: string;
10
+ problem: string;
11
+ thinking: string;
12
+ result: string;
13
+ lesson: string;
14
+ tags: string;
15
+ created_at: string;
16
+ updated_at: string;
17
+ }
18
+ export interface CaseInput {
19
+ project_id?: string;
20
+ project_path?: string;
21
+ model_id: string;
22
+ model_name?: string;
23
+ category: string;
24
+ problem: string;
25
+ thinking: string;
26
+ result: string;
27
+ lesson: string;
28
+ tags?: string;
29
+ }
30
+ export interface SearchResult {
31
+ id: number;
32
+ project_id: string;
33
+ model_id: string;
34
+ category: string;
35
+ problem: string;
36
+ lesson: string;
37
+ tags: string;
38
+ score: number;
39
+ is_current_project: boolean;
40
+ }
41
+ export interface StatsResult {
42
+ total: number;
43
+ by_project: Record<string, number>;
44
+ by_model: Record<string, number>;
45
+ by_category: Record<string, number>;
46
+ recent_30d: number;
47
+ recent_7d: number;
48
+ }
49
+ export declare function insertCase(input: CaseInput): number;
50
+ export declare function getCaseById(id: number): DebugCase | undefined;
51
+ export declare function updateCase(id: number, fields: Partial<CaseInput>): boolean;
52
+ export declare function deleteCase(id: number): boolean;
53
+ export declare function searchCases(query: string, currentProjectId?: string, limit?: number): SearchResult[];
54
+ export declare function listCases(options: {
55
+ project_id?: string;
56
+ category?: string;
57
+ model_id?: string;
58
+ limit?: number;
59
+ offset?: number;
60
+ }): DebugCase[];
61
+ export declare function getStats(project_id?: string): StatsResult;
62
+ export declare function getModels(): {
63
+ model_id: string;
64
+ model_name: string;
65
+ count: number;
66
+ }[];
67
+ export interface JsonCase {
68
+ category: string;
69
+ problem: string;
70
+ thinking: string;
71
+ result: string;
72
+ lesson: string;
73
+ }
74
+ export declare function migrateFromJson(jsonPath: string, projectId: string, modelId: string): number;
75
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
package/dist/db.js ADDED
@@ -0,0 +1,230 @@
1
+ import Database from "better-sqlite3";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ function getDbPath() {
7
+ if (process.env.DB_PATH) {
8
+ return process.env.DB_PATH.replace(/^~/, process.env.HOME || process.env.USERPROFILE || "");
9
+ }
10
+ // Default: data/debug-lessons.db relative to project root
11
+ const root = path.resolve(__dirname, "..");
12
+ const dataDir = path.join(root, "data");
13
+ if (!fs.existsSync(dataDir)) {
14
+ fs.mkdirSync(dataDir, { recursive: true });
15
+ }
16
+ return path.join(dataDir, "debug-lessons.db");
17
+ }
18
+ let db;
19
+ export function getDb() {
20
+ if (!db) {
21
+ const dbPath = getDbPath();
22
+ db = new Database(dbPath);
23
+ db.pragma("journal_mode = WAL");
24
+ db.pragma("foreign_keys = ON");
25
+ initSchema(db);
26
+ }
27
+ return db;
28
+ }
29
+ function initSchema(db) {
30
+ db.exec(`
31
+ CREATE TABLE IF NOT EXISTS cases (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ project_id TEXT NOT NULL,
34
+ project_path TEXT NOT NULL DEFAULT '',
35
+ model_id TEXT NOT NULL,
36
+ model_name TEXT NOT NULL DEFAULT '',
37
+ category TEXT NOT NULL,
38
+ problem TEXT NOT NULL,
39
+ thinking TEXT NOT NULL DEFAULT '',
40
+ result TEXT NOT NULL DEFAULT '',
41
+ lesson TEXT NOT NULL,
42
+ tags TEXT NOT NULL DEFAULT '',
43
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
44
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
45
+ );
46
+
47
+ CREATE INDEX IF NOT EXISTS idx_cases_project ON cases(project_id);
48
+ CREATE INDEX IF NOT EXISTS idx_cases_model ON cases(model_id);
49
+ CREATE INDEX IF NOT EXISTS idx_cases_category ON cases(category);
50
+ CREATE INDEX IF NOT EXISTS idx_cases_created ON cases(created_at);
51
+ CREATE INDEX IF NOT EXISTS idx_cases_tags ON cases(tags);
52
+ `);
53
+ }
54
+ // ---- CRUD ----
55
+ export function insertCase(input) {
56
+ const db = getDb();
57
+ const stmt = db.prepare(`
58
+ INSERT INTO cases (project_id, project_path, model_id, model_name, category, problem, thinking, result, lesson, tags)
59
+ VALUES (@project_id, @project_path, @model_id, @model_name, @category, @problem, @thinking, @result, @lesson, @tags)
60
+ `);
61
+ const result = stmt.run({
62
+ project_id: input.project_id || "unknown",
63
+ project_path: input.project_path || "",
64
+ model_id: input.model_id,
65
+ model_name: input.model_name || "",
66
+ category: input.category,
67
+ problem: input.problem,
68
+ thinking: input.thinking,
69
+ result: input.result,
70
+ lesson: input.lesson,
71
+ tags: input.tags || "",
72
+ });
73
+ return Number(result.lastInsertRowid);
74
+ }
75
+ export function getCaseById(id) {
76
+ const db = getDb();
77
+ return db.prepare("SELECT * FROM cases WHERE id = ?").get(id);
78
+ }
79
+ export function updateCase(id, fields) {
80
+ const db = getDb();
81
+ const existing = getCaseById(id);
82
+ if (!existing)
83
+ return false;
84
+ const updates = [];
85
+ const params = { id };
86
+ for (const [key, value] of Object.entries(fields)) {
87
+ if (value !== undefined) {
88
+ updates.push(`${key} = @${key}`);
89
+ params[key] = value;
90
+ }
91
+ }
92
+ if (updates.length === 0)
93
+ return false;
94
+ updates.push("updated_at = datetime('now')");
95
+ db.prepare(`UPDATE cases SET ${updates.join(", ")} WHERE id = @id`).run(params);
96
+ return true;
97
+ }
98
+ export function deleteCase(id) {
99
+ const db = getDb();
100
+ const result = db.prepare("DELETE FROM cases WHERE id = ?").run(id);
101
+ return result.changes > 0;
102
+ }
103
+ // ---- Search ----
104
+ export function searchCases(query, currentProjectId, limit = 10) {
105
+ const db = getDb();
106
+ const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
107
+ // Build a LIKE-based search across all text fields
108
+ const conditions = tokens
109
+ .map(() => `(LOWER(problem || ' ' || thinking || ' ' || result || ' ' || lesson || ' ' || tags || ' ' || category) LIKE ?)`)
110
+ .join(" AND ");
111
+ const likeParams = tokens.map((t) => `%${t}%`);
112
+ const rows = db
113
+ .prepare(`SELECT id, project_id, model_id, category, problem, lesson, tags FROM cases WHERE ${conditions}`)
114
+ .all(...likeParams);
115
+ // Score: each token match = 10 pts, exact phrase match = 20 pts, current project = 50 pts
116
+ const results = rows.map((row) => {
117
+ const text = `${row.problem} ${row.thinking} ${row.result} ${row.lesson} ${row.tags} ${row.category}`.toLowerCase();
118
+ let score = 0;
119
+ for (const t of tokens) {
120
+ if (text.includes(t))
121
+ score += 10;
122
+ }
123
+ if (text.includes(query.toLowerCase()))
124
+ score += 20;
125
+ if (currentProjectId && row.project_id === currentProjectId)
126
+ score += 50;
127
+ return {
128
+ id: row.id,
129
+ project_id: row.project_id,
130
+ model_id: row.model_id,
131
+ category: row.category,
132
+ problem: row.problem,
133
+ lesson: row.lesson,
134
+ tags: row.tags,
135
+ score,
136
+ is_current_project: currentProjectId ? row.project_id === currentProjectId : false,
137
+ };
138
+ });
139
+ // Sort by score descending, then by id descending (newer first)
140
+ results.sort((a, b) => b.score - a.score || b.id - a.id);
141
+ return results.slice(0, limit);
142
+ }
143
+ // ---- List ----
144
+ export function listCases(options) {
145
+ const db = getDb();
146
+ const conditions = [];
147
+ const params = {};
148
+ if (options.project_id) {
149
+ conditions.push("project_id = @project_id");
150
+ params.project_id = options.project_id;
151
+ }
152
+ if (options.category) {
153
+ conditions.push("category = @category");
154
+ params.category = options.category;
155
+ }
156
+ if (options.model_id) {
157
+ conditions.push("model_id = @model_id");
158
+ params.model_id = options.model_id;
159
+ }
160
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
161
+ const limit = options.limit || 50;
162
+ const offset = options.offset || 0;
163
+ return db
164
+ .prepare(`SELECT * FROM cases ${where} ORDER BY id DESC LIMIT ? OFFSET ?`)
165
+ .all(limit, offset);
166
+ }
167
+ // ---- Stats ----
168
+ export function getStats(project_id) {
169
+ const db = getDb();
170
+ const whereProject = project_id ? "WHERE project_id = ?" : "";
171
+ const params = project_id ? [project_id] : [];
172
+ const total = db.prepare(`SELECT COUNT(*) as count FROM cases ${whereProject}`).get(...params).count;
173
+ const byProject = db
174
+ .prepare(`SELECT project_id, COUNT(*) as count FROM cases ${whereProject} GROUP BY project_id ORDER BY count DESC`)
175
+ .all(...params);
176
+ const byModel = db
177
+ .prepare(`SELECT model_id, model_name, COUNT(*) as count FROM cases ${whereProject} GROUP BY model_id ORDER BY count DESC`)
178
+ .all(...params);
179
+ const byCategory = db
180
+ .prepare(`SELECT category, COUNT(*) as count FROM cases ${whereProject} GROUP BY category ORDER BY count DESC`)
181
+ .all(...params);
182
+ const recent30d = db
183
+ .prepare(`SELECT COUNT(*) as count FROM cases ${whereProject} ${project_id ? "AND" : "WHERE"} created_at >= datetime('now', '-30 days')`)
184
+ .get(...params).count;
185
+ const recent7d = db
186
+ .prepare(`SELECT COUNT(*) as count FROM cases ${whereProject} ${project_id ? "AND" : "WHERE"} created_at >= datetime('now', '-7 days')`)
187
+ .get(...params).count;
188
+ return {
189
+ total,
190
+ by_project: Object.fromEntries(byProject.map((r) => [r.project_id, r.count])),
191
+ by_model: Object.fromEntries(byModel.map((r) => [`${r.model_id}${r.model_name ? ` (${r.model_name})` : ""}`, r.count])),
192
+ by_category: Object.fromEntries(byCategory.map((r) => [r.category, r.count])),
193
+ recent_30d: recent30d,
194
+ recent_7d: recent7d,
195
+ };
196
+ }
197
+ export function getModels() {
198
+ const db = getDb();
199
+ return db
200
+ .prepare("SELECT model_id, model_name, COUNT(*) as count FROM cases GROUP BY model_id, model_name ORDER BY count DESC")
201
+ .all();
202
+ }
203
+ export function migrateFromJson(jsonPath, projectId, modelId) {
204
+ const content = fs.readFileSync(jsonPath, "utf-8");
205
+ const cases = JSON.parse(content);
206
+ const db = getDb();
207
+ const stmt = db.prepare(`
208
+ INSERT INTO cases (project_id, project_path, model_id, category, problem, thinking, result, lesson)
209
+ VALUES (@project_id, @project_path, @model_id, @category, @problem, @thinking, @result, @lesson)
210
+ `);
211
+ const insertMany = db.transaction((items) => {
212
+ let count = 0;
213
+ for (const item of items) {
214
+ stmt.run({
215
+ project_id: projectId,
216
+ project_path: "",
217
+ model_id: modelId,
218
+ category: item.category,
219
+ problem: item.problem,
220
+ thinking: item.thinking,
221
+ result: item.result,
222
+ lesson: item.lesson,
223
+ });
224
+ count++;
225
+ }
226
+ return count;
227
+ });
228
+ return insertMany(cases);
229
+ }
230
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function startServer(): Promise<void>;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsYA,wBAAsB,WAAW,kBAIhC"}
package/dist/index.js ADDED
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { insertCase, getCaseById, updateCase, deleteCase, searchCases, listCases, getStats, getModels, migrateFromJson, } from "./db.js";
6
+ import { detectCurrentProject, truncate } from "./utils.js";
7
+ // ---- Server Setup ----
8
+ const server = new Server({
9
+ name: "debug-lessons-mcp",
10
+ version: "1.0.0",
11
+ }, {
12
+ capabilities: {
13
+ tools: {},
14
+ },
15
+ });
16
+ // ---- Tool Definitions ----
17
+ const tools = [
18
+ {
19
+ name: "search_cases",
20
+ description: "搜索踩坑案例。在 problem、thinking、result、lesson、tags、category 字段中全文搜索。当前项目的案例自动加权优先排在前面。返回匹配列表,包含 id、项目、模型、分类、问题摘要、教训。",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ query: { type: "string", description: "搜索关键词(支持多词,空格分隔)" },
25
+ project_id: { type: "string", description: "项目标识(可选,不传则自动检测)" },
26
+ limit: { type: "number", description: "返回数量上限(默认 10)" },
27
+ },
28
+ required: ["query"],
29
+ },
30
+ },
31
+ {
32
+ name: "list_cases",
33
+ description: "浏览踩坑案例列表。支持按项目、分类、模型筛选,带分页。",
34
+ inputSchema: {
35
+ type: "object",
36
+ properties: {
37
+ project_id: { type: "string", description: "按项目筛选(可选)" },
38
+ category: { type: "string", description: "按分类筛选(可选)" },
39
+ model_id: { type: "string", description: "按模型筛选(可选)" },
40
+ limit: { type: "number", description: "每页数量(默认 50)" },
41
+ offset: { type: "number", description: "偏移量(默认 0)" },
42
+ },
43
+ },
44
+ },
45
+ {
46
+ name: "get_case",
47
+ description: "查看一个踩坑案例的完整详情。包含 problem、thinking、result、lesson 全部字段。",
48
+ inputSchema: {
49
+ type: "object",
50
+ properties: {
51
+ id: { type: "number", description: "案例 ID" },
52
+ },
53
+ required: ["id"],
54
+ },
55
+ },
56
+ {
57
+ name: "add_case",
58
+ description: "新增一条踩坑案例。project_id 不传则自动检测当前项目。model_id 必填,用于后续按模型统计。",
59
+ inputSchema: {
60
+ type: "object",
61
+ properties: {
62
+ project_id: { type: "string", description: "项目标识(可选,不传则自动检测)" },
63
+ model_id: { type: "string", description: "模型标识,如 claude-opus-4-8、deepseek-v4-pro" },
64
+ model_name: { type: "string", description: "模型显示名称(可选)" },
65
+ category: { type: "string", description: "分类,如 Docker/Build、Frontend、Database/Schema" },
66
+ problem: { type: "string", description: "问题描述 — 发生了什么?" },
67
+ thinking: { type: "string", description: "排查思路 — 当时怎么分析的?" },
68
+ result: { type: "string", description: "解决方案 — 最终怎么修好的?" },
69
+ lesson: { type: "string", description: "教训总结 — 未来如何避免?(可操作、可直接套用)" },
70
+ tags: { type: "string", description: "逗号分隔的标签(可选)" },
71
+ },
72
+ required: ["model_id", "category", "problem", "thinking", "result", "lesson"],
73
+ },
74
+ },
75
+ {
76
+ name: "update_case",
77
+ description: "编辑已有案例的任意字段。",
78
+ inputSchema: {
79
+ type: "object",
80
+ properties: {
81
+ id: { type: "number", description: "案例 ID" },
82
+ project_id: { type: "string", description: "项目标识" },
83
+ model_id: { type: "string", description: "模型标识" },
84
+ model_name: { type: "string", description: "模型显示名称" },
85
+ category: { type: "string", description: "分类" },
86
+ problem: { type: "string", description: "问题描述" },
87
+ thinking: { type: "string", description: "排查思路" },
88
+ result: { type: "string", description: "解决方案" },
89
+ lesson: { type: "string", description: "教训总结" },
90
+ tags: { type: "string", description: "标签" },
91
+ },
92
+ required: ["id"],
93
+ },
94
+ },
95
+ {
96
+ name: "delete_case",
97
+ description: "删除一条踩坑案例。",
98
+ inputSchema: {
99
+ type: "object",
100
+ properties: {
101
+ id: { type: "number", description: "案例 ID" },
102
+ confirm: { type: "boolean", description: "确认删除(必须为 true)" },
103
+ },
104
+ required: ["id", "confirm"],
105
+ },
106
+ },
107
+ {
108
+ name: "get_stats",
109
+ description: "获取踩坑案例的统计概览:总数、按模型分布、按分类分布、按项目分布、近7/30天新增趋势。用于分析模型间差异和案例积累趋势。",
110
+ inputSchema: {
111
+ type: "object",
112
+ properties: {
113
+ project_id: { type: "string", description: "限定项目(可选,不传=全局统计)" },
114
+ },
115
+ },
116
+ },
117
+ {
118
+ name: "get_models",
119
+ description: "列出所有出现过的模型标识及案例数量。用于了解哪些模型被记录过踩坑案例,以及后续做模型间对比分析。",
120
+ inputSchema: {
121
+ type: "object",
122
+ properties: {},
123
+ },
124
+ },
125
+ {
126
+ name: "migrate_from_json",
127
+ description: "从旧版 debug-lessons.json 文件批量导入案例到 SQLite 数据库。适合首次从项目内 JSON 迁移到共享 MCP 服务。",
128
+ inputSchema: {
129
+ type: "object",
130
+ properties: {
131
+ json_path: { type: "string", description: "debug-lessons.json 文件的绝对路径" },
132
+ project_id: { type: "string", description: "导入后归属的项目标识" },
133
+ model_id: { type: "string", description: "导入案例的模型标识(可后续单独修正)" },
134
+ },
135
+ required: ["json_path", "project_id", "model_id"],
136
+ },
137
+ },
138
+ ];
139
+ // ---- Tool Handler ----
140
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
141
+ return { tools };
142
+ });
143
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
144
+ const { name, arguments: args } = request.params;
145
+ try {
146
+ switch (name) {
147
+ case "search_cases": {
148
+ const query = args.query;
149
+ const project = detectCurrentProject(args.project_id);
150
+ const limit = args.limit || 10;
151
+ const results = searchCases(query, project.project_id || undefined, limit);
152
+ if (results.length === 0) {
153
+ return { content: [{ type: "text", text: "未找到匹配的案例。" }] };
154
+ }
155
+ const lines = results.map((r, i) => {
156
+ const badge = r.is_current_project ? "📌" : " ";
157
+ return [
158
+ `[${r.id}] ${badge} ${r.category} │ 模型: ${r.model_id} │ 项目: ${r.project_id}`,
159
+ ` 问题: ${truncate(r.problem, 120)}`,
160
+ ` 教训: ${truncate(r.lesson, 120)}`,
161
+ "",
162
+ ].join("\n");
163
+ });
164
+ return {
165
+ content: [
166
+ {
167
+ type: "text",
168
+ text: `找到 ${results.length} 条匹配案例(📌 = 当前项目):\n\n${lines.join("\n")}`,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ case "list_cases": {
174
+ const rows = listCases({
175
+ project_id: args.project_id,
176
+ category: args.category,
177
+ model_id: args.model_id,
178
+ limit: args.limit || 50,
179
+ offset: args.offset || 0,
180
+ });
181
+ if (rows.length === 0) {
182
+ return { content: [{ type: "text", text: "没有找到案例。" }] };
183
+ }
184
+ const lines = rows.map((r) => `[${r.id}] ${r.category} │ 项目: ${r.project_id} │ 模型: ${r.model_id} │ ${truncate(r.problem, 80)}`);
185
+ return {
186
+ content: [{ type: "text", text: `共 ${rows.length} 条案例:\n\n${lines.join("\n")}` }],
187
+ };
188
+ }
189
+ case "get_case": {
190
+ const id = args.id;
191
+ const c = getCaseById(id);
192
+ if (!c) {
193
+ return { content: [{ type: "text", text: `案例 #${id} 不存在。` }] };
194
+ }
195
+ const text = [
196
+ `══════ 案例 #${c.id} ══════`,
197
+ `项目: ${c.project_id}`,
198
+ `模型: ${c.model_id}${c.model_name ? ` (${c.model_name})` : ""}`,
199
+ `分类: ${c.category}`,
200
+ `标签: ${c.tags || "(无)"}`,
201
+ `创建: ${c.created_at}`,
202
+ `更新: ${c.updated_at}`,
203
+ ``,
204
+ `━━━ 问题 ━━━`,
205
+ c.problem,
206
+ ``,
207
+ `━━━ 排查思路 ━━━`,
208
+ c.thinking,
209
+ ``,
210
+ `━━━ 解决方案 ━━━`,
211
+ c.result,
212
+ ``,
213
+ `━━━ 教训总结 ━━━`,
214
+ c.lesson,
215
+ ].join("\n");
216
+ return { content: [{ type: "text", text }] };
217
+ }
218
+ case "add_case": {
219
+ const project = detectCurrentProject(args.project_id);
220
+ const input = args;
221
+ const id = insertCase({
222
+ project_id: project.project_id || input.project_id || "unknown",
223
+ project_path: project.project_path || "",
224
+ model_id: input.model_id,
225
+ model_name: input.model_name || "",
226
+ category: input.category,
227
+ problem: input.problem,
228
+ thinking: input.thinking,
229
+ result: input.result,
230
+ lesson: input.lesson,
231
+ tags: input.tags || "",
232
+ });
233
+ return {
234
+ content: [
235
+ {
236
+ type: "text",
237
+ text: `✅ 案例已添加,ID: ${id}\n项目: ${project.project_id || input.project_id || "unknown"}\n模型: ${input.model_id}\n分类: ${input.category}`,
238
+ },
239
+ ],
240
+ };
241
+ }
242
+ case "update_case": {
243
+ const id = args.id;
244
+ const input = args;
245
+ const { id: _id, ...fields } = input;
246
+ const ok = updateCase(id, fields);
247
+ if (!ok) {
248
+ return { content: [{ type: "text", text: `案例 #${id} 不存在。` }] };
249
+ }
250
+ return { content: [{ type: "text", text: `✅ 案例 #${id} 已更新。` }] };
251
+ }
252
+ case "delete_case": {
253
+ const id = args.id;
254
+ const confirm = args.confirm;
255
+ if (!confirm) {
256
+ return {
257
+ content: [{ type: "text", text: "删除操作需要 confirm: true 确认。请重新调用并设置 confirm 为 true。" }],
258
+ };
259
+ }
260
+ const ok = deleteCase(id);
261
+ if (!ok) {
262
+ return { content: [{ type: "text", text: `案例 #${id} 不存在。` }] };
263
+ }
264
+ return { content: [{ type: "text", text: `🗑️ 案例 #${id} 已删除。` }] };
265
+ }
266
+ case "get_stats": {
267
+ const project_id = args.project_id;
268
+ const stats = getStats(project_id);
269
+ const text = [
270
+ `══════ 踩坑案例统计 ${project_id ? `(${project_id})` : "(全局)"} ══════`,
271
+ ``,
272
+ `总计: ${stats.total} 条`,
273
+ `近 7 天新增: ${stats.recent_7d} 条`,
274
+ `近 30 天新增: ${stats.recent_30d} 条`,
275
+ ``,
276
+ `━━━ 按项目分布 ━━━`,
277
+ ...Object.entries(stats.by_project).map(([k, v]) => ` ${k}: ${v}`),
278
+ ``,
279
+ `━━━ 按模型分布 ━━━`,
280
+ ...Object.entries(stats.by_model).map(([k, v]) => ` ${k}: ${v}`),
281
+ ``,
282
+ `━━━ 按分类分布 ━━━`,
283
+ ...Object.entries(stats.by_category).map(([k, v]) => ` ${k}: ${v}`),
284
+ ].join("\n");
285
+ return { content: [{ type: "text", text }] };
286
+ }
287
+ case "get_models": {
288
+ const models = getModels();
289
+ if (models.length === 0) {
290
+ return { content: [{ type: "text", text: "暂无任何模型记录。" }] };
291
+ }
292
+ const lines = models.map((m) => ` ${m.model_id}${m.model_name ? ` (${m.model_name})` : ""} — ${m.count} 条案例`);
293
+ return {
294
+ content: [
295
+ {
296
+ type: "text",
297
+ text: `已记录的模型(共 ${models.length} 种):\n\n${lines.join("\n")}`,
298
+ },
299
+ ],
300
+ };
301
+ }
302
+ case "migrate_from_json": {
303
+ const jsonPath = args.json_path;
304
+ const projectId = args.project_id;
305
+ const modelId = args.model_id;
306
+ const count = migrateFromJson(jsonPath, projectId, modelId);
307
+ return {
308
+ content: [
309
+ {
310
+ type: "text",
311
+ text: `✅ 迁移完成:从 ${jsonPath} 导入了 ${count} 条案例。\n项目: ${projectId}\n模型: ${modelId}\n\n提示:后续可通过 update_case 逐一修正每条案例的 model_id。`,
312
+ },
313
+ ],
314
+ };
315
+ }
316
+ default:
317
+ return {
318
+ content: [{ type: "text", text: `未知工具: ${name}` }],
319
+ isError: true,
320
+ };
321
+ }
322
+ }
323
+ catch (error) {
324
+ return {
325
+ content: [{ type: "text", text: `错误: ${error.message}` }],
326
+ isError: true,
327
+ };
328
+ }
329
+ });
330
+ // ---- Start ----
331
+ export async function startServer() {
332
+ const transport = new StdioServerTransport();
333
+ await server.connect(transport);
334
+ console.error("Debug Lessons MCP server running on stdio");
335
+ }
336
+ // Auto-start when run directly (node dist/index.js), skip when imported
337
+ const isDirectRun = process.argv[1] &&
338
+ (import.meta.url === `file://${process.argv[1]}` ||
339
+ import.meta.url === `file://${process.argv[1].replace(/\\/g, "/")}` ||
340
+ import.meta.url.endsWith(`/${process.argv[1].replace(/\\/g, "/").split("/").pop()}`));
341
+ if (isDirectRun) {
342
+ startServer().catch((err) => {
343
+ console.error("Fatal error:", err);
344
+ process.exit(1);
345
+ });
346
+ }
347
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Get the user's home directory in a cross-platform way.
3
+ */
4
+ export declare function getHomeDir(): string;
5
+ /**
6
+ * Resolve a path that may start with ~ to an absolute path.
7
+ */
8
+ export declare function resolveHome(filepath: string): string;
9
+ /**
10
+ * Get the Claude Code config directory (~/.claude).
11
+ */
12
+ export declare function getClaudeDir(): string;
13
+ /**
14
+ * Get the path to mcp.json.
15
+ */
16
+ export declare function getMcpConfigPath(): string;
17
+ /**
18
+ * Get the path to the Claude Code skills directory.
19
+ */
20
+ export declare function getSkillsDir(): string;
21
+ /**
22
+ * Get the default data directory for the shared database.
23
+ */
24
+ export declare function getDefaultDataDir(): string;
25
+ /**
26
+ * Detect the current project ID from available sources.
27
+ * Priority:
28
+ * 1. Explicit project_id parameter (handled in tool call)
29
+ * 2. PROJECT_ID env var — direct project identifier (most reliable)
30
+ * 3. CLAUDE_PROJECT_DIR / PROJECT_DIR env var — extract dir name as project_id
31
+ * 4. PWD / cwd path matching
32
+ */
33
+ export declare function detectCurrentProject(explicitProjectId?: string): {
34
+ project_id: string;
35
+ project_path: string;
36
+ source: "explicit" | "env" | "db_match" | "fallback";
37
+ };
38
+ /**
39
+ * Truncate a string to n characters, adding "..." if truncated.
40
+ */
41
+ export declare function truncate(s: string, n: number): string;
42
+ /**
43
+ * List known projects from the database.
44
+ */
45
+ export declare function listKnownProjects(): string[];
46
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;CACtD,CAqBA;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAM5C"}
package/dist/utils.js ADDED
@@ -0,0 +1,88 @@
1
+ import { getDb } from "./db.js";
2
+ import { homedir } from "node:os";
3
+ import path from "node:path";
4
+ /**
5
+ * Get the user's home directory in a cross-platform way.
6
+ */
7
+ export function getHomeDir() {
8
+ return process.env.HOME || process.env.USERPROFILE || homedir();
9
+ }
10
+ /**
11
+ * Resolve a path that may start with ~ to an absolute path.
12
+ */
13
+ export function resolveHome(filepath) {
14
+ if (filepath.startsWith("~")) {
15
+ return path.join(getHomeDir(), filepath.slice(1));
16
+ }
17
+ return filepath;
18
+ }
19
+ /**
20
+ * Get the Claude Code config directory (~/.claude).
21
+ */
22
+ export function getClaudeDir() {
23
+ return path.join(getHomeDir(), ".claude");
24
+ }
25
+ /**
26
+ * Get the path to mcp.json.
27
+ */
28
+ export function getMcpConfigPath() {
29
+ return path.join(getClaudeDir(), "mcp.json");
30
+ }
31
+ /**
32
+ * Get the path to the Claude Code skills directory.
33
+ */
34
+ export function getSkillsDir() {
35
+ return path.join(getClaudeDir(), "skills");
36
+ }
37
+ /**
38
+ * Get the default data directory for the shared database.
39
+ */
40
+ export function getDefaultDataDir() {
41
+ return path.join(getClaudeDir(), "debug-lessons-mcp", "data");
42
+ }
43
+ /**
44
+ * Detect the current project ID from available sources.
45
+ * Priority:
46
+ * 1. Explicit project_id parameter (handled in tool call)
47
+ * 2. PROJECT_ID env var — direct project identifier (most reliable)
48
+ * 3. CLAUDE_PROJECT_DIR / PROJECT_DIR env var — extract dir name as project_id
49
+ * 4. PWD / cwd path matching
50
+ */
51
+ export function detectCurrentProject(explicitProjectId) {
52
+ // 1. Explicit parameter
53
+ if (explicitProjectId) {
54
+ return { project_id: explicitProjectId, project_path: "", source: "explicit" };
55
+ }
56
+ // 2. Direct PROJECT_ID env var
57
+ if (process.env.PROJECT_ID) {
58
+ return { project_id: process.env.PROJECT_ID, project_path: process.env.CLAUDE_PROJECT_DIR || "", source: "env" };
59
+ }
60
+ // 3. Path-based env vars — extract dir name as project_id
61
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.PROJECT_DIR || process.env.PWD || "";
62
+ if (projectDir) {
63
+ const normalized = projectDir.replace(/\\/g, "/");
64
+ const dirName = normalized.split("/").filter(Boolean).pop() || normalized;
65
+ return { project_id: dirName, project_path: normalized, source: "env" };
66
+ }
67
+ // 4. Fallback — no detection possible
68
+ return { project_id: "", project_path: "", source: "fallback" };
69
+ }
70
+ /**
71
+ * Truncate a string to n characters, adding "..." if truncated.
72
+ */
73
+ export function truncate(s, n) {
74
+ if (s.length <= n)
75
+ return s;
76
+ return s.slice(0, n) + "...";
77
+ }
78
+ /**
79
+ * List known projects from the database.
80
+ */
81
+ export function listKnownProjects() {
82
+ const db = getDb();
83
+ const rows = db
84
+ .prepare("SELECT DISTINCT project_id FROM cases ORDER BY project_id")
85
+ .all();
86
+ return rows.map((r) => r.project_id);
87
+ }
88
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "debug-lessons-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for shared debugging case library across Claude Code projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "debug-lessons-mcp": "dist/cli.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "files": [
11
+ "dist/",
12
+ "skills/",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "start": "node dist/index.js",
18
+ "dev": "tsc && node dist/index.js",
19
+ "prepare": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "debug",
24
+ "lessons",
25
+ "claude-code"
26
+ ],
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.0.0",
30
+ "better-sqlite3": "^11.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/better-sqlite3": "^7.6.8",
34
+ "@types/node": "^22.0.0",
35
+ "typescript": "^5.5.0"
36
+ }
37
+ }
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: 搜索踩坑
3
+ description: 在共享踩坑案例库中搜索类似问题。支持多关键词,当前项目案例自动加权优先。
4
+ argument-hint: "[搜索关键词]"
5
+ ---
6
+
7
+ # 搜索踩坑
8
+
9
+ 在踩坑案例库中搜索相关经验,在动手排查之前先看看有没有人踩过类似的坑。
10
+
11
+ ## 流程
12
+
13
+ 1. 如果用户在命令后提供了搜索关键词,直接使用。否则询问要搜索的内容。
14
+ 2. 调用 `search_cases` MCP tool:
15
+ - query: 用户提供的关键词(多词空格分隔,每个词独立匹配)
16
+ - 不传 project_id — 服务端自动检测当前项目,当前项目案例 +50 分加权优先
17
+ - limit: 最多返回 10 条
18
+ 3. 以清晰格式展示搜索结果,每条包含:
19
+ - 编号 [id]、📌 标记(当前项目案例)
20
+ - 所属项目、模型、分类
21
+ - 问题摘要(1-2 句话)
22
+ - 教训摘要(核心结论)
23
+ 4. 用户可输入编号查看完整案例详情 — 调用 `get_case` 展示完整内容(问题、排查思路、解决方案、教训总结)。
24
+
25
+ ## 搜索技巧
26
+ - 用多个简短关键词比一个长句子效果好(如 "Docker 端口 冲突")
27
+ - 当前项目的案例标记 📌 并自动排在前面
28
+ - 没找到完全匹配的?试试相关领域的词
29
+ - 搜索结果按相关度排序,优先看排在前面的
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: 浏览踩坑
3
+ description: 按项目、分类或模型浏览踩坑案例列表,支持分页。
4
+ argument-hint: "[筛选条件:项目名/分类/模型]"
5
+ ---
6
+
7
+ # 浏览踩坑
8
+
9
+ 按条件浏览案例列表,适合不定向地翻阅和学习。
10
+
11
+ ## 流程
12
+
13
+ 1. 解析用户的筛选意图:
14
+ - 用户说「Docker 相关的」→ category: "Docker/Build"
15
+ - 用户说「sparx 项目的」→ project_id: "sparx"
16
+ - 用户说「Claude Opus 的案例」→ model_id: "claude-opus-4-8"
17
+ - 用户说「最近的案例」→ 不加筛选,按 ID 倒序(最新的在前)
18
+ - 用户没有提供筛选条件 → 询问想按什么维度浏览
19
+ 2. 调用 `list_cases` MCP tool:
20
+ - 传入对应的筛选参数(project_id / category / model_id)
21
+ - 默认每页 20 条
22
+ 3. 以列表形式展示结果,每条包含:
23
+ - [id] 分类 | 项目 | 模型 | 问题摘要(1 行)
24
+ 4. 用户可输入编号查看完整案例 → 调用 `get_case`
25
+ 5. 如果结果较多,提示用户可缩小筛选范围(如限定分类或项目)
26
+
27
+ ## 筛选维度参考
28
+ - **按项目**:project_id,如 "sparx", "my-app"
29
+ - **按分类**:Docker/Build, Frontend, Backend/API, Database/Schema, Config/Env, CI/CD, Tooling, Testing, Performance, Security
30
+ - **按模型**:model_id,如 "claude-opus-4-8", "deepseek-v4-pro"
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: 记录踩坑
3
+ description: 记录一条调试踩坑案例到共享知识库。引导式收集问题、排查思路、解决方案和教训总结。
4
+ argument-hint: "[遇到的问题简述]"
5
+ ---
6
+
7
+ # 记录踩坑
8
+
9
+ 将当前调试经验记录到共享踩坑案例库。
10
+
11
+ ## 流程
12
+
13
+ 1. 如果用户在命令后提供了问题简述,以此作为起点。否则先问用户:「遇到了什么问题?」
14
+ 2. 逐项收集以下信息。如果用户一次性描述了完整经历,直接提取并确认,无需逐项询问:
15
+ - **问题描述** (problem) — 发生了什么?具体的错误信息或异常行为
16
+ - **排查思路** (thinking) — 当时怎么分析的?试过哪些方法?排除了哪些可能?
17
+ - **解决方案** (result) — 最终怎么修好的?具体的修改或命令
18
+ - **教训总结** (lesson) — 未来如何避免?要可操作、可直接套用。不要说「下次注意」,要说「在 X 场景下先检查 Y」
19
+ - **分类** (category) — 尝试从问题描述中推断。常见分类:Docker/Build, Frontend, Backend/API, Database/Schema, Config/Env, CI/CD, Tooling, Testing, Performance, Security, Other
20
+ - **标签** (tags) — 可选,逗号分隔的关键词
21
+ 3. 调用 `add_case` MCP tool 提交案例。不需传 project_id 和 model_id — 服务端自动检测。
22
+ 4. 显示保存结果(案例 ID 和关键信息摘要)。
23
+
24
+ ## 注意
25
+ - 所有案例内容使用中文
26
+ - 教训总结是核心价值——要具体、可操作、能直接套用到未来的类似场景
27
+ - 如果用户描述不清,帮助他们梳理:从症状 → 假设 → 验证 → 结论的链条
28
+ - category 如果拿不准,选一个最接近的即可,后续可以修改
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: 踩坑统计
3
+ description: 查看踩坑案例库的统计概览:总数、按项目/模型/分类分布、近期趋势。
4
+ ---
5
+
6
+ # 踩坑统计
7
+
8
+ 展示踩坑案例库的统计数据和趋势分析。
9
+
10
+ ## 流程
11
+
12
+ 1. 调用 `get_stats` MCP tool 获取全局统计(不传 project_id = 全局)。
13
+ 2. 调用 `get_models` MCP tool 获取模型分布。
14
+ 3. 以结构化方式展示:
15
+ - **总览**:案例总数、近 7 天新增、近 30 天新增
16
+ - **按项目分布**:每个项目的案例数,识别最活跃的项目
17
+ - **按分类分布**:各类问题的频率,识别当前技术栈的高频踩坑类型
18
+ - **按模型分布**:每个模型记录的案例数(用于对比不同模型的行为差异)
19
+ 4. 如果发现明显的趋势或异常(如某个分类案例近期激增、某个模型问题集中),主动指出并给出建议。
20
+
21
+ ## 补充
22
+ - 如果用户想只看某个项目的统计,可以传入项目名,如「看 sparx 项目的统计」
23
+ - 统计结果可以帮助团队识别:哪些类型的 Bug 最频繁、哪个模型更容易遇到特定问题