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,339 @@
1
+ import type { TextRange } from "../types.js";
2
+ /**
3
+ * SonarQube 常见分页响应。
4
+ *
5
+ * @remarks
6
+ * `pageIndex/pageSize/total` 的语义在 issue 与 hotspot 接口中保持一致。
7
+ */
8
+ export interface SonarPaging {
9
+ /** 当前页码,从 1 开始。 */
10
+ pageIndex: number;
11
+ /** 当前页大小。 */
12
+ pageSize: number;
13
+ /** 总记录数。 */
14
+ total: number;
15
+ }
16
+ /**
17
+ * SonarQube 中项目、文件、目录等组件的通用描述。
18
+ *
19
+ * @remarks
20
+ * 同一结构会出现在 `components/show`、issue 结果补充和 hotspot 详情里。
21
+ */
22
+ export interface SonarProjectComponent {
23
+ /** 组件 key。 */
24
+ key: string;
25
+ /** 组件短名。 */
26
+ name: string;
27
+ /** 组件长名。 */
28
+ longName?: string;
29
+ /** 组件限定符,例如 `TRK` 或 `FIL`。 */
30
+ qualifier?: string;
31
+ /** 相对路径;文件组件常见。 */
32
+ path?: string;
33
+ }
34
+ /**
35
+ * `/api/components/show` 返回结构。
36
+ *
37
+ * @remarks
38
+ * 这里只声明当前服务实际用到的字段。
39
+ */
40
+ export interface SonarComponentShowResponse {
41
+ /** 当前查询到的组件。 */
42
+ component: SonarProjectComponent;
43
+ }
44
+ /**
45
+ * SonarQube 新版 impacts 字段中的单条影响记录。
46
+ *
47
+ * @remarks
48
+ * 用于从新版质量模型中推导更贴近业务语义的严重级别。
49
+ */
50
+ export interface SonarImpact {
51
+ /** 软件质量维度。 */
52
+ softwareQuality: string;
53
+ /** 严重程度。 */
54
+ severity: string;
55
+ }
56
+ /**
57
+ * issue 评论的最小结构。
58
+ *
59
+ * @remarks
60
+ * 不追求完整覆盖,只保留当前服务有机会透传给上层的字段。
61
+ */
62
+ export interface SonarIssueComment {
63
+ /** 评论 key。 */
64
+ key?: string;
65
+ /** 评论作者登录名。 */
66
+ login?: string;
67
+ /** HTML 形式的评论内容。 */
68
+ htmlText?: string;
69
+ /** Markdown 形式的评论内容。 */
70
+ markdown?: string;
71
+ /** 当前用户是否可编辑。 */
72
+ updatable?: boolean;
73
+ /** 评论创建时间。 */
74
+ createdAt?: string;
75
+ }
76
+ /**
77
+ * `/api/issues/search` 中的单条 issue。
78
+ *
79
+ * @remarks
80
+ * 字段是按当前标准化需求裁剪过的,不是 Sonar 官方完整模型镜像。
81
+ */
82
+ export interface SonarIssue {
83
+ /** issue key。 */
84
+ key: string;
85
+ /** 规则 key。 */
86
+ rule: string;
87
+ /** 旧版严重度字段。 */
88
+ severity?: string;
89
+ /** SonarQube 原始 issue 类型。 */
90
+ type?: string;
91
+ /** 组件 key,通常包含项目 key 和相对路径。 */
92
+ component: string;
93
+ /** 项目 key。 */
94
+ project?: string;
95
+ /** 所在行号。 */
96
+ line?: number;
97
+ /** 文本范围。 */
98
+ textRange?: TextRange;
99
+ /** 数据流或执行流信息。 */
100
+ flows?: unknown[];
101
+ /** 处理结果。 */
102
+ resolution?: string;
103
+ /** 当前状态。 */
104
+ status: string;
105
+ /** 问题消息。 */
106
+ message: string;
107
+ /** 富文本消息格式化信息。 */
108
+ messageFormattings?: unknown[];
109
+ /** 估算工作量。 */
110
+ effort?: string;
111
+ /** 技术债务字段。 */
112
+ debt?: string;
113
+ /** 问题作者。 */
114
+ author?: string;
115
+ /** 问题负责人。 */
116
+ assignee?: string;
117
+ /** 标签列表。 */
118
+ tags?: string[];
119
+ /** 创建时间。 */
120
+ creationDate: string;
121
+ /** 最后更新时间。 */
122
+ updateDate: string;
123
+ /** 关闭时间。 */
124
+ closeDate?: string;
125
+ /** Clean Code 属性。 */
126
+ cleanCodeAttribute?: string;
127
+ /** 新版质量影响列表。 */
128
+ impacts?: SonarImpact[];
129
+ /** 评论列表。 */
130
+ comments?: SonarIssueComment[];
131
+ }
132
+ /**
133
+ * issue search / rule show 中共用的规则摘要结构。
134
+ *
135
+ * @remarks
136
+ * 列表接口只会返回摘要,详情接口会补齐 `mdDesc/htmlDesc` 等字段。
137
+ */
138
+ export interface SonarIssueRuleSummary {
139
+ /** 规则 key。 */
140
+ key: string;
141
+ /** 规则名称。 */
142
+ name: string;
143
+ /** 语言标识。 */
144
+ lang?: string;
145
+ /** 规则严重度。 */
146
+ severity?: string;
147
+ /** 规则类型。 */
148
+ type?: string;
149
+ /** HTML 规则描述。 */
150
+ htmlDesc?: string;
151
+ /** Markdown 规则描述。 */
152
+ mdDesc?: string;
153
+ /** Clean Code 属性。 */
154
+ cleanCodeAttribute?: string;
155
+ /** 标签。 */
156
+ tags?: string[];
157
+ /** 系统标签。 */
158
+ sysTags?: string[];
159
+ }
160
+ /**
161
+ * `/api/issues/search` 返回结构。
162
+ *
163
+ * @remarks
164
+ * `rules/components/users` 等补充块在不同 Sonar 版本中可能裁剪,但这里统一做可选处理。
165
+ */
166
+ export interface SonarIssueSearchResponse {
167
+ /** 分页信息。 */
168
+ paging: SonarPaging;
169
+ /** issue 列表。 */
170
+ issues: SonarIssue[];
171
+ /** 规则摘要列表。 */
172
+ rules?: SonarIssueRuleSummary[];
173
+ /** 组件补充信息。 */
174
+ components?: SonarProjectComponent[];
175
+ /** 用户补充信息。 */
176
+ users?: unknown[];
177
+ }
178
+ /**
179
+ * `/api/issues/changelog` 中的单次变更记录。
180
+ *
181
+ * @remarks
182
+ * 变更明细字段比较松散,因此保留为最小兼容结构。
183
+ */
184
+ export interface SonarIssueChangelogEntry {
185
+ /** 本次变更创建时间。 */
186
+ creationDate?: string;
187
+ /** 变更发起人。 */
188
+ user?: string;
189
+ /** 字段变更列表。 */
190
+ diffs?: Array<{
191
+ /** 变更字段名。 */
192
+ key?: string;
193
+ /** 变更后的值。 */
194
+ newValue?: string;
195
+ /** 变更前的值。 */
196
+ oldValue?: string;
197
+ }>;
198
+ }
199
+ /**
200
+ * `/api/issues/changelog` 返回结构。
201
+ *
202
+ * @remarks
203
+ * 当前只需要 `changelog` 数组本身。
204
+ */
205
+ export interface SonarIssueChangelogResponse {
206
+ /** 全量 changelog 列表。 */
207
+ changelog: SonarIssueChangelogEntry[];
208
+ }
209
+ /**
210
+ * `/api/rules/show` 返回结构。
211
+ *
212
+ * @remarks
213
+ * 规则详情接口是列表结果补全描述、修复建议等信息的主要来源。
214
+ */
215
+ export interface SonarRuleDetailsResponse {
216
+ /** 规则详情主体。 */
217
+ rule: SonarIssueRuleSummary & {
218
+ /** HTML 备注。 */
219
+ htmlNote?: string;
220
+ /** 备注作者。 */
221
+ noteLogin?: string;
222
+ /** 备注原始数据。 */
223
+ noteData?: string;
224
+ /** 技术债系数。 */
225
+ debtRemFnCoeff?: string;
226
+ /** 技术债函数类型。 */
227
+ debtRemFnType?: string;
228
+ };
229
+ /** 激活配置列表。 */
230
+ actives?: unknown[];
231
+ }
232
+ /**
233
+ * `/api/hotspots/search` 中的单条热点摘要。
234
+ *
235
+ * @remarks
236
+ * 列表接口不含完整规则说明,因此后续通常还会调用 `show` 补详情。
237
+ */
238
+ export interface SonarHotspotSearchItem {
239
+ /** hotspot key。 */
240
+ key: string;
241
+ /** 规则 key。 */
242
+ ruleKey: string;
243
+ /** 组件 key。 */
244
+ component: string;
245
+ /** 项目 key。 */
246
+ project?: string;
247
+ /** 所在行号。 */
248
+ line?: number;
249
+ /** 问题消息。 */
250
+ message: string;
251
+ /** 当前状态。 */
252
+ status: string;
253
+ /** 当前结论。 */
254
+ resolution?: string;
255
+ /** 作者。 */
256
+ author?: string;
257
+ /** 负责人。 */
258
+ assignee?: string;
259
+ /** 创建时间。 */
260
+ creationDate: string;
261
+ /** 最后更新时间。 */
262
+ updateDate: string;
263
+ /** 风险概率。 */
264
+ vulnerabilityProbability?: string;
265
+ }
266
+ /**
267
+ * `/api/hotspots/search` 返回结构。
268
+ *
269
+ * @remarks
270
+ * 与 issue 列表一样采用分页返回。
271
+ */
272
+ export interface SonarHotspotSearchResponse {
273
+ /** 分页信息。 */
274
+ paging: SonarPaging;
275
+ /** hotspot 列表。 */
276
+ hotspots: SonarHotspotSearchItem[];
277
+ /** 组件补充信息。 */
278
+ components?: SonarProjectComponent[];
279
+ }
280
+ /**
281
+ * hotspot 详情中携带的规则信息。
282
+ *
283
+ * @remarks
284
+ * 相比普通 rule summary,hotspot 规则更关注风险说明与修复建议。
285
+ */
286
+ export interface SonarHotspotRule {
287
+ /** 规则 key。 */
288
+ key: string;
289
+ /** 规则名称。 */
290
+ name: string;
291
+ /** 风险说明。 */
292
+ riskDescription?: string;
293
+ /** 漏洞说明。 */
294
+ vulnerabilityDescription?: string;
295
+ /** 修复建议。 */
296
+ fixRecommendations?: string;
297
+ }
298
+ /**
299
+ * `/api/hotspots/show` 返回结构。
300
+ *
301
+ * @remarks
302
+ * 这是 Security Hotspot 详情接口的核心结构,后续会被标准化成统一 FindingSummary。
303
+ */
304
+ export interface SonarHotspotShowResponse {
305
+ /** hotspot key。 */
306
+ key: string;
307
+ /** 所在行号。 */
308
+ line?: number;
309
+ /** 问题消息。 */
310
+ message: string;
311
+ /** 当前状态。 */
312
+ status: string;
313
+ /** 当前处理结论。 */
314
+ resolution?: string;
315
+ /** 作者。 */
316
+ author?: string;
317
+ /** 负责人。 */
318
+ assignee?: string;
319
+ /** 创建时间。 */
320
+ creationDate: string;
321
+ /** 最后更新时间。 */
322
+ updateDate: string;
323
+ /** 文本范围。 */
324
+ textRange?: TextRange;
325
+ /** 数据流/执行流。 */
326
+ flows?: unknown[];
327
+ /** 评论列表。 */
328
+ comment?: unknown[];
329
+ /** 变更记录。 */
330
+ changelog?: unknown[];
331
+ /** 文件组件信息。 */
332
+ component: SonarProjectComponent;
333
+ /** 项目信息。 */
334
+ project: SonarProjectComponent;
335
+ /** 规则详情。 */
336
+ rule: SonarHotspotRule;
337
+ /** 代码变体信息。 */
338
+ codeVariants?: string[];
339
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-types.js","sourceRoot":"","sources":["../../src/sonarqube/api-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,183 @@
1
+ import type { ProjectRef } from "../types.js";
2
+ import type { SonarComponentShowResponse, SonarHotspotSearchResponse, SonarHotspotShowResponse, SonarIssue, SonarIssueRuleSummary } from "./api-types.js";
3
+ /**
4
+ * SonarQube HTTP client 的运行参数。
5
+ *
6
+ * @remarks
7
+ * 这里仅包含请求层所需配置,不引入任何业务语义字段。
8
+ */
9
+ export interface SonarQubeClientOptions {
10
+ /** SonarQube Basic Auth 使用的 token。 */
11
+ token: string;
12
+ /** 单次请求超时时间,单位毫秒。 */
13
+ requestTimeoutMs: number;
14
+ /** 最大重试次数。 */
15
+ retryCount: number;
16
+ /** 当前项目请求使用的可选代理。 */
17
+ httpProxy: string | null;
18
+ }
19
+ /**
20
+ * SonarQube Web API 访问层。
21
+ *
22
+ * @remarks
23
+ * 这一层只做“请求、分页、鉴权、错误映射、轻量缓存”,不承担业务标准化职责。
24
+ */
25
+ export declare class SonarQubeClient {
26
+ private readonly projectRef;
27
+ private readonly options;
28
+ /** 规则详情缓存,避免列表和详情阶段重复拉取同一 rule。 */
29
+ private readonly ruleCache;
30
+ private readonly dispatcher;
31
+ constructor(projectRef: ProjectRef, options: SonarQubeClientOptions);
32
+ /**
33
+ * 获取 SonarQube 服务版本,用于预检和调试输出。
34
+ *
35
+ * @returns SonarQube 版本字符串。
36
+ * @throws {SonarQubeMcpError} 当请求失败时抛出。
37
+ */
38
+ getServerVersion(): Promise<string>;
39
+ /**
40
+ * 校验并读取项目组件基础信息。
41
+ *
42
+ * @returns 项目组件信息。
43
+ * @throws {SonarQubeMcpError} 当项目不存在或无法访问时抛出。
44
+ */
45
+ getProjectComponent(): Promise<SonarComponentShowResponse["component"]>;
46
+ /**
47
+ * 拉取指定 issue 类型的全部“当前未解决”问题。
48
+ *
49
+ * @param type - issue 类型,仅支持 `BUG` 和 `VULNERABILITY`。
50
+ * @returns 问题列表以及列表接口内嵌的规则摘要缓存。
51
+ *
52
+ * @remarks
53
+ * 当前 MCP 口径固定为:
54
+ * - Security: `VULNERABILITY + resolved=false`
55
+ * - Reliability: `BUG + resolved=false`
56
+ *
57
+ * @throws {SonarQubeMcpError} 当请求失败或响应异常时抛出。
58
+ */
59
+ searchOpenIssues(type: "BUG" | "VULNERABILITY"): Promise<{
60
+ issues: SonarIssue[];
61
+ embeddedRules: Map<string, SonarIssueRuleSummary>;
62
+ }>;
63
+ /**
64
+ * 通过 issue key 获取单条 issue。
65
+ *
66
+ * @param issueKey - SonarQube issue key。
67
+ * @returns 单条 issue 及其可能内嵌的规则摘要。
68
+ * @throws {SonarQubeMcpError} 当 issue 不存在或请求失败时抛出。
69
+ */
70
+ getIssueByKey(issueKey: string): Promise<{
71
+ issue: SonarIssue;
72
+ embeddedRule: SonarIssueRuleSummary | null;
73
+ }>;
74
+ /**
75
+ * 获取单条 issue 的 changelog。
76
+ *
77
+ * @param issueKey - SonarQube issue key。
78
+ * @returns changelog 数组。
79
+ * @throws {SonarQubeMcpError} 当请求失败时抛出。
80
+ */
81
+ getIssueChangelog(issueKey: string): Promise<unknown[]>;
82
+ /**
83
+ * 拉取全部待复核的 Security Hotspots。
84
+ *
85
+ * @returns hotspot 摘要列表。
86
+ * @throws {SonarQubeMcpError} 当请求失败或响应异常时抛出。
87
+ */
88
+ searchOpenHotspots(): Promise<SonarHotspotSearchResponse["hotspots"]>;
89
+ /**
90
+ * 按 key 获取单条 hotspot 详情。
91
+ *
92
+ * @param hotspotKey - SonarQube hotspot key。
93
+ * @returns hotspot 详情。
94
+ * @throws {SonarQubeMcpError} 当请求失败时抛出。
95
+ */
96
+ getHotspotDetail(hotspotKey: string): Promise<SonarHotspotShowResponse>;
97
+ /**
98
+ * 获取规则详情。
99
+ *
100
+ * @param ruleKey - SonarQube 规则 key。
101
+ * @returns 规则详情或合并后的完整规则摘要。
102
+ *
103
+ * @remarks
104
+ * 如果缓存里已有完整描述,则直接复用;否则继续调用 `/api/rules/show` 补全。
105
+ *
106
+ * @throws {SonarQubeMcpError} 当请求失败时抛出。
107
+ */
108
+ getRule(ruleKey: string): Promise<SonarIssueRuleSummary>;
109
+ /**
110
+ * 请求 JSON 接口并完成解析。
111
+ *
112
+ * @param path - API 路径。
113
+ * @param searchParams - 可选查询参数。
114
+ * @returns 解析后的 JSON 结构。
115
+ */
116
+ private requestJson;
117
+ /**
118
+ * 请求纯文本接口。
119
+ *
120
+ * @param path - API 路径。
121
+ * @param searchParams - 可选查询参数。
122
+ * @returns 去首尾空白后的文本响应。
123
+ */
124
+ private requestText;
125
+ /**
126
+ * 底层 HTTP 请求封装。
127
+ *
128
+ * @param path - API 路径。
129
+ * @param searchParams - 可选查询参数。
130
+ * @returns 成功的原始 `Response` 对象。
131
+ *
132
+ * @remarks
133
+ * 这里统一处理:
134
+ * - Basic token 鉴权
135
+ * - 可选 HTTP 代理
136
+ * - 超时控制
137
+ * - 可重试状态码
138
+ * - SonarQube 错误映射
139
+ *
140
+ * @throws {SonarQubeMcpError} 当请求最终失败时抛出。
141
+ */
142
+ private request;
143
+ /**
144
+ * 判断当前 HTTP 状态是否值得重试。
145
+ *
146
+ * @param status - HTTP 状态码。
147
+ * @param attempt - 当前已重试次数。
148
+ * @returns 是否继续重试。
149
+ */
150
+ private shouldRetry;
151
+ /**
152
+ * 判断当前异常是否属于可重试的网络层失败。
153
+ *
154
+ * @param error - 原始异常。
155
+ * @param attempt - 当前已重试次数。
156
+ * @returns 是否继续重试。
157
+ */
158
+ private shouldRetryForException;
159
+ /**
160
+ * 将 HTTP 错误响应映射为统一的 MCP 错误类型。
161
+ *
162
+ * @param response - 失败的 HTTP 响应。
163
+ * @param requestUrl - 便于排查的完整请求地址。
164
+ * @returns 统一错误对象。
165
+ */
166
+ private buildHttpError;
167
+ /**
168
+ * 解析 SonarQube JSON 响应,并在结构不合法时抛出统一错误。
169
+ *
170
+ * @param response - 原始 HTTP 响应。
171
+ * @param path - 当前请求路径,仅用于错误提示。
172
+ * @returns 解析后的 JSON 结构。
173
+ * @throws {SonarQubeMcpError} 当响应不是合法 JSON 时抛出。
174
+ */
175
+ private parseJson;
176
+ /**
177
+ * 尽量把 SonarQube 的错误体提炼成稳定 message + details 结构。
178
+ *
179
+ * @param response - 原始 HTTP 响应。
180
+ * @returns 规范化后的错误 message 与 details。
181
+ */
182
+ private parseErrorPayload;
183
+ }