@usewhisper/mcp-server 2.11.0 → 2.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.
Files changed (2) hide show
  1. package/dist/server.js +171 -33
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -3799,6 +3799,7 @@ var API_KEY = process.env.WHISPER_API_KEY || "";
3799
3799
  var DEFAULT_PROJECT = process.env.WHISPER_PROJECT || "";
3800
3800
  var BASE_URL = process.env.WHISPER_BASE_URL;
3801
3801
  var RUNTIME_MODE = (process.env.WHISPER_MCP_MODE || "remote").toLowerCase();
3802
+ var MCP_RETRIEVAL_PRECISION_V1_DEFAULT = /^true$/i.test(process.env.MCP_RETRIEVAL_PRECISION_V1_DEFAULT || "false");
3802
3803
  var CLI_ARGS = process.argv.slice(2);
3803
3804
  var IS_MANAGEMENT_ONLY = CLI_ARGS.includes("--print-tool-map") || CLI_ARGS[0] === "scope";
3804
3805
  function createWhisperMcpClient(options) {
@@ -3833,6 +3834,16 @@ var server = new McpServer({
3833
3834
  function createMcpServer() {
3834
3835
  return server;
3835
3836
  }
3837
+ var WORKSPACE_HEALTH_VALUES = ["unbound", "unindexed", "stale", "drifted", "healthy"];
3838
+ var RETRIEVAL_READINESS_VALUES = [
3839
+ "no_project",
3840
+ "project_unverified",
3841
+ "project_bound_no_repo_source",
3842
+ "project_repo_source_stale",
3843
+ "project_repo_source_ready",
3844
+ "local_fallback"
3845
+ ];
3846
+ var RETRIEVAL_ROUTE_VALUES = ["project_repo", "local_workspace_fallback", "memory_only", "none"];
3836
3847
  var STATE_DIR = join(homedir(), ".whisper-mcp");
3837
3848
  var STATE_PATH = join(STATE_DIR, "state.json");
3838
3849
  var AUDIT_LOG_PATH = join(STATE_DIR, "forget-audit.log");
@@ -3874,6 +3885,75 @@ var ALIAS_TOOL_MAP = [
3874
3885
  { alias: "learn", target: "context.add_text | context.add_source | context.add_document" },
3875
3886
  { alias: "share_context", target: "context.share" }
3876
3887
  ];
3888
+ var MCP_RETRIEVAL_PROFILE_VALUES = ["legacy", "precision_v1"];
3889
+ var RECOMMENDED_NEXT_CALL_ALLOWLIST = /* @__PURE__ */ new Set([
3890
+ "index.workspace_resolve",
3891
+ "context.list_projects",
3892
+ "index.workspace_status",
3893
+ "index.workspace_run",
3894
+ "search_code",
3895
+ "grep",
3896
+ "context.list_sources",
3897
+ "context.add_source",
3898
+ "index.local_scan_ingest",
3899
+ "context.get_relevant"
3900
+ ]);
3901
+ var UNTRUSTED_CODEBASE_HEALTH = /* @__PURE__ */ new Set(["unbound", "unindexed"]);
3902
+ var UNTRUSTED_CODEBASE_PROJECT_READINESS = /* @__PURE__ */ new Set([
3903
+ "project_unverified",
3904
+ "project_bound_no_repo_source"
3905
+ ]);
3906
+ function sanitizeRecommendedNextCalls(nextCalls) {
3907
+ return Array.from(
3908
+ new Set(
3909
+ nextCalls.map((entry) => String(entry || "").trim()).filter((entry) => RECOMMENDED_NEXT_CALL_ALLOWLIST.has(entry))
3910
+ )
3911
+ );
3912
+ }
3913
+ function getRepoReadinessNextCalls(readiness) {
3914
+ if (readiness !== "project_bound_no_repo_source" && readiness !== "project_unverified") {
3915
+ return [];
3916
+ }
3917
+ if (RUNTIME_MODE === "remote") {
3918
+ return sanitizeRecommendedNextCalls([
3919
+ "context.list_sources",
3920
+ "context.add_source",
3921
+ "index.workspace_status",
3922
+ "context.get_relevant"
3923
+ ]);
3924
+ }
3925
+ return sanitizeRecommendedNextCalls([
3926
+ "context.list_sources",
3927
+ "index.local_scan_ingest",
3928
+ "index.workspace_status",
3929
+ "context.get_relevant"
3930
+ ]);
3931
+ }
3932
+ function resolveMcpRetrievalProfile(requested) {
3933
+ if (requested && MCP_RETRIEVAL_PROFILE_VALUES.includes(requested)) {
3934
+ return requested;
3935
+ }
3936
+ return MCP_RETRIEVAL_PRECISION_V1_DEFAULT ? "precision_v1" : "legacy";
3937
+ }
3938
+ function shouldAbstainForCodebaseTrust(args) {
3939
+ if (args.retrievalProfile !== "precision_v1" || !args.codebaseIntent) return false;
3940
+ return UNTRUSTED_CODEBASE_HEALTH.has(args.preflight.trust_state.health) || UNTRUSTED_CODEBASE_PROJECT_READINESS.has(args.preflight.project_retrieval_readiness);
3941
+ }
3942
+ function buildCodebaseTrustAbstainPayload(args) {
3943
+ return {
3944
+ status: "abstained",
3945
+ reason: "stale_index",
3946
+ message: args.preflight.warnings[0] || "Codebase retrieval is not trusted yet for this workspace/project. Resolve index trust before answering.",
3947
+ query: args.query,
3948
+ trust_state: args.preflight.trust_state,
3949
+ retrieval_readiness: args.preflight.retrieval_readiness,
3950
+ project_retrieval_readiness: args.preflight.project_retrieval_readiness,
3951
+ retrieval_route: args.preflight.retrieval_route,
3952
+ retrieval_profile: args.retrievalProfile,
3953
+ warnings: args.preflight.warnings,
3954
+ recommended_next_calls: sanitizeRecommendedNextCalls(args.preflight.recommended_next_calls)
3955
+ };
3956
+ }
3877
3957
  function ensureStateDir() {
3878
3958
  if (!existsSync(STATE_DIR)) {
3879
3959
  mkdirSync(STATE_DIR, { recursive: true });
@@ -4044,16 +4124,25 @@ function classifyProjectRepoReadiness(args) {
4044
4124
  function classifyRepoGroundedQuery(args) {
4045
4125
  const query = args.query.toLowerCase();
4046
4126
  let score = 0;
4047
- if (/(^|[\s"'])where is\b|which file|what file|show me|wiring|handler|middleware|implementation|route|endpoint|function|class|module|repo|workspace|code/.test(query)) {
4127
+ if (/(^|[\s"'])where is\b|which file|what file|show me|wiring|handler|middleware|implementation|route|endpoint|function|class|module|repo|workspace|code|project/.test(query)) {
4048
4128
  score += 1;
4049
4129
  }
4050
4130
  if (/\bauth\b|\burl\b|\bcookie\b|\bsession\b|\bapi\b/.test(query)) {
4051
4131
  score += 1;
4052
4132
  }
4133
+ if (/\berror\b|\berrors\b|\bexception\b|\bexceptions\b/.test(query)) {
4134
+ score += 1;
4135
+ }
4136
+ if (/\bretry\b/.test(query)) {
4137
+ score += 1;
4138
+ }
4139
+ if (/\bflow\b|\blogic\b|\bstack\b|\btrace\b|\blogging\b|\bfailure\b|\bfailures\b|\bthrow\b|\bcatch\b|\bdebug\b/.test(query)) {
4140
+ score += 1;
4141
+ }
4053
4142
  if (/[A-Za-z0-9/_-]+\.[A-Za-z0-9]+/.test(args.query) || /\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]{2,}/.test(args.query)) {
4054
4143
  score += 2;
4055
4144
  }
4056
- if (/[A-Za-z_$][A-Za-z0-9_$-]*\(/.test(args.query) || /[A-Z][A-Za-z0-9]+/.test(args.query)) {
4145
+ if (/[A-Za-z_$][A-Za-z0-9_$-]*\(/.test(args.query) || /\b[A-Z][a-z0-9]+[A-Z][A-Za-z0-9]*\b/.test(args.query)) {
4057
4146
  score += 1;
4058
4147
  }
4059
4148
  if ((args.chunk_types || []).some((chunkType) => ["code", "function", "class", "config", "schema", "api_spec"].includes(chunkType))) {
@@ -4181,9 +4270,9 @@ async function resolveProjectDescriptor(projectRef) {
4181
4270
  }
4182
4271
  }
4183
4272
  function getWorkspaceRecommendedNextCalls(health) {
4184
- if (health === "unbound") return ["index.workspace_resolve", "context.list_projects", "index.workspace_status"];
4185
- if (health === "unindexed") return ["index.workspace_status", "index.workspace_run", "search_code", "grep"];
4186
- if (health === "stale" || health === "drifted") return ["index.workspace_status", "index.workspace_run", "grep", "search_code"];
4273
+ if (health === "unbound") return sanitizeRecommendedNextCalls(["index.workspace_resolve", "context.list_projects", "index.workspace_status"]);
4274
+ if (health === "unindexed") return sanitizeRecommendedNextCalls(["index.workspace_status", "index.workspace_run", "search_code", "grep"]);
4275
+ if (health === "stale" || health === "drifted") return sanitizeRecommendedNextCalls(["index.workspace_status", "index.workspace_run", "grep", "search_code"]);
4187
4276
  return [];
4188
4277
  }
4189
4278
  function getWorkspaceWarnings(args) {
@@ -4380,17 +4469,18 @@ async function resolveRepoGroundingPreflight(args) {
4380
4469
  }
4381
4470
  const recommendedNextCalls = [...trust.recommended_next_calls];
4382
4471
  if (sourceVerification.retrieval_readiness === "project_bound_no_repo_source" || sourceVerification.retrieval_readiness === "project_unverified") {
4383
- recommendedNextCalls.push("context.list_sources", "index.local_scan_ingest");
4472
+ recommendedNextCalls.push(...getRepoReadinessNextCalls(sourceVerification.retrieval_readiness));
4384
4473
  }
4385
4474
  return {
4386
4475
  repo_grounded: repoGrounded,
4387
4476
  trust_state: trust,
4477
+ project_retrieval_readiness: sourceVerification.retrieval_readiness,
4388
4478
  retrieval_readiness: retrievalReadiness,
4389
4479
  retrieval_route: retrievalRoute,
4390
4480
  matched_sources: sourceVerification.matched_sources,
4391
4481
  matched_source_ids: sourceVerification.matched_source_ids,
4392
4482
  warnings: Array.from(new Set(warnings)),
4393
- recommended_next_calls: Array.from(new Set(recommendedNextCalls))
4483
+ recommended_next_calls: sanitizeRecommendedNextCalls(recommendedNextCalls)
4394
4484
  };
4395
4485
  }
4396
4486
  async function ingestSessionWithSyncFallback(params) {
@@ -4485,7 +4575,9 @@ function buildAbstain(args) {
4485
4575
  closest_evidence: args.closest_evidence,
4486
4576
  warnings: args.warnings || [],
4487
4577
  trust_state: args.trust_state,
4488
- recommended_next_calls: args.recommended_next_calls || ["index.workspace_status", "index.workspace_run", "grep", "context.get_relevant"],
4578
+ recommended_next_calls: sanitizeRecommendedNextCalls(
4579
+ args.recommended_next_calls || ["index.workspace_status", "index.workspace_run", "grep", "context.get_relevant"]
4580
+ ),
4489
4581
  diagnostics: {
4490
4582
  claims_evaluated: args.claims_evaluated,
4491
4583
  evidence_items_found: args.evidence_items_found,
@@ -4656,6 +4748,8 @@ async function queryWithDegradedFallback(params) {
4656
4748
  user_id: params.user_id,
4657
4749
  session_id: params.session_id,
4658
4750
  source_ids: params.source_ids,
4751
+ retrieval_profile: params.retrieval_profile,
4752
+ include_parent_content: params.include_parent_content,
4659
4753
  hybrid: true,
4660
4754
  rerank: true
4661
4755
  });
@@ -4671,6 +4765,8 @@ async function queryWithDegradedFallback(params) {
4671
4765
  user_id: params.user_id,
4672
4766
  session_id: params.session_id,
4673
4767
  source_ids: params.source_ids,
4768
+ retrieval_profile: params.retrieval_profile,
4769
+ include_parent_content: params.include_parent_content,
4674
4770
  hybrid: false,
4675
4771
  rerank: false,
4676
4772
  vector_weight: 0,
@@ -5033,7 +5129,9 @@ function saveIngestManifest(manifest) {
5033
5129
  }
5034
5130
  async function ingestLocalPath(params) {
5035
5131
  if (RUNTIME_MODE === "remote") {
5036
- throw new Error("Local ingestion is disabled in remote mode. Set WHISPER_MCP_MODE=auto or local.");
5132
+ throw new Error(
5133
+ "Local ingestion is disabled in remote mode. Use context.add_source for remote projects, or run MCP with WHISPER_MCP_MODE=auto/local."
5134
+ );
5037
5135
  }
5038
5136
  const rootPath = params.path || process.cwd();
5039
5137
  const gate = isPathAllowed(rootPath);
@@ -5311,12 +5409,10 @@ server.tool(
5311
5409
  health: trust.health,
5312
5410
  retrieval_readiness: repoVerification.retrieval_readiness,
5313
5411
  warnings: Array.from(/* @__PURE__ */ new Set([...trust.warnings, ...repoVerification.warnings])),
5314
- recommended_next_calls: Array.from(
5315
- /* @__PURE__ */ new Set([
5316
- ...trust.recommended_next_calls,
5317
- ...repoVerification.retrieval_readiness === "project_bound_no_repo_source" ? ["context.list_sources", "index.local_scan_ingest"] : []
5318
- ])
5319
- ),
5412
+ recommended_next_calls: sanitizeRecommendedNextCalls([
5413
+ ...trust.recommended_next_calls,
5414
+ ...getRepoReadinessNextCalls(repoVerification.retrieval_readiness)
5415
+ ]),
5320
5416
  freshness: trust.freshness,
5321
5417
  coverage: trust.coverage,
5322
5418
  last_indexed_commit: trust.last_indexed_commit,
@@ -5332,7 +5428,7 @@ server.tool(
5332
5428
  );
5333
5429
  server.tool(
5334
5430
  "index.workspace_run",
5335
- "Index workspace in full or incremental mode and update index metadata for freshness checks.",
5431
+ "Refresh local workspace index metadata (coverage, commit, freshness) for trust checks. This does not upload files or create backend embeddings.",
5336
5432
  {
5337
5433
  workspace_id: z.string().optional(),
5338
5434
  path: z.string().optional(),
@@ -5374,7 +5470,7 @@ server.tool(
5374
5470
  );
5375
5471
  server.tool(
5376
5472
  "index.local_scan_ingest",
5377
- "Scan a local folder safely (allowlist + secret filters), ingest changed files, and persist incremental manifest.",
5473
+ "Ingest local files into Whisper backend (chunk/embed/index) and persist incremental manifest. Requires WHISPER_MCP_MODE=auto or local.",
5378
5474
  {
5379
5475
  project: z.string().optional().describe("Project name or slug"),
5380
5476
  path: z.string().optional().describe("Local path to ingest. Defaults to current working directory."),
@@ -5410,7 +5506,7 @@ server.tool(
5410
5506
  );
5411
5507
  server.tool(
5412
5508
  "context.get_relevant",
5413
- "Default grounded retrieval step for workspace/project questions. Call this before answering when you need ranked evidence with file:line citations instead of relying on model memory.",
5509
+ "Default grounded retrieval step for workspace/project questions. Returns ranked evidence with file:line citations and may abstain when workspace/repo trust is not ready.",
5414
5510
  {
5415
5511
  question: z.string().describe("Task/question to retrieve context for"),
5416
5512
  path: z.string().optional().describe("Workspace path. Defaults to current working directory."),
@@ -5420,11 +5516,25 @@ server.tool(
5420
5516
  include_memories: z.boolean().optional().default(true),
5421
5517
  include_graph: z.boolean().optional().default(true),
5422
5518
  session_id: z.string().optional(),
5423
- user_id: z.string().optional()
5519
+ user_id: z.string().optional(),
5520
+ include_parent_content: z.boolean().optional().default(false),
5521
+ retrieval_profile: z.enum(MCP_RETRIEVAL_PROFILE_VALUES).optional()
5424
5522
  },
5425
- async ({ question, path, workspace_id, project, top_k, include_memories, include_graph, session_id, user_id }) => {
5523
+ async ({ question, path, workspace_id, project, top_k, include_memories, include_graph, session_id, user_id, include_parent_content, retrieval_profile }) => {
5426
5524
  try {
5427
5525
  const preflight = await resolveRepoGroundingPreflight({ query: question, path, workspace_id, project });
5526
+ const retrievalProfile = resolveMcpRetrievalProfile(retrieval_profile);
5527
+ if (shouldAbstainForCodebaseTrust({
5528
+ retrievalProfile,
5529
+ codebaseIntent: preflight.repo_grounded,
5530
+ preflight
5531
+ })) {
5532
+ return toTextResult(buildCodebaseTrustAbstainPayload({
5533
+ query: question,
5534
+ preflight,
5535
+ retrievalProfile
5536
+ }));
5537
+ }
5428
5538
  if (preflight.retrieval_route === "local_workspace_fallback") {
5429
5539
  const localRetrieval = await runLocalWorkspaceRetrieval({
5430
5540
  query: question,
@@ -5480,7 +5590,9 @@ server.tool(
5480
5590
  include_graph,
5481
5591
  session_id,
5482
5592
  user_id,
5483
- source_ids: preflight.repo_grounded ? preflight.matched_source_ids : void 0
5593
+ source_ids: preflight.repo_grounded ? preflight.matched_source_ids : void 0,
5594
+ retrieval_profile: retrievalProfile,
5595
+ include_parent_content
5484
5596
  });
5485
5597
  const response = queryResult.response;
5486
5598
  const rawResults = preflight.repo_grounded ? filterProjectRepoResults(response.results || [], preflight.matched_source_ids) : response.results || [];
@@ -5741,7 +5853,7 @@ server.tool(
5741
5853
  );
5742
5854
  server.tool(
5743
5855
  "context.query",
5744
- "Use this when answering from project knowledge rather than general model memory. Retrieves packed context for a query using hybrid vector+keyword search with optional memory/graph expansion.",
5856
+ "Use this when answering from project knowledge rather than general model memory. Retrieves packed context and auto-falls back between repo, local, and memory routes based on trust/readiness.",
5745
5857
  {
5746
5858
  project: z.string().optional().describe("Project name or slug (optional if WHISPER_PROJECT is set)"),
5747
5859
  query: z.string().describe("What are you looking for?"),
@@ -5752,11 +5864,25 @@ server.tool(
5752
5864
  include_graph: z.boolean().optional().default(false).describe("Include knowledge graph traversal"),
5753
5865
  user_id: z.string().optional().describe("User ID for memory scoping"),
5754
5866
  session_id: z.string().optional().describe("Session ID for memory scoping"),
5755
- max_tokens: z.number().optional().describe("Max tokens for packed context")
5867
+ max_tokens: z.number().optional().describe("Max tokens for packed context"),
5868
+ include_parent_content: z.boolean().optional().default(false),
5869
+ retrieval_profile: z.enum(MCP_RETRIEVAL_PROFILE_VALUES).optional()
5756
5870
  },
5757
- async ({ project, query, path, top_k, chunk_types, include_memories, include_graph, user_id, session_id, max_tokens }) => {
5871
+ async ({ project, query, path, top_k, chunk_types, include_memories, include_graph, user_id, session_id, max_tokens, include_parent_content, retrieval_profile }) => {
5758
5872
  try {
5759
5873
  const preflight = await resolveRepoGroundingPreflight({ query, path, project, chunk_types });
5874
+ const retrievalProfile = resolveMcpRetrievalProfile(retrieval_profile);
5875
+ if (shouldAbstainForCodebaseTrust({
5876
+ retrievalProfile,
5877
+ codebaseIntent: preflight.repo_grounded,
5878
+ preflight
5879
+ })) {
5880
+ return toTextResult(buildCodebaseTrustAbstainPayload({
5881
+ query,
5882
+ preflight,
5883
+ retrievalProfile
5884
+ }));
5885
+ }
5760
5886
  const resolvedProject = preflight.trust_state.project_ref || await resolveProjectRef(project);
5761
5887
  if (!resolvedProject && !preflight.repo_grounded) {
5762
5888
  return { content: [{ type: "text", text: "Error: No project resolved. Set WHISPER_PROJECT or pass project." }] };
@@ -5795,7 +5921,9 @@ server.tool(
5795
5921
  include_graph,
5796
5922
  user_id: user_id || scope.userId,
5797
5923
  session_id: session_id || scope.sessionId,
5798
- source_ids: preflight.matched_source_ids
5924
+ source_ids: preflight.matched_source_ids,
5925
+ retrieval_profile: retrievalProfile,
5926
+ include_parent_content
5799
5927
  });
5800
5928
  const repoResults = filterProjectRepoResults(queryResult2.response.results || [], preflight.matched_source_ids);
5801
5929
  if (repoResults.length > 0) {
@@ -5867,8 +5995,8 @@ workspace=${preflight.trust_state.workspace_id} identity_source=${preflight.trus
5867
5995
  const memoryRescue = include_memories !== false ? await runContextQueryMemoryRescue({
5868
5996
  project: resolvedProject,
5869
5997
  query,
5870
- user_id: user_id ? scope2.userId : void 0,
5871
- session_id: session_id ? scope2.sessionId : void 0,
5998
+ user_id: user_id ? scope.userId : void 0,
5999
+ session_id: session_id ? scope.sessionId : void 0,
5872
6000
  top_k
5873
6001
  }) : { results: [], rescue_mode: null };
5874
6002
  if (memoryRescue.results.length && memoryRescue.rescue_mode) {
@@ -5878,7 +6006,7 @@ workspace=${preflight.trust_state.workspace_id} identity_source=${preflight.trus
5878
6006
  text: renderContextQueryMemoryRescue({
5879
6007
  project: resolvedProject,
5880
6008
  query,
5881
- scope: scope2,
6009
+ scope,
5882
6010
  results: memoryRescue.results,
5883
6011
  rescue_mode: memoryRescue.rescue_mode
5884
6012
  })
@@ -5897,11 +6025,11 @@ ${prepared.retrieval.warnings.join("\n")}` : "";
5897
6025
  `deduped=${prepared.retrieval.dedupedCount}`,
5898
6026
  `dropped_below_floor=${prepared.retrieval.droppedBelowFloor}`
5899
6027
  ].join(" ");
5900
- const scope2 = `project=${prepared.scope.project} user=${prepared.scope.userId} session=${prepared.scope.sessionId}`;
6028
+ const scopeLabel = `project=${prepared.scope.project} user=${prepared.scope.userId} session=${prepared.scope.sessionId}`;
5901
6029
  return {
5902
6030
  content: [{
5903
6031
  type: "text",
5904
- text: `Found ${prepared.items.length} runtime-ranked items (${prepared.retrieval.durationMs}ms, ${scope2}, ${diagnostics}):
6032
+ text: `Found ${prepared.items.length} runtime-ranked items (${prepared.retrieval.durationMs}ms, ${scopeLabel}, ${diagnostics}):
5905
6033
 
5906
6034
  ${prepared.context}${warnings}`
5907
6035
  }]
@@ -5915,7 +6043,9 @@ ${prepared.context}${warnings}`
5915
6043
  include_memories: include_memories === true,
5916
6044
  include_graph,
5917
6045
  user_id: user_id || scope.userId,
5918
- session_id: session_id || scope.sessionId
6046
+ session_id: session_id || scope.sessionId,
6047
+ retrieval_profile: retrievalProfile,
6048
+ include_parent_content
5919
6049
  });
5920
6050
  const response2 = queryResult2.response;
5921
6051
  if (response2.results.length === 0) {
@@ -5968,7 +6098,9 @@ ${automaticWarning}${suffix2}` }] };
5968
6098
  include_memories: include_memories === true,
5969
6099
  include_graph,
5970
6100
  user_id: user_id || scope.userId,
5971
- session_id: session_id || scope.sessionId
6101
+ session_id: session_id || scope.sessionId,
6102
+ retrieval_profile: retrievalProfile,
6103
+ include_parent_content
5972
6104
  });
5973
6105
  const response = queryResult.response;
5974
6106
  if (response.results.length === 0) {
@@ -7861,6 +7993,10 @@ if (process.argv[1] && /server\.(mjs|cjs|js|ts)$/.test(process.argv[1])) {
7861
7993
  main().catch(console.error);
7862
7994
  }
7863
7995
  export {
7996
+ RECOMMENDED_NEXT_CALL_ALLOWLIST,
7997
+ RETRIEVAL_READINESS_VALUES,
7998
+ RETRIEVAL_ROUTE_VALUES,
7999
+ WORKSPACE_HEALTH_VALUES,
7864
8000
  canonicalizeWorkspacePath,
7865
8001
  chooseWorkspaceProjectSource,
7866
8002
  classifyProjectRepoReadiness,
@@ -7873,5 +8009,7 @@ export {
7873
8009
  renderScopedMcpConfig,
7874
8010
  resolveForgetQueryCandidates,
7875
8011
  resolveWorkspaceIdentity,
7876
- runSearchCodeSearch
8012
+ runSearchCodeSearch,
8013
+ sanitizeRecommendedNextCalls,
8014
+ shouldAbstainForCodebaseTrust
7877
8015
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usewhisper/mcp-server",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "whisperContractVersion": "2026.03.10",
5
5
  "scripts": {
6
6
  "build": "tsup ../src/mcp/server.ts --format esm --out-dir dist",