@pschroee/redmine-mcp 0.5.5 → 0.5.7

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.
@@ -211,8 +211,10 @@ export function formatJournals(journals, lookup = {}, options = {}) {
211
211
  return "";
212
212
  }
213
213
  const header = `## History (${journals.length} entries)\n\n`;
214
+ // Sort journals chronologically (oldest first) to ensure correct numbering
215
+ const sortedJournals = [...journals].sort((a, b) => new Date(a.created_on).getTime() - new Date(b.created_on).getTime());
214
216
  // Format entries with correct note numbers (1 = oldest), then reverse for display (newest first)
215
- const formattedEntries = journals.map((j, i) => formatJournalEntry(j, i + 1, lookup, options));
217
+ const formattedEntries = sortedJournals.map((j, i) => formatJournalEntry(j, i + 1, lookup, options));
216
218
  const entries = formattedEntries.reverse().join("\n---\n\n");
217
219
  return header + entries;
218
220
  }
@@ -184,11 +184,12 @@ export function formatQueryList(response) {
184
184
  const lines = [];
185
185
  lines.push(`# Saved Queries (${queries.length})`);
186
186
  lines.push("");
187
- lines.push("| ID | Name | Visibility |");
188
- lines.push("|----|------|------------|");
187
+ lines.push("| ID | Name | Project | Visibility |");
188
+ lines.push("|----|------|---------|------------|");
189
189
  for (const query of queries) {
190
190
  const visibility = query.is_public ? "Public" : "Private";
191
- lines.push(`| ${query.id} | ${query.name} | ${visibility} |`);
191
+ const project = query.project_id ? `#${query.project_id}` : "Global";
192
+ lines.push(`| ${query.id} | ${query.name} | ${project} | ${visibility} |`);
192
193
  }
193
194
  return lines.join("\n");
194
195
  }
@@ -230,7 +230,9 @@ export declare class RedmineClient {
230
230
  }>>;
231
231
  deleteIssueCategory(id: number, reassignToId?: number): Promise<RedmineResult<void>>;
232
232
  listCustomFields(): Promise<RedmineResult<RedmineCustomFieldsResponse>>;
233
- listQueries(): Promise<RedmineResult<RedmineQueriesResponse>>;
233
+ listQueries(params?: {
234
+ project_id?: string | number;
235
+ }): Promise<RedmineResult<RedmineQueriesResponse>>;
234
236
  search(params: {
235
237
  q: string;
236
238
  scope?: string;
@@ -305,7 +305,10 @@ export class RedmineClient {
305
305
  return this.request("GET", "/custom_fields.json");
306
306
  }
307
307
  // ==================== QUERIES ====================
308
- async listQueries() {
308
+ async listQueries(params) {
309
+ if (params?.project_id) {
310
+ return this.request("GET", `/projects/${params.project_id}/queries.json`);
311
+ }
309
312
  return this.request("GET", "/queries.json");
310
313
  }
311
314
  // ==================== SEARCH ====================
@@ -119,8 +119,11 @@ export function registerMetadataTools(server, client) {
119
119
  // === QUERIES ===
120
120
  server.registerTool("list_queries", {
121
121
  description: "List all saved issue queries (public and private)",
122
- }, async () => {
123
- const result = await client.listQueries();
122
+ inputSchema: {
123
+ project_id: z.union([z.string(), z.number()]).optional().describe("Filter queries by project ID or identifier"),
124
+ },
125
+ }, async (params) => {
126
+ const result = await client.listQueries(params.project_id ? { project_id: params.project_id } : undefined);
124
127
  if ("error" in result) {
125
128
  return {
126
129
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pschroee/redmine-mcp",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "MCP server for Redmine - full API access with configurable tool groups",
5
5
  "type": "module",
6
6
  "bin": {