@kaddo/mcp 3.83.0 → 3.85.0

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 +172 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11771,6 +11771,51 @@ function parseSecrets(raw, id, findings) {
11771
11771
  }
11772
11772
  return secrets;
11773
11773
  }
11774
+ function toStringArray3(raw) {
11775
+ if (raw == null) return void 0;
11776
+ if (Array.isArray(raw)) return raw.filter((v) => typeof v === "string" && v.trim() !== "").map((v) => v.trim());
11777
+ if (typeof raw === "string" && raw.trim()) return [raw.trim()];
11778
+ return void 0;
11779
+ }
11780
+ function parseFilters(raw) {
11781
+ if (raw == null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
11782
+ const o2 = raw;
11783
+ const filters = {};
11784
+ let hasAny = false;
11785
+ const types = toStringArray3(o2.types);
11786
+ if (types?.length) {
11787
+ filters.types = types;
11788
+ hasAny = true;
11789
+ }
11790
+ const statuses = toStringArray3(o2.statuses);
11791
+ if (statuses?.length) {
11792
+ filters.statuses = statuses;
11793
+ hasAny = true;
11794
+ }
11795
+ const labels = toStringArray3(o2.labels);
11796
+ if (labels?.length) {
11797
+ filters.labels = labels;
11798
+ hasAny = true;
11799
+ }
11800
+ const assignees = toStringArray3(o2.assignees);
11801
+ if (assignees?.length) {
11802
+ filters.assignees = assignees;
11803
+ hasAny = true;
11804
+ }
11805
+ if (typeof o2.updatedAfter === "string" && o2.updatedAfter.trim()) {
11806
+ filters.updatedAfter = o2.updatedAfter.trim();
11807
+ hasAny = true;
11808
+ }
11809
+ if (typeof o2.search === "string" && o2.search.trim()) {
11810
+ filters.search = o2.search.trim();
11811
+ hasAny = true;
11812
+ }
11813
+ if (typeof o2.providerQuery === "string" && o2.providerQuery.trim()) {
11814
+ filters.providerQuery = o2.providerQuery.trim();
11815
+ hasAny = true;
11816
+ }
11817
+ return hasAny ? filters : void 0;
11818
+ }
11774
11819
  function parseIntegrationsConfig(raw, opts) {
11775
11820
  const findings = [];
11776
11821
  const integrations = [];
@@ -11804,8 +11849,9 @@ function parseIntegrationsConfig(raw, opts) {
11804
11849
  const config = o2.config && typeof o2.config === "object" && !Array.isArray(o2.config) ? o2.config : {};
11805
11850
  const credentials = parseCredentials(o2.credentials, id, findings);
11806
11851
  const secrets = parseSecrets(o2.secrets, id, findings);
11852
+ const filters = parseFilters(o2.filters);
11807
11853
  const timeoutMs = typeof o2.timeout_ms === "number" ? o2.timeout_ms : typeof o2.timeoutMs === "number" ? o2.timeoutMs : void 0;
11808
- integrations.push({ id, adapter, enabled, config, credentials, secrets, timeoutMs });
11854
+ integrations.push({ id, adapter, enabled, config, credentials, secrets, filters, timeoutMs });
11809
11855
  }
11810
11856
  return { integrations, findings };
11811
11857
  }
@@ -11825,6 +11871,20 @@ async function resolveAllCredentials(integration, resolver, env) {
11825
11871
  }
11826
11872
  return { credentials, missing };
11827
11873
  }
11874
+ function mergeFilters(base, overlay) {
11875
+ if (!base && !overlay) return {};
11876
+ if (!base) return { ...overlay };
11877
+ if (!overlay) return { ...base };
11878
+ return {
11879
+ types: overlay.types?.length ? overlay.types : base.types,
11880
+ statuses: overlay.statuses?.length ? overlay.statuses : base.statuses,
11881
+ labels: overlay.labels?.length ? overlay.labels : base.labels,
11882
+ assignees: overlay.assignees?.length ? overlay.assignees : base.assignees,
11883
+ updatedAfter: overlay.updatedAfter ?? base.updatedAfter,
11884
+ search: overlay.search ?? base.search,
11885
+ providerQuery: overlay.providerQuery ?? base.providerQuery
11886
+ };
11887
+ }
11828
11888
 
11829
11889
  // ../integrations/src/secrets.ts
11830
11890
  import { readFileSync as readFileSync2, writeFileSync, mkdirSync, existsSync as existsSync2, unlinkSync } from "fs";
@@ -11941,6 +12001,7 @@ var DEFAULT_ITEMS = [
11941
12001
  status: "Open",
11942
12002
  url: "https://example.test/mock/EXT-001",
11943
12003
  labels: ["registration", "beta"],
12004
+ assignees: [{ name: "Alice" }],
11944
12005
  createdAt: "2026-01-05T10:00:00.000Z",
11945
12006
  updatedAt: "2026-02-01T09:30:00.000Z",
11946
12007
  rawMetadata: { board: "delivery" }
@@ -11954,8 +12015,86 @@ var DEFAULT_ITEMS = [
11954
12015
  status: "To Do",
11955
12016
  url: "https://example.test/mock/EXT-002",
11956
12017
  labels: ["onboarding"],
12018
+ assignees: [{ name: "Bob" }],
11957
12019
  createdAt: "2026-01-08T12:00:00.000Z",
11958
12020
  updatedAt: "2026-01-20T15:00:00.000Z"
12021
+ },
12022
+ {
12023
+ externalId: "EXT-003",
12024
+ provider: MOCK_ADAPTER_ID,
12025
+ title: "Fix authentication error on mobile",
12026
+ description: "Users on iOS 17 see a blank screen after OAuth redirect.",
12027
+ type: "Bug",
12028
+ status: "In Progress",
12029
+ url: "https://example.test/mock/EXT-003",
12030
+ labels: ["auth", "mobile", "critical"],
12031
+ assignees: [{ name: "Alice" }],
12032
+ createdAt: "2026-02-10T08:00:00.000Z",
12033
+ updatedAt: "2026-03-01T14:00:00.000Z"
12034
+ },
12035
+ {
12036
+ externalId: "EXT-004",
12037
+ provider: MOCK_ADAPTER_ID,
12038
+ title: "Design system token audit",
12039
+ description: "Review and consolidate design tokens across the component library.",
12040
+ type: "Task",
12041
+ status: "To Do",
12042
+ url: "https://example.test/mock/EXT-004",
12043
+ labels: ["frontend", "design-system"],
12044
+ createdAt: "2026-02-15T10:00:00.000Z",
12045
+ updatedAt: "2026-02-20T11:00:00.000Z"
12046
+ },
12047
+ {
12048
+ externalId: "EXT-005",
12049
+ provider: MOCK_ADAPTER_ID,
12050
+ title: "Migrate billing service to new payment gateway",
12051
+ description: "Stripe v2 migration \u2014 switch from legacy Charges API to Payment Intents.",
12052
+ type: "Epic",
12053
+ status: "Open",
12054
+ url: "https://example.test/mock/EXT-005",
12055
+ labels: ["billing", "backend", "migration"],
12056
+ assignees: [{ name: "Carol" }],
12057
+ createdAt: "2026-01-20T09:00:00.000Z",
12058
+ updatedAt: "2026-03-05T16:00:00.000Z"
12059
+ },
12060
+ {
12061
+ externalId: "EXT-006",
12062
+ provider: MOCK_ADAPTER_ID,
12063
+ title: "Add CSV export to reports",
12064
+ description: "Users need to export analytics reports as CSV for external tools.",
12065
+ type: "Feature",
12066
+ status: "In Progress",
12067
+ url: "https://example.test/mock/EXT-006",
12068
+ labels: ["reports", "backend"],
12069
+ assignees: [{ name: "Bob" }],
12070
+ createdAt: "2026-02-25T13:00:00.000Z",
12071
+ updatedAt: "2026-03-10T10:00:00.000Z"
12072
+ },
12073
+ {
12074
+ externalId: "EXT-007",
12075
+ provider: MOCK_ADAPTER_ID,
12076
+ title: "Improve search relevance scoring",
12077
+ description: "Tweak TF-IDF weights and add trigram matching for better search results.",
12078
+ type: "Task",
12079
+ status: "Done",
12080
+ url: "https://example.test/mock/EXT-007",
12081
+ labels: ["search", "backend"],
12082
+ assignees: [{ name: "Alice" }],
12083
+ createdAt: "2026-01-12T07:00:00.000Z",
12084
+ updatedAt: "2026-02-28T17:00:00.000Z"
12085
+ },
12086
+ {
12087
+ externalId: "EXT-008",
12088
+ provider: MOCK_ADAPTER_ID,
12089
+ title: "Set up E2E test pipeline",
12090
+ description: "Configure Playwright tests running on every PR via GitHub Actions.",
12091
+ type: "Task",
12092
+ status: "Done",
12093
+ url: "https://example.test/mock/EXT-008",
12094
+ labels: ["testing", "ci"],
12095
+ assignees: [{ name: "Carol" }],
12096
+ createdAt: "2026-01-30T11:00:00.000Z",
12097
+ updatedAt: "2026-02-15T09:00:00.000Z"
11959
12098
  }
11960
12099
  ];
11961
12100
  function simulationOf(context, fallback) {
@@ -11987,6 +12126,16 @@ function createMockAdapter(opts = {}) {
11987
12126
  displayName: "Mock Work Source",
11988
12127
  version: "1.0.0",
11989
12128
  description: "Deterministic offline reference adapter for validating the integration foundation.",
12129
+ icon: "mock",
12130
+ filterCapabilities: {
12131
+ types: { supported: true, multiple: true },
12132
+ statuses: { supported: true, multiple: true },
12133
+ labels: { supported: true, multiple: true },
12134
+ assignees: { supported: true, multiple: true },
12135
+ updatedAfter: { supported: true },
12136
+ search: { supported: true },
12137
+ providerQuery: { supported: false }
12138
+ },
11990
12139
  configSchema: {
11991
12140
  simulate: {
11992
12141
  type: "select",
@@ -12005,7 +12154,7 @@ function createMockAdapter(opts = {}) {
12005
12154
  },
12006
12155
  secretSchema: {
12007
12156
  token: {
12008
- type: "string",
12157
+ type: "password",
12009
12158
  required: false,
12010
12159
  label: "API Token",
12011
12160
  description: "Optional token for testing secret handling (not used by the mock adapter)."
@@ -12033,9 +12182,24 @@ function createMockAdapter(opts = {}) {
12033
12182
  readFailure(simulationOf(request.context, defaultSim));
12034
12183
  let pool = items;
12035
12184
  const f3 = request.filters;
12036
- if (f3?.status) pool = pool.filter((i) => (i.status ?? "").toLowerCase() === f3.status.toLowerCase());
12037
- if (f3?.query) pool = pool.filter((i) => `${i.title} ${i.description ?? ""}`.toLowerCase().includes(f3.query.toLowerCase()));
12038
- if (f3?.updatedSince) pool = pool.filter((i) => (i.updatedAt ?? "") >= f3.updatedSince);
12185
+ if (f3?.statuses?.length) {
12186
+ const lower = f3.statuses.map((s) => s.toLowerCase());
12187
+ pool = pool.filter((i) => lower.includes((i.status ?? "").toLowerCase()));
12188
+ }
12189
+ if (f3?.types?.length) {
12190
+ const lower = f3.types.map((t) => t.toLowerCase());
12191
+ pool = pool.filter((i) => lower.includes((i.type ?? "").toLowerCase()));
12192
+ }
12193
+ if (f3?.labels?.length) {
12194
+ const lower = f3.labels.map((l2) => l2.toLowerCase());
12195
+ pool = pool.filter((i) => i.labels?.some((il) => lower.includes(il.toLowerCase())));
12196
+ }
12197
+ if (f3?.assignees?.length) {
12198
+ const lower = f3.assignees.map((a2) => a2.toLowerCase());
12199
+ pool = pool.filter((i) => i.assignees?.some((a2) => lower.includes((a2.name ?? "").toLowerCase())));
12200
+ }
12201
+ if (f3?.search) pool = pool.filter((i) => `${i.title} ${i.description ?? ""}`.toLowerCase().includes(f3.search.toLowerCase()));
12202
+ if (f3?.updatedAfter) pool = pool.filter((i) => (i.updatedAt ?? "") >= f3.updatedAfter);
12039
12203
  const size = Math.max(1, request.pageSize ?? defaultPageSize);
12040
12204
  const start = request.cursor ? Math.max(0, Number.parseInt(request.cursor, 10) || 0) : 0;
12041
12205
  const slice = pool.slice(start, start + size);
@@ -12105,6 +12269,7 @@ function listIntegrations(dir) {
12105
12269
  credentialRefs: Object.values(integration.credentials).map((c) => c.env),
12106
12270
  secretRefs: Object.values(integration.secrets),
12107
12271
  secretStatus: {},
12272
+ filters: integration.filters,
12108
12273
  findings: findings.filter((f3) => f3.id === integration.id)
12109
12274
  };
12110
12275
  });
@@ -12171,7 +12336,8 @@ async function listExternalWorkItems(dir, id, opts = {}, env = process.env) {
12171
12336
  const adapter = resolveAdapter(integration);
12172
12337
  if (!adapter.capabilities.workItems.list) throw integrationError("UNSUPPORTED_CAPABILITY", `Adapter "${adapter.id}" cannot list work items.`);
12173
12338
  const { context } = await buildContextWithSecrets(dir, integration, env);
12174
- return withTimeout(adapter.listWorkItems({ context, cursor: opts.cursor, pageSize: opts.pageSize, filters: opts.filters }), context.timeoutMs);
12339
+ const filters = mergeFilters(integration.filters, opts.filters);
12340
+ return withTimeout(adapter.listWorkItems({ context, cursor: opts.cursor, pageSize: opts.pageSize, filters }), context.timeoutMs);
12175
12341
  }
12176
12342
  async function getExternalWorkItem(dir, id, externalId, env = process.env) {
12177
12343
  const { integration } = requireIntegration(dir, id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.83.0",
3
+ "version": "3.85.0",
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": {