@dependfix/mcp 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/README.en-US.md +78 -0
- package/README.md +12 -1
- package/dist/index.d.mts +2 -3
- package/dist/src.mjs +74 -7
- package/dist/src.mjs.map +1 -1
- package/package.json +6 -6
package/README.en-US.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @dependfix/mcp
|
|
2
|
+
|
|
3
|
+
<!-- i18n: switch -->
|
|
4
|
+
[简体中文](./README.md) | [English](./README.en-US.md)
|
|
5
|
+
|
|
6
|
+
> dependfix MCP Server package. Exposes dependfix's scan/fix capabilities to AI coding assistants (Claude, Copilot, Cursor, etc.) via [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @dependfix/mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Tools
|
|
15
|
+
|
|
16
|
+
| Tool | Function | Inputs |
|
|
17
|
+
|:-----||:---------|:-------|
|
|
18
|
+
| `fetch_alerts` | Fetch Dependabot security alerts for specified repo (optionally parallel Code Scanning, read-only) | `repo`, `severity?`, `code_scanning?` |
|
|
19
|
+
| `discover_repos` | Auto-discover repos by owner / org (read-only) | `owner[]`, `topics?`, `include?`, `exclude?`, `probe_dependabot?` |
|
|
20
|
+
| `run_scan` | Run dependfix scan and fix on target repo | `repo`, `mode?`, `severity?`, `code_scanning?`, `max_alerts?`, `max_concurrency?`, `dry_run?`, `allow_major_upgrade?`, `ai_enabled?`, `ai_provider?`, `ai_model?`, `ai_trigger?` |
|
|
21
|
+
| `fix_dependency` | Fix single dependency or lockfile (override / direct / lockfile) | `workDir`, `fix_type?`, `packageName?`, `targetVersion?` |
|
|
22
|
+
| `cleanup_branches` | Clean up merged/closed dependfix branches (non-interactive) | `repo`, `dry_run?` |
|
|
23
|
+
| `history` | Query history run summary for specified repo (read-only) | `repo` |
|
|
24
|
+
| `get_last_report` | Read most recent JSON report (read-only) | — |
|
|
25
|
+
|
|
26
|
+
Parameter semantics align with CLI (severity is threshold semantics: `high` keeps critical + high; `dry_run` defaults inferred from mode; AI params only pass through switch and model, apiKey read from env var).
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
Add via MCP config file (stdio transport):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"dependfix": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["@dependfix/mcp"],
|
|
38
|
+
"env": {
|
|
39
|
+
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Environment variables:
|
|
47
|
+
|
|
48
|
+
| Variable | Description |
|
|
49
|
+
|:---------|:------------|
|
|
50
|
+
| `GITHUB_TOKEN` | GitHub access credential (required for fetching alerts / running scans / branch cleanup) |
|
|
51
|
+
| `DEPENDFIX_MCP_REPORT_DIR` | JSON report output dir (default `./dependfix-reports`) |
|
|
52
|
+
| `DEPENDFIX_AI_API_KEY` | AI assessment API Key (required when `run_scan` `ai_enabled` enabled; only via env var, never via tool params) |
|
|
53
|
+
|
|
54
|
+
## Security boundaries
|
|
55
|
+
|
|
56
|
+
- Credentials only read from environment variables (`GITHUB_TOKEN` / `DEPENDFIX_AI_API_KEY`), tool params do not pass sensitive information
|
|
57
|
+
- `cleanup_branches` is pure GitHub API ops (list/status/delete remote branch), no local repo needed; only deletes `dependfix/` prefixed merged/closed branches, never touches open PR branches
|
|
58
|
+
- `fix_dependency` requires locally cloned repo dir (`workDir`, operates on package.json / pnpm-workspace.yaml / pnpm-lock.yaml)
|
|
59
|
+
|
|
60
|
+
## Local development
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm --filter @dependfix/mcp build # Build dist
|
|
64
|
+
pnpm --filter @dependfix/mcp test # Consistency test
|
|
65
|
+
node packages/mcp/dist/bin.mjs # stdio launch
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Design
|
|
69
|
+
|
|
70
|
+
See [mcp-server.md](https://github.com/dependfix/dependfix/blob/master/docs/design/governance/mcp-server.md) (Tool schema, CLI consistency, error handling, capability gaps and evolution path).
|
|
71
|
+
|
|
72
|
+
## Related packages
|
|
73
|
+
|
|
74
|
+
- [dependfix main project](https://github.com/dependfix/dependfix) — this package's source and full docs
|
|
75
|
+
- [@dependfix/core](https://github.com/dependfix/dependfix/blob/master/packages/core/README.md) — core domain model library (this package depends on)
|
|
76
|
+
- [@dependfix/engine](https://github.com/dependfix/dependfix/blob/master/packages/engine/README.md) — execution engine (this package depends on)
|
|
77
|
+
- [dependfix](https://github.com/dependfix/dependfix/blob/master/packages/cli/README.md) — CLI application entry (same source capabilities)
|
|
78
|
+
- [@dependfix/skills](https://github.com/dependfix/dependfix/blob/master/packages/skills/README.md) — Agent Skill source of truth
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @dependfix/mcp
|
|
2
2
|
|
|
3
|
+
<!-- i18n: switch -->
|
|
4
|
+
[简体中文](./README.md) | [English](./README.en-US.md)
|
|
5
|
+
|
|
3
6
|
> dependfix 的 MCP Server 包。通过 [Model Context Protocol](https://modelcontextprotocol.io/) 将 dependfix 的扫描/修复能力暴露给 AI 编程助手(Claude、Copilot、Cursor 等)。
|
|
4
7
|
|
|
5
8
|
## 安装
|
|
@@ -64,4 +67,12 @@ node packages/mcp/dist/bin.mjs # stdio 启动
|
|
|
64
67
|
|
|
65
68
|
## 设计
|
|
66
69
|
|
|
67
|
-
详见 [mcp-server.md](
|
|
70
|
+
详见 [mcp-server.md](https://github.com/dependfix/dependfix/blob/master/docs/design/governance/mcp-server.md)(Tool schema、与 CLI 的一致性、错误处理、能力差距与演进路线)。
|
|
71
|
+
|
|
72
|
+
## 相关包
|
|
73
|
+
|
|
74
|
+
- [dependfix 主项目](https://github.com/dependfix/dependfix) — 本包源码与完整文档
|
|
75
|
+
- [@dependfix/core](https://github.com/dependfix/dependfix/blob/master/packages/core/README.md) — 核心领域模型库(本包依赖)
|
|
76
|
+
- [@dependfix/engine](https://github.com/dependfix/dependfix/blob/master/packages/engine/README.md) — 执行引擎(本包依赖)
|
|
77
|
+
- [dependfix](https://github.com/dependfix/dependfix/blob/master/packages/cli/README.md) — CLI 应用入口(同源能力)
|
|
78
|
+
- [@dependfix/skills](https://github.com/dependfix/dependfix/blob/master/packages/skills/README.md) — 产品 Agent Skill 权威源
|
package/dist/index.d.mts
CHANGED
|
@@ -11,9 +11,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
11
11
|
* - history(只读):查询仓库历史运行摘要
|
|
12
12
|
* 凭据从 GITHUB_TOKEN 环境变量读取(mcp-server.md §4.3)。
|
|
13
13
|
*/
|
|
14
|
-
declare const createMcpServer: () => McpServer;
|
|
14
|
+
export declare const createMcpServer: () => McpServer;
|
|
15
15
|
/** 连接 stdio 传输(bin 入口调用) */
|
|
16
|
-
declare const connectStdio: () => Promise<void>;
|
|
16
|
+
export declare const connectStdio: () => Promise<void>;
|
|
17
17
|
//#endregion
|
|
18
|
-
export { connectStdio, createMcpServer };
|
|
19
18
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/src.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { DEFAULT_RUNTIME_CONFIG, DependfixApp, RUNTIME_MODES, SEVERITY_THRESHOLDS, createGitHubClient, deleteRemoteBranch, discoverRepositories, fetchCodeScanningAlerts, fetchDependabotAlerts, getBranchPrStatus, listDependfixBranches, overrideTransitiveDependency, queryRepoHistory, repairLockfile, upgradeDependency } from "@dependfix/engine";
|
|
4
|
+
import { DEFAULT_RUNTIME_CONFIG, DependfixApp, RUNTIME_MODES, SEVERITY_THRESHOLDS, createGitHubClient, deleteRemoteBranch, discoverRepositories, fetchCodeScanningAlerts, fetchDependabotAlerts, fetchPnpmAuditAlerts, getBranchPrStatus, listDependfixBranches, overrideTransitiveDependency, queryRepoHistory, repairLockfile, upgradeDependency } from "@dependfix/engine";
|
|
5
|
+
import { fromPat } from "@dependfix/engine/auth";
|
|
5
6
|
import { filterAlerts, isValidRepoIdentifier } from "@dependfix/core";
|
|
6
7
|
import { readFileSync, readdirSync } from "node:fs";
|
|
7
8
|
import { join } from "node:path";
|
|
@@ -56,7 +57,8 @@ const discoverReposSchema = z.object({
|
|
|
56
57
|
topics: z.array(z.string()).optional().describe("topic 白名单(AND 语义:必须包含全部指定 topics)"),
|
|
57
58
|
include: z.array(z.string()).optional().describe("仓库白名单 glob(如 owner/*、owner/pkg-*)"),
|
|
58
59
|
exclude: z.array(z.string()).optional().describe("仓库黑名单 glob(与 include 冲突时胜出)"),
|
|
59
|
-
probe_dependabot: z.boolean().optional().describe("探测 .github/dependabot.yml 存在性(默认 true;会额外触达 contents API)")
|
|
60
|
+
probe_dependabot: z.boolean().optional().describe("探测 .github/dependabot.yml 存在性(默认 true;会额外触达 contents API)"),
|
|
61
|
+
max_repos: z.number().int().min(0).optional().describe("发现规模上限:最多保留的仓库数(默认 100;0 表示不限制)")
|
|
60
62
|
});
|
|
61
63
|
/** `cleanup_branches` 输入:清理已合并/已关闭的 dependfix 分支 */
|
|
62
64
|
const cleanupBranchesSchema = z.object({
|
|
@@ -65,6 +67,13 @@ const cleanupBranchesSchema = z.object({
|
|
|
65
67
|
});
|
|
66
68
|
/** `history` 输入:查询仓库历史运行摘要 */
|
|
67
69
|
const historySchema = z.object({ repo: z.string().describe("目标仓库,格式 owner/repo") });
|
|
70
|
+
/** `pnpm_audit` 输入:本地 pnpm audit 回退数据源 */
|
|
71
|
+
const pnpmAuditSchema = z.object({
|
|
72
|
+
/** 本地仓库工作目录(已 clone,包含 pnpm-lock.yaml) */
|
|
73
|
+
workDir: z.string().describe("本地仓库工作目录(已 clone,包含 pnpm-lock.yaml)"),
|
|
74
|
+
/** 仓库标识(owner/repo 或 local 兜底;与 CLI --repo 同源语义) */
|
|
75
|
+
repository: z.string().describe("仓库标识(owner/repo 或 local 兜底;用于归一化 NormalizedSecurityAlert.repository 字段)")
|
|
76
|
+
});
|
|
68
77
|
|
|
69
78
|
//#endregion
|
|
70
79
|
//#region src/tools/errors.ts
|
|
@@ -96,7 +105,7 @@ const fetchAlerts = async (input) => {
|
|
|
96
105
|
};
|
|
97
106
|
const [owner, repo] = input.repo.split("/");
|
|
98
107
|
try {
|
|
99
|
-
const client = createGitHubClient({ token });
|
|
108
|
+
const client = createGitHubClient({ auth: fromPat(token) });
|
|
100
109
|
const params = {
|
|
101
110
|
owner,
|
|
102
111
|
repo,
|
|
@@ -219,7 +228,12 @@ const runScan = async (input) => {
|
|
|
219
228
|
stage: e.stage,
|
|
220
229
|
category: e.category,
|
|
221
230
|
message: e.message
|
|
222
|
-
}))
|
|
231
|
+
})),
|
|
232
|
+
startedAt: result.startedAt,
|
|
233
|
+
finishedAt: result.finishedAt,
|
|
234
|
+
config: result.config,
|
|
235
|
+
alerts: result.alerts,
|
|
236
|
+
actions: result.actions
|
|
223
237
|
};
|
|
224
238
|
} catch (error) {
|
|
225
239
|
return toToolError(error);
|
|
@@ -340,7 +354,7 @@ const discoverRepos = async (input) => {
|
|
|
340
354
|
error: "owner 必填(至少一个 owner/org)"
|
|
341
355
|
};
|
|
342
356
|
try {
|
|
343
|
-
const client = createGitHubClient({ token });
|
|
357
|
+
const client = createGitHubClient({ auth: fromPat(token) });
|
|
344
358
|
const policy = {
|
|
345
359
|
include: input.include && input.include.length > 0 ? input.include : void 0,
|
|
346
360
|
exclude: input.exclude && input.exclude.length > 0 ? input.exclude : void 0
|
|
@@ -350,7 +364,8 @@ const discoverRepos = async (input) => {
|
|
|
350
364
|
owners: input.owner,
|
|
351
365
|
topics: input.topics,
|
|
352
366
|
policy,
|
|
353
|
-
probeDependabot: input.probe_dependabot ?? true
|
|
367
|
+
probeDependabot: input.probe_dependabot ?? true,
|
|
368
|
+
maxRepos: input.max_repos
|
|
354
369
|
});
|
|
355
370
|
return {
|
|
356
371
|
ok: true,
|
|
@@ -391,7 +406,7 @@ const cleanupBranches = async (input) => {
|
|
|
391
406
|
const [owner, repo] = input.repo.split("/");
|
|
392
407
|
const dryRun = input.dry_run ?? false;
|
|
393
408
|
try {
|
|
394
|
-
const client = createGitHubClient({ token });
|
|
409
|
+
const client = createGitHubClient({ auth: fromPat(token) });
|
|
395
410
|
const branches = await listDependfixBranches(client, owner, repo);
|
|
396
411
|
const statuses = await Promise.all(branches.map((branch) => getBranchPrStatus(client, owner, repo, branch)));
|
|
397
412
|
const merged = statuses.filter((s) => s.merged);
|
|
@@ -459,6 +474,48 @@ const getHistory = async (input) => {
|
|
|
459
474
|
}
|
|
460
475
|
};
|
|
461
476
|
|
|
477
|
+
//#endregion
|
|
478
|
+
//#region src/tools/pnpm-audit.tool.ts
|
|
479
|
+
/**
|
|
480
|
+
* `pnpm_audit`:本地 pnpm audit 回退数据源(无 GitHub token 或 403 场景)。
|
|
481
|
+
*
|
|
482
|
+
* 设计意图(详见 docs/design/pnpm-audit-fallback.md):
|
|
483
|
+
* - 显式 `--alerts-source pnpm-audit` 触发(CLI)或显式调用 `pnpm_audit` tool(MCP)触发
|
|
484
|
+
* - 复用 `fetchPnpmAuditAlerts` 解析 + 归一化逻辑(与 CLI 同源)
|
|
485
|
+
* - audit 自身失败(无 lockfile / pnpm 不可用 / JSON 解析失败)→ 硬失败,绝不静默空跑
|
|
486
|
+
*
|
|
487
|
+
* 凭据:pnpm-audit 不需要 GitHub token(本地命令);但保留 `requireToken()`
|
|
488
|
+
* 调用与其它 tool 一致(保持 pattern 统一,未来如需 pnpm registry token 可扩展)。
|
|
489
|
+
*
|
|
490
|
+
* @param input.workDir 本地仓库工作目录(包含 pnpm-lock.yaml)
|
|
491
|
+
* @param input.repository 仓库标识(owner/repo 或 local 兜底;与 CLI --repo 同源语义)
|
|
492
|
+
*/
|
|
493
|
+
const pnpmAudit = async (input) => {
|
|
494
|
+
const token = requireToken();
|
|
495
|
+
if (typeof token !== "string") return token;
|
|
496
|
+
try {
|
|
497
|
+
const normalizedAlerts = await fetchPnpmAuditAlerts(input);
|
|
498
|
+
return {
|
|
499
|
+
ok: true,
|
|
500
|
+
count: normalizedAlerts.length,
|
|
501
|
+
workDir: input.workDir,
|
|
502
|
+
repository: input.repository,
|
|
503
|
+
alerts: normalizedAlerts.map((a) => ({
|
|
504
|
+
id: a.id,
|
|
505
|
+
severity: a.severity,
|
|
506
|
+
packageName: a.packageName,
|
|
507
|
+
manifestPath: a.manifestPath,
|
|
508
|
+
recommendedVersion: a.recommendedVersion,
|
|
509
|
+
fixable: a.fixable,
|
|
510
|
+
htmlUrl: a.htmlUrl,
|
|
511
|
+
summary: a.summary
|
|
512
|
+
}))
|
|
513
|
+
};
|
|
514
|
+
} catch (error) {
|
|
515
|
+
return toToolError(error);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
|
|
462
519
|
//#endregion
|
|
463
520
|
//#region src/index.ts
|
|
464
521
|
/**
|
|
@@ -547,6 +604,16 @@ const createMcpServer = () => {
|
|
|
547
604
|
text: JSON.stringify(result, null, 2)
|
|
548
605
|
}] };
|
|
549
606
|
});
|
|
607
|
+
server.registerTool("pnpm_audit", {
|
|
608
|
+
description: "本地 pnpm audit 回退数据源(无需 GitHub token;audit 失败硬返回错误)",
|
|
609
|
+
inputSchema: pnpmAuditSchema
|
|
610
|
+
}, async (input) => {
|
|
611
|
+
const result = await pnpmAudit(input);
|
|
612
|
+
return { content: [{
|
|
613
|
+
type: "text",
|
|
614
|
+
text: JSON.stringify(result, null, 2)
|
|
615
|
+
}] };
|
|
616
|
+
});
|
|
550
617
|
return server;
|
|
551
618
|
};
|
|
552
619
|
/** 连接 stdio 传输(bin 入口调用) */
|
package/dist/src.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src.mjs","names":[],"sources":["../src/tools/schemas.ts","../src/tools/errors.ts","../src/tools/fetch-alerts.ts","../src/tools/get-last-report.ts","../src/tools/run-scan.ts","../src/tools/fix-dependency.ts","../src/tools/discover-repos.ts","../src/tools/cleanup-branches.ts","../src/tools/history.ts","../src/index.ts"],"sourcesContent":["import { z } from 'zod'\nimport { RUNTIME_MODES, SEVERITY_THRESHOLDS } from '@dependfix/engine'\n\n// run_scan 的 mode 子集:排除 cleanup-branches(由独立 cleanup_branches tool 承担;\n// DependfixApp 的该 mode 走交互确认,MCP stdio 不可用——见 mcp-server.md §8.3)。\n// 从 cli RUNTIME_MODES 派生(filter 跟随 cli 演进),非独立硬编码。\n// as unknown 桥接:filter 返回数组类型,z.enum 需要 readonly 元组。\nconst RUN_SCAN_MODES = RUNTIME_MODES.filter((m) => m !== 'cleanup-branches') as unknown as readonly ['report-only', 'fix', 'fix-and-pr']\n\n/** `fetch_alerts` 输入:拉取指定仓库的安全告警(Dependabot + 可选 Code Scanning) */\nexport const fetchAlertsSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n severity: z.enum(SEVERITY_THRESHOLDS).default('high').describe('严重级别阈值(high 保留 critical + high,与 CLI 一致)'),\n code_scanning: z.boolean().optional().describe('同时拉取 Code Scanning 告警(与 Dependabot 并行;需要 token 具备 security-events: read)'),\n})\n\n/** `get_last_report` 输入:读取最近一次 JSON 报告 */\nexport const getLastReportSchema = z.object({})\n\n/** `run_scan` 输入:对目标仓库执行 dependfix 扫描并修复 */\nexport const runScanSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n mode: z.enum(RUN_SCAN_MODES).default('report-only').describe('执行模式(默认仅报告)'),\n severity: z.enum(SEVERITY_THRESHOLDS).default('high').describe('严重级别阈值'),\n code_scanning: z.boolean().optional().describe('同时拉取 Code Scanning 告警(默认 false)'),\n max_alerts: z.number().int().min(1).max(1000).optional().describe('每仓库最多处理的告警数(默认 20)'),\n max_concurrency: z.number().int().min(1).max(16).optional().describe('多仓库并发窗口(默认 1 保守串行)'),\n dry_run: z.boolean().optional().describe('试运行不实际写入;缺省按 mode 推断(report-only 为 true)。与 mode=fix/fix-and-pr 互斥(会返回配置校验错误)'),\n allow_major_upgrade: z.boolean().optional().describe('跨线 major 升级显式授权(默认 false;仅根直接依赖 + lockfile 单版本,强制完整验证)'),\n ai_enabled: z.boolean().optional().describe('开启 AI breaking change 研判(默认 false;apiKey 从 DEPENDFIX_AI_API_KEY env 读取,禁止经 tool 参数传入)'),\n ai_provider: z.enum(['openai-compatible', 'anthropic']).optional().describe('AI 提供商(默认 openai-compatible)'),\n ai_model: z.string().optional().describe('AI 模型名(默认 deepseek-v4-flash)'),\n ai_trigger: z.enum(['failure', 'major', 'both']).optional().describe('AI 触发范围(默认 both)'),\n})\n\n/** `fix_dependency` 输入:修复单个依赖(多修复类型) */\nexport const fixDependencySchema = z.object({\n /** 本地仓库路径(已 clone 的目录,含 package.json/pnpm-lock.yaml) */\n workDir: z.string().describe('本地仓库工作目录(已 clone,包含 package.json 与 pnpm-lock.yaml)'),\n /** 修复类型:override(间接依赖 overrides)/ direct(直接依赖升级)/ lockfile(frozen-lockfile 漂移修复) */\n fix_type: z.enum(['override', 'direct', 'lockfile']).default('override').describe('修复类型(默认 override)'),\n /** override / direct 必填 */\n packageName: z.string().optional().describe('依赖包名(fix_type=override/direct 必填)'),\n /** override / direct 必填 */\n targetVersion: z.string().optional().describe('目标精确版本,如 4.17.21(fix_type=override/direct 必填)'),\n})\n\n/** `discover_repos` 输入:按 owner / org 自动发现仓库 */\nexport const discoverReposSchema = z.object({\n owner: z.array(z.string()).min(1).describe('owner / org 列表(分别发现后合并)'),\n topics: z.array(z.string()).optional().describe('topic 白名单(AND 语义:必须包含全部指定 topics)'),\n include: z.array(z.string()).optional().describe('仓库白名单 glob(如 owner/*、owner/pkg-*)'),\n exclude: z.array(z.string()).optional().describe('仓库黑名单 glob(与 include 冲突时胜出)'),\n probe_dependabot: z.boolean().optional().describe('探测 .github/dependabot.yml 存在性(默认 true;会额外触达 contents API)'),\n})\n\n/** `cleanup_branches` 输入:清理已合并/已关闭的 dependfix 分支 */\nexport const cleanupBranchesSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n dry_run: z.boolean().optional().describe('仅列出待清理分支,不执行删除(默认 false)'),\n})\n\n/** `history` 输入:查询仓库历史运行摘要 */\nexport const historySchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n})\n","// 统一 tool 错误模板(复用收口):\n// - requireToken:GITHUB_TOKEN 检查。返回 token 字符串或错误对象;\n// 调用方用 `typeof token !== 'string'` 守卫收窄(项目未开 strictNullChecks,\n// truthiness 判别收窄不生效,typeof 守卫是兼容形式)。\n// - toToolError:任意错误 → ok:false(统一 Error.message / String 转换)\n// 各 tool 的返回联合类型均含 `{ ok: false, error: string }` 分支,可安全返回。\n\nexport type ToolError = { ok: false, error: string }\n\nexport const requireToken = (): string | ToolError => {\n const token = process.env.GITHUB_TOKEN\n if (!token) {\n return { ok: false, error: 'GITHUB_TOKEN not set(请配置环境变量)' }\n }\n return token\n}\n\nexport const toToolError = (error: unknown): ToolError => ({\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n})\n","import { createGitHubClient, fetchCodeScanningAlerts, fetchDependabotAlerts, type FetchDependabotAlertsParams } from '@dependfix/engine'\nimport { filterAlerts, isValidRepoIdentifier, type SeverityThreshold } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `fetch_alerts` 返回结构 */\nexport type FetchAlertsResult =\n | {\n ok: true\n count: number\n alerts: Array<{\n id: number\n severity: string\n packageName: string\n manifestPath: string\n recommendedVersion: string\n fixable: boolean\n htmlUrl: string\n summary: string\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `fetch_alerts`:拉取指定仓库的 Dependabot 安全告警(只读)。\n * 凭据从 GITHUB_TOKEN 环境变量读取(mcp-server.md §4.3)。\n */\nexport const fetchAlerts = async (input: { repo: string, severity: SeverityThreshold, code_scanning?: boolean }): Promise<FetchAlertsResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n\n // repo 格式校验复用 core(与 CLI 同源,避免自研校验漂移)\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n\n try {\n const client = createGitHubClient({ token })\n const params: FetchDependabotAlertsParams = {\n owner,\n repo,\n state: 'open',\n }\n\n // Dependabot + 可选 Code Scanning 并行(复用 cli fetcher;与 CLI --code-scanning 同源)。\n // 注意:CS 拉取失败(权限/网络)会使整个 tool 失败——与 CLI 现状一致\n // (per-source 错误隔离为 backlog 登记项,暂缓),结果不静默丢弃。\n const codeScanningEnabled = input.code_scanning ?? false\n const [dependabotAlerts, codeScanningAlerts] = await Promise.all([\n fetchDependabotAlerts(client, params),\n codeScanningEnabled\n ? fetchCodeScanningAlerts(client, { owner, repo })\n : Promise.resolve([] as Awaited<ReturnType<typeof fetchDependabotAlerts>>),\n ])\n const alerts = [...dependabotAlerts, ...codeScanningAlerts]\n\n // 严重级别过滤复用 core 阈值语义(与 CLI 一致:high 保留 critical + high;\n // all 不过滤;Code Scanning 源 unknown 恒透传)。不使用相等匹配,避免 high 漏掉 critical。\n const { filtered } = filterAlerts(alerts, { severityThreshold: input.severity })\n\n return {\n ok: true,\n count: filtered.length,\n alerts: filtered.map((a) => ({\n id: a.id,\n severity: a.severity,\n packageName: a.packageName,\n manifestPath: a.manifestPath,\n recommendedVersion: a.recommendedVersion,\n fixable: a.fixable,\n htmlUrl: a.htmlUrl,\n summary: a.summary,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { readFileSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { toToolError } from './errors'\n\n/** `get_last_report` 返回结构 */\nexport type GetLastReportResult =\n | { ok: true, file: string, report: unknown }\n | { ok: false, error: string }\n\n/**\n * `get_last_report`:读取最近一次 JSON 报告(只读)。\n * 报告目录默认为 `./dependfix-reports`(可用 `DEPENDFIX_MCP_REPORT_DIR` 覆盖)。\n */\nexport const getLastReport = async (): Promise<GetLastReportResult> => {\n const reportDir = process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports'\n try {\n const files = readdirSync(reportDir)\n .filter((f) => f.endsWith('.json'))\n .sort()\n if (files.length === 0) {\n return { ok: false, error: `未找到报告(目录 ${reportDir} 为空)` }\n }\n const latest = files[files.length - 1]\n const content = readFileSync(join(reportDir, latest), 'utf-8')\n return {\n ok: true,\n file: latest,\n report: JSON.parse(content),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { DependfixApp, DEFAULT_RUNTIME_CONFIG, type RuntimeConfig } from '@dependfix/engine'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `run_scan` 返回结构 */\nexport type RunScanResult =\n | {\n ok: true\n exitCode: number\n runId: string\n summary: import('@dependfix/core').RunSummary\n repositories: Array<Record<string, unknown>>\n errors: Array<Record<string, unknown>>\n }\n | { ok: false, error: string }\n\n/**\n * `run_scan`:对目标仓库执行 dependfix 扫描并修复。\n * 凭据从 GITHUB_TOKEN 环境变量读取;repo 为 GitHub 远程仓库(report-only 无需 clone)。\n */\nexport const runScan = async (input: {\n repo: string\n mode: 'report-only' | 'fix' | 'fix-and-pr'\n severity: string\n code_scanning?: boolean\n max_alerts?: number\n max_concurrency?: number\n dry_run?: boolean\n allow_major_upgrade?: boolean\n ai_enabled?: boolean\n ai_provider?: 'openai-compatible' | 'anthropic'\n ai_model?: string\n ai_trigger?: 'failure' | 'major' | 'both'\n}): Promise<RunScanResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n\n // repo 格式校验复用 core(与 CLI 同源)\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n\n // 展开 cli 默认配置(maxAlerts/maxConcurrency/maxRetries/maxBackoff/alertSource/ai 默认等\n // 与 CLI 单一事实源对齐,避免手写默认值漂移),仅覆盖 tool 参数可控制字段。\n const defaultAi = DEFAULT_RUNTIME_CONFIG.ai\n const config: RuntimeConfig = {\n ...DEFAULT_RUNTIME_CONFIG,\n mode: input.mode,\n severityThreshold: input.severity as 'critical' | 'high' | 'medium' | 'all',\n repositories: [`${owner}/${repo}`],\n // dry-run 显式参数优先,缺省按 mode 推断(report-only 即只读)\n dryRun: input.dry_run ?? (input.mode === 'report-only'),\n createPullRequest: input.mode === 'fix-and-pr',\n commit: input.mode === 'fix',\n cleanupBranches: false,\n cleanupBranchesAuto: false,\n githubToken: token,\n codeScanningEnabled: input.code_scanning ?? DEFAULT_RUNTIME_CONFIG.codeScanningEnabled,\n allowMajorUpgrade: input.allow_major_upgrade ?? DEFAULT_RUNTIME_CONFIG.allowMajorUpgrade,\n maxAlertsPerRepository: input.max_alerts ?? DEFAULT_RUNTIME_CONFIG.maxAlertsPerRepository,\n maxConcurrency: input.max_concurrency ?? DEFAULT_RUNTIME_CONFIG.maxConcurrency,\n // AI 研判:展开 cli 默认(provider/model/baseUrl/trigger 与 CLI 对齐),\n // 仅覆盖开关与显式参数;apiKey 只从 env 读取(DEPENDFIX_AI_API_KEY),\n // 禁止经 tool 参数传入(防客户端日志泄露)。\n // defaultAi 收窄:默认配置缺失时视为未开启(与类型声明一致,运行时恒有值)\n ai: input.ai_enabled && defaultAi\n ? {\n ...defaultAi,\n enabled: true,\n provider: input.ai_provider ?? defaultAi.provider,\n model: input.ai_model ?? defaultAi.model,\n trigger: input.ai_trigger ?? defaultAi.trigger,\n apiKey: process.env.DEPENDFIX_AI_API_KEY,\n }\n : undefined,\n }\n\n try {\n const app = new DependfixApp({\n config,\n workDir: process.cwd(),\n reportOutputDir: process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports',\n })\n const { result, exitCode } = await app.run()\n\n return {\n ok: true,\n exitCode,\n runId: result.runId,\n summary: result.summary,\n repositories: result.repositories.map((r) => ({\n repository: r.repository,\n alertsCount: r.alertsCount,\n fixable: r.fixable,\n fixed: r.fixed,\n failed: r.failed,\n lockfileRepaired: r.lockfileRepaired,\n verificationPassed: r.verificationPassed ?? undefined,\n durationMs: r.durationMs,\n })),\n errors: result.errors.map((e) => ({\n repository: e.repository,\n stage: e.stage,\n category: e.category,\n message: e.message,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { overrideTransitiveDependency, repairLockfile, upgradeDependency, type LockfileDiff } from '@dependfix/engine'\nimport { toToolError } from './errors'\n\n/** `fix_dependency` 返回结构(按 fixType 判别) */\nexport type FixDependencyResult =\n | {\n ok: true\n fixType: 'override' | 'direct'\n packageName: string\n fromVersion: string\n toVersion: string\n isMajor: boolean\n warning?: string\n }\n | {\n ok: true\n fixType: 'lockfile'\n strategy?: string\n diff?: LockfileDiff | null\n lockfileVersion?: string\n lockfileVersionChanged?: boolean\n }\n | {\n ok: false\n fixType: 'override' | 'direct' | 'lockfile'\n packageName?: string\n fromVersion?: string\n toVersion?: string\n isMajor?: boolean\n error: string\n }\n\n/**\n * `fix_dependency`:修复单个依赖或 lockfile(按 `fix_type` 分发,复用 cli fixers):\n * - `override`(默认):间接依赖 → `overrideTransitiveDependency`(写入 pnpm overrides)\n * - `direct`:直接依赖 → `upgradeDependency`(改写 manifest + `pnpm install`,失败回滚)\n * - `lockfile`:frozen-lockfile 漂移 → `repairLockfile`(策略链修复,全部失败回滚)\n * 均需本地已 clone 的仓库目录(workDir)。\n */\nexport const fixDependency = async (input: {\n workDir: string\n fix_type?: 'override' | 'direct' | 'lockfile'\n packageName?: string\n targetVersion?: string\n}): Promise<FixDependencyResult> => {\n const fixType = input.fix_type ?? 'override'\n try {\n switch (fixType) {\n case 'lockfile': {\n const result = repairLockfile({ workDir: input.workDir })\n if (result.success) {\n return {\n ok: true,\n fixType: 'lockfile',\n strategy: result.strategy,\n diff: result.diff ?? null,\n lockfileVersion: result.lockfileVersion,\n lockfileVersionChanged: result.lockfileVersionChanged,\n }\n }\n return {\n ok: false,\n fixType: 'lockfile',\n error: result.failureDetail ?? 'lockfile repair failed',\n }\n }\n case 'direct': {\n if (!input.packageName || !input.targetVersion) {\n return { ok: false, fixType: 'direct', error: 'packageName 与 targetVersion 必填(fix_type=direct)' }\n }\n const result = await upgradeDependency({\n packageName: input.packageName,\n targetVersion: input.targetVersion,\n workDir: input.workDir,\n })\n if (result.success) {\n return {\n ok: true,\n fixType: 'direct',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n warning: result.warning,\n }\n }\n return {\n ok: false,\n fixType: 'direct',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n error: result.error ?? 'upgrade failed',\n }\n }\n case 'override': {\n if (!input.packageName || !input.targetVersion) {\n return { ok: false, fixType: 'override', error: 'packageName 与 targetVersion 必填(fix_type=override)' }\n }\n const result = await overrideTransitiveDependency({\n packageName: input.packageName,\n targetVersion: input.targetVersion,\n workDir: input.workDir,\n })\n if (result.success) {\n return {\n ok: true,\n fixType: 'override',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n warning: result.warning,\n }\n }\n return {\n ok: false,\n fixType: 'override',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n error: result.error ?? 'override failed',\n }\n }\n }\n } catch (error) {\n return {\n ok: false,\n fixType,\n error: toToolError(error).error,\n }\n }\n}\n","import { createGitHubClient, discoverRepositories, type RepoPolicy } from '@dependfix/engine'\nimport { requireToken, toToolError } from './errors'\n\n/** `discover_repos` 返回结构 */\nexport type DiscoverReposResult =\n | {\n ok: true\n count: number\n repositories: Array<{\n fullName: string\n defaultBranch: string\n topics: string[]\n hasDependabotConfig: boolean\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `discover_repos`:按 owner / org 自动发现仓库(复用 cli discoverRepositories,\n * 与 CLI `--owner` / `--repo-topics` / `--repo-include` / `--repo-exclude` 同源过滤链)。\n * 凭据从 GITHUB_TOKEN 环境变量读取。\n */\nexport const discoverRepos = async (input: {\n owner: string[]\n topics?: string[]\n include?: string[]\n exclude?: string[]\n probe_dependabot?: boolean\n}): Promise<DiscoverReposResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n if (input.owner.length === 0) {\n return { ok: false, error: 'owner 必填(至少一个 owner/org)' }\n }\n\n try {\n const client = createGitHubClient({ token })\n const policy: RepoPolicy = {\n include: input.include && input.include.length > 0 ? input.include : undefined,\n exclude: input.exclude && input.exclude.length > 0 ? input.exclude : undefined,\n }\n const repos = await discoverRepositories({\n client,\n owners: input.owner,\n topics: input.topics,\n policy,\n probeDependabot: input.probe_dependabot ?? true,\n })\n return {\n ok: true,\n count: repos.length,\n repositories: repos.map((r) => ({\n fullName: r.fullName,\n defaultBranch: r.defaultBranch,\n topics: r.topics,\n hasDependabotConfig: r.hasDependabotConfig,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { createGitHubClient, deleteRemoteBranch, getBranchPrStatus, listDependfixBranches } from '@dependfix/engine'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `cleanup_branches` 返回结构 */\nexport type CleanupBranchesResult =\n | {\n ok: true\n dryRun: boolean\n scanned: string[]\n /** 已删除分支(dry_run 时为空) */\n deleted: string[]\n /** 保留分支(open PR / 无 PR 未关闭) */\n kept: string[]\n /** 删除失败分支(best-effort,不中断) */\n failed: string[]\n }\n | { ok: false, error: string }\n\n/**\n * `cleanup_branches`:清理已合并/已关闭的 dependfix 分支(非交互)。\n *\n * 复用 cli pr-creator 底层函数自编排,语义对齐 `autoCleanupMergedBranches`:\n * - 只处理 `dependfix/` 前缀分支(listDependfixBranches 已过滤)\n * - 删除候选 = 已合并(merged)+ 已关闭未合并(orphaned);绝不触碰 open PR 分支\n * - 单分支删除失败记录到 `failed`,不中断其余删除(best-effort)\n * - dry_run 仅列清单(deleted/failed 为空)\n *\n * 刻意不走 DependfixApp 的 cleanup-branches mode:`runBranchCleanupForRepo`\n * 含交互式确认(非 TTY 默认拒绝),MCP stdio 下不可用。\n */\nexport const cleanupBranches = async (input: { repo: string, dry_run?: boolean }): Promise<CleanupBranchesResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n const dryRun = input.dry_run ?? false\n\n try {\n const client = createGitHubClient({ token })\n const branches = await listDependfixBranches(client, owner, repo)\n const statuses = await Promise.all(\n branches.map((branch) => getBranchPrStatus(client, owner, repo, branch)),\n )\n\n const merged = statuses.filter((s) => s.merged)\n const orphaned = statuses.filter((s) => s.closed && !s.merged)\n const kept = statuses.filter((s) => !s.closed)\n const candidates = [...merged, ...orphaned]\n\n if (dryRun) {\n return {\n ok: true,\n dryRun: true,\n scanned: branches,\n deleted: [],\n kept: kept.map((s) => s.branch),\n failed: [],\n }\n }\n\n const deleted: string[] = []\n const failed: string[] = []\n for (const s of candidates) {\n try {\n await deleteRemoteBranch(client, owner, repo, s.branch)\n deleted.push(s.branch)\n } catch {\n // 单分支删除失败(分支保护/不存在)不中断其余删除,best-effort\n failed.push(s.branch)\n }\n }\n\n return {\n ok: true,\n dryRun: false,\n scanned: branches,\n deleted,\n kept: kept.map((s) => s.branch),\n failed,\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { queryRepoHistory } from '@dependfix/engine'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { toToolError } from './errors'\n\n/** `history` 返回结构 */\nexport type HistoryResult =\n | {\n ok: true\n repo: string\n runs: Array<{\n runId: string\n startedAt: string\n durationMs: number\n repositories: string[]\n summary: Record<string, unknown>\n repoStats: Array<Record<string, unknown>>\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `history`:查询某仓库的历史运行摘要(倒序时间:最新在前)。\n * 复用 cli `queryRepoHistory`(读 dependfix-reports/index.json 聚合索引,\n * 与 `get_last_report` 的单文件语义不同);报告目录可用 `DEPENDFIX_MCP_REPORT_DIR` 覆盖。\n */\nexport const getHistory = async (input: { repo: string }): Promise<HistoryResult> => {\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n try {\n const reportDir = process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports'\n const entries = queryRepoHistory(input.repo, reportDir)\n return {\n ok: true,\n repo: input.repo,\n runs: entries.map((e) => ({\n runId: e.runId,\n startedAt: e.startedAt,\n durationMs: e.durationMs,\n repositories: e.repositories,\n // 桥接:RunSummary/ArchiveRepoStats 无索引签名,显式转 unknown 再收窄\n summary: e.summary as unknown as Record<string, unknown>,\n repoStats: e.repoStats as unknown as Array<Record<string, unknown>>,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { fetchAlertsSchema, getLastReportSchema, runScanSchema, fixDependencySchema, discoverReposSchema, cleanupBranchesSchema, historySchema } from './tools/schemas'\nimport { fetchAlerts } from './tools/fetch-alerts'\nimport { getLastReport } from './tools/get-last-report'\nimport { runScan } from './tools/run-scan'\nimport { fixDependency } from './tools/fix-dependency'\nimport { discoverRepos } from './tools/discover-repos'\nimport { cleanupBranches } from './tools/cleanup-branches'\nimport { getHistory } from './tools/history'\n\n/**\n * dependfix MCP Server:向 AI 助手暴露 7 个 tool。\n * - fetch_alerts(只读):拉取 Dependabot / Code Scanning 告警\n * - get_last_report(只读):读取最近 JSON 报告\n * - run_scan(写入):执行扫描/修复(默认 report-only;支持 AI 研判透传)\n * - fix_dependency(写入):修复单个依赖(override / direct / lockfile)\n * - discover_repos(只读):按 owner / org 自动发现仓库\n * - cleanup_branches(写入):清理已合并/已关闭的 dependfix 分支(非交互)\n * - history(只读):查询仓库历史运行摘要\n * 凭据从 GITHUB_TOKEN 环境变量读取(mcp-server.md §4.3)。\n */\nexport const createMcpServer = (): McpServer => {\n const server = new McpServer({\n name: 'dependfix',\n version: '0.1.0',\n })\n\n server.registerTool(\n 'fetch_alerts',\n {\n description: '拉取指定仓库的 Dependabot 安全告警(可选并行 Code Scanning,只读)',\n inputSchema: fetchAlertsSchema,\n },\n async (input) => {\n const result = await fetchAlerts(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'get_last_report',\n {\n description: '读取最近一次 dependfix JSON 报告(只读)',\n inputSchema: getLastReportSchema,\n },\n async () => {\n const result = await getLastReport()\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'run_scan',\n {\n description: '对目标仓库执行 dependfix 扫描并修复(默认 report-only;支持 code-scanning / AI 研判等参数)',\n inputSchema: runScanSchema,\n },\n async (input) => {\n const result = await runScan(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'fix_dependency',\n {\n description: '修复单个依赖或 lockfile(override / direct / lockfile;需要本地已 clone 仓库目录)',\n inputSchema: fixDependencySchema,\n },\n async (input) => {\n const result = await fixDependency(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'discover_repos',\n {\n description: '按 owner / org 自动发现仓库(支持 topics / include / exclude 名单策略,只读)',\n inputSchema: discoverReposSchema,\n },\n async (input) => {\n const result = await discoverRepos(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'cleanup_branches',\n {\n description: '清理已合并/已关闭的 dependfix 分支(非交互;只删 dependfix/ 前缀且 merged/closed,绝不触碰 open PR 分支)',\n inputSchema: cleanupBranchesSchema,\n },\n async (input) => {\n const result = await cleanupBranches(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'history',\n {\n description: '查询指定仓库的历史运行摘要(倒序时间,只读)',\n inputSchema: historySchema,\n },\n async (input) => {\n const result = await getHistory(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n return server\n}\n\n/** 连接 stdio 传输(bin 入口调用) */\nexport const connectStdio = async (): Promise<void> => {\n const server = createMcpServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"src.mjs","names":[],"sources":["../src/tools/schemas.ts","../src/tools/errors.ts","../src/tools/fetch-alerts.ts","../src/tools/get-last-report.ts","../src/tools/run-scan.ts","../src/tools/fix-dependency.ts","../src/tools/discover-repos.ts","../src/tools/cleanup-branches.ts","../src/tools/history.ts","../src/tools/pnpm-audit.tool.ts","../src/index.ts"],"sourcesContent":["import { z } from 'zod'\nimport { RUNTIME_MODES, SEVERITY_THRESHOLDS } from '@dependfix/engine'\n\n// run_scan 的 mode 子集:排除 cleanup-branches(由独立 cleanup_branches tool 承担;\n// DependfixApp 的该 mode 走交互确认,MCP stdio 不可用——见 mcp-server.md §8.3)。\n// 从 cli RUNTIME_MODES 派生(filter 跟随 cli 演进),非独立硬编码。\n// as unknown 桥接:filter 返回数组类型,z.enum 需要 readonly 元组。\nconst RUN_SCAN_MODES = RUNTIME_MODES.filter((m) => m !== 'cleanup-branches') as unknown as readonly ['report-only', 'fix', 'fix-and-pr']\n\n/** `fetch_alerts` 输入:拉取指定仓库的安全告警(Dependabot + 可选 Code Scanning) */\nexport const fetchAlertsSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n severity: z.enum(SEVERITY_THRESHOLDS).default('high').describe('严重级别阈值(high 保留 critical + high,与 CLI 一致)'),\n code_scanning: z.boolean().optional().describe('同时拉取 Code Scanning 告警(与 Dependabot 并行;需要 token 具备 security-events: read)'),\n})\n\n/** `get_last_report` 输入:读取最近一次 JSON 报告 */\nexport const getLastReportSchema = z.object({})\n\n/** `run_scan` 输入:对目标仓库执行 dependfix 扫描并修复 */\nexport const runScanSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n mode: z.enum(RUN_SCAN_MODES).default('report-only').describe('执行模式(默认仅报告)'),\n severity: z.enum(SEVERITY_THRESHOLDS).default('high').describe('严重级别阈值'),\n code_scanning: z.boolean().optional().describe('同时拉取 Code Scanning 告警(默认 false)'),\n max_alerts: z.number().int().min(1).max(1000).optional().describe('每仓库最多处理的告警数(默认 20)'),\n max_concurrency: z.number().int().min(1).max(16).optional().describe('多仓库并发窗口(默认 1 保守串行)'),\n dry_run: z.boolean().optional().describe('试运行不实际写入;缺省按 mode 推断(report-only 为 true)。与 mode=fix/fix-and-pr 互斥(会返回配置校验错误)'),\n allow_major_upgrade: z.boolean().optional().describe('跨线 major 升级显式授权(默认 false;仅根直接依赖 + lockfile 单版本,强制完整验证)'),\n ai_enabled: z.boolean().optional().describe('开启 AI breaking change 研判(默认 false;apiKey 从 DEPENDFIX_AI_API_KEY env 读取,禁止经 tool 参数传入)'),\n ai_provider: z.enum(['openai-compatible', 'anthropic']).optional().describe('AI 提供商(默认 openai-compatible)'),\n ai_model: z.string().optional().describe('AI 模型名(默认 deepseek-v4-flash)'),\n ai_trigger: z.enum(['failure', 'major', 'both']).optional().describe('AI 触发范围(默认 both)'),\n})\n\n/** `fix_dependency` 输入:修复单个依赖(多修复类型) */\nexport const fixDependencySchema = z.object({\n /** 本地仓库路径(已 clone 的目录,含 package.json/pnpm-lock.yaml) */\n workDir: z.string().describe('本地仓库工作目录(已 clone,包含 package.json 与 pnpm-lock.yaml)'),\n /** 修复类型:override(间接依赖 overrides)/ direct(直接依赖升级)/ lockfile(frozen-lockfile 漂移修复) */\n fix_type: z.enum(['override', 'direct', 'lockfile']).default('override').describe('修复类型(默认 override)'),\n /** override / direct 必填 */\n packageName: z.string().optional().describe('依赖包名(fix_type=override/direct 必填)'),\n /** override / direct 必填 */\n targetVersion: z.string().optional().describe('目标精确版本,如 4.17.21(fix_type=override/direct 必填)'),\n})\n\n/** `discover_repos` 输入:按 owner / org 自动发现仓库 */\nexport const discoverReposSchema = z.object({\n owner: z.array(z.string()).min(1).describe('owner / org 列表(分别发现后合并)'),\n topics: z.array(z.string()).optional().describe('topic 白名单(AND 语义:必须包含全部指定 topics)'),\n include: z.array(z.string()).optional().describe('仓库白名单 glob(如 owner/*、owner/pkg-*)'),\n exclude: z.array(z.string()).optional().describe('仓库黑名单 glob(与 include 冲突时胜出)'),\n probe_dependabot: z.boolean().optional().describe('探测 .github/dependabot.yml 存在性(默认 true;会额外触达 contents API)'),\n max_repos: z.number().int().min(0).optional().describe('发现规模上限:最多保留的仓库数(默认 100;0 表示不限制)'),\n})\n\n/** `cleanup_branches` 输入:清理已合并/已关闭的 dependfix 分支 */\nexport const cleanupBranchesSchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n dry_run: z.boolean().optional().describe('仅列出待清理分支,不执行删除(默认 false)'),\n})\n\n/** `history` 输入:查询仓库历史运行摘要 */\nexport const historySchema = z.object({\n repo: z.string().describe('目标仓库,格式 owner/repo'),\n})\n\n/** `pnpm_audit` 输入:本地 pnpm audit 回退数据源 */\nexport const pnpmAuditSchema = z.object({\n /** 本地仓库工作目录(已 clone,包含 pnpm-lock.yaml) */\n workDir: z.string().describe('本地仓库工作目录(已 clone,包含 pnpm-lock.yaml)'),\n /** 仓库标识(owner/repo 或 local 兜底;与 CLI --repo 同源语义) */\n repository: z.string().describe('仓库标识(owner/repo 或 local 兜底;用于归一化 NormalizedSecurityAlert.repository 字段)'),\n})\n","// 统一 tool 错误模板(复用收口):\n// - requireToken:GITHUB_TOKEN 检查。返回 token 字符串或错误对象;\n// 调用方用 `typeof token !== 'string'` 守卫收窄(项目未开 strictNullChecks,\n// truthiness 判别收窄不生效,typeof 守卫是兼容形式)。\n// - toToolError:任意错误 → ok:false(统一 Error.message / String 转换)\n// 各 tool 的返回联合类型均含 `{ ok: false, error: string }` 分支,可安全返回。\n\nexport type ToolError = { ok: false, error: string }\n\nexport const requireToken = (): string | ToolError => {\n const token = process.env.GITHUB_TOKEN\n if (!token) {\n return { ok: false, error: 'GITHUB_TOKEN not set(请配置环境变量)' }\n }\n return token\n}\n\nexport const toToolError = (error: unknown): ToolError => ({\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n})\n","import { createGitHubClient, fetchCodeScanningAlerts, fetchDependabotAlerts, type FetchDependabotAlertsParams } from '@dependfix/engine'\nimport { fromPat } from '@dependfix/engine/auth'\nimport { filterAlerts, isValidRepoIdentifier, type SeverityThreshold } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `fetch_alerts` 返回结构 */\nexport type FetchAlertsResult =\n | {\n ok: true\n count: number\n alerts: Array<{\n id: number\n severity: string\n packageName: string\n manifestPath: string\n recommendedVersion: string\n fixable: boolean\n htmlUrl: string\n summary: string\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `fetch_alerts`:拉取指定仓库的 Dependabot 安全告警(只读)。\n * 凭据从 GITHUB_TOKEN 环境变量读取(mcp-server.md §4.3)。\n */\nexport const fetchAlerts = async (input: { repo: string, severity: SeverityThreshold, code_scanning?: boolean }): Promise<FetchAlertsResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n\n // repo 格式校验复用 core(与 CLI 同源,避免自研校验漂移)\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n\n try {\n const client = createGitHubClient({ auth: fromPat(token) })\n const params: FetchDependabotAlertsParams = {\n owner,\n repo,\n state: 'open',\n }\n\n // Dependabot + 可选 Code Scanning 并行(复用 cli fetcher;与 CLI --code-scanning 同源)。\n // 注意:CS 拉取失败(权限/网络)会使整个 tool 失败——与 CLI 现状一致\n // (per-source 错误隔离为 backlog 登记项,暂缓),结果不静默丢弃。\n const codeScanningEnabled = input.code_scanning ?? false\n const [dependabotAlerts, codeScanningAlerts] = await Promise.all([\n fetchDependabotAlerts(client, params),\n codeScanningEnabled\n ? fetchCodeScanningAlerts(client, { owner, repo })\n : Promise.resolve([] as Awaited<ReturnType<typeof fetchDependabotAlerts>>),\n ])\n const alerts = [...dependabotAlerts, ...codeScanningAlerts]\n\n // 严重级别过滤复用 core 阈值语义(与 CLI 一致:high 保留 critical + high;\n // all 不过滤;Code Scanning 源 unknown 恒透传)。不使用相等匹配,避免 high 漏掉 critical。\n const { filtered } = filterAlerts(alerts, { severityThreshold: input.severity })\n\n return {\n ok: true,\n count: filtered.length,\n alerts: filtered.map((a) => ({\n id: a.id,\n severity: a.severity,\n packageName: a.packageName,\n manifestPath: a.manifestPath,\n recommendedVersion: a.recommendedVersion,\n fixable: a.fixable,\n htmlUrl: a.htmlUrl,\n summary: a.summary,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { readFileSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { toToolError } from './errors'\n\n/** `get_last_report` 返回结构 */\nexport type GetLastReportResult =\n | { ok: true, file: string, report: unknown }\n | { ok: false, error: string }\n\n/**\n * `get_last_report`:读取最近一次 JSON 报告(只读)。\n * 报告目录默认为 `./dependfix-reports`(可用 `DEPENDFIX_MCP_REPORT_DIR` 覆盖)。\n */\nexport const getLastReport = async (): Promise<GetLastReportResult> => {\n const reportDir = process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports'\n try {\n const files = readdirSync(reportDir)\n .filter((f) => f.endsWith('.json'))\n .sort()\n if (files.length === 0) {\n return { ok: false, error: `未找到报告(目录 ${reportDir} 为空)` }\n }\n const latest = files[files.length - 1]\n const content = readFileSync(join(reportDir, latest), 'utf-8')\n return {\n ok: true,\n file: latest,\n report: JSON.parse(content),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { DependfixApp, DEFAULT_RUNTIME_CONFIG, type RuntimeConfig } from '@dependfix/engine'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `run_scan` 返回结构(M28.4 RunResult 对齐 + 向后兼容)\n *\n * 字段对齐 `RunResult` 接口(packages/core/src/report/types.ts):\n * - 8 字段保留(向后兼容——老客户端忽略未知字段):\n * ok / exitCode / runId / summary / repositories / errors\n * - 5 字段新增(M28.4 RunResult 对齐):\n * startedAt / finishedAt / config / alerts / actions\n *\n * 2 字段可选(按 --ai 开启 + 供应链信号决定;不在 RunScanResult 必填):\n * aiUsage? / supplyChainWarnings?(暂不映射——避免 RunScanResult 类型膨胀)\n */\nexport type RunScanResult =\n | {\n ok: true\n exitCode: number\n runId: string\n summary: import('@dependfix/core').RunSummary\n repositories: Array<Record<string, unknown>>\n errors: Array<Record<string, unknown>>\n /** RunResult.startedAt:ISO 8601 字符串 */\n startedAt: string\n /** RunResult.finishedAt:ISO 8601 字符串 */\n finishedAt: string\n /** RunResult.config:本次运行配置快照(RuntimeConfig) */\n config: import('@dependfix/core').RunReportConfig\n /** RunResult.alerts:所有仓库合并归一化告警 */\n alerts: Array<import('@dependfix/core').NormalizedSecurityAlert>\n /** RunResult.actions:所有仓库合并的修复动作 */\n actions: Array<import('@dependfix/core').FixAction>\n }\n | { ok: false, error: string }\n\n/**\n * `run_scan`:对目标仓库执行 dependfix 扫描并修复。\n * 凭据从 GITHUB_TOKEN 环境变量读取;repo 为 GitHub 远程仓库(report-only 无需 clone)。\n */\nexport const runScan = async (input: {\n repo: string\n mode: 'report-only' | 'fix' | 'fix-and-pr'\n severity: string\n code_scanning?: boolean\n max_alerts?: number\n max_concurrency?: number\n dry_run?: boolean\n allow_major_upgrade?: boolean\n ai_enabled?: boolean\n ai_provider?: 'openai-compatible' | 'anthropic'\n ai_model?: string\n ai_trigger?: 'failure' | 'major' | 'both'\n}): Promise<RunScanResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n\n // repo 格式校验复用 core(与 CLI 同源)\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n\n // 展开 cli 默认配置(maxAlerts/maxConcurrency/maxRetries/maxBackoff/alertSource/ai 默认等\n // 与 CLI 单一事实源对齐,避免手写默认值漂移),仅覆盖 tool 参数可控制字段。\n const defaultAi = DEFAULT_RUNTIME_CONFIG.ai\n const config: RuntimeConfig = {\n ...DEFAULT_RUNTIME_CONFIG,\n mode: input.mode,\n severityThreshold: input.severity as 'critical' | 'high' | 'medium' | 'all',\n repositories: [`${owner}/${repo}`],\n // dry-run 显式参数优先,缺省按 mode 推断(report-only 即只读)\n dryRun: input.dry_run ?? (input.mode === 'report-only'),\n createPullRequest: input.mode === 'fix-and-pr',\n commit: input.mode === 'fix',\n cleanupBranches: false,\n cleanupBranchesAuto: false,\n githubToken: token,\n codeScanningEnabled: input.code_scanning ?? DEFAULT_RUNTIME_CONFIG.codeScanningEnabled,\n allowMajorUpgrade: input.allow_major_upgrade ?? DEFAULT_RUNTIME_CONFIG.allowMajorUpgrade,\n maxAlertsPerRepository: input.max_alerts ?? DEFAULT_RUNTIME_CONFIG.maxAlertsPerRepository,\n maxConcurrency: input.max_concurrency ?? DEFAULT_RUNTIME_CONFIG.maxConcurrency,\n // AI 研判:展开 cli 默认(provider/model/baseUrl/trigger 与 CLI 对齐),\n // 仅覆盖开关与显式参数;apiKey 只从 env 读取(DEPENDFIX_AI_API_KEY),\n // 禁止经 tool 参数传入(防客户端日志泄露)。\n // defaultAi 收窄:默认配置缺失时视为未开启(与类型声明一致,运行时恒有值)\n ai: input.ai_enabled && defaultAi\n ? {\n ...defaultAi,\n enabled: true,\n provider: input.ai_provider ?? defaultAi.provider,\n model: input.ai_model ?? defaultAi.model,\n trigger: input.ai_trigger ?? defaultAi.trigger,\n apiKey: process.env.DEPENDFIX_AI_API_KEY,\n }\n : undefined,\n }\n\n try {\n const app = new DependfixApp({\n config,\n workDir: process.cwd(),\n reportOutputDir: process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports',\n })\n const { result, exitCode } = await app.run()\n\n return {\n ok: true,\n exitCode,\n runId: result.runId,\n summary: result.summary,\n repositories: result.repositories.map((r) => ({\n repository: r.repository,\n alertsCount: r.alertsCount,\n fixable: r.fixable,\n fixed: r.fixed,\n failed: r.failed,\n lockfileRepaired: r.lockfileRepaired,\n verificationPassed: r.verificationPassed ?? undefined,\n durationMs: r.durationMs,\n })),\n errors: result.errors.map((e) => ({\n repository: e.repository,\n stage: e.stage,\n category: e.category,\n message: e.message,\n })),\n startedAt: result.startedAt,\n finishedAt: result.finishedAt,\n config: result.config,\n alerts: result.alerts,\n actions: result.actions,\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { overrideTransitiveDependency, repairLockfile, upgradeDependency, type LockfileDiff } from '@dependfix/engine'\nimport { toToolError } from './errors'\n\n/** `fix_dependency` 返回结构(按 fixType 判别) */\nexport type FixDependencyResult =\n | {\n ok: true\n fixType: 'override' | 'direct'\n packageName: string\n fromVersion: string\n toVersion: string\n isMajor: boolean\n warning?: string\n }\n | {\n ok: true\n fixType: 'lockfile'\n strategy?: string\n diff?: LockfileDiff | null\n lockfileVersion?: string\n lockfileVersionChanged?: boolean\n }\n | {\n ok: false\n fixType: 'override' | 'direct' | 'lockfile'\n packageName?: string\n fromVersion?: string\n toVersion?: string\n isMajor?: boolean\n error: string\n }\n\n/**\n * `fix_dependency`:修复单个依赖或 lockfile(按 `fix_type` 分发,复用 cli fixers):\n * - `override`(默认):间接依赖 → `overrideTransitiveDependency`(写入 pnpm overrides)\n * - `direct`:直接依赖 → `upgradeDependency`(改写 manifest + `pnpm install`,失败回滚)\n * - `lockfile`:frozen-lockfile 漂移 → `repairLockfile`(策略链修复,全部失败回滚)\n * 均需本地已 clone 的仓库目录(workDir)。\n */\nexport const fixDependency = async (input: {\n workDir: string\n fix_type?: 'override' | 'direct' | 'lockfile'\n packageName?: string\n targetVersion?: string\n}): Promise<FixDependencyResult> => {\n const fixType = input.fix_type ?? 'override'\n try {\n switch (fixType) {\n case 'lockfile': {\n const result = repairLockfile({ workDir: input.workDir })\n if (result.success) {\n return {\n ok: true,\n fixType: 'lockfile',\n strategy: result.strategy,\n diff: result.diff ?? null,\n lockfileVersion: result.lockfileVersion,\n lockfileVersionChanged: result.lockfileVersionChanged,\n }\n }\n return {\n ok: false,\n fixType: 'lockfile',\n error: result.failureDetail ?? 'lockfile repair failed',\n }\n }\n case 'direct': {\n if (!input.packageName || !input.targetVersion) {\n return { ok: false, fixType: 'direct', error: 'packageName 与 targetVersion 必填(fix_type=direct)' }\n }\n const result = await upgradeDependency({\n packageName: input.packageName,\n targetVersion: input.targetVersion,\n workDir: input.workDir,\n })\n if (result.success) {\n return {\n ok: true,\n fixType: 'direct',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n warning: result.warning,\n }\n }\n return {\n ok: false,\n fixType: 'direct',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n error: result.error ?? 'upgrade failed',\n }\n }\n case 'override': {\n if (!input.packageName || !input.targetVersion) {\n return { ok: false, fixType: 'override', error: 'packageName 与 targetVersion 必填(fix_type=override)' }\n }\n const result = await overrideTransitiveDependency({\n packageName: input.packageName,\n targetVersion: input.targetVersion,\n workDir: input.workDir,\n })\n if (result.success) {\n return {\n ok: true,\n fixType: 'override',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n warning: result.warning,\n }\n }\n return {\n ok: false,\n fixType: 'override',\n packageName: result.packageName,\n fromVersion: result.fromVersion,\n toVersion: result.toVersion,\n isMajor: result.isMajor,\n error: result.error ?? 'override failed',\n }\n }\n }\n } catch (error) {\n return {\n ok: false,\n fixType,\n error: toToolError(error).error,\n }\n }\n}\n","import { createGitHubClient, discoverRepositories, type RepoPolicy } from '@dependfix/engine'\nimport { fromPat } from '@dependfix/engine/auth'\nimport { requireToken, toToolError } from './errors'\n\n/** `discover_repos` 返回结构 */\nexport type DiscoverReposResult =\n | {\n ok: true\n count: number\n repositories: Array<{\n fullName: string\n defaultBranch: string\n topics: string[]\n hasDependabotConfig: boolean\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `discover_repos`:按 owner / org 自动发现仓库(复用 cli discoverRepositories,\n * 与 CLI `--owner` / `--repo-topics` / `--repo-include` / `--repo-exclude` 同源过滤链)。\n * 凭据从 GITHUB_TOKEN 环境变量读取。\n */\nexport const discoverRepos = async (input: {\n owner: string[]\n topics?: string[]\n include?: string[]\n exclude?: string[]\n probe_dependabot?: boolean\n max_repos?: number\n}): Promise<DiscoverReposResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n if (input.owner.length === 0) {\n return { ok: false, error: 'owner 必填(至少一个 owner/org)' }\n }\n\n try {\n const client = createGitHubClient({ auth: fromPat(token) })\n const policy: RepoPolicy = {\n include: input.include && input.include.length > 0 ? input.include : undefined,\n exclude: input.exclude && input.exclude.length > 0 ? input.exclude : undefined,\n }\n const repos = await discoverRepositories({\n client,\n owners: input.owner,\n topics: input.topics,\n policy,\n probeDependabot: input.probe_dependabot ?? true,\n maxRepos: input.max_repos,\n })\n return {\n ok: true,\n count: repos.length,\n repositories: repos.map((r) => ({\n fullName: r.fullName,\n defaultBranch: r.defaultBranch,\n topics: r.topics,\n hasDependabotConfig: r.hasDependabotConfig,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { createGitHubClient, deleteRemoteBranch, getBranchPrStatus, listDependfixBranches } from '@dependfix/engine'\nimport { fromPat } from '@dependfix/engine/auth'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { requireToken, toToolError } from './errors'\n\n/** `cleanup_branches` 返回结构 */\nexport type CleanupBranchesResult =\n | {\n ok: true\n dryRun: boolean\n scanned: string[]\n /** 已删除分支(dry_run 时为空) */\n deleted: string[]\n /** 保留分支(open PR / 无 PR 未关闭) */\n kept: string[]\n /** 删除失败分支(best-effort,不中断) */\n failed: string[]\n }\n | { ok: false, error: string }\n\n/**\n * `cleanup_branches`:清理已合并/已关闭的 dependfix 分支(非交互)。\n *\n * 复用 cli pr-creator 底层函数自编排,语义对齐 `autoCleanupMergedBranches`:\n * - 只处理 `dependfix/` 前缀分支(listDependfixBranches 已过滤)\n * - 删除候选 = 已合并(merged)+ 已关闭未合并(orphaned);绝不触碰 open PR 分支\n * - 单分支删除失败记录到 `failed`,不中断其余删除(best-effort)\n * - dry_run 仅列清单(deleted/failed 为空)\n *\n * 刻意不走 DependfixApp 的 cleanup-branches mode:`runBranchCleanupForRepo`\n * 含交互式确认(非 TTY 默认拒绝),MCP stdio 下不可用。\n */\nexport const cleanupBranches = async (input: { repo: string, dry_run?: boolean }): Promise<CleanupBranchesResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n const [owner, repo] = input.repo.split('/')\n const dryRun = input.dry_run ?? false\n\n try {\n const client = createGitHubClient({ auth: fromPat(token) })\n const branches = await listDependfixBranches(client, owner, repo)\n const statuses = await Promise.all(\n branches.map((branch) => getBranchPrStatus(client, owner, repo, branch)),\n )\n\n const merged = statuses.filter((s) => s.merged)\n const orphaned = statuses.filter((s) => s.closed && !s.merged)\n const kept = statuses.filter((s) => !s.closed)\n const candidates = [...merged, ...orphaned]\n\n if (dryRun) {\n return {\n ok: true,\n dryRun: true,\n scanned: branches,\n deleted: [],\n kept: kept.map((s) => s.branch),\n failed: [],\n }\n }\n\n const deleted: string[] = []\n const failed: string[] = []\n for (const s of candidates) {\n try {\n await deleteRemoteBranch(client, owner, repo, s.branch)\n deleted.push(s.branch)\n } catch {\n // 单分支删除失败(分支保护/不存在)不中断其余删除,best-effort\n failed.push(s.branch)\n }\n }\n\n return {\n ok: true,\n dryRun: false,\n scanned: branches,\n deleted,\n kept: kept.map((s) => s.branch),\n failed,\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { queryRepoHistory } from '@dependfix/engine'\nimport { isValidRepoIdentifier } from '@dependfix/core'\nimport { toToolError } from './errors'\n\n/** `history` 返回结构 */\nexport type HistoryResult =\n | {\n ok: true\n repo: string\n runs: Array<{\n runId: string\n startedAt: string\n durationMs: number\n repositories: string[]\n summary: Record<string, unknown>\n repoStats: Array<Record<string, unknown>>\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `history`:查询某仓库的历史运行摘要(倒序时间:最新在前)。\n * 复用 cli `queryRepoHistory`(读 dependfix-reports/index.json 聚合索引,\n * 与 `get_last_report` 的单文件语义不同);报告目录可用 `DEPENDFIX_MCP_REPORT_DIR` 覆盖。\n */\nexport const getHistory = async (input: { repo: string }): Promise<HistoryResult> => {\n if (!isValidRepoIdentifier(input.repo)) {\n return { ok: false, error: `repo 格式非法(预期 owner/repo,收到 ${input.repo})` }\n }\n try {\n const reportDir = process.env.DEPENDFIX_MCP_REPORT_DIR ?? './dependfix-reports'\n const entries = queryRepoHistory(input.repo, reportDir)\n return {\n ok: true,\n repo: input.repo,\n runs: entries.map((e) => ({\n runId: e.runId,\n startedAt: e.startedAt,\n durationMs: e.durationMs,\n repositories: e.repositories,\n // 桥接:RunSummary/ArchiveRepoStats 无索引签名,显式转 unknown 再收窄\n summary: e.summary as unknown as Record<string, unknown>,\n repoStats: e.repoStats as unknown as Array<Record<string, unknown>>,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { fetchPnpmAuditAlerts, type FetchPnpmAuditAlertsParams } from '@dependfix/engine'\nimport { requireToken, toToolError } from './errors'\n\n/**\n * `pnpm_audit` 返回结构\n *\n * 复用 `fetchAlerts` 的子集结构(id / severity / packageName / manifestPath /\n * recommendedVersion / fixable / htmlUrl / summary),让客户端能以一致形式\n * 消费 Dependabot / Code Scanning / pnpm-audit 三源告警。\n */\nexport type PnpmAuditResult =\n | {\n ok: true\n /** pnpm-audit 归一化后的告警数 */\n count: number\n /** 工作目录(与 input.workDir 一致;方便客户端无需记录入参) */\n workDir: string\n /** 注入的仓库标识(owner/repo 或 local 兜底) */\n repository: string\n alerts: Array<{\n id: number\n severity: string\n packageName: string\n manifestPath: string\n recommendedVersion: string\n fixable: boolean\n htmlUrl: string\n summary: string\n }>\n }\n | { ok: false, error: string }\n\n/**\n * `pnpm_audit`:本地 pnpm audit 回退数据源(无 GitHub token 或 403 场景)。\n *\n * 设计意图(详见 docs/design/pnpm-audit-fallback.md):\n * - 显式 `--alerts-source pnpm-audit` 触发(CLI)或显式调用 `pnpm_audit` tool(MCP)触发\n * - 复用 `fetchPnpmAuditAlerts` 解析 + 归一化逻辑(与 CLI 同源)\n * - audit 自身失败(无 lockfile / pnpm 不可用 / JSON 解析失败)→ 硬失败,绝不静默空跑\n *\n * 凭据:pnpm-audit 不需要 GitHub token(本地命令);但保留 `requireToken()`\n * 调用与其它 tool 一致(保持 pattern 统一,未来如需 pnpm registry token 可扩展)。\n *\n * @param input.workDir 本地仓库工作目录(包含 pnpm-lock.yaml)\n * @param input.repository 仓库标识(owner/repo 或 local 兜底;与 CLI --repo 同源语义)\n */\nexport const pnpmAudit = async (input: FetchPnpmAuditAlertsParams): Promise<PnpmAuditResult> => {\n const token = requireToken()\n if (typeof token !== 'string') {\n return token\n }\n\n try {\n const normalizedAlerts = await fetchPnpmAuditAlerts(input)\n return {\n ok: true,\n count: normalizedAlerts.length,\n workDir: input.workDir,\n repository: input.repository,\n alerts: normalizedAlerts.map((a) => ({\n id: a.id,\n severity: a.severity,\n packageName: a.packageName,\n manifestPath: a.manifestPath,\n recommendedVersion: a.recommendedVersion,\n fixable: a.fixable,\n htmlUrl: a.htmlUrl,\n summary: a.summary,\n })),\n }\n } catch (error) {\n return toToolError(error)\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { fetchAlertsSchema, getLastReportSchema, runScanSchema, fixDependencySchema, discoverReposSchema, cleanupBranchesSchema, historySchema, pnpmAuditSchema } from './tools/schemas'\nimport { fetchAlerts } from './tools/fetch-alerts'\nimport { getLastReport } from './tools/get-last-report'\nimport { runScan } from './tools/run-scan'\nimport { fixDependency } from './tools/fix-dependency'\nimport { discoverRepos } from './tools/discover-repos'\nimport { cleanupBranches } from './tools/cleanup-branches'\nimport { getHistory } from './tools/history'\nimport { pnpmAudit } from './tools/pnpm-audit.tool'\n\n/**\n * dependfix MCP Server:向 AI 助手暴露 7 个 tool。\n * - fetch_alerts(只读):拉取 Dependabot / Code Scanning 告警\n * - get_last_report(只读):读取最近 JSON 报告\n * - run_scan(写入):执行扫描/修复(默认 report-only;支持 AI 研判透传)\n * - fix_dependency(写入):修复单个依赖(override / direct / lockfile)\n * - discover_repos(只读):按 owner / org 自动发现仓库\n * - cleanup_branches(写入):清理已合并/已关闭的 dependfix 分支(非交互)\n * - history(只读):查询仓库历史运行摘要\n * 凭据从 GITHUB_TOKEN 环境变量读取(mcp-server.md §4.3)。\n */\nexport const createMcpServer = (): McpServer => {\n const server = new McpServer({\n name: 'dependfix',\n version: '0.1.0',\n })\n\n server.registerTool(\n 'fetch_alerts',\n {\n description: '拉取指定仓库的 Dependabot 安全告警(可选并行 Code Scanning,只读)',\n inputSchema: fetchAlertsSchema,\n },\n async (input) => {\n const result = await fetchAlerts(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'get_last_report',\n {\n description: '读取最近一次 dependfix JSON 报告(只读)',\n inputSchema: getLastReportSchema,\n },\n async () => {\n const result = await getLastReport()\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'run_scan',\n {\n description: '对目标仓库执行 dependfix 扫描并修复(默认 report-only;支持 code-scanning / AI 研判等参数)',\n inputSchema: runScanSchema,\n },\n async (input) => {\n const result = await runScan(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'fix_dependency',\n {\n description: '修复单个依赖或 lockfile(override / direct / lockfile;需要本地已 clone 仓库目录)',\n inputSchema: fixDependencySchema,\n },\n async (input) => {\n const result = await fixDependency(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'discover_repos',\n {\n description: '按 owner / org 自动发现仓库(支持 topics / include / exclude 名单策略,只读)',\n inputSchema: discoverReposSchema,\n },\n async (input) => {\n const result = await discoverRepos(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'cleanup_branches',\n {\n description: '清理已合并/已关闭的 dependfix 分支(非交互;只删 dependfix/ 前缀且 merged/closed,绝不触碰 open PR 分支)',\n inputSchema: cleanupBranchesSchema,\n },\n async (input) => {\n const result = await cleanupBranches(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'history',\n {\n description: '查询指定仓库的历史运行摘要(倒序时间,只读)',\n inputSchema: historySchema,\n },\n async (input) => {\n const result = await getHistory(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n server.registerTool(\n 'pnpm_audit',\n {\n description: '本地 pnpm audit 回退数据源(无需 GitHub token;audit 失败硬返回错误)',\n inputSchema: pnpmAuditSchema,\n },\n async (input) => {\n const result = await pnpmAudit(input)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n },\n )\n\n return server\n}\n\n/** 连接 stdio 传输(bin 入口调用) */\nexport const connectStdio = async (): Promise<void> => {\n const server = createMcpServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dependfix/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "dependfix MCP 服务:向 AI 助手暴露扫描/修复能力(stdio)",
|
|
5
5
|
"author": "CaoMeiYouRen",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
45
|
-
"zod": "^4.
|
|
46
|
-
"@dependfix/
|
|
47
|
-
"@dependfix/
|
|
45
|
+
"zod": "^4.6.1",
|
|
46
|
+
"@dependfix/core": "0.5.0",
|
|
47
|
+
"@dependfix/engine": "0.4.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"nock": "^14.0.17",
|
|
51
51
|
"rimraf": "^6.1.3",
|
|
52
|
-
"tsdown": "^0.
|
|
52
|
+
"tsdown": "^0.23.0",
|
|
53
53
|
"typescript": "^6.0.3"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|