@pschroee/redmine-mcp 0.4.4 → 0.4.5

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.
@@ -3,6 +3,58 @@ import { diffLines } from "diff";
3
3
  * Fields that contain large text and should use diff formatting
4
4
  */
5
5
  const LARGE_TEXT_FIELDS = ["description"];
6
+ /**
7
+ * Format checklist changes as a readable diff
8
+ * Only shows items that changed between old and new state
9
+ */
10
+ function formatChecklistDiff(oldValue, newValue) {
11
+ let oldItems = [];
12
+ let newItems = [];
13
+ try {
14
+ oldItems = JSON.parse(oldValue || "[]");
15
+ }
16
+ catch {
17
+ // Invalid JSON, fall back to raw display
18
+ return null;
19
+ }
20
+ try {
21
+ newItems = JSON.parse(newValue || "[]");
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ // Create maps for easy lookup by subject (more reliable than ID for diffing)
27
+ const oldBySubject = new Map(oldItems.map(item => [item.subject, item]));
28
+ const newBySubject = new Map(newItems.map(item => [item.subject, item]));
29
+ const changes = [];
30
+ // Find changed and added items
31
+ for (const newItem of newItems) {
32
+ const oldItem = oldBySubject.get(newItem.subject);
33
+ if (!oldItem) {
34
+ // New item added
35
+ const status = newItem.is_done ? "✅" : "❌";
36
+ changes.push(` - ➕ ${newItem.subject}: ${status}`);
37
+ }
38
+ else if (oldItem.is_done !== newItem.is_done) {
39
+ // Status changed
40
+ const oldStatus = oldItem.is_done ? "✅" : "❌";
41
+ const newStatus = newItem.is_done ? "✅" : "❌";
42
+ changes.push(` - ${newItem.subject}: ${oldStatus} → ${newStatus}`);
43
+ }
44
+ // If subject and status are same, no change to report
45
+ }
46
+ // Find removed items
47
+ for (const oldItem of oldItems) {
48
+ if (!newBySubject.has(oldItem.subject)) {
49
+ const status = oldItem.is_done ? "✅" : "❌";
50
+ changes.push(` - ➖ ${oldItem.subject}: ${status}`);
51
+ }
52
+ }
53
+ if (changes.length === 0) {
54
+ return null; // No meaningful changes
55
+ }
56
+ return changes.join("\n");
57
+ }
6
58
  /**
7
59
  * Field name mappings for display (remove _id suffix)
8
60
  */
@@ -97,6 +149,14 @@ function formatDetail(detail, lookup) {
97
149
  }
98
150
  // Handle attribute changes
99
151
  if (property === "attr") {
152
+ // Checklist changes get special formatting
153
+ if (name === "checklist") {
154
+ const checklistDiff = formatChecklistDiff(old_value || "", new_value || "");
155
+ if (checklistDiff) {
156
+ return `- checklist:\n${checklistDiff}`;
157
+ }
158
+ // Fall through to default formatting if parsing failed
159
+ }
100
160
  // Large text fields get diff formatting
101
161
  if (LARGE_TEXT_FIELDS.includes(name) && old_value && new_value) {
102
162
  const diff = generateDiff(old_value, new_value);
package/dist/server.js CHANGED
@@ -3,7 +3,7 @@ import { registerTools } from "./tools/index.js";
3
3
  export function createServer(redmineClient, toolGroups) {
4
4
  const server = new McpServer({
5
5
  name: "redmine-mcp",
6
- version: "0.4.4",
6
+ version: "0.4.5",
7
7
  });
8
8
  registerTools(server, redmineClient, toolGroups);
9
9
  return server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pschroee/redmine-mcp",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "MCP server for Redmine - full API access with configurable tool groups",
5
5
  "type": "module",
6
6
  "bin": {