gitflic-cli-mcp 0.4.0 → 0.4.2
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/package.json +2 -2
- package/slim.mjs +24 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitflic-cli-mcp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "MCP server wrapping the gitflic CLI — exposes the GitFlic REST API as typed tools for AI agents (Claude Code, Cursor, etc.)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49
|
-
"gitflic-cli": "
|
|
49
|
+
"gitflic-cli": "0.3.5",
|
|
50
50
|
"zod": "^3.25.76"
|
|
51
51
|
}
|
|
52
52
|
}
|
package/slim.mjs
CHANGED
|
@@ -79,7 +79,12 @@ const P = {
|
|
|
79
79
|
status: statusId(i.status),
|
|
80
80
|
labels: labelTitles(i.labels) ?? [],
|
|
81
81
|
assignedUsers: (i.assignedUsers || []).map(userName).filter(Boolean),
|
|
82
|
-
|
|
82
|
+
// NOT i.userAlias: on an issue that is the *project owner's* alias (the
|
|
83
|
+
// `<userAlias>/<projectAlias>` path), identical on every issue in the repo —
|
|
84
|
+
// using it would report the owner as the author of everyone's issues.
|
|
85
|
+
// GitFlic's issue API exposes no author at all, so this stays undefined
|
|
86
|
+
// (key dropped on serialize) unless the API ever starts sending createdBy.
|
|
87
|
+
author: userName(i.createdBy),
|
|
83
88
|
...(i.updatedBy ? { updatedBy: userName(i.updatedBy) } : {}),
|
|
84
89
|
createdAt: i.createdAt, updatedAt: i.updatedAt,
|
|
85
90
|
...(i.description != null ? { description: i.description } : {}),
|
|
@@ -209,7 +214,9 @@ export function applyListFilters(items, args = {}) {
|
|
|
209
214
|
let out = items;
|
|
210
215
|
if (args.label) out = out.filter((i) => (labelTitles(i.labels) || []).some((t) => ci(t).includes(ci(args.label))));
|
|
211
216
|
if (args.assignee) out = out.filter((i) => (i.assignedUsers || []).some((u) => ci(userName(u)) === ci(args.assignee)));
|
|
212
|
-
|
|
217
|
+
// Mirrors the author resolution in P.mr / slimCommit. i.userAlias is NOT in
|
|
218
|
+
// the chain on purpose — it is the project owner's alias, not an author.
|
|
219
|
+
if (args.author) out = out.filter((i) => ci(userName(i.createdBy) || userName(i.author) || userName(i.user) || i.authorIdent?.name).includes(ci(args.author)));
|
|
213
220
|
if (args.status) out = out.filter((i) => ci(statusId(i.status)) === ci(args.status));
|
|
214
221
|
if (args.targetBranch) out = out.filter((i) => ci(branchName(i.targetBranch)).includes(ci(args.targetBranch)));
|
|
215
222
|
if (args.sourceBranch) out = out.filter((i) => ci(branchName(i.sourceBranch)).includes(ci(args.sourceBranch)));
|
|
@@ -223,7 +230,15 @@ export function applyListFilters(items, args = {}) {
|
|
|
223
230
|
if (args.name) { const re = globToRe(args.name); out = out.filter((i) => re.test(i.name ?? "") || ci(i.name).includes(ci(args.name))); }
|
|
224
231
|
if (args.q) {
|
|
225
232
|
const q = ci(args.q);
|
|
226
|
-
|
|
233
|
+
// Haystack spans every entity's free-text/identity fields so `q` works for
|
|
234
|
+
// issues/MRs (title+description), commits (messages), users (username/
|
|
235
|
+
// fullName/name), projects (title/alias) and releases (tagName). Missing
|
|
236
|
+
// fields collapse to "" — harmless. (Bug fix: user_search used to drop all
|
|
237
|
+
// server results because the haystack lacked username/fullName.)
|
|
238
|
+
out = out.filter((i) =>
|
|
239
|
+
`${i.title ?? ""} ${i.description ?? ""} ${i.shortMessage ?? ""} ${i.message ?? ""} ${i.username ?? ""} ${i.fullName ?? ""} ${i.name ?? ""} ${i.alias ?? ""} ${i.tagName ?? ""}`
|
|
240
|
+
.toLowerCase()
|
|
241
|
+
.includes(q));
|
|
227
242
|
}
|
|
228
243
|
if (args.sort) {
|
|
229
244
|
const desc = String(args.sort)[0] === "-";
|
|
@@ -279,7 +294,12 @@ export function slimResult(toolName, result, args = {}, env = process.env) {
|
|
|
279
294
|
// Treat known list tools as lists even when GitFlic omits `_embedded` on a
|
|
280
295
|
// zero-result response, so the {items,total,returned} contract is consistent.
|
|
281
296
|
let lst = listOf(result);
|
|
282
|
-
|
|
297
|
+
// Zero-result lists omit `_embedded` entirely. Treat any list tool (mapped
|
|
298
|
+
// OR an unmapped *_list/*_search) carrying a `page` envelope as an empty list
|
|
299
|
+
// so the {items,total,returned} contract holds even when there are no items.
|
|
300
|
+
if (!lst && result.page && (shape.list || /_(list|search)$/.test(toolName))) {
|
|
301
|
+
lst = { items: [], total: result.page.totalElements };
|
|
302
|
+
}
|
|
283
303
|
|
|
284
304
|
if (lst) {
|
|
285
305
|
let items = Array.isArray(lst.items) ? lst.items : [];
|