@oss-scout/mcp 0.12.1 → 0.13.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.
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ export { registerResources } from "./resources.js";
12
12
  /** Server identity, kept in one place for the bin and any embedding host. */
13
13
  export declare const SERVER_INFO: {
14
14
  readonly name: "oss-scout-mcp";
15
- readonly version: "0.12.1";
15
+ readonly version: "0.13.0";
16
16
  };
17
17
  /**
18
18
  * Build a fully-wired MCP server (tools + resources) around a scout.
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ export { registerResources } from "./resources.js";
15
15
  /** Server identity, kept in one place for the bin and any embedding host. */
16
16
  export const SERVER_INFO = {
17
17
  name: "oss-scout-mcp",
18
- version: "0.12.1", // x-release-please-version
18
+ version: "0.13.0", // x-release-please-version
19
19
  };
20
20
  /**
21
21
  * Build a fully-wired MCP server (tools + resources) around a scout.
@@ -7,7 +7,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
9
  var __commonJS = (cb, mod) => function __require() {
10
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ try {
11
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
+ } catch (e) {
13
+ throw mod = 0, e;
14
+ }
11
15
  };
12
16
  var __export = (target, all) => {
13
17
  for (var name in all)
@@ -40688,15 +40692,17 @@ var OssScout = class {
40688
40692
  starred: rotation.starredOffset ?? 0,
40689
40693
  maintained: rotation.maintainedOffset ?? 0
40690
40694
  },
40691
- strategyRotationOffset: rotation.strategyOffset ?? 0
40695
+ // A full search runs every enabled phase in one run, so it skips the
40696
+ // one-strategy round-robin (#336) that the default search uses.
40697
+ strategyRotationOffset: options?.full ? void 0 : rotation.strategyOffset ?? 0
40692
40698
  }));
40693
40699
  } catch (err) {
40694
40700
  if (err instanceof ValidationError) {
40695
- this.advanceRotation(rotation, err.strategiesUsed ?? []);
40701
+ this.advanceRotation(rotation, err.strategiesUsed ?? [], options?.full);
40696
40702
  }
40697
40703
  throw err;
40698
40704
  }
40699
- this.advanceRotation(rotation, strategiesUsed);
40705
+ this.advanceRotation(rotation, strategiesUsed, options?.full);
40700
40706
  for (const c of candidates) {
40701
40707
  this.updateRepoSignalsFromHealth(c.projectHealth);
40702
40708
  }
@@ -40718,9 +40724,10 @@ var OssScout = class {
40718
40724
  * nothing must still rotate, or the same barren slice would lead every
40719
40725
  * subsequent run. Skipped/gated phases don't burn a rotation slot. The
40720
40726
  * round-robin strategy cursor (#336) moves to just after the strategy that
40721
- * led (the first one used), so the next search starts with the next one.
40727
+ * led (the first one used), so the next search starts with the next one. A
40728
+ * full search ran every strategy, so it leaves that cursor where it was.
40722
40729
  */
40723
- advanceRotation(rotation, strategiesUsed) {
40730
+ advanceRotation(rotation, strategiesUsed, full = false) {
40724
40731
  const ran = (strategy) => strategiesUsed.includes(strategy) ? 1 : 0;
40725
40732
  if (strategiesUsed.length === 0)
40726
40733
  return;
@@ -40730,7 +40737,7 @@ var OssScout = class {
40730
40737
  phase0Offset: (rotation.phase0Offset ?? 0) + ran("merged"),
40731
40738
  starredOffset: (rotation.starredOffset ?? 0) + ran("starred"),
40732
40739
  maintainedOffset: (rotation.maintainedOffset ?? 0) + ran("maintained"),
40733
- strategyOffset: CONCRETE_STRATEGIES.indexOf(strategiesUsed[0]) + 1,
40740
+ strategyOffset: full ? rotation.strategyOffset : CONCRETE_STRATEGIES.indexOf(strategiesUsed[0]) + 1,
40734
40741
  lastRotatedAt: (/* @__PURE__ */ new Date()).toISOString()
40735
40742
  };
40736
40743
  this.dirty = true;
@@ -41221,6 +41228,7 @@ var OssScout = class {
41221
41228
  if (hit) {
41222
41229
  if (metadata?.permanent === true && hit.permanent !== true) {
41223
41230
  hit.permanent = true;
41231
+ hit.skippedAt = (/* @__PURE__ */ new Date()).toISOString();
41224
41232
  this.dirty = true;
41225
41233
  }
41226
41234
  return;
@@ -41272,13 +41280,14 @@ var OssScout = class {
41272
41280
  * Called at the start of each search (#348) to re-surface issues whose
41273
41281
  * transient block condition (closed competing PR, own in-flight PR, soft-skip
41274
41282
  * accumulation) has aged out. Permanent entries (manual skips, terminal vetter
41275
- * reasons) are never touched.
41283
+ * reasons) are never touched. Culled URLs get deletion tombstones so a gist
41284
+ * merge with another machine's older copy does not bring them back.
41276
41285
  * @returns The number of expired entries that were removed.
41277
41286
  */
41278
41287
  cullExpiredSkips(maxDays = 90) {
41279
41288
  const cutoff = /* @__PURE__ */ new Date();
41280
41289
  cutoff.setDate(cutoff.getDate() - maxDays);
41281
- const before = (this.state.skippedIssues ?? []).length;
41290
+ const culledUrls = [];
41282
41291
  this.state.skippedIssues = (this.state.skippedIssues ?? []).filter((s) => {
41283
41292
  if (s.permanent !== false)
41284
41293
  return true;
@@ -41286,12 +41295,16 @@ var OssScout = class {
41286
41295
  if (isNaN(d.getTime())) {
41287
41296
  return true;
41288
41297
  }
41289
- return d >= cutoff;
41298
+ if (d >= cutoff)
41299
+ return true;
41300
+ culledUrls.push(s.url);
41301
+ return false;
41290
41302
  });
41291
- const culled = before - this.state.skippedIssues.length;
41292
- if (culled > 0)
41303
+ if (culledUrls.length > 0) {
41304
+ this.addTombstones(culledUrls);
41293
41305
  this.dirty = true;
41294
- return culled;
41306
+ }
41307
+ return culledUrls.length;
41295
41308
  }
41296
41309
  // ── Persistence ─────────────────────────────────────────────────────
41297
41310
  /**
@@ -41538,6 +41551,9 @@ function registerTools(server, scout) {
41538
41551
  strategies: external_exports3.string().optional().describe(
41539
41552
  "Comma-separated search strategies: merged, orgs, starred, broad, maintained, all"
41540
41553
  ),
41554
+ full: external_exports3.boolean().optional().describe(
41555
+ "Run every enabled strategy in this search instead of one per search in rotation. More API calls, so it can take a few minutes"
41556
+ ),
41541
41557
  preferLanguages: external_exports3.array(external_exports3.string()).optional().describe(
41542
41558
  "Soft-boost ranking for candidates whose repo language matches one of these (case-insensitive). Personalization tier between recommendation and viabilityScore (#1244). Not a filter; only reorders."
41543
41559
  ),
@@ -41557,6 +41573,7 @@ function registerTools(server, scout) {
41557
41573
  async ({
41558
41574
  maxResults,
41559
41575
  strategies,
41576
+ full,
41560
41577
  preferLanguages,
41561
41578
  preferRepos,
41562
41579
  avoidRepos,
@@ -41578,6 +41595,7 @@ function registerTools(server, scout) {
41578
41595
  scout.search({
41579
41596
  maxResults: maxResults ?? 10,
41580
41597
  strategies: parsedStrategies,
41598
+ full,
41581
41599
  preferLanguages,
41582
41600
  preferRepos,
41583
41601
  avoidRepos,
@@ -41884,7 +41902,7 @@ function registerResources(server, scout) {
41884
41902
  // src/index.ts
41885
41903
  var SERVER_INFO = {
41886
41904
  name: "oss-scout-mcp",
41887
- version: "0.12.1"
41905
+ version: "0.13.0"
41888
41906
  // x-release-please-version
41889
41907
  };
41890
41908
  function createServer(scout) {
package/dist/tools.js CHANGED
@@ -45,6 +45,10 @@ export function registerTools(server, scout) {
45
45
  .string()
46
46
  .optional()
47
47
  .describe("Comma-separated search strategies: merged, orgs, starred, broad, maintained, all"),
48
+ full: z
49
+ .boolean()
50
+ .optional()
51
+ .describe("Run every enabled strategy in this search instead of one per search in rotation. More API calls, so it can take a few minutes"),
48
52
  preferLanguages: z
49
53
  .array(z.string())
50
54
  .optional()
@@ -67,7 +71,7 @@ export function registerTools(server, scout) {
67
71
  .max(1)
68
72
  .optional()
69
73
  .describe("Diversity counterweight (#1244): fraction of result slots reserved for candidates that matched NEITHER preference list. Counters echo-chamber bias when boosts accumulate over time. 0 disables, 1 reserves every slot for diversity. Default 0."),
70
- }, async ({ maxResults, strategies, preferLanguages, preferRepos, avoidRepos, boostIssueTypes, diversityRatio, }) => {
74
+ }, async ({ maxResults, strategies, full, preferLanguages, preferRepos, avoidRepos, boostIssueTypes, diversityRatio, }) => {
71
75
  try {
72
76
  // Validate each CSV entry with a readable error instead of letting a
73
77
  // raw ZodError string reach the model (#295).
@@ -84,6 +88,7 @@ export function registerTools(server, scout) {
84
88
  const result = await withTimeout(scout.search({
85
89
  maxResults: maxResults ?? 10,
86
90
  strategies: parsedStrategies,
91
+ full,
87
92
  preferLanguages,
88
93
  preferRepos,
89
94
  avoidRepos,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-scout/mcp",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "MCP server for oss-scout — exposes issue discovery and vetting as MCP tools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,16 +18,16 @@
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.32.1",
20
20
  "zod": "^4.3.6",
21
- "@oss-scout/core": "^1.8.1"
21
+ "@oss-scout/core": "^1.9.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^25.5.0",
25
- "@vitest/coverage-v8": "^4.1.4",
26
- "esbuild": "^0.27.4",
27
- "tsx": "^4.21.0",
25
+ "@vitest/coverage-v8": "^4.1.11",
26
+ "esbuild": "^0.28.1",
27
+ "tsx": "^4.23.15",
28
28
  "typescript": "^5.9.3",
29
29
  "vite": "^8.0.5",
30
- "vitest": "^4.1.4"
30
+ "vitest": "^4.1.11"
31
31
  },
32
32
  "keywords": [
33
33
  "mcp",