sonarqube-issue-mcp 0.0.1

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.
@@ -0,0 +1,472 @@
1
+ import { SonarQubeMcpError } from "../errors.js";
2
+ import { buildHotspotBrowseUrl, buildIssueBrowseUrl, buildProjectBrowseUrl, parseProjectUrl } from "../project-ref.js";
3
+ import { SonarQubeClient } from "./client.js";
4
+ /**
5
+ * issue 严重度排序权重,值越大越靠前。
6
+ *
7
+ * @remarks
8
+ * 这里兼容旧 severity 与新版 impacts severity 的常见取值。
9
+ */
10
+ const ISSUE_SEVERITY_RANK = {
11
+ BLOCKER: 5,
12
+ CRITICAL: 4,
13
+ HIGH: 4,
14
+ MAJOR: 3,
15
+ MEDIUM: 3,
16
+ MINOR: 2,
17
+ LOW: 2,
18
+ INFO: 1
19
+ };
20
+ /**
21
+ * hotspot 风险概率排序权重,值越大越靠前。
22
+ *
23
+ * @remarks
24
+ * 与 SonarQube `vulnerabilityProbability` 字段保持一致。
25
+ */
26
+ const HOTSPOT_PROBABILITY_RANK = {
27
+ HIGH: 3,
28
+ MEDIUM: 2,
29
+ LOW: 1
30
+ };
31
+ /**
32
+ * SonarQube 业务服务层。
33
+ *
34
+ * @remarks
35
+ * 这一层负责把原始 SonarQube API 数据重新组装为 MCP 对外返回结构,
36
+ * 包括查询口径、规则补全、排序规则、详情标准化和项目归属校验。
37
+ */
38
+ export class SonarQubeFindingService {
39
+ config;
40
+ constructor(config) {
41
+ this.config = config;
42
+ }
43
+ /**
44
+ * 获取项目级三类问题汇总。
45
+ *
46
+ * @param projectUrl - SonarQube 项目 dashboard URL。
47
+ * @param detailLevel - 返回详情级别,默认 `standard`。
48
+ * @returns 已标准化并排序的项目问题汇总。
49
+ *
50
+ * @remarks
51
+ * 这里会并行完成版本检查、项目检查、issue 列表与 hotspot 列表拉取,
52
+ * 然后统一做规则补充和结果标准化。
53
+ *
54
+ * @throws {SonarQubeMcpError} 当 URL 非法、项目不可访问或任一 API 请求失败时抛出。
55
+ */
56
+ async getProjectFindings(projectUrl, detailLevel = "standard") {
57
+ const projectRef = parseProjectUrl(projectUrl);
58
+ const client = this.createClient(projectRef);
59
+ const [serverVersion, projectComponent, security, reliability, hotspots] = await Promise.all([
60
+ client.getServerVersion(),
61
+ client.getProjectComponent(),
62
+ client.searchOpenIssues("VULNERABILITY"),
63
+ client.searchOpenIssues("BUG"),
64
+ client.searchOpenHotspots()
65
+ ]);
66
+ // issue 与 hotspot 的规则需要单独补齐规则描述,先做去重再批量拉取。
67
+ const allIssueRuleKeys = unique([
68
+ ...security.issues.map((issue) => issue.rule),
69
+ ...reliability.issues.map((issue) => issue.rule)
70
+ ]);
71
+ const hotspotRuleKeys = unique(hotspots.map((hotspot) => hotspot.ruleKey));
72
+ const hotspotDetails = await mapWithConcurrency(hotspots, 8, async (hotspot) => client.getHotspotDetail(hotspot.key));
73
+ const [issueRules, hotspotRules] = await Promise.all([
74
+ this.getRulesByKey(client, allIssueRuleKeys),
75
+ this.getRulesByKey(client, hotspotRuleKeys)
76
+ ]);
77
+ const project = this.buildProjectInfo(projectRef, projectComponent.name, projectComponent.qualifier, serverVersion);
78
+ const securityIssues = security.issues
79
+ .map((issue) => this.normalizeIssue(issue, issueRules.get(issue.rule) ?? security.embeddedRules.get(issue.rule) ?? null, projectRef, "security", detailLevel))
80
+ .sort(compareIssues);
81
+ const reliabilityIssues = reliability.issues
82
+ .map((issue) => this.normalizeIssue(issue, issueRules.get(issue.rule) ?? reliability.embeddedRules.get(issue.rule) ?? null, projectRef, "reliability", detailLevel))
83
+ .sort(compareIssues);
84
+ const hotspotByKey = new Map(hotspotDetails.map((item) => [item.key, item]));
85
+ const securityHotspots = hotspots
86
+ .map((hotspot) => this.normalizeHotspot(hotspotByKey.get(hotspot.key) ?? null, hotspot, hotspotRules.get(hotspot.ruleKey) ?? null, projectRef, detailLevel))
87
+ .sort(compareHotspots);
88
+ return {
89
+ project,
90
+ summary: {
91
+ securityIssueCount: securityIssues.length,
92
+ reliabilityIssueCount: reliabilityIssues.length,
93
+ securityHotspotCount: securityHotspots.length,
94
+ totalFindings: securityIssues.length + reliabilityIssues.length + securityHotspots.length,
95
+ detailLevel
96
+ },
97
+ securityIssues,
98
+ reliabilityIssues,
99
+ securityHotspots
100
+ };
101
+ }
102
+ /**
103
+ * 获取单条问题详情。
104
+ *
105
+ * @param projectUrl - SonarQube 项目 dashboard URL。
106
+ * @param kind - 详情类型,`issue` 或 `hotspot`。
107
+ * @param key - SonarQube 侧的问题 key。
108
+ * @returns 单条问题的标准化详情。
109
+ *
110
+ * @remarks
111
+ * 详情接口会再次校验问题是否属于当前项目,避免误传别的项目 key 时串数据。
112
+ *
113
+ * @throws {SonarQubeMcpError}
114
+ * 当项目不匹配、问题类型不在支持范围内或底层请求失败时抛出。
115
+ */
116
+ async getFindingDetail(projectUrl, kind, key) {
117
+ const projectRef = parseProjectUrl(projectUrl);
118
+ const client = this.createClient(projectRef);
119
+ const [serverVersion, projectComponent] = await Promise.all([
120
+ client.getServerVersion(),
121
+ client.getProjectComponent()
122
+ ]);
123
+ const project = this.buildProjectInfo(projectRef, projectComponent.name, projectComponent.qualifier, serverVersion);
124
+ if (kind === "issue") {
125
+ const { issue, embeddedRule } = await client.getIssueByKey(key);
126
+ const issueProjectKey = issue.project ?? deriveProjectKey(issue.component);
127
+ if (issueProjectKey !== projectRef.projectKey) {
128
+ throw new SonarQubeMcpError("VALIDATION", `issue ${key} 不属于项目 ${projectRef.projectKey},实际项目为 ${issueProjectKey ?? "unknown"}。`);
129
+ }
130
+ const [rule, changelog] = await Promise.all([
131
+ this.getRuleOrFallback(client, issue.rule, embeddedRule),
132
+ client.getIssueChangelog(key)
133
+ ]);
134
+ // 详情接口只允许 Security / Reliability 这两类 issue,
135
+ // 其他 SonarQube 类型不会通过这个 MCP 暴露。
136
+ const category = issue.type === "VULNERABILITY" ? "security" : issue.type === "BUG" ? "reliability" : null;
137
+ if (!category) {
138
+ throw new SonarQubeMcpError("VALIDATION", `issue ${key} 不是 Security 或 Reliability 范围内的问题,当前类型为 ${issue.type ?? "unknown"}。`);
139
+ }
140
+ return {
141
+ project,
142
+ summary: this.normalizeIssue(issue, rule, projectRef, category, "full"),
143
+ comments: issue.comments ?? [],
144
+ changelog,
145
+ flows: issue.flows ?? [],
146
+ raw: {
147
+ issue,
148
+ rule,
149
+ changelog
150
+ }
151
+ };
152
+ }
153
+ const hotspot = await client.getHotspotDetail(key);
154
+ if (hotspot.project.key !== projectRef.projectKey) {
155
+ throw new SonarQubeMcpError("VALIDATION", `hotspot ${key} 不属于项目 ${projectRef.projectKey},实际项目为 ${hotspot.project.key}。`);
156
+ }
157
+ const rule = await this.getRuleOrFallback(client, hotspot.rule.key, null);
158
+ return {
159
+ project,
160
+ summary: this.normalizeHotspot(hotspot, null, rule, projectRef, "full"),
161
+ comments: hotspot.comment ?? [],
162
+ changelog: hotspot.changelog ?? [],
163
+ flows: hotspot.flows ?? [],
164
+ raw: {
165
+ hotspot,
166
+ rule
167
+ }
168
+ };
169
+ }
170
+ /**
171
+ * 基于全局配置为当前项目创建隔离的 SonarQube client。
172
+ *
173
+ * @param projectRef - 当前项目上下文。
174
+ * @returns 已绑定项目上下文的 SonarQube client。
175
+ */
176
+ createClient(projectRef) {
177
+ return new SonarQubeClient(projectRef, {
178
+ token: this.config.sonarToken,
179
+ requestTimeoutMs: this.config.sonarRequestTimeoutMs,
180
+ retryCount: this.config.sonarRetryCount,
181
+ httpProxy: this.config.sonarHttpProxy
182
+ });
183
+ }
184
+ /**
185
+ * 组装对外暴露的项目基础信息。
186
+ *
187
+ * @param projectRef - 当前项目上下文。
188
+ * @param projectName - SonarQube 返回的项目名。
189
+ * @param qualifier - SonarQube 组件限定符。
190
+ * @param serverVersion - SonarQube 服务版本。
191
+ * @returns 对外返回的项目基础信息。
192
+ */
193
+ buildProjectInfo(projectRef, projectName, qualifier, serverVersion) {
194
+ return {
195
+ key: projectRef.projectKey,
196
+ name: projectName,
197
+ qualifier: qualifier ?? null,
198
+ branch: projectRef.branch,
199
+ pullRequest: projectRef.pullRequest,
200
+ dashboardUrl: projectRef.dashboardUrl,
201
+ browseUrl: buildProjectBrowseUrl(projectRef),
202
+ serverVersion
203
+ };
204
+ }
205
+ /**
206
+ * 批量获取并缓存规则详情。
207
+ *
208
+ * @param client - SonarQube client。
209
+ * @param keys - 待查询的规则 key 列表。
210
+ * @returns 规则 key 到规则详情的映射。
211
+ */
212
+ async getRulesByKey(client, keys) {
213
+ const rules = await mapWithConcurrency(keys, 8, async (key) => client.getRule(key));
214
+ return new Map(rules.map((rule) => [rule.key, rule]));
215
+ }
216
+ /**
217
+ * 规则详情补充失败时,尽量回落到列表接口内嵌的规则摘要。
218
+ *
219
+ * @param client - SonarQube client。
220
+ * @param ruleKey - 规则 key。
221
+ * @param embeddedRule - 列表接口中已拿到的规则摘要。
222
+ * @returns 完整规则详情或回退摘要。
223
+ */
224
+ async getRuleOrFallback(client, ruleKey, embeddedRule) {
225
+ try {
226
+ return await client.getRule(ruleKey);
227
+ }
228
+ catch {
229
+ return embeddedRule;
230
+ }
231
+ }
232
+ /**
233
+ * 将 SonarQube issue 标准化为统一 `FindingSummary`。
234
+ *
235
+ * @param issue - 原始 issue。
236
+ * @param rule - 已补全的规则信息。
237
+ * @param projectRef - 当前项目上下文。
238
+ * @param category - 目标分类。
239
+ * @param detailLevel - 返回详情级别。
240
+ * @returns 统一结构的问题摘要。
241
+ */
242
+ normalizeIssue(issue, rule, projectRef, category, detailLevel) {
243
+ return {
244
+ key: issue.key,
245
+ kind: "issue",
246
+ category,
247
+ ruleKey: issue.rule,
248
+ ruleName: rule?.name ?? null,
249
+ message: issue.message,
250
+ status: issue.status,
251
+ resolution: issue.resolution ?? null,
252
+ severity: this.pickIssueSeverity(issue),
253
+ vulnerabilityProbability: null,
254
+ impacts: issue.impacts ?? [],
255
+ cleanCodeAttribute: issue.cleanCodeAttribute ?? rule?.cleanCodeAttribute ?? null,
256
+ file: extractFilePath(issue.component, projectRef.projectKey),
257
+ line: issue.line ?? null,
258
+ textRange: issue.textRange ?? null,
259
+ author: issue.author ?? null,
260
+ assignee: issue.assignee ?? null,
261
+ tags: issue.tags ?? [],
262
+ createdAt: issue.creationDate,
263
+ updatedAt: issue.updateDate,
264
+ sonarUrl: buildIssueBrowseUrl(projectRef, issue.key),
265
+ ruleDescription: detailLevel === "full" ? pickRuleDescription(rule) : null,
266
+ riskDescription: null,
267
+ fixRecommendations: null,
268
+ vulnerabilityDescription: null
269
+ };
270
+ }
271
+ /**
272
+ * 将 hotspot 列表/详情合并后标准化为统一 `FindingSummary`。
273
+ *
274
+ * @param hotspotDetail - hotspot 详情;如果调用方尚未获取详情则可为 `null`。
275
+ * @param hotspotSearch - hotspot 列表摘要;如果调用方只持有详情则可为 `null`。
276
+ * @param rule - 已补全的规则信息。
277
+ * @param projectRef - 当前项目上下文。
278
+ * @param detailLevel - 返回详情级别。
279
+ * @returns 统一结构的热点摘要。
280
+ * @throws {SonarQubeMcpError} 当关键字段缺失时抛出。
281
+ */
282
+ normalizeHotspot(hotspotDetail, hotspotSearch, rule, projectRef, detailLevel) {
283
+ const key = hotspotDetail?.key ?? hotspotSearch?.key;
284
+ const ruleKey = hotspotDetail?.rule.key ?? hotspotSearch?.ruleKey;
285
+ const message = hotspotDetail?.message ?? hotspotSearch?.message;
286
+ const status = hotspotDetail?.status ?? hotspotSearch?.status;
287
+ const resolution = hotspotDetail?.resolution ?? hotspotSearch?.resolution ?? null;
288
+ const updatedAt = hotspotDetail?.updateDate ?? hotspotSearch?.updateDate;
289
+ const createdAt = hotspotDetail?.creationDate ?? hotspotSearch?.creationDate;
290
+ if (!key || !ruleKey || !message || !status || !updatedAt || !createdAt) {
291
+ throw new SonarQubeMcpError("REMOTE", "Security Hotspot 数据不完整,无法标准化返回。");
292
+ }
293
+ return {
294
+ key,
295
+ kind: "hotspot",
296
+ category: "security-hotspot",
297
+ ruleKey,
298
+ ruleName: hotspotDetail?.rule.name ?? rule?.name ?? null,
299
+ message,
300
+ status,
301
+ resolution,
302
+ severity: null,
303
+ vulnerabilityProbability: hotspotSearch?.vulnerabilityProbability ?? null,
304
+ impacts: [],
305
+ cleanCodeAttribute: rule?.cleanCodeAttribute ?? null,
306
+ file: hotspotDetail?.component.path ??
307
+ hotspotDetail?.component.longName ??
308
+ extractFilePath(hotspotSearch?.component ?? null, projectRef.projectKey),
309
+ line: hotspotDetail?.line ?? hotspotSearch?.line ?? null,
310
+ textRange: hotspotDetail?.textRange ?? null,
311
+ author: hotspotDetail?.author ?? hotspotSearch?.author ?? null,
312
+ assignee: hotspotDetail?.assignee ?? hotspotSearch?.assignee ?? null,
313
+ tags: rule?.tags ?? rule?.sysTags ?? [],
314
+ createdAt,
315
+ updatedAt,
316
+ sonarUrl: buildHotspotBrowseUrl(projectRef, key),
317
+ ruleDescription: detailLevel === "full" ? pickRuleDescription(rule) : null,
318
+ riskDescription: detailLevel === "full" ? hotspotDetail?.rule.riskDescription ?? null : null,
319
+ fixRecommendations: detailLevel === "full" ? hotspotDetail?.rule.fixRecommendations ?? null : null,
320
+ vulnerabilityDescription: detailLevel === "full" ? hotspotDetail?.rule.vulnerabilityDescription ?? null : null
321
+ };
322
+ }
323
+ /**
324
+ * issue 优先使用 impacts 推导的业务严重度,没有时再回退到旧 severity。
325
+ *
326
+ * @param issue - 原始 issue。
327
+ * @returns 统一后的严重度字符串。
328
+ */
329
+ pickIssueSeverity(issue) {
330
+ if (issue.impacts?.length) {
331
+ const [topImpact] = [...issue.impacts].sort((left, right) => severityRank(right.severity) - severityRank(left.severity));
332
+ if (topImpact) {
333
+ return topImpact.severity;
334
+ }
335
+ }
336
+ return issue.severity ?? null;
337
+ }
338
+ }
339
+ /**
340
+ * issue 列表排序:严重度优先,其次更新时间,再次 key。
341
+ *
342
+ * @param left - 左侧问题。
343
+ * @param right - 右侧问题。
344
+ * @returns 标准 `Array.prototype.sort` 比较结果。
345
+ */
346
+ function compareIssues(left, right) {
347
+ return (severityRank(right.severity) - severityRank(left.severity) ||
348
+ Date.parse(right.updatedAt) - Date.parse(left.updatedAt) ||
349
+ left.key.localeCompare(right.key));
350
+ }
351
+ /**
352
+ * hotspot 列表排序:风险概率优先,其次更新时间,再次 key。
353
+ *
354
+ * @param left - 左侧热点。
355
+ * @param right - 右侧热点。
356
+ * @returns 标准 `Array.prototype.sort` 比较结果。
357
+ */
358
+ function compareHotspots(left, right) {
359
+ return (hotspotRank(right.vulnerabilityProbability) - hotspotRank(left.vulnerabilityProbability) ||
360
+ Date.parse(right.updatedAt) - Date.parse(left.updatedAt) ||
361
+ left.key.localeCompare(right.key));
362
+ }
363
+ /**
364
+ * 将严重度映射为可排序的数值。
365
+ *
366
+ * @param severity - 严重度字符串。
367
+ * @returns 排序权重。
368
+ */
369
+ function severityRank(severity) {
370
+ if (!severity) {
371
+ return 0;
372
+ }
373
+ return ISSUE_SEVERITY_RANK[severity] ?? 0;
374
+ }
375
+ /**
376
+ * 将 hotspot 概率映射为可排序的数值。
377
+ *
378
+ * @param probability - 风险概率字符串。
379
+ * @returns 排序权重。
380
+ */
381
+ function hotspotRank(probability) {
382
+ if (!probability) {
383
+ return 0;
384
+ }
385
+ return HOTSPOT_PROBABILITY_RANK[probability] ?? 0;
386
+ }
387
+ /**
388
+ * 优先选择 Markdown 规则描述,缺失时回退到 HTML 描述。
389
+ *
390
+ * @param rule - 规则详情。
391
+ * @returns 最适合展示的规则描述文本。
392
+ */
393
+ function pickRuleDescription(rule) {
394
+ return rule?.mdDesc ?? rule?.htmlDesc ?? null;
395
+ }
396
+ /**
397
+ * 从 `projectKey:path/to/file` 形式的 component key 中抽出相对文件路径。
398
+ *
399
+ * @param component - SonarQube component key。
400
+ * @param projectKey - 当前项目 key。
401
+ * @returns 相对文件路径;如果无法解析则回退原值或 `null`。
402
+ */
403
+ function extractFilePath(component, projectKey) {
404
+ if (!component) {
405
+ return null;
406
+ }
407
+ const prefix = `${projectKey}:`;
408
+ if (component.startsWith(prefix)) {
409
+ return component.slice(prefix.length);
410
+ }
411
+ return component;
412
+ }
413
+ /**
414
+ * 从 component key 中推导项目 key,用于详情场景的归属校验。
415
+ *
416
+ * @param component - SonarQube component key。
417
+ * @returns 推导出的项目 key;如果为空则返回 `null`。
418
+ */
419
+ function deriveProjectKey(component) {
420
+ if (!component) {
421
+ return null;
422
+ }
423
+ const separatorIndex = component.indexOf(":");
424
+ if (separatorIndex === -1) {
425
+ return component;
426
+ }
427
+ return component.slice(0, separatorIndex);
428
+ }
429
+ /**
430
+ * 对字符串数组做去重,保留原始顺序。
431
+ *
432
+ * @param values - 原始字符串数组。
433
+ * @returns 去重后的数组。
434
+ */
435
+ function unique(values) {
436
+ return [...new Set(values)];
437
+ }
438
+ /**
439
+ * 受控并发 map。
440
+ *
441
+ * @param items - 待处理数组。
442
+ * @param concurrency - 最大并发数。
443
+ * @param mapper - 单项异步转换函数。
444
+ * @returns 与输入顺序一致的结果数组。
445
+ *
446
+ * @remarks
447
+ * 这里用于批量拉取 rule / hotspot 详情,避免一次性放大到过多并发请求。
448
+ */
449
+ async function mapWithConcurrency(items, concurrency, mapper) {
450
+ if (items.length === 0) {
451
+ return [];
452
+ }
453
+ const results = new Array(items.length);
454
+ let nextIndex = 0;
455
+ async function worker() {
456
+ while (nextIndex < items.length) {
457
+ // 通过共享索引把任务分配给多个 worker;这里不需要额外锁,
458
+ // 因为 JavaScript 事件循环下同一时刻只会有一个同步段修改 nextIndex。
459
+ const currentIndex = nextIndex;
460
+ nextIndex += 1;
461
+ const item = items[currentIndex];
462
+ if (item === undefined) {
463
+ continue;
464
+ }
465
+ results[currentIndex] = await mapper(item, currentIndex);
466
+ }
467
+ }
468
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
469
+ await Promise.all(workers);
470
+ return results;
471
+ }
472
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/sonarqube/service.ts"],"names":[],"mappings":"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"}