@kaddo/mcp 3.88.1 → 3.88.3

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.
Files changed (2) hide show
  1. package/dist/index.js +45 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12295,7 +12295,7 @@ function buildJql(filters) {
12295
12295
  if (filters?.updatedAfter) clauses.push(`updated >= ${escapeJql(filters.updatedAfter)}`);
12296
12296
  if (filters?.search) clauses.push(`(summary ~ ${escapeJql(filters.search)} OR description ~ ${escapeJql(filters.search)})`);
12297
12297
  if (filters?.providerQuery) clauses.push(`(${filters.providerQuery})`);
12298
- return clauses.join(" AND ") || "ORDER BY updated DESC";
12298
+ return clauses.join(" AND ");
12299
12299
  }
12300
12300
  function normalizeBaseUrl(raw) {
12301
12301
  let url = raw.trim();
@@ -12306,6 +12306,24 @@ function authHeader(email, token) {
12306
12306
  const encoded = typeof Buffer !== "undefined" ? Buffer.from(`${email}:${token}`).toString("base64") : btoa(`${email}:${token}`);
12307
12307
  return `Basic ${encoded}`;
12308
12308
  }
12309
+ async function handleJiraResponse(res) {
12310
+ if (res.status === 401) throw integrationError("INTEGRATION_UNAUTHORIZED");
12311
+ if (res.status === 403) throw integrationError("INTEGRATION_FORBIDDEN");
12312
+ if (res.status === 404) throw integrationError("INTEGRATION_NOT_FOUND");
12313
+ if (res.status === 410) throw integrationError("INTEGRATION_UNAVAILABLE", "Jira API endpoint deprecated (410 Gone).");
12314
+ if (res.status === 429) throw integrationError("INTEGRATION_RATE_LIMITED");
12315
+ if (res.status >= 500) throw integrationError("INTEGRATION_UNAVAILABLE");
12316
+ if (!res.ok) {
12317
+ let detail = "";
12318
+ try {
12319
+ const body = await res.json();
12320
+ detail = body.errorMessages?.[0] ?? "";
12321
+ } catch {
12322
+ }
12323
+ throw integrationError("INTEGRATION_PROVIDER_ERROR", detail || `Jira responded with status ${res.status}.`);
12324
+ }
12325
+ return await res.json();
12326
+ }
12309
12327
  async function jiraFetch(baseUrl, path6, auth, timeoutMs, params) {
12310
12328
  const url = new URL(path6, baseUrl + "/");
12311
12329
  if (params) for (const [k2, v] of Object.entries(params)) url.searchParams.set(k2, v);
@@ -12317,13 +12335,26 @@ async function jiraFetch(baseUrl, path6, auth, timeoutMs, params) {
12317
12335
  headers: { Authorization: auth, Accept: "application/json" },
12318
12336
  signal: controller.signal
12319
12337
  });
12320
- if (res.status === 401) throw integrationError("INTEGRATION_UNAUTHORIZED");
12321
- if (res.status === 403) throw integrationError("INTEGRATION_FORBIDDEN");
12322
- if (res.status === 404) throw integrationError("INTEGRATION_NOT_FOUND");
12323
- if (res.status === 429) throw integrationError("INTEGRATION_RATE_LIMITED");
12324
- if (res.status >= 500) throw integrationError("INTEGRATION_UNAVAILABLE");
12325
- if (!res.ok) throw integrationError("INTEGRATION_PROVIDER_ERROR", `Jira responded with status ${res.status}.`);
12326
- return await res.json();
12338
+ return await handleJiraResponse(res);
12339
+ } catch (err) {
12340
+ if (err instanceof Error && err.name === "AbortError") throw integrationError("INTEGRATION_TIMEOUT");
12341
+ throw normalizeProviderError(err);
12342
+ } finally {
12343
+ clearTimeout(timer);
12344
+ }
12345
+ }
12346
+ async function jiraPost(baseUrl, path6, auth, timeoutMs, body) {
12347
+ const url = new URL(path6, baseUrl + "/");
12348
+ const controller = new AbortController();
12349
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
12350
+ try {
12351
+ const res = await fetch(url.toString(), {
12352
+ method: "POST",
12353
+ headers: { Authorization: auth, Accept: "application/json", "Content-Type": "application/json" },
12354
+ body: JSON.stringify(body),
12355
+ signal: controller.signal
12356
+ });
12357
+ return await handleJiraResponse(res);
12327
12358
  } catch (err) {
12328
12359
  if (err instanceof Error && err.name === "AbortError") throw integrationError("INTEGRATION_TIMEOUT");
12329
12360
  throw normalizeProviderError(err);
@@ -12444,11 +12475,12 @@ function createJiraAdapter() {
12444
12475
  const pageSize = Math.min(Math.max(1, request.pageSize ?? DEFAULT_PAGE_SIZE), 100);
12445
12476
  const startAt = request.cursor ? Math.max(0, Number.parseInt(request.cursor, 10) || 0) : 0;
12446
12477
  try {
12447
- const data = await jiraFetch(baseUrl, "/rest/api/3/search", auth, request.context.timeoutMs, {
12448
- jql: jql.startsWith("ORDER BY") ? jql : jql + " ORDER BY updated DESC",
12449
- startAt: String(startAt),
12450
- maxResults: String(pageSize),
12451
- fields: SEARCH_FIELDS
12478
+ const fullJql = jql ? jql + " ORDER BY updated DESC" : "ORDER BY updated DESC";
12479
+ const data = await jiraPost(baseUrl, "/rest/api/3/search/jql", auth, request.context.timeoutMs, {
12480
+ jql: fullJql,
12481
+ startAt,
12482
+ maxResults: pageSize,
12483
+ fields: SEARCH_FIELDS.split(",")
12452
12484
  });
12453
12485
  const items = data.issues.map((issue) => normalizeIssue(issue, baseUrl, request.context.integrationId));
12454
12486
  const nextStart = data.startAt + data.issues.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.88.1",
3
+ "version": "3.88.3",
4
4
  "description": "MCP server for Kaddo project knowledge: read-only resources/tools/prompts plus safe derived generation under .kaddo/.",
5
5
  "license": "MIT",
6
6
  "repository": {