@pkgseer/cli 0.4.10 → 0.5.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/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  version
4
- } from "./shared/chunk-5nhq42tx.js";
4
+ } from "./shared/chunk-kh5enjt9.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -315,13 +315,17 @@ var SearchResultsDocument = gql`
315
315
  }
316
316
  `;
317
317
  var FetchCodeContextDocument = gql`
318
- query FetchCodeContext($repoUrl: String!, $gitRef: String!, $filePath: String!, $startLine: Int, $endLine: Int) {
318
+ query FetchCodeContext($repoUrl: String, $gitRef: String, $registry: Registry, $packageName: String, $version: String, $filePath: String!, $startLine: Int, $endLine: Int, $waitTimeoutMs: Int) {
319
319
  fetchCodeContext(
320
320
  repoUrl: $repoUrl
321
321
  gitRef: $gitRef
322
+ registry: $registry
323
+ packageName: $packageName
324
+ version: $version
322
325
  filePath: $filePath
323
326
  startLine: $startLine
324
327
  endLine: $endLine
328
+ waitTimeoutMs: $waitTimeoutMs
325
329
  ) {
326
330
  content
327
331
  filePath
@@ -656,10 +660,12 @@ var SearchPackageDocsDocument = gql`
656
660
  }
657
661
  `;
658
662
  var FindSymbolDocument = gql`
659
- query FindSymbol($registry: Registry!, $packageName: String!, $name: String, $namespace: String, $kind: SymbolKind, $publicOnly: Boolean, $version: String, $includeCode: Boolean, $contextLines: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
663
+ query FindSymbol($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $name: String, $namespace: String, $kind: SymbolKind, $publicOnly: Boolean, $version: String, $includeCode: Boolean, $contextLines: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
660
664
  findSymbol(
661
665
  registry: $registry
662
666
  packageName: $packageName
667
+ repoUrl: $repoUrl
668
+ gitRef: $gitRef
663
669
  name: $name
664
670
  namespace: $namespace
665
671
  kind: $kind
@@ -697,10 +703,12 @@ var FindSymbolDocument = gql`
697
703
  }
698
704
  `;
699
705
  var SearchSymbolsDocument = gql`
700
- query SearchSymbols($registry: Registry!, $packageName: String!, $query: String, $keywords: [String!], $matchMode: MatchMode, $kind: SymbolKind, $filePath: String, $version: String, $limit: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
706
+ query SearchSymbols($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $query: String, $keywords: [String!], $matchMode: MatchMode, $kind: SymbolKind, $filePath: String, $version: String, $limit: Int, $mode: NavigationMode, $waitTimeoutMs: Int) {
701
707
  searchSymbols(
702
708
  registry: $registry
703
709
  packageName: $packageName
710
+ repoUrl: $repoUrl
711
+ gitRef: $gitRef
704
712
  query: $query
705
713
  keywords: $keywords
706
714
  matchMode: $matchMode
@@ -743,10 +751,12 @@ var SearchSymbolsDocument = gql`
743
751
  }
744
752
  `;
745
753
  var ListSymbolsDocument = gql`
746
- query ListSymbols($registry: Registry!, $packageName: String!, $scope: ListScope!, $filePath: String, $namespace: String, $publicOnly: Boolean, $includePopularity: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
754
+ query ListSymbols($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $scope: ListScope!, $filePath: String, $namespace: String, $publicOnly: Boolean, $includePopularity: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
747
755
  listSymbols(
748
756
  registry: $registry
749
757
  packageName: $packageName
758
+ repoUrl: $repoUrl
759
+ gitRef: $gitRef
750
760
  scope: $scope
751
761
  filePath: $filePath
752
762
  namespace: $namespace
@@ -848,10 +858,12 @@ var SymbolDependentsDocument = gql`
848
858
  }
849
859
  `;
850
860
  var PackageImportsDocument = gql`
851
- query PackageImports($registry: Registry!, $packageName: String!, $filePath: String, $resolvedOnly: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
861
+ query PackageImports($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String, $resolvedOnly: Boolean, $limit: Int, $version: String, $mode: NavigationMode, $waitTimeoutMs: Int) {
852
862
  packageImports(
853
863
  registry: $registry
854
864
  packageName: $packageName
865
+ repoUrl: $repoUrl
866
+ gitRef: $gitRef
855
867
  filePath: $filePath
856
868
  resolvedOnly: $resolvedOnly
857
869
  limit: $limit
@@ -941,10 +953,12 @@ var SearchProjectDocsDocument = gql`
941
953
  }
942
954
  `;
943
955
  var ListRepoFilesDocument = gql`
944
- query ListRepoFiles($registry: Registry!, $packageName: String!, $version: String, $pathPrefix: String, $limit: Int, $waitTimeoutMs: Int) {
956
+ query ListRepoFiles($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $version: String, $pathPrefix: String, $limit: Int, $waitTimeoutMs: Int) {
945
957
  listRepoFiles(
946
958
  registry: $registry
947
959
  packageName: $packageName
960
+ repoUrl: $repoUrl
961
+ gitRef: $gitRef
948
962
  version: $version
949
963
  pathPrefix: $pathPrefix
950
964
  limit: $limit
@@ -971,10 +985,12 @@ var ListRepoFilesDocument = gql`
971
985
  }
972
986
  `;
973
987
  var GrepRepoFileDocument = gql`
974
- query GrepRepoFile($registry: Registry!, $packageName: String!, $filePath: String!, $pattern: String!, $contextLines: Int, $maxMatches: Int, $version: String, $waitTimeoutMs: Int) {
988
+ query GrepRepoFile($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $filePath: String!, $pattern: String!, $contextLines: Int, $maxMatches: Int, $version: String, $waitTimeoutMs: Int) {
975
989
  grepRepoFile(
976
990
  registry: $registry
977
991
  packageName: $packageName
992
+ repoUrl: $repoUrl
993
+ gitRef: $gitRef
978
994
  filePath: $filePath
979
995
  pattern: $pattern
980
996
  contextLines: $contextLines
@@ -1005,10 +1021,12 @@ var GrepRepoFileDocument = gql`
1005
1021
  }
1006
1022
  `;
1007
1023
  var VersionDiffDocument = gql`
1008
- query VersionDiff($registry: Registry!, $packageName: String!, $fromVersion: String!, $toVersion: String!, $includePrivate: Boolean, $kind: SymbolKind, $limit: Int, $waitTimeoutMs: Int) {
1024
+ query VersionDiff($registry: Registry, $packageName: String, $repoUrl: String, $gitRef: String, $fromVersion: String!, $toVersion: String!, $includePrivate: Boolean, $kind: SymbolKind, $limit: Int, $waitTimeoutMs: Int) {
1009
1025
  versionDiff(
1010
1026
  registry: $registry
1011
1027
  packageName: $packageName
1028
+ repoUrl: $repoUrl
1029
+ gitRef: $gitRef
1012
1030
  fromVersion: $fromVersion
1013
1031
  toVersion: $toVersion
1014
1032
  includePrivate: $includePrivate
@@ -1641,20 +1659,26 @@ var TOOL_NAMES = [
1641
1659
  "fetch_package_doc",
1642
1660
  "search",
1643
1661
  "search_status",
1644
- "fetch_code_context",
1662
+ "read_file",
1645
1663
  "search_project_docs",
1664
+ "list_files",
1665
+ "grep_file",
1646
1666
  "find_symbol",
1647
1667
  "search_symbols",
1648
1668
  "list_symbols",
1649
1669
  "symbol_callers",
1650
1670
  "symbol_callees",
1651
- "package_imports",
1671
+ "list_imports",
1652
1672
  "call_path",
1653
1673
  "trigger_indexing",
1654
- "list_repo_files",
1655
- "grep_repo_file",
1656
1674
  "version_diff"
1657
1675
  ];
1676
+ var TOOL_NAME_MIGRATION = {
1677
+ fetch_code_context: "read_file",
1678
+ list_package_files: "list_files",
1679
+ grep_package_file: "grep_file",
1680
+ package_imports: "list_imports"
1681
+ };
1658
1682
  var ToolNameSchema = z.enum(TOOL_NAMES);
1659
1683
  var SharedConfigFields = {
1660
1684
  enabled_tools: z.array(ToolNameSchema).optional()
@@ -1762,6 +1786,24 @@ class ConfigServiceImpl {
1762
1786
  if (parsed === null || parsed === undefined) {
1763
1787
  return schema.parse({});
1764
1788
  }
1789
+ if (parsed && typeof parsed === "object" && Array.isArray(parsed.enabled_tools)) {
1790
+ const migrated = [];
1791
+ let hasMigrations = false;
1792
+ for (const name of parsed.enabled_tools) {
1793
+ const replacement = TOOL_NAME_MIGRATION[name];
1794
+ if (replacement) {
1795
+ migrated.push(replacement);
1796
+ hasMigrations = true;
1797
+ } else {
1798
+ migrated.push(name);
1799
+ }
1800
+ }
1801
+ if (hasMigrations) {
1802
+ const oldNames = parsed.enabled_tools.filter((n) => TOOL_NAME_MIGRATION[n]);
1803
+ console.warn(`[pkgseer] Config at ${path}: migrating deprecated tool names: ${oldNames.join(", ")}. Update your config to use the new names.`);
1804
+ parsed.enabled_tools = migrated;
1805
+ }
1806
+ }
1765
1807
  const result = schema.safeParse(parsed);
1766
1808
  if (result.success) {
1767
1809
  return result.data;
@@ -2207,9 +2249,13 @@ class PkgseerServiceImpl {
2207
2249
  const result = await this.client.FetchCodeContext({
2208
2250
  repoUrl,
2209
2251
  gitRef,
2252
+ registry: options?.registry,
2253
+ packageName: options?.packageName,
2254
+ version: options?.version,
2210
2255
  filePath,
2211
2256
  startLine: options?.startLine,
2212
- endLine: options?.endLine
2257
+ endLine: options?.endLine,
2258
+ waitTimeoutMs: options?.waitTimeoutMs
2213
2259
  });
2214
2260
  return { data: result.data, errors: result.errors };
2215
2261
  }
@@ -2217,6 +2263,8 @@ class PkgseerServiceImpl {
2217
2263
  const result = await this.client.FindSymbol({
2218
2264
  registry,
2219
2265
  packageName,
2266
+ repoUrl: options?.repoUrl,
2267
+ gitRef: options?.gitRef,
2220
2268
  name: options?.name,
2221
2269
  namespace: options?.namespace,
2222
2270
  kind: options?.kind,
@@ -2233,6 +2281,8 @@ class PkgseerServiceImpl {
2233
2281
  const result = await this.client.SearchSymbols({
2234
2282
  registry,
2235
2283
  packageName,
2284
+ repoUrl: options?.repoUrl,
2285
+ gitRef: options?.gitRef,
2236
2286
  query: options?.query,
2237
2287
  keywords: options?.keywords,
2238
2288
  matchMode: options?.matchMode,
@@ -2249,6 +2299,8 @@ class PkgseerServiceImpl {
2249
2299
  const result = await this.client.ListSymbols({
2250
2300
  registry,
2251
2301
  packageName,
2302
+ repoUrl: options?.repoUrl,
2303
+ gitRef: options?.gitRef,
2252
2304
  scope,
2253
2305
  filePath: options?.filePath,
2254
2306
  namespace: options?.namespace,
@@ -2289,6 +2341,8 @@ class PkgseerServiceImpl {
2289
2341
  const result = await this.client.PackageImports({
2290
2342
  registry,
2291
2343
  packageName,
2344
+ repoUrl: options?.repoUrl,
2345
+ gitRef: options?.gitRef,
2292
2346
  filePath: options?.filePath,
2293
2347
  resolvedOnly: options?.resolvedOnly,
2294
2348
  limit: options?.limit,
@@ -2312,6 +2366,8 @@ class PkgseerServiceImpl {
2312
2366
  const result = await this.client.ListRepoFiles({
2313
2367
  registry,
2314
2368
  packageName,
2369
+ repoUrl: options?.repoUrl,
2370
+ gitRef: options?.gitRef,
2315
2371
  version: options?.version,
2316
2372
  pathPrefix: options?.pathPrefix,
2317
2373
  limit: options?.limit,
@@ -2323,6 +2379,8 @@ class PkgseerServiceImpl {
2323
2379
  const result = await this.client.GrepRepoFile({
2324
2380
  registry,
2325
2381
  packageName,
2382
+ repoUrl: options?.repoUrl,
2383
+ gitRef: options?.gitRef,
2326
2384
  filePath,
2327
2385
  pattern,
2328
2386
  contextLines: options?.contextLines,
@@ -2336,6 +2394,8 @@ class PkgseerServiceImpl {
2336
2394
  const result = await this.client.VersionDiff({
2337
2395
  registry,
2338
2396
  packageName,
2397
+ repoUrl: options?.repoUrl,
2398
+ gitRef: options?.gitRef,
2339
2399
  fromVersion,
2340
2400
  toVersion,
2341
2401
  includePrivate: options?.includePrivate,
@@ -2749,8 +2809,8 @@ function outputError(message, json) {
2749
2809
  }
2750
2810
  var CLI_HINTS = {
2751
2811
  being_indexed: " Hint: package is being indexed. Try again with a longer --wait value (e.g., --wait 30000).",
2752
- timeout: " Hint: lower the limit or narrow the scope, then retry.",
2753
- not_found: " Hint: verify the name/registry and that the resource exists.",
2812
+ timeout: " Hint: this may be transient — retry the same command. If the issue persists, try simplifying the query.",
2813
+ not_found: " Hint: verify the package name and registry are correct.",
2754
2814
  auth: " Hint: check login or token validity (pkgseer auth-status).",
2755
2815
  rate_limit: " Hint: wait and retry, or reduce request frequency.",
2756
2816
  unknown: ""
@@ -3007,14 +3067,10 @@ async function codeCalleesAction(symbolArg, options, deps) {
3007
3067
  waitTimeoutMs: parseWaitTimeout(options.wait)
3008
3068
  });
3009
3069
  handleErrors(result.errors, options.json ?? false);
3010
- if (!result.data?.symbolDependencies) {
3011
- outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
3012
- return;
3013
- }
3014
3070
  if (options.json) {
3015
- output(result.data?.symbolDependencies, true);
3071
+ output(result.data.symbolDependencies, true);
3016
3072
  } else {
3017
- console.log(formatCalleesResult(result.data?.symbolDependencies));
3073
+ console.log(formatCalleesResult(result.data.symbolDependencies));
3018
3074
  }
3019
3075
  }
3020
3076
  var CALLEES_DESCRIPTION = `Find what a symbol calls.
@@ -3058,14 +3114,10 @@ async function codeCallersAction(symbolArg, options, deps) {
3058
3114
  waitTimeoutMs: parseWaitTimeout(options.wait)
3059
3115
  });
3060
3116
  handleErrors(result.errors, options.json ?? false);
3061
- if (!result.data?.symbolDependents) {
3062
- outputError("Symbol not found. Verify the symbol reference or use --ref.", options.json ?? false);
3063
- return;
3064
- }
3065
3117
  if (options.json) {
3066
- output(result.data?.symbolDependents, true);
3118
+ output(result.data.symbolDependents, true);
3067
3119
  } else {
3068
- console.log(formatCallersResult(result.data?.symbolDependents));
3120
+ console.log(formatCallersResult(result.data.symbolDependents));
3069
3121
  }
3070
3122
  }
3071
3123
  var CALLERS_DESCRIPTION = `Find what calls a symbol.
@@ -3130,14 +3182,10 @@ async function codeDiffAction(packageArg, fromVersion, toVersion, options, deps)
3130
3182
  waitTimeoutMs: parseWaitTimeout(options.wait)
3131
3183
  });
3132
3184
  handleErrors(result.errors, options.json ?? false);
3133
- if (!result.data?.versionDiff) {
3134
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3135
- return;
3136
- }
3137
3185
  if (options.json) {
3138
- output(result.data?.versionDiff, true);
3186
+ output(result.data.versionDiff, true);
3139
3187
  } else {
3140
- console.log(formatDiffResult(result.data?.versionDiff));
3188
+ console.log(formatDiffResult(result.data.versionDiff));
3141
3189
  }
3142
3190
  }
3143
3191
  var DIFF_DESCRIPTION = `Compare symbols between two package versions.
@@ -3190,11 +3238,7 @@ async function codeFilesAction(packageArg, options, deps) {
3190
3238
  waitTimeoutMs: parseWaitTimeout(options.wait)
3191
3239
  });
3192
3240
  handleErrors(result.errors, options.json ?? false);
3193
- if (!result.data?.listRepoFiles) {
3194
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3195
- return;
3196
- }
3197
- const data = result.data?.listRepoFiles;
3241
+ const data = result.data.listRepoFiles;
3198
3242
  if (options.json) {
3199
3243
  output(data, true);
3200
3244
  } else {
@@ -3255,11 +3299,7 @@ async function codeFindAction(packageArg, nameArg, options, deps) {
3255
3299
  waitTimeoutMs: parseWaitTimeout(options.wait)
3256
3300
  });
3257
3301
  handleErrors(result.errors, options.json ?? false);
3258
- if (!result.data?.findSymbol) {
3259
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3260
- return;
3261
- }
3262
- const data = result.data?.findSymbol;
3302
+ const data = result.data.findSymbol;
3263
3303
  if (options.json) {
3264
3304
  output(data, true);
3265
3305
  } else {
@@ -3329,11 +3369,7 @@ async function codeGrepAction(packageArg, filePath, pattern, options, deps) {
3329
3369
  waitTimeoutMs: parseWaitTimeout(options.wait)
3330
3370
  });
3331
3371
  handleErrors(result.errors, options.json ?? false);
3332
- if (!result.data?.grepRepoFile) {
3333
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3334
- return;
3335
- }
3336
- const data = result.data?.grepRepoFile;
3372
+ const data = result.data.grepRepoFile;
3337
3373
  if (options.json) {
3338
3374
  output(data, true);
3339
3375
  } else {
@@ -3416,14 +3452,10 @@ async function codeImportsAction(packageArg, options, deps) {
3416
3452
  waitTimeoutMs: parseWaitTimeout(options.wait)
3417
3453
  });
3418
3454
  handleErrors(result.errors, options.json ?? false);
3419
- if (!result.data?.packageImports) {
3420
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3421
- return;
3422
- }
3423
3455
  if (options.json) {
3424
- output(result.data?.packageImports, true);
3456
+ output(result.data.packageImports, true);
3425
3457
  } else {
3426
- console.log(formatImportsResult(result.data?.packageImports));
3458
+ console.log(formatImportsResult(result.data.packageImports));
3427
3459
  }
3428
3460
  }
3429
3461
  var IMPORTS_DESCRIPTION = `List import statements in a package.
@@ -3485,14 +3517,10 @@ async function codeListAction(packageArg, options, deps) {
3485
3517
  waitTimeoutMs: parseWaitTimeout(options.wait)
3486
3518
  });
3487
3519
  handleErrors(result.errors, options.json ?? false);
3488
- if (!result.data?.listSymbols) {
3489
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3490
- return;
3491
- }
3492
3520
  if (options.json) {
3493
- output(result.data?.listSymbols, true);
3521
+ output(result.data.listSymbols, true);
3494
3522
  } else {
3495
- console.log(formatListResult(result.data?.listSymbols));
3523
+ console.log(formatListResult(result.data.listSymbols));
3496
3524
  }
3497
3525
  }
3498
3526
  var LIST_DESCRIPTION = `Browse symbols in a package.
@@ -3550,14 +3578,10 @@ async function codePathAction(fromArg, toArg, options, deps) {
3550
3578
  waitTimeoutMs: parseWaitTimeout(options.wait)
3551
3579
  });
3552
3580
  handleErrors(result.errors, options.json ?? false);
3553
- if (!result.data?.callPath) {
3554
- outputError("Could not find call path. Verify the symbol references.", options.json ?? false);
3555
- return;
3556
- }
3557
3581
  if (options.json) {
3558
- output(result.data?.callPath, true);
3582
+ output(result.data.callPath, true);
3559
3583
  } else {
3560
- console.log(formatPathResult(result.data?.callPath));
3584
+ console.log(formatPathResult(result.data.callPath));
3561
3585
  }
3562
3586
  }
3563
3587
  var PATH_DESCRIPTION = `Find call path between two symbols.
@@ -3630,11 +3654,7 @@ async function codeSearchAction(packageArg, query, options, deps) {
3630
3654
  waitTimeoutMs: parseWaitTimeout(options.wait)
3631
3655
  });
3632
3656
  handleErrors(result.errors, options.json ?? false);
3633
- if (!result.data?.searchSymbols) {
3634
- outputError(`Package not found: ${parsed.name} in ${parsed.registry}`, options.json ?? false);
3635
- return;
3636
- }
3637
- const data = result.data?.searchSymbols;
3657
+ const data = result.data.searchSymbols;
3638
3658
  if (options.json) {
3639
3659
  output(data, true);
3640
3660
  } else {
@@ -5118,7 +5138,7 @@ async function setupCodexViaCli(shellService) {
5118
5138
  }
5119
5139
  function showAvailableTools(hasProject, useColors) {
5120
5140
  console.log(`
5121
- Available MCP tools (21):`);
5141
+ Available MCP tools (22):`);
5122
5142
  console.log("");
5123
5143
  console.log(" Navigate source:");
5124
5144
  console.log(" • find_symbol - Read source code of functions/classes");
@@ -5129,8 +5149,8 @@ Available MCP tools (21):`);
5129
5149
  console.log(" • call_path - Find call path between two functions");
5130
5150
  console.log("");
5131
5151
  console.log(" Browse files:");
5132
- console.log(" • list_repo_files - Explore package file structure");
5133
- console.log(" • grep_repo_file - Search for patterns in source files");
5152
+ console.log(" • list_package_files - Explore package file structure");
5153
+ console.log(" • grep_package_file - Search for patterns in source files");
5134
5154
  console.log(" • fetch_code_context - Read source by file path and line range");
5135
5155
  console.log("");
5136
5156
  console.log(" Search & docs:");
@@ -6782,27 +6802,99 @@ function toListScope(scope) {
6782
6802
  var schemas = {
6783
6803
  registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).describe("Package registry (npm, pypi, hex, crates, nuget, maven, zig, or vcpkg)"),
6784
6804
  packageName: z2.string().max(255).describe("Name of the package"),
6785
- version: z2.string().max(100).optional().describe("Specific version (defaults to latest)"),
6805
+ version: z2.string().max(100).optional().describe("Specific version, e.g. '4.18.2' (defaults to latest)"),
6786
6806
  navigationMode: z2.enum(["summary", "detailed"]).optional().describe("Response detail level. summary (default) returns core fields; detailed adds all optional fields."),
6787
- waitTimeoutMs: z2.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000). 0 = error immediately if not indexed."),
6807
+ waitTimeoutMs: z2.coerce.number().int().min(0).max(30000).optional().describe("Max milliseconds to wait for package indexing (0-30000, default 10000). Set 0 to error immediately if not indexed."),
6788
6808
  symbolReference: z2.object({
6789
6809
  symbol_ref: z2.string().optional().describe("Compound symbol reference (registry:package:version:id) from find_symbol or list_symbols results. Self-contained — no additional fields needed."),
6790
- registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry (required for name-based lookup)"),
6791
- package_name: z2.string().max(255).optional().describe("Package name (required for name-based lookup)"),
6792
- symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath.")
6793
- })
6810
+ registry: z2.enum(["npm", "pypi", "hex", "crates", "nuget", "maven", "zig", "vcpkg"]).optional().describe("Package registry. For package-scoped lookup (with package_name + symbol_name)."),
6811
+ package_name: z2.string().max(255).optional().describe("Package name. For package-scoped lookup (with registry + symbol_name)."),
6812
+ symbol_name: z2.string().max(500).optional().describe("Symbol name or qualified path (required for name-based lookup). Matches both short name and qualifiedPath."),
6813
+ version: z2.string().max(100).optional().describe("Package version. For package-scoped lookup."),
6814
+ repo_url: z2.string().optional().describe("Repository URL (GitHub). For repo-scoped lookup (with git_ref + symbol_name)."),
6815
+ git_ref: z2.string().optional().describe("Git ref (tag, branch, commit, or HEAD). Required with repo_url.")
6816
+ }),
6817
+ codeTarget: z2.object({
6818
+ registry: z2.enum([
6819
+ "npm",
6820
+ "pypi",
6821
+ "hex",
6822
+ "crates",
6823
+ "nuget",
6824
+ "maven",
6825
+ "zig",
6826
+ "vcpkg"
6827
+ ]).optional().describe("Package registry (npm, pypi, hex, etc.). Required for package scope."),
6828
+ package_name: z2.string().max(255).optional().describe("Package name. Required for package scope."),
6829
+ version: z2.string().max(100).optional().describe("Package version, e.g. '4.18.2' (defaults to latest). For package scope only."),
6830
+ repo_url: z2.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
6831
+ git_ref: z2.string().optional().describe("Git ref — tag, branch, or commit. Required for repo scope. Use HEAD for latest.")
6832
+ }).describe("Target: provide registry + package_name (package scope) OR repo_url + git_ref (repo scope).")
6794
6833
  };
6795
6834
  function toSymbolReferenceInput(ref) {
6796
6835
  return {
6797
6836
  symbolRef: ref.symbol_ref,
6798
6837
  registry: ref.registry ? toGraphQLRegistry(ref.registry) : undefined,
6799
6838
  packageName: ref.package_name,
6800
- symbolName: ref.symbol_name
6839
+ symbolName: ref.symbol_name,
6840
+ version: ref.version,
6841
+ repoUrl: ref.repo_url,
6842
+ gitRef: ref.git_ref
6843
+ };
6844
+ }
6845
+ function isToolError(value) {
6846
+ return "content" in value;
6847
+ }
6848
+ function resolveCodeTarget(target) {
6849
+ const hasPackage = target.registry || target.package_name;
6850
+ const hasRepo = target.repo_url || target.git_ref;
6851
+ if (hasPackage && hasRepo) {
6852
+ return errorResult("Invalid target: provide either registry + package_name (package scope) or repo_url + git_ref (repo scope), not both.");
6853
+ }
6854
+ if (!hasPackage && !hasRepo) {
6855
+ return errorResult("Missing target: provide registry + package_name (package scope) or repo_url + git_ref (repo scope).");
6856
+ }
6857
+ if (hasPackage) {
6858
+ if (!target.registry || !target.package_name) {
6859
+ return errorResult("Incomplete package target: both registry and package_name are required for package scope.");
6860
+ }
6861
+ return {
6862
+ mode: "package",
6863
+ registry: target.registry,
6864
+ packageName: target.package_name,
6865
+ version: target.version
6866
+ };
6867
+ }
6868
+ if (!target.repo_url) {
6869
+ return errorResult("Incomplete repo target: repo_url is required with git_ref.");
6870
+ }
6871
+ if (!target.git_ref) {
6872
+ return errorResult("Incomplete repo target: git_ref is required with repo_url (use HEAD for latest).");
6873
+ }
6874
+ return { mode: "repo", repoUrl: target.repo_url, gitRef: target.git_ref };
6875
+ }
6876
+ function buildCodeTargetVars(resolved) {
6877
+ if (resolved.mode === "package") {
6878
+ return {
6879
+ registry: toGraphQLRegistry(resolved.registry),
6880
+ packageName: resolved.packageName,
6881
+ version: resolved.version,
6882
+ repoUrl: undefined,
6883
+ gitRef: undefined
6884
+ };
6885
+ }
6886
+ return {
6887
+ registry: undefined,
6888
+ packageName: undefined,
6889
+ version: undefined,
6890
+ repoUrl: resolved.repoUrl,
6891
+ gitRef: resolved.gitRef
6801
6892
  };
6802
6893
  }
6894
+ var DEFAULT_WAIT_TIMEOUT_MS2 = 1e4;
6803
6895
  var MCP_HINTS = {
6804
6896
  being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6805
- timeout: "Hint: try lowering the limit or narrowing the scope, then retry."
6897
+ timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6806
6898
  };
6807
6899
  function buildHintedMessage(operation, message) {
6808
6900
  const kind = classifyError(message);
@@ -6830,9 +6922,9 @@ function buildHintedMessage(operation, message) {
6830
6922
  return `Failed to ${operation}: ${message}`;
6831
6923
  }
6832
6924
  var MCP_GRAPHQL_HINTS = {
6833
- not_found: "Hint: verify the name/registry and that the resource exists.",
6925
+ not_found: "Hint: verify the package name and registry are correct.",
6834
6926
  being_indexed: "Hint: package is being indexed. Try again with a longer wait_timeout_ms (e.g., 30000).",
6835
- timeout: "Hint: try lowering the limit or narrowing the scope, then retry."
6927
+ timeout: "Hint: this may be transient — retry the same query. If the issue persists, try simplifying the query."
6836
6928
  };
6837
6929
  function handleGraphQLErrors(errors) {
6838
6930
  if (errors && errors.length > 0) {
@@ -6852,45 +6944,42 @@ async function withErrorHandling(operation, fn) {
6852
6944
  }
6853
6945
  }
6854
6946
  function notFoundError(packageName, registry) {
6855
- return errorResult(`Package not found: ${packageName} in ${registry}`);
6947
+ return errorResult(`Package not found: ${packageName} in ${registry}. Verify the package name and registry are correct.`);
6856
6948
  }
6857
6949
 
6858
6950
  // src/tools/call-path.ts
6859
6951
  var argsSchema = {
6860
- from: schemas.symbolReference.describe("Source symbol. Provide either symbol_ref or registry + package_name + symbol_name."),
6861
- to: schemas.symbolReference.describe("Destination symbol. Provide either symbol_ref or registry + package_name + symbol_name."),
6862
- max_depth: z3.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
6952
+ from: schemas.symbolReference.describe("Source symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
6953
+ to: schemas.symbolReference.describe("Destination symbol. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
6954
+ max_depth: z3.coerce.number().int().min(1).max(10).optional().describe("Maximum path length to search (max hops between from and to)"),
6863
6955
  mode: schemas.navigationMode,
6864
6956
  wait_timeout_ms: schemas.waitTimeoutMs
6865
6957
  };
6866
6958
  function createCallPathTool(pkgseerService) {
6867
6959
  return {
6868
6960
  name: "call_path",
6869
- description: "Trace how execution flows from one function to another in a dependency — " + "debug how a public API reaches an internal function or error handler. " + "Uses BFS through intermediate calls. " + "Returns ordered call paths (shortest first) with hop details. " + "For direct callers/callees only, use symbol_callers or symbol_callees instead.",
6961
+ description: "Trace how execution flows from one function to another in a dependency — " + "debug how a public API reaches an internal function or error handler. " + "Uses BFS through intermediate calls. " + "Returns ordered call paths (shortest first) with hop details. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "For direct callers/callees only, use symbol_callers or symbol_callees instead.",
6870
6962
  schema: argsSchema,
6871
6963
  annotations: { readOnlyHint: true },
6872
6964
  handler: async (args, _extra) => {
6873
6965
  return withErrorHandling("find call path", async () => {
6874
6966
  const fromInput = toSymbolReferenceInput(args.from);
6875
6967
  const toInput = toSymbolReferenceInput(args.to);
6876
- if (!fromInput.symbolRef && (!fromInput.symbolName || !fromInput.registry || !fromInput.packageName)) {
6877
- return errorResult("Invalid 'from' symbol: provide either symbol_ref or symbol_name with registry and package_name.");
6968
+ if (!fromInput.symbolRef && !(fromInput.symbolName && fromInput.registry && fromInput.packageName) && !(fromInput.symbolName && fromInput.repoUrl && fromInput.gitRef)) {
6969
+ return errorResult("Invalid 'from' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
6878
6970
  }
6879
- if (!toInput.symbolRef && (!toInput.symbolName || !toInput.registry || !toInput.packageName)) {
6880
- return errorResult("Invalid 'to' symbol: provide either symbol_ref or symbol_name with registry and package_name.");
6971
+ if (!toInput.symbolRef && !(toInput.symbolName && toInput.registry && toInput.packageName) && !(toInput.symbolName && toInput.repoUrl && toInput.gitRef)) {
6972
+ return errorResult("Invalid 'to' symbol: provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
6881
6973
  }
6882
6974
  const result = await pkgseerService.callPath(fromInput, toInput, {
6883
6975
  maxDepth: args.max_depth,
6884
6976
  mode: toNavigationMode(args.mode),
6885
- waitTimeoutMs: args.wait_timeout_ms
6977
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
6886
6978
  });
6887
6979
  const graphqlError = handleGraphQLErrors(result.errors);
6888
6980
  if (graphqlError)
6889
6981
  return graphqlError;
6890
- if (!result.data?.callPath) {
6891
- return errorResult("Could not find call path. Verify the symbols exist and the package is indexed.");
6892
- }
6893
- return textResult(JSON.stringify(result.data?.callPath, null, 2));
6982
+ return textResult(JSON.stringify(result.data.callPath, null, 2));
6894
6983
  });
6895
6984
  }
6896
6985
  };
@@ -6908,7 +6997,7 @@ var argsSchema2 = {
6908
6997
  function createComparePackagesTool(pkgseerService) {
6909
6998
  return {
6910
6999
  name: "compare_packages",
6911
- description: "Compare 2-10 packages side-by-side. Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
7000
+ description: "Compare 2-10 packages side-by-side (available immediately — no indexing required). " + "Use this when evaluating alternatives (e.g., react vs preact vs solid-js). " + "Returns for each package: quality score, download counts, vulnerability count, license, and latest version. " + "Supports cross-registry comparison (npm, pypi, hex, crates). " + 'Format: [{"registry":"npm","name":"lodash"},{"registry":"npm","name":"underscore"}]',
6912
7001
  schema: argsSchema2,
6913
7002
  annotations: { readOnlyHint: true },
6914
7003
  handler: async ({ packages }, _extra) => {
@@ -6930,48 +7019,16 @@ function createComparePackagesTool(pkgseerService) {
6930
7019
  }
6931
7020
  };
6932
7021
  }
6933
- // src/tools/fetch-code-context.ts
7022
+ // src/tools/fetch-package-doc.ts
6934
7023
  import { z as z5 } from "zod";
6935
7024
  var argsSchema3 = {
6936
- repo_url: z5.string().min(1).describe("Repository URL (GitHub). Example: https://github.com/expressjs/express"),
6937
- git_ref: z5.string().min(1).describe("Git reference (tag, commit, or branch). Example: v4.18.2"),
6938
- file_path: z5.string().min(1).describe("Path to file in repository. Example: src/router/index.js"),
6939
- start_line: z5.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
6940
- end_line: z5.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file.")
6941
- };
6942
- function createFetchCodeContextTool(pkgseerService) {
6943
- return {
6944
- name: "fetch_code_context",
6945
- description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Requires repo_url, git_ref, and file_path.",
6946
- schema: argsSchema3,
6947
- annotations: { readOnlyHint: true },
6948
- handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
6949
- return withErrorHandling("fetch code context", async () => {
6950
- const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
6951
- startLine: start_line,
6952
- endLine: end_line
6953
- });
6954
- const graphqlError = handleGraphQLErrors(result.errors);
6955
- if (graphqlError)
6956
- return graphqlError;
6957
- if (!result.data?.fetchCodeContext) {
6958
- return errorResult(`Code not found: ${file_path} at ${git_ref} in ${repo_url}. ` + "Check that the repository, file path, and git ref are correct.");
6959
- }
6960
- return textResult(JSON.stringify(result.data?.fetchCodeContext, null, 2));
6961
- });
6962
- }
6963
- };
6964
- }
6965
- // src/tools/fetch-package-doc.ts
6966
- import { z as z6 } from "zod";
6967
- var argsSchema4 = {
6968
- page_id: z6.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
7025
+ page_id: z5.string().max(500).describe("Globally unique documentation page identifier (from list_package_docs)")
6969
7026
  };
6970
7027
  function createFetchPackageDocTool(pkgseerService) {
6971
7028
  return {
6972
7029
  name: "fetch_package_doc",
6973
- description: "Get full content of a documentation page. Requires page_id from list_package_docs. " + "Returns: title, full content (markdown/HTML), format type, navigation breadcrumbs, " + "source URL, and last updated timestamp. Use this when you need complete documentation, " + "not just search snippets.",
6974
- schema: argsSchema4,
7030
+ description: "Get full content of a documentation page. Requires page_id from list_package_docs. " + "Returns: title, full content (markdown/HTML), format type, navigation breadcrumbs, " + "source URL, and last updated timestamp. Use this when you need complete documentation, " + "not just search snippets. " + "Requires documentation to have been crawled — if page_id is from a stale listing, re-check with list_package_docs.",
7031
+ schema: argsSchema3,
6975
7032
  annotations: { readOnlyHint: true },
6976
7033
  handler: async ({ page_id }, _extra) => {
6977
7034
  return withErrorHandling("fetch documentation page", async () => {
@@ -6988,13 +7045,12 @@ function createFetchPackageDocTool(pkgseerService) {
6988
7045
  };
6989
7046
  }
6990
7047
  // src/tools/find-symbol.ts
6991
- import { z as z7 } from "zod";
6992
- var argsSchema5 = {
6993
- registry: schemas.registry,
6994
- package_name: schemas.packageName.describe("Name of the package to search for symbols"),
6995
- name: z7.string().max(500).optional().describe("Symbol name to search for (exact match or prefix). Omit to return all public exports."),
6996
- namespace: z7.string().max(500).optional().describe("Filter by namespace/module path prefix"),
6997
- kind: z7.enum([
7048
+ import { z as z6 } from "zod";
7049
+ var argsSchema4 = {
7050
+ target: schemas.codeTarget,
7051
+ name: z6.string().max(500).optional().describe("Symbol name to search for (exact match or prefix). Omit to return all public exports."),
7052
+ namespace: z6.string().max(500).optional().describe("Filter by namespace/module path prefix"),
7053
+ kind: z6.enum([
6998
7054
  "function",
6999
7055
  "method",
7000
7056
  "class",
@@ -7003,39 +7059,41 @@ var argsSchema5 = {
7003
7059
  "type",
7004
7060
  "doc_section"
7005
7061
  ]).optional().describe("Filter by symbol kind"),
7006
- public_only: z7.boolean().optional().describe("Only return public/exported symbols"),
7007
- version: schemas.version,
7008
- include_code: z7.boolean().optional().describe("Include source code in results"),
7009
- context_lines: z7.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
7062
+ public_only: z6.boolean().optional().describe("Only return public/exported symbols"),
7063
+ include_code: z6.boolean().optional().describe("Include source code in results"),
7064
+ context_lines: z6.coerce.number().int().min(0).max(30).optional().describe("Lines of surrounding context when include_code=true (max 30)"),
7010
7065
  mode: schemas.navigationMode,
7011
7066
  wait_timeout_ms: schemas.waitTimeoutMs
7012
7067
  };
7013
7068
  function createFindSymbolTool(pkgseerService) {
7014
7069
  return {
7015
7070
  name: "find_symbol",
7016
- description: "Read source code of any function, class, or method in a third-party package " + "use instead of guessing implementations from training data. " + "Set include_code=true for full source inline. " + "Returns: symbol ref, name, qualified path, kind, file location, and optionally source code. " + "Omit name to get all public exports. Use namespace to filter by module path.",
7017
- schema: argsSchema5,
7071
+ description: "Read source code of any function, class, or method use instead of guessing " + "implementations from training data. Accepts package scope (registry + package_name) " + "or repo scope (repo_url + git_ref) via the target parameter. " + "Set include_code=true for full source inline. " + "Returns: symbolRef, name, qualified path, kind, file location, and optionally source code. " + "Omit name to get all public exports. Use namespace to filter by module path. " + "Pass symbolRef from results to symbol_callers, symbol_callees, or call_path.",
7072
+ schema: argsSchema4,
7018
7073
  annotations: { readOnlyHint: true },
7019
7074
  handler: async (args, _extra) => {
7020
7075
  return withErrorHandling("find symbol", async () => {
7021
- const result = await pkgseerService.findSymbol(toGraphQLRegistry(args.registry), args.package_name, {
7076
+ const resolved = resolveCodeTarget(args.target);
7077
+ if (isToolError(resolved))
7078
+ return resolved;
7079
+ const tv = buildCodeTargetVars(resolved);
7080
+ const result = await pkgseerService.findSymbol(tv.registry, tv.packageName, {
7022
7081
  name: args.name,
7023
7082
  namespace: args.namespace,
7024
7083
  kind: toSymbolKind(args.kind),
7025
7084
  publicOnly: args.public_only,
7026
- version: args.version,
7085
+ version: tv.version,
7027
7086
  includeCode: args.include_code,
7028
7087
  contextLines: args.context_lines,
7029
7088
  mode: toNavigationMode(args.mode),
7030
- waitTimeoutMs: args.wait_timeout_ms
7089
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7090
+ repoUrl: tv.repoUrl,
7091
+ gitRef: tv.gitRef
7031
7092
  });
7032
7093
  const graphqlError = handleGraphQLErrors(result.errors);
7033
7094
  if (graphqlError)
7034
7095
  return graphqlError;
7035
- if (!result.data?.findSymbol) {
7036
- return notFoundError(args.package_name, args.registry);
7037
- }
7038
- const data = result.data?.findSymbol;
7096
+ const data = result.data.findSymbol;
7039
7097
  if (data.symbols.length === 0 && data.diagnostics?.hint) {
7040
7098
  return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7041
7099
  }
@@ -7044,39 +7102,40 @@ function createFindSymbolTool(pkgseerService) {
7044
7102
  }
7045
7103
  };
7046
7104
  }
7047
- // src/tools/grep-repo-file.ts
7048
- import { z as z8 } from "zod";
7049
- var argsSchema6 = {
7050
- registry: schemas.registry,
7051
- package_name: schemas.packageName.describe("Name of the package to search within"),
7052
- file_path: z8.string().describe("Path to the file (relative to package root)"),
7053
- pattern: z8.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
7054
- context_lines: z8.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
7055
- max_matches: z8.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
7056
- version: schemas.version,
7105
+ // src/tools/grep-file.ts
7106
+ import { z as z7 } from "zod";
7107
+ var argsSchema5 = {
7108
+ target: schemas.codeTarget,
7109
+ file_path: z7.string().describe("Path to the file (relative to package root)"),
7110
+ pattern: z7.string().max(200).describe("Case-insensitive substring to search for (max 200 chars)"),
7111
+ context_lines: z7.coerce.number().int().min(0).max(10).optional().describe("Lines of context around each match (max 10)"),
7112
+ max_matches: z7.coerce.number().int().min(1).max(200).optional().describe("Maximum matches to return (max 200)"),
7057
7113
  wait_timeout_ms: schemas.waitTimeoutMs
7058
7114
  };
7059
- function createGrepRepoFileTool(pkgseerService) {
7115
+ function createGrepFileTool(pkgseerService) {
7060
7116
  return {
7061
- name: "grep_repo_file",
7062
- description: "Search for a pattern within a dependency's source file — " + "find error messages, config keys, or specific patterns without cloning the repo. " + "Case-insensitive substring matching with context lines. " + "Faster than fetch_code_context for large files. " + "Use list_repo_files to discover file paths.",
7063
- schema: argsSchema6,
7117
+ name: "grep_file",
7118
+ description: "Search for a pattern within a dependency's source file — " + "find error messages, config keys, or specific patterns without cloning the repo. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Case-insensitive substring matching with context lines. " + "Use when you know the file path and are looking for specific text. " + "Use list_files to discover file paths. " + "In monorepos with package scope, operates only within this package's subdirectory. " + "Requires code indexing.",
7119
+ schema: argsSchema5,
7064
7120
  annotations: { readOnlyHint: true },
7065
7121
  handler: async (args, _extra) => {
7066
- return withErrorHandling("grep repo file", async () => {
7067
- const result = await pkgseerService.grepRepoFile(toGraphQLRegistry(args.registry), args.package_name, args.file_path, args.pattern, {
7122
+ return withErrorHandling("grep file", async () => {
7123
+ const resolved = resolveCodeTarget(args.target);
7124
+ if (isToolError(resolved))
7125
+ return resolved;
7126
+ const tv = buildCodeTargetVars(resolved);
7127
+ const result = await pkgseerService.grepRepoFile(tv.registry, tv.packageName, args.file_path, args.pattern, {
7068
7128
  contextLines: args.context_lines,
7069
7129
  maxMatches: args.max_matches,
7070
- version: args.version,
7071
- waitTimeoutMs: args.wait_timeout_ms
7130
+ version: tv.version,
7131
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7132
+ repoUrl: tv.repoUrl,
7133
+ gitRef: tv.gitRef
7072
7134
  });
7073
7135
  const graphqlError = handleGraphQLErrors(result.errors);
7074
7136
  if (graphqlError)
7075
7137
  return graphqlError;
7076
- if (!result.data?.grepRepoFile) {
7077
- return notFoundError(args.package_name, args.registry);
7078
- }
7079
- const data = result.data?.grepRepoFile;
7138
+ const data = result.data.grepRepoFile;
7080
7139
  if (data.matches.length === 0 && data.diagnostics?.hint) {
7081
7140
  return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7082
7141
  }
@@ -7085,67 +7144,108 @@ function createGrepRepoFileTool(pkgseerService) {
7085
7144
  }
7086
7145
  };
7087
7146
  }
7088
- // src/tools/list-package-docs.ts
7089
- var argsSchema7 = {
7090
- registry: schemas.registry,
7091
- package_name: schemas.packageName.describe("Name of the package to list documentation for"),
7092
- version: schemas.version
7147
+ // src/tools/list-files.ts
7148
+ import { z as z8 } from "zod";
7149
+ var argsSchema6 = {
7150
+ target: schemas.codeTarget,
7151
+ path_prefix: z8.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
7152
+ limit: z8.coerce.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
7153
+ wait_timeout_ms: schemas.waitTimeoutMs
7093
7154
  };
7094
- function createListPackageDocsTool(pkgseerService) {
7155
+ function createListFilesTool(pkgseerService) {
7095
7156
  return {
7096
- name: "list_package_docs",
7097
- description: "Discover available documentation pages for a package. Start here before fetching or searching docs. " + "Returns: page titles, unique IDs (needed for fetch_package_doc), word counts, and update timestamps. " + "Workflow: list_package_docs fetch_package_doc for full content, or search(mode='docs') to find specific topics.",
7098
- schema: argsSchema7,
7157
+ name: "list_files",
7158
+ description: "Explore a dependency's file structure " + "see what source files, configs, and docs exist. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals. " + "In monorepos with package scope, returns only files within this package's subdirectory. " + "Requires code indexing.",
7159
+ schema: argsSchema6,
7099
7160
  annotations: { readOnlyHint: true },
7100
- handler: async ({ registry, package_name, version: version2 }, _extra) => {
7101
- return withErrorHandling("list package documentation", async () => {
7102
- const result = await pkgseerService.listPackageDocs(toGraphQLRegistry(registry), package_name, version2);
7161
+ handler: async (args, _extra) => {
7162
+ return withErrorHandling("list files", async () => {
7163
+ const resolved = resolveCodeTarget(args.target);
7164
+ if (isToolError(resolved))
7165
+ return resolved;
7166
+ const tv = buildCodeTargetVars(resolved);
7167
+ const result = await pkgseerService.listRepoFiles(tv.registry, tv.packageName, {
7168
+ version: tv.version,
7169
+ pathPrefix: args.path_prefix,
7170
+ limit: args.limit,
7171
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7172
+ repoUrl: tv.repoUrl,
7173
+ gitRef: tv.gitRef
7174
+ });
7103
7175
  const graphqlError = handleGraphQLErrors(result.errors);
7104
7176
  if (graphqlError)
7105
7177
  return graphqlError;
7106
- if (!result.data?.listPackageDocs) {
7107
- return notFoundError(package_name, registry);
7178
+ const data = result.data.listRepoFiles;
7179
+ if (data.files.length === 0 && data.diagnostics?.hint) {
7180
+ return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7108
7181
  }
7109
- return textResult(JSON.stringify(result.data?.listPackageDocs, null, 2));
7182
+ return textResult(JSON.stringify(data, null, 2));
7110
7183
  });
7111
7184
  }
7112
7185
  };
7113
7186
  }
7114
- // src/tools/list-repo-files.ts
7187
+ // src/tools/list-imports.ts
7115
7188
  import { z as z9 } from "zod";
7116
- var argsSchema8 = {
7117
- registry: schemas.registry,
7118
- package_name: schemas.packageName.describe("Name of the package to list files for"),
7119
- version: schemas.version,
7120
- path_prefix: z9.string().optional().describe("Filter to files under this path (e.g., 'src/')"),
7121
- limit: z9.number().int().min(1).max(1000).optional().describe("Max files to return (max 1000)"),
7189
+ var argsSchema7 = {
7190
+ target: schemas.codeTarget,
7191
+ file_path: z9.string().max(1000).optional().describe("Filter to a specific file path"),
7192
+ resolved_only: z9.boolean().optional().describe("Only return imports resolved to a known package"),
7193
+ limit: z9.coerce.number().int().min(1).max(500).optional().describe("Max imports to return"),
7194
+ mode: schemas.navigationMode,
7122
7195
  wait_timeout_ms: schemas.waitTimeoutMs
7123
7196
  };
7124
- function createListRepoFilesTool(pkgseerService) {
7197
+ function createListImportsTool(pkgseerService) {
7125
7198
  return {
7126
- name: "list_repo_files",
7127
- description: "Explore a dependency's file structure — " + "see what source files, configs, and docs exist. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Good first step when investigating unfamiliar package internals.",
7128
- schema: argsSchema8,
7199
+ name: "list_imports",
7200
+ description: "See what a dependency importsunderstand its internal dependencies and external package usage. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns parsed import/require/use statements with optional resolution to known packages. " + "Use resolved_only=true to see only imports that map to packages in the PkgSeer registry. " + "Includes: source path, imported names, and de-duplicated dependency list.",
7201
+ schema: argsSchema7,
7129
7202
  annotations: { readOnlyHint: true },
7130
7203
  handler: async (args, _extra) => {
7131
- return withErrorHandling("list repo files", async () => {
7132
- const result = await pkgseerService.listRepoFiles(toGraphQLRegistry(args.registry), args.package_name, {
7133
- version: args.version,
7134
- pathPrefix: args.path_prefix,
7204
+ return withErrorHandling("list imports", async () => {
7205
+ const resolved = resolveCodeTarget(args.target);
7206
+ if (isToolError(resolved))
7207
+ return resolved;
7208
+ const tv = buildCodeTargetVars(resolved);
7209
+ const result = await pkgseerService.packageImports(tv.registry, tv.packageName, {
7210
+ filePath: args.file_path,
7211
+ resolvedOnly: args.resolved_only,
7135
7212
  limit: args.limit,
7136
- waitTimeoutMs: args.wait_timeout_ms
7213
+ version: tv.version,
7214
+ mode: toNavigationMode(args.mode),
7215
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7216
+ repoUrl: tv.repoUrl,
7217
+ gitRef: tv.gitRef
7137
7218
  });
7138
7219
  const graphqlError = handleGraphQLErrors(result.errors);
7139
7220
  if (graphqlError)
7140
7221
  return graphqlError;
7141
- if (!result.data?.listRepoFiles) {
7142
- return notFoundError(args.package_name, args.registry);
7143
- }
7144
- const data = result.data?.listRepoFiles;
7145
- if (data.files.length === 0 && data.diagnostics?.hint) {
7146
- return textResult(JSON.stringify({ ...data, _hint: data.diagnostics.hint }, null, 2));
7222
+ return textResult(JSON.stringify(result.data.packageImports, null, 2));
7223
+ });
7224
+ }
7225
+ };
7226
+ }
7227
+ // src/tools/list-package-docs.ts
7228
+ var argsSchema8 = {
7229
+ registry: schemas.registry,
7230
+ package_name: schemas.packageName.describe("Name of the package to list documentation for"),
7231
+ version: schemas.version
7232
+ };
7233
+ function createListPackageDocsTool(pkgseerService) {
7234
+ return {
7235
+ name: "list_package_docs",
7236
+ description: "Discover available documentation pages for a package. Start here before fetching or searching docs. " + "Returns: page titles, unique IDs (needed for fetch_package_doc), word counts, and update timestamps. " + "Workflow: list_package_docs → fetch_package_doc for full content, or search(mode='docs') to find specific topics. " + "Requires documentation to have been crawled — if results are empty, use trigger_indexing first, then retry.",
7237
+ schema: argsSchema8,
7238
+ annotations: { readOnlyHint: true },
7239
+ handler: async ({ registry, package_name, version: version2 }, _extra) => {
7240
+ return withErrorHandling("list package documentation", async () => {
7241
+ const result = await pkgseerService.listPackageDocs(toGraphQLRegistry(registry), package_name, version2);
7242
+ const graphqlError = handleGraphQLErrors(result.errors);
7243
+ if (graphqlError)
7244
+ return graphqlError;
7245
+ if (!result.data?.listPackageDocs) {
7246
+ return notFoundError(package_name, registry);
7147
7247
  }
7148
- return textResult(JSON.stringify(data, null, 2));
7248
+ return textResult(JSON.stringify(result.data?.listPackageDocs, null, 2));
7149
7249
  });
7150
7250
  }
7151
7251
  };
@@ -7153,22 +7253,20 @@ function createListRepoFilesTool(pkgseerService) {
7153
7253
  // src/tools/list-symbols.ts
7154
7254
  import { z as z10 } from "zod";
7155
7255
  var argsSchema9 = {
7156
- registry: schemas.registry,
7157
- package_name: schemas.packageName.describe("Name of the package to browse symbols for"),
7256
+ target: schemas.codeTarget,
7158
7257
  scope: z10.enum(["exports", "file"]).describe("Browsing scope: 'exports' for public API, 'file' for all symbols in a specific file"),
7159
7258
  file_path: z10.string().max(1000).optional().describe("File path within the repo (required when scope=file)"),
7160
7259
  namespace: z10.string().max(500).optional().describe("Filter by namespace prefix (e.g., 'React' to see React.*)"),
7161
7260
  public_only: z10.boolean().optional().describe("Only return public symbols"),
7162
7261
  include_popularity: z10.boolean().optional().describe("Include callerCount for each symbol (slightly slower)"),
7163
- limit: z10.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7164
- version: schemas.version,
7262
+ limit: z10.coerce.number().int().min(1).max(100).optional().describe("Max symbols to return (max 100)"),
7165
7263
  mode: schemas.navigationMode,
7166
7264
  wait_timeout_ms: schemas.waitTimeoutMs
7167
7265
  };
7168
7266
  function createListSymbolsTool(pkgseerService) {
7169
7267
  return {
7170
7268
  name: "list_symbols",
7171
- description: "Browse a dependency's public API or file-level symbols. " + "Use scope='exports' for the public API with optional popularity ranking. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbol refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to read source for any result.",
7269
+ description: "Browse a dependency's public API or file-level symbols. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Use scope='exports' for the public API with optional popularity ranking. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbol refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to read source for any result.",
7172
7270
  schema: argsSchema9,
7173
7271
  annotations: { readOnlyHint: true },
7174
7272
  handler: async (args, _extra) => {
@@ -7185,23 +7283,26 @@ function createListSymbolsTool(pkgseerService) {
7185
7283
  isError: true
7186
7284
  };
7187
7285
  }
7188
- const result = await pkgseerService.listSymbols(toGraphQLRegistry(args.registry), args.package_name, scope, {
7286
+ const resolved = resolveCodeTarget(args.target);
7287
+ if (isToolError(resolved))
7288
+ return resolved;
7289
+ const tv = buildCodeTargetVars(resolved);
7290
+ const result = await pkgseerService.listSymbols(tv.registry, tv.packageName, scope, {
7189
7291
  filePath: args.file_path,
7190
7292
  namespace: args.namespace,
7191
7293
  publicOnly: args.public_only,
7192
7294
  includePopularity: args.include_popularity,
7193
7295
  limit: args.limit,
7194
- version: args.version,
7296
+ version: tv.version,
7195
7297
  mode: toNavigationMode(args.mode),
7196
- waitTimeoutMs: args.wait_timeout_ms
7298
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7299
+ repoUrl: tv.repoUrl,
7300
+ gitRef: tv.gitRef
7197
7301
  });
7198
7302
  const graphqlError = handleGraphQLErrors(result.errors);
7199
7303
  if (graphqlError)
7200
7304
  return graphqlError;
7201
- if (!result.data?.listSymbols) {
7202
- return notFoundError(args.package_name, args.registry);
7203
- }
7204
- return textResult(JSON.stringify(result.data?.listSymbols, null, 2));
7305
+ return textResult(JSON.stringify(result.data.listSymbols, null, 2));
7205
7306
  });
7206
7307
  }
7207
7308
  };
@@ -7213,7 +7314,7 @@ var argsSchema10 = {
7213
7314
  package_name: schemas.packageName.describe("Name of the package to retrieve dependencies for"),
7214
7315
  version: schemas.version,
7215
7316
  include_transitive: z11.boolean().optional().describe("Whether to include transitive dependency DAG"),
7216
- max_depth: z11.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7317
+ max_depth: z11.coerce.number().int().min(1).max(10).optional().describe("Maximum depth for transitive traversal (1-10)")
7217
7318
  };
7218
7319
  function decodeDag(rawDag) {
7219
7320
  if (!rawDag || typeof rawDag !== "object")
@@ -7329,47 +7430,8 @@ function createPackageDependenciesTool(pkgseerService) {
7329
7430
  }
7330
7431
  };
7331
7432
  }
7332
- // src/tools/package-imports.ts
7333
- import { z as z12 } from "zod";
7334
- var argsSchema11 = {
7335
- registry: schemas.registry,
7336
- package_name: schemas.packageName.describe("Name of the package to get imports for"),
7337
- file_path: z12.string().max(1000).optional().describe("Filter to a specific file path"),
7338
- resolved_only: z12.boolean().optional().describe("Only return imports resolved to a known package"),
7339
- limit: z12.number().int().min(1).max(500).optional().describe("Max imports to return"),
7340
- version: schemas.version,
7341
- mode: schemas.navigationMode,
7342
- wait_timeout_ms: schemas.waitTimeoutMs
7343
- };
7344
- function createPackageImportsTool(pkgseerService) {
7345
- return {
7346
- name: "package_imports",
7347
- description: "See what a dependency imports — understand its internal dependencies and external package usage. " + "Returns parsed import/require/use statements with optional resolution to known packages. " + "Use resolved_only=true to see only imports that map to packages in the PkgSeer registry. " + "Includes: source path, imported names, and de-duplicated dependency list.",
7348
- schema: argsSchema11,
7349
- annotations: { readOnlyHint: true },
7350
- handler: async (args, _extra) => {
7351
- return withErrorHandling("fetch package imports", async () => {
7352
- const result = await pkgseerService.packageImports(toGraphQLRegistry(args.registry), args.package_name, {
7353
- filePath: args.file_path,
7354
- resolvedOnly: args.resolved_only,
7355
- limit: args.limit,
7356
- version: args.version,
7357
- mode: toNavigationMode(args.mode),
7358
- waitTimeoutMs: args.wait_timeout_ms
7359
- });
7360
- const graphqlError = handleGraphQLErrors(result.errors);
7361
- if (graphqlError)
7362
- return graphqlError;
7363
- if (!result.data?.packageImports) {
7364
- return notFoundError(args.package_name, args.registry);
7365
- }
7366
- return textResult(JSON.stringify(result.data?.packageImports, null, 2));
7367
- });
7368
- }
7369
- };
7370
- }
7371
7433
  // src/tools/package-quality.ts
7372
- var argsSchema12 = {
7434
+ var argsSchema11 = {
7373
7435
  registry: schemas.registry,
7374
7436
  package_name: schemas.packageName.describe("Name of the package to analyze"),
7375
7437
  version: schemas.version
@@ -7377,8 +7439,8 @@ var argsSchema12 = {
7377
7439
  function createPackageQualityTool(pkgseerService) {
7378
7440
  return {
7379
7441
  name: "package_quality",
7380
- description: "Evaluate package maintenance health and code quality. Use this to assess if a package is well-maintained " + "before adding it as a dependency. Returns: overall score (0-100), category scores (documentation, " + "testing, community, maintenance), and individual rule results with pass/fail status. " + "Useful for comparing quality between alternative packages.",
7381
- schema: argsSchema12,
7442
+ description: "Evaluate package maintenance health and code quality (available immediately — no indexing required). " + "Use this to assess if a package is well-maintained " + "before adding it as a dependency. Returns: overall score (0-100), category scores (documentation, " + "testing, community, maintenance), and individual rule results with pass/fail status. " + "Useful for comparing quality between alternative packages.",
7443
+ schema: argsSchema11,
7382
7444
  annotations: { readOnlyHint: true },
7383
7445
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7384
7446
  return withErrorHandling("fetch package quality", async () => {
@@ -7395,15 +7457,15 @@ function createPackageQualityTool(pkgseerService) {
7395
7457
  };
7396
7458
  }
7397
7459
  // src/tools/package-summary.ts
7398
- var argsSchema13 = {
7460
+ var argsSchema12 = {
7399
7461
  registry: schemas.registry,
7400
7462
  package_name: schemas.packageName.describe("Name of the package to retrieve summary for")
7401
7463
  };
7402
7464
  function createPackageSummaryTool(pkgseerService) {
7403
7465
  return {
7404
7466
  name: "package_summary",
7405
- description: "Get a comprehensive overview of a package. Use this as your first tool when researching a package. " + "Returns: description, latest version, license, repository URL, download stats, " + "active security advisories count, and quickstart/installation instructions. " + "For deeper analysis, follow up with package_quality (maintenance health) or " + "package_vulnerabilities (security details).",
7406
- schema: argsSchema13,
7467
+ description: "Get a comprehensive overview of a package (available immediately — no indexing required). " + "Use this as your first tool when researching a package. " + "Returns: description, latest version, license, repository URL, download stats, " + "active security advisories count, and quickstart/installation instructions. " + "For deeper analysis, follow up with package_quality (maintenance health) or " + "package_vulnerabilities (security details). " + "Use package.repositoryUrl + package.latestVersion as git_ref with fetch_code_context to read source files.",
7468
+ schema: argsSchema12,
7407
7469
  annotations: { readOnlyHint: true },
7408
7470
  handler: async ({ registry, package_name }, _extra) => {
7409
7471
  return withErrorHandling("fetch package summary", async () => {
@@ -7420,7 +7482,7 @@ function createPackageSummaryTool(pkgseerService) {
7420
7482
  };
7421
7483
  }
7422
7484
  // src/tools/package-vulnerabilities.ts
7423
- var argsSchema14 = {
7485
+ var argsSchema13 = {
7424
7486
  registry: schemas.registry,
7425
7487
  package_name: schemas.packageName.describe("Name of the package to inspect for vulnerabilities"),
7426
7488
  version: schemas.version
@@ -7428,8 +7490,8 @@ var argsSchema14 = {
7428
7490
  function createPackageVulnerabilitiesTool(pkgseerService) {
7429
7491
  return {
7430
7492
  name: "package_vulnerabilities",
7431
- description: "Check security vulnerabilities for a package. Use this before adding dependencies or when auditing existing ones. " + "Returns: list of CVEs/advisories with severity levels, affected version ranges, fixed versions, " + "and upgrade recommendations. If version is specified, shows only vulnerabilities affecting that version.",
7432
- schema: argsSchema14,
7493
+ description: "Check security vulnerabilities for a package (available immediately — no indexing required). " + "Use this before adding dependencies or when auditing existing ones. " + "Returns: list of CVEs/advisories with severity levels, affected version ranges, fixed versions, " + "and upgrade recommendations. If version is specified, shows only vulnerabilities affecting that version.",
7494
+ schema: argsSchema13,
7433
7495
  annotations: { readOnlyHint: true },
7434
7496
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7435
7497
  return withErrorHandling("fetch package vulnerabilities", async () => {
@@ -7445,6 +7507,48 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
7445
7507
  }
7446
7508
  };
7447
7509
  }
7510
+ // src/tools/read-file.ts
7511
+ import { z as z12 } from "zod";
7512
+ var argsSchema14 = {
7513
+ target: schemas.codeTarget,
7514
+ file_path: z12.string({
7515
+ error: "file_path is required. Get file paths from find_symbol (returns file locations) " + "or list_files (browse file structure)."
7516
+ }).min(1).describe("Path to file in repository. Example: src/router/index.js"),
7517
+ start_line: z12.coerce.number().int().positive().optional().describe("Starting line (1-indexed). If omitted, starts from line 1."),
7518
+ end_line: z12.coerce.number().int().positive().optional().describe("Ending line. If omitted, returns to end of file."),
7519
+ wait_timeout_ms: schemas.waitTimeoutMs
7520
+ };
7521
+ function createReadFileTool(pkgseerService) {
7522
+ return {
7523
+ name: "read_file",
7524
+ description: "Read source code from a dependency's repository by file path and line range — " + "use when you have a file path from a stack trace or symbol lookup. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Returns full file or a specific line range. " + "Prefer find_symbol(include_code=true) for function/class lookup. " + "Use list_files to discover file paths. " + "With repo scope, operates on the full repository. " + "With package scope, scoped to the package subdirectory in monorepos.",
7525
+ schema: argsSchema14,
7526
+ annotations: { readOnlyHint: true },
7527
+ handler: async (args, _extra) => {
7528
+ return withErrorHandling("read file", async () => {
7529
+ const resolved = resolveCodeTarget(args.target);
7530
+ if (isToolError(resolved))
7531
+ return resolved;
7532
+ const tv = buildCodeTargetVars(resolved);
7533
+ const result = await pkgseerService.fetchCodeContext(tv.repoUrl, tv.gitRef, args.file_path, {
7534
+ startLine: args.start_line,
7535
+ endLine: args.end_line,
7536
+ registry: tv.registry,
7537
+ packageName: tv.packageName,
7538
+ version: tv.version,
7539
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7540
+ });
7541
+ const graphqlError = handleGraphQLErrors(result.errors);
7542
+ if (graphqlError)
7543
+ return graphqlError;
7544
+ if (!result.data?.fetchCodeContext) {
7545
+ return errorResult(`File not found: ${args.file_path}. ` + "Check that the file path and target are correct. " + "Use list_files to discover available files.");
7546
+ }
7547
+ return textResult(JSON.stringify(result.data.fetchCodeContext, null, 2));
7548
+ });
7549
+ }
7550
+ };
7551
+ }
7448
7552
  // src/tools/search.ts
7449
7553
  import { z as z13 } from "zod";
7450
7554
  var packageInputSchema2 = z13.object({
@@ -7452,13 +7556,16 @@ var packageInputSchema2 = z13.object({
7452
7556
  name: z13.string().min(1).describe("Package name"),
7453
7557
  version: z13.string().optional().describe("Specific version (defaults to latest)")
7454
7558
  });
7455
- var DEFAULT_AGENT_WAIT_TIMEOUT_MS = 1e4;
7456
7559
  var argsSchema15 = {
7457
- packages: z13.array(packageInputSchema2).min(1).max(20).describe("Packages to search (1-20). Each package needs registry and name."),
7458
- query: z13.string().min(1).describe("Search query - natural language or keywords"),
7560
+ packages: z13.array(packageInputSchema2, {
7561
+ error: 'packages is required. Provide 1-20 packages as [{registry: "npm", name: "express"}]. ' + "Use package_summary to verify a package exists. " + "For project-wide doc search without specifying packages, use search_project_docs instead."
7562
+ }).min(1).max(20).describe('Packages to search (1-20). Format: [{"registry":"npm","name":"express"}]'),
7563
+ query: z13.string({
7564
+ error: "query is required. Provide search terms as natural language or keywords, " + "e.g., 'error handling middleware'."
7565
+ }).min(1).describe("Search query - natural language or keywords"),
7459
7566
  mode: z13.enum(["all", "code", "docs"]).optional().describe('Search mode: "all" (default), "code" only, or "docs" only'),
7460
- limit: z13.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
7461
- waitTimeoutMs: z13.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
7567
+ limit: z13.coerce.number().int().min(1).max(100).optional().describe("Maximum results (default: 20)"),
7568
+ waitTimeoutMs: z13.coerce.number().int().min(0).max(60000).optional().describe("Max milliseconds to wait for indexing (default: 10000, 0=immediate)")
7462
7569
  };
7463
7570
  function toSearchMode2(mode) {
7464
7571
  if (!mode)
@@ -7496,7 +7603,7 @@ Results may be incomplete. Retry later for more complete results.`;
7496
7603
  function createSearchTool(pkgseerService) {
7497
7604
  return {
7498
7605
  name: "search",
7499
- description: "Search code and documentation across packages. Returns functions, classes, and doc pages " + "matching your query. Use mode='code' for code only, mode='docs' for docs only, or " + "mode='all' (default). Provide 1-20 packages. Results include relevance scores and snippets. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "If packages need indexing, waits up to waitTimeoutMs (default 10s) or returns searchRef — use search_status to poll.",
7606
+ description: "Search code and documentation across packages using full-text search. " + "Returns code chunks and doc pages matching your query with relevance scores and snippets. " + "Use mode='code' for code only, mode='docs' for docs only, or mode='all' (default). " + "Provide 1-20 packages. For symbol-level results that feed into symbol_callers/symbol_callees, " + "use search_symbols instead. " + "For full source of code results, use find_symbol(name=<title>, include_code=true). " + "Code results include repoUrl and filePath for use with fetch_code_context. " + "If packages need indexing, waits up to waitTimeoutMs (default 10s) or returns searchRef — use search_status to poll.",
7500
7607
  schema: argsSchema15,
7501
7608
  annotations: { readOnlyHint: true },
7502
7609
  handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
@@ -7513,7 +7620,7 @@ function createSearchTool(pkgseerService) {
7513
7620
  const result = await pkgseerService.combinedSearch(graphqlPackages, normalizedQuery, {
7514
7621
  mode: toSearchMode2(mode),
7515
7622
  limit,
7516
- waitTimeoutMs: waitTimeoutMs ?? DEFAULT_AGENT_WAIT_TIMEOUT_MS
7623
+ waitTimeoutMs: waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS2
7517
7624
  });
7518
7625
  const graphqlError = handleGraphQLErrors(result.errors);
7519
7626
  if (graphqlError)
@@ -7557,7 +7664,7 @@ var argsSchema16 = {
7557
7664
  terms: z14.array(z14.string()).optional().describe("Search terms to match. Provide a few key words or phrases that should appear in results."),
7558
7665
  match_mode: z14.enum(["any", "or", "all", "and"]).optional().describe('How to combine terms: "any" (OR) or "all" (AND).'),
7559
7666
  include_snippets: z14.boolean().optional().describe("Include content excerpts around matches"),
7560
- limit: z14.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7667
+ limit: z14.coerce.number().int().min(1).max(100).optional().describe("Maximum number of results to return")
7561
7668
  };
7562
7669
  function createSearchProjectDocsTool(deps) {
7563
7670
  const { pkgseerService, configService, defaultProjectDir } = deps;
@@ -7582,7 +7689,9 @@ function createSearchProjectDocsTool(deps) {
7582
7689
  return errorResult(`No project specified and no pkgseer.yml found. To fix:
7583
7690
  ` + ` 1. Pass project_directory: '/path/to/project' (folder containing pkgseer.yml)
7584
7691
  ` + ` 2. Pass project: 'project-name' directly if you know the project name
7585
- ` + " 3. Run 'pkgseer project init' to create pkgseer.yml in your project");
7692
+ ` + ` 3. Run 'pkgseer project init' to create pkgseer.yml in your project
7693
+
7694
+ ` + "Or use search(mode='docs', packages=[{registry: 'npm', name: '...'}]) to search " + "specific packages without a project.");
7586
7695
  }
7587
7696
  const normalizedTerms = terms?.map((term) => term.trim()).filter((term) => term.length > 0) ?? [];
7588
7697
  if (normalizedTerms.length === 0) {
@@ -7663,8 +7772,7 @@ function createSearchStatusTool(pkgseerService) {
7663
7772
  // src/tools/search-symbols.ts
7664
7773
  import { z as z16 } from "zod";
7665
7774
  var argsSchema18 = {
7666
- registry: schemas.registry,
7667
- package_name: schemas.packageName.describe("Name of the package to search within"),
7775
+ target: schemas.codeTarget,
7668
7776
  query: z16.string().max(500).optional().describe("Search query for full-text code search (max 500 chars). Required if keywords not provided."),
7669
7777
  keywords: z16.array(z16.string()).max(20).optional().describe("Search keywords (max 20). Combined using match_mode. Alternative to query."),
7670
7778
  match_mode: z16.enum(["or", "and"]).optional().describe("How to combine keywords: or (any match) or and (all must match)"),
@@ -7678,37 +7786,39 @@ var argsSchema18 = {
7678
7786
  "doc_section"
7679
7787
  ]).optional().describe("Filter results by code chunk type"),
7680
7788
  file_path: z16.string().optional().describe("Filter results to files whose path starts with this value (e.g., 'src/' for a directory)"),
7681
- version: schemas.version,
7682
- limit: z16.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7789
+ limit: z16.coerce.number().int().min(1).max(50).optional().describe("Max results to return (max 50)"),
7683
7790
  mode: schemas.navigationMode,
7684
7791
  wait_timeout_ms: schemas.waitTimeoutMs
7685
7792
  };
7686
7793
  function createSearchSymbolsTool(pkgseerService) {
7687
7794
  return {
7688
7795
  name: "search_symbols",
7689
- description: "Search a dependency's source code by text — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns matching code chunks with name, type, file path, line numbers, and content previews. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source.",
7796
+ description: "Search a dependency's source code by text using the code navigation index — " + "find where error messages, exceptions, or patterns appear across functions, classes, and modules. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "Supports query string or keyword list with match_mode. " + "Use file_path to filter by directory (e.g., 'src/'). " + "Returns symbol-level results that can feed directly into symbol_callers, symbol_callees, or call_path. " + "Follow up with find_symbol(name=<result.name>, include_code=true) for full source. " + "For free-form text search across multiple packages, use search(mode='code') instead.",
7690
7797
  schema: argsSchema18,
7691
7798
  annotations: { readOnlyHint: true },
7692
7799
  handler: async (args, _extra) => {
7693
7800
  return withErrorHandling("search symbols", async () => {
7694
- const result = await pkgseerService.searchSymbols(toGraphQLRegistry(args.registry), args.package_name, {
7801
+ const resolved = resolveCodeTarget(args.target);
7802
+ if (isToolError(resolved))
7803
+ return resolved;
7804
+ const tv = buildCodeTargetVars(resolved);
7805
+ const result = await pkgseerService.searchSymbols(tv.registry, tv.packageName, {
7695
7806
  query: args.query,
7696
7807
  keywords: args.keywords,
7697
7808
  matchMode: toMatchMode(args.match_mode),
7698
7809
  kind: toSymbolKind(args.kind),
7699
7810
  filePath: args.file_path,
7700
- version: args.version,
7811
+ version: tv.version,
7701
7812
  limit: args.limit,
7702
7813
  mode: toNavigationMode(args.mode),
7703
- waitTimeoutMs: args.wait_timeout_ms
7814
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
7815
+ repoUrl: tv.repoUrl,
7816
+ gitRef: tv.gitRef
7704
7817
  });
7705
7818
  const graphqlError = handleGraphQLErrors(result.errors);
7706
7819
  if (graphqlError)
7707
7820
  return graphqlError;
7708
- if (!result.data?.searchSymbols) {
7709
- return notFoundError(args.package_name, args.registry);
7710
- }
7711
- const data = result.data?.searchSymbols;
7821
+ const data = result.data.searchSymbols;
7712
7822
  const extra = {};
7713
7823
  if (data.results.length === 0 && data.diagnostics?.hint) {
7714
7824
  extra._hint = data.diagnostics.hint;
@@ -7727,10 +7837,10 @@ function createSearchSymbolsTool(pkgseerService) {
7727
7837
  // src/tools/symbol-callees.ts
7728
7838
  import { z as z17 } from "zod";
7729
7839
  var argsSchema19 = {
7730
- symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide either symbol_ref or registry + package_name + symbol_name."),
7731
- max_depth: z17.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
7732
- limit: z17.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
7733
- include_external: z17.boolean().optional().describe("Include calls to symbols in other packages"),
7840
+ symbol: schemas.symbolReference.describe("Symbol to find callees for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
7841
+ max_depth: z17.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callees only, 2+ = transitive, max 5)"),
7842
+ limit: z17.coerce.number().int().min(1).max(100).optional().describe("Maximum dependency entries to return"),
7843
+ include_external: z17.boolean().optional().describe("Include calls to symbols in other indexed packages. " + "Default (false) shows only calls within the same package."),
7734
7844
  include_builtins: z17.boolean().optional().describe("Include calls to built-in/standard library functions (console, Math, etc.)"),
7735
7845
  mode: schemas.navigationMode,
7736
7846
  wait_timeout_ms: schemas.waitTimeoutMs
@@ -7738,14 +7848,14 @@ var argsSchema19 = {
7738
7848
  function createSymbolCalleesTool(pkgseerService) {
7739
7849
  return {
7740
7850
  name: "symbol_callees",
7741
- description: "Trace what a function calls internally — " + "understand dependency behavior by following its execution path. " + "Returns direct callees at max_depth=1, or transitive call chains at higher depths. " + "Includes callee names, qualified paths, file locations, call lines, and external package references. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callers for the reverse.",
7851
+ description: "Trace what a function calls internally — " + "understand dependency behavior by following its execution path. " + "Returns direct callees at max_depth=1, or transitive call chains at higher depths. " + "Includes callee names, qualified paths, file locations, call lines, and external package references. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callers for the reverse.",
7742
7852
  schema: argsSchema19,
7743
7853
  annotations: { readOnlyHint: true },
7744
7854
  handler: async (args, _extra) => {
7745
7855
  return withErrorHandling("find symbol callees", async () => {
7746
7856
  const symbolInput = toSymbolReferenceInput(args.symbol);
7747
- if (!symbolInput.symbolRef && (!symbolInput.symbolName || !symbolInput.registry || !symbolInput.packageName)) {
7748
- return errorResult("Provide either symbol_ref or symbol_name with registry and package_name to identify the symbol.");
7857
+ if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
7858
+ return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
7749
7859
  }
7750
7860
  const result = await pkgseerService.symbolDependencies(symbolInput, {
7751
7861
  maxDepth: args.max_depth,
@@ -7753,15 +7863,12 @@ function createSymbolCalleesTool(pkgseerService) {
7753
7863
  includeExternal: args.include_external,
7754
7864
  includeBuiltins: args.include_builtins,
7755
7865
  mode: toNavigationMode(args.mode),
7756
- waitTimeoutMs: args.wait_timeout_ms
7866
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7757
7867
  });
7758
7868
  const graphqlError = handleGraphQLErrors(result.errors);
7759
7869
  if (graphqlError)
7760
7870
  return graphqlError;
7761
- if (!result.data?.symbolDependencies) {
7762
- return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
7763
- }
7764
- return textResult(JSON.stringify(result.data?.symbolDependencies, null, 2));
7871
+ return textResult(JSON.stringify(result.data.symbolDependencies, null, 2));
7765
7872
  });
7766
7873
  }
7767
7874
  };
@@ -7769,39 +7876,36 @@ function createSymbolCalleesTool(pkgseerService) {
7769
7876
  // src/tools/symbol-callers.ts
7770
7877
  import { z as z18 } from "zod";
7771
7878
  var argsSchema20 = {
7772
- symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide either symbol_ref or registry + package_name + symbol_name."),
7773
- same_package_only: z18.boolean().optional().describe("Only return callers from the same package"),
7774
- max_depth: z18.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
7775
- limit: z18.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
7879
+ symbol: schemas.symbolReference.describe("Symbol to find callers for. Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name."),
7880
+ same_package_only: z18.boolean().optional().describe("Only return callers from the same package. " + "Default (false) includes callers from other indexed packages."),
7881
+ max_depth: z18.coerce.number().int().min(1).max(5).optional().describe("BFS traversal depth (1 = direct callers only, 2+ = transitive, max 5)"),
7882
+ limit: z18.coerce.number().int().min(1).max(100).optional().describe("Maximum entries to return"),
7776
7883
  mode: schemas.navigationMode,
7777
7884
  wait_timeout_ms: schemas.waitTimeoutMs
7778
7885
  };
7779
7886
  function createSymbolCallersTool(pkgseerService) {
7780
7887
  return {
7781
7888
  name: "symbol_callers",
7782
- description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse.",
7889
+ description: "Trace what calls a function in a dependency's source code — " + "find entry points or debug why behavior triggers. " + "Returns callers with file locations and call line numbers. " + "Supports package scope (registry + package_name) or repo scope (repo_url + git_ref). " + "Use same_package_only for within-package callers only. " + "Get symbol_ref from find_symbol or list_symbols. See symbol_callees for the reverse. " + "Use find_symbol(include_code=true) on any caller to read its source.",
7783
7890
  schema: argsSchema20,
7784
7891
  annotations: { readOnlyHint: true },
7785
7892
  handler: async (args, _extra) => {
7786
7893
  return withErrorHandling("find symbol callers", async () => {
7787
7894
  const symbolInput = toSymbolReferenceInput(args.symbol);
7788
- if (!symbolInput.symbolRef && (!symbolInput.symbolName || !symbolInput.registry || !symbolInput.packageName)) {
7789
- return errorResult("Provide either symbol_ref or symbol_name with registry and package_name to identify the symbol.");
7895
+ if (!symbolInput.symbolRef && !(symbolInput.symbolName && symbolInput.registry && symbolInput.packageName) && !(symbolInput.symbolName && symbolInput.repoUrl && symbolInput.gitRef)) {
7896
+ return errorResult("Provide symbol_ref, or registry + package_name + symbol_name, or repo_url + git_ref + symbol_name.");
7790
7897
  }
7791
7898
  const result = await pkgseerService.symbolDependents(symbolInput, {
7792
7899
  samePackageOnly: args.same_package_only,
7793
7900
  maxDepth: args.max_depth,
7794
7901
  maxResults: args.limit,
7795
7902
  mode: toNavigationMode(args.mode),
7796
- waitTimeoutMs: args.wait_timeout_ms
7903
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2
7797
7904
  });
7798
7905
  const graphqlError = handleGraphQLErrors(result.errors);
7799
7906
  if (graphqlError)
7800
7907
  return graphqlError;
7801
- if (!result.data?.symbolDependents) {
7802
- return errorResult("Symbol not found. Verify the symbol reference and that the package is indexed.");
7803
- }
7804
- return textResult(JSON.stringify(result.data?.symbolDependents, null, 2));
7908
+ return textResult(JSON.stringify(result.data.symbolDependents, null, 2));
7805
7909
  });
7806
7910
  }
7807
7911
  };
@@ -7825,7 +7929,7 @@ var argsSchema21 = {
7825
7929
  function createTriggerIndexingTool(pkgseerService) {
7826
7930
  return {
7827
7931
  name: "trigger_indexing",
7828
- description: "Pre-warm PkgSeer indexes by triggering indexing for packages and/or repositories. " + "Fire-and-forget: triggers jobs and returns immediately with accepted/skipped counts. " + "Use before search requests to ensure packages are indexed. " + "Rate limited to 10 requests per minute.",
7932
+ description: "Pre-warm PkgSeer indexes by triggering indexing for packages and/or repositories. " + "Fire-and-forget: triggers jobs and returns immediately with accepted/skipped counts. " + "Use before search or doc requests to ensure packages are indexed. " + "Code tools auto-wait via wait_timeout_ms on subsequent calls. Most packages index within 10-30s. " + "Rate limited to 10 requests per minute.",
7829
7933
  schema: argsSchema21,
7830
7934
  annotations: { readOnlyHint: false, idempotentHint: true },
7831
7935
  handler: async (args, _extra) => {
@@ -7866,8 +7970,7 @@ function createTriggerIndexingTool(pkgseerService) {
7866
7970
  // src/tools/version-diff.ts
7867
7971
  import { z as z20 } from "zod";
7868
7972
  var argsSchema22 = {
7869
- registry: schemas.registry,
7870
- package_name: schemas.packageName.describe("Name of the package to compare versions for"),
7973
+ target: schemas.codeTarget,
7871
7974
  from_version: z20.string().max(100).describe("Source version (git ref, e.g., 'v4.18.2')"),
7872
7975
  to_version: z20.string().max(100).describe("Target version (git ref, e.g., 'v5.0.0')"),
7873
7976
  include_private: z20.boolean().optional().describe("Include private/non-exported symbols in the diff"),
@@ -7880,30 +7983,33 @@ var argsSchema22 = {
7880
7983
  "type",
7881
7984
  "doc_section"
7882
7985
  ]).optional().describe("Filter by symbol kind"),
7883
- limit: z20.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
7986
+ limit: z20.coerce.number().int().min(1).max(500).optional().describe("Max changes to return (max 500). Summary always reflects full counts."),
7884
7987
  wait_timeout_ms: schemas.waitTimeoutMs
7885
7988
  };
7886
7989
  function createVersionDiffTool(pkgseerService) {
7887
7990
  return {
7888
7991
  name: "version_diff",
7889
- description: "Compare two versions of a dependency to understand what changed — " + "use when debugging issues after upgrades or planning migrations. " + "Detects added, removed, moved, and modified symbols with severity " + "(breaking, behavior_change, non_breaking, internal). " + "Returns summary counts and per-symbol changes with file locations.",
7992
+ description: "Compare two versions of a dependency to understand what changed — " + "use when debugging issues after upgrades or planning migrations. " + "Accepts package scope (registry + package_name) or repo scope (repo_url + git_ref) via the target parameter. " + "With repo scope, from_version and to_version are literal git refs (tags, branches, commits) — " + "the backend does not normalize them. Use target.git_ref=HEAD to identify the repository. " + "Detects added, removed, moved, and modified symbols with severity " + "(breaking, behavior_change, non_breaking, internal). " + "Returns summary counts and per-symbol changes with file locations.",
7890
7993
  schema: argsSchema22,
7891
7994
  annotations: { readOnlyHint: true },
7892
7995
  handler: async (args, _extra) => {
7893
7996
  return withErrorHandling("version diff", async () => {
7894
- const result = await pkgseerService.versionDiff(toGraphQLRegistry(args.registry), args.package_name, args.from_version, args.to_version, {
7997
+ const resolved = resolveCodeTarget(args.target);
7998
+ if (isToolError(resolved))
7999
+ return resolved;
8000
+ const tv = buildCodeTargetVars(resolved);
8001
+ const result = await pkgseerService.versionDiff(tv.registry, tv.packageName, args.from_version, args.to_version, {
7895
8002
  includePrivate: args.include_private,
7896
8003
  kind: toSymbolKind(args.kind),
7897
8004
  limit: args.limit,
7898
- waitTimeoutMs: args.wait_timeout_ms
8005
+ waitTimeoutMs: args.wait_timeout_ms ?? DEFAULT_WAIT_TIMEOUT_MS2,
8006
+ repoUrl: tv.repoUrl,
8007
+ gitRef: tv.gitRef
7899
8008
  });
7900
8009
  const graphqlError = handleGraphQLErrors(result.errors);
7901
8010
  if (graphqlError)
7902
8011
  return graphqlError;
7903
- if (!result.data?.versionDiff) {
7904
- return notFoundError(args.package_name, args.registry);
7905
- }
7906
- return textResult(JSON.stringify(result.data?.versionDiff, null, 2));
8012
+ return textResult(JSON.stringify(result.data.versionDiff, null, 2));
7907
8013
  });
7908
8014
  }
7909
8015
  };
@@ -7919,18 +8025,54 @@ Use PkgSeer when:
7919
8025
  - You need to understand what changed between package versions
7920
8026
 
7921
8027
  Instead of guessing library behavior from training data, use find_symbol(include_code=true) to read actual source.
7922
- Instead of cloning repos to search code, use search_symbols or grep_repo_file.
8028
+ Instead of cloning repos to search code, use search_symbols or grep_file.
7923
8029
  Instead of manually tracing call chains on GitHub, use symbol_callers and symbol_callees.
7924
8030
 
7925
- Tool groups:
7926
- - Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
7927
- - Browse files: list_repo_files, grep_repo_file, fetch_code_context
7928
- - Search across packages: search, search_project_docs
7929
- - Browse docs: list_package_docs, fetch_package_doc
7930
- - Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
7931
- - Utility: trigger_indexing, search_status, package_imports
8031
+ Dual addressing — code tools accept a target object with two modes:
8032
+ - Package scope: target: { registry: "npm", package_name: "express" } (optional version)
8033
+ In monorepos, results are scoped to the package's subdirectory.
8034
+ - Repo scope: target: { repo_url: "https://github.com/expressjs/express", git_ref: "v4.18.2" }
8035
+ Operates on the full repository, not filtered to a package subdirectory.
8036
+
8037
+ Use package scope when you know the package name. Use repo scope when you have a repo URL (e.g., from package_summary) and need full-repo access or the repo isn't published as a package.
8038
+
8039
+ Data availability — tools are grouped by what backend data they need:
8040
+
8041
+ 1. Registry metadata (available immediately, no indexing):
8042
+ package_summary, package_quality, package_vulnerabilities, package_dependencies, compare_packages
8043
+ Start here when researching a package — these always work instantly.
8044
+
8045
+ 2. Documentation (requires doc site crawling):
8046
+ list_package_docs, fetch_package_doc, search(mode='docs'), search_project_docs
8047
+ If results are empty, docs may not be crawled yet — use trigger_indexing first, then retry.
8048
+
8049
+ 3. Code navigation (requires code repo indexing, dual addressing via target):
8050
+ find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path,
8051
+ list_imports, version_diff, list_files, grep_file, read_file, search(mode='code')
8052
+ These wait up to wait_timeout_ms (default 10s) for indexing. If indexing takes longer, you'll get a "being indexed" response — retry the same call. Most packages index within 10-30 seconds.
8053
+
8054
+ Symbol reference tools (symbol_callers, symbol_callees, call_path) accept a symbol object with either:
8055
+ - symbol_ref from a previous find_symbol/search_symbols result (preferred, fastest)
8056
+ - Package lookup: registry + package_name + symbol_name
8057
+ - Repo lookup: repo_url + git_ref + symbol_name
8058
+ symbol_callers/symbol_callees can show cross-package results from other indexed packages.
8059
+
8060
+ Choosing a code search tool:
8061
+ - search_symbols: single package, symbol-level → results feed symbol_callers/callees/call_path
8062
+ - search(mode='code'): multi-package, full-text → code chunks with snippets
8063
+ - grep_file: single file, pattern match → when you know the file path
8064
+
8065
+ Utility: trigger_indexing (pre-warm indexes), search_status (poll async search).
8066
+
8067
+ Quick start: find_symbol(target={registry:"npm", package_name:"<pkg>"}, name="<function>", include_code=true) often answers the question in one call.
7932
8068
 
7933
- Quick start: find_symbol(registry="npm", name="<function>", package_name="<pkg>", include_code=true) often answers the question in one call.`;
8069
+ Common workflows (pass symbolRef between tools for chaining):
8070
+ - Read source: find_symbol(target={registry, package_name}, name=<fn>, include_code=true)
8071
+ - Trace calls: find_symbol → symbol_callees(symbol={symbol_ref: <symbolRef>})
8072
+ - Find callers: find_symbol → symbol_callers(symbol={symbol_ref: <symbolRef>})
8073
+ - Read file: read_file(target={registry, package_name}, file_path=<path>) or read_file(target={repo_url, git_ref}, file_path=<path>)
8074
+ - Search code: search_symbols (single pkg, feeds callers/callees) or search(mode='code', packages=[...]) (multi-pkg)
8075
+ - Browse docs: list_package_docs → fetch_package_doc(page_id)`;
7934
8076
  var TOOL_FACTORIES = {
7935
8077
  package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
7936
8078
  package_vulnerabilities: ({ pkgseerService }) => createPackageVulnerabilitiesTool(pkgseerService),
@@ -7941,7 +8083,7 @@ var TOOL_FACTORIES = {
7941
8083
  fetch_package_doc: ({ pkgseerService }) => createFetchPackageDocTool(pkgseerService),
7942
8084
  search: ({ pkgseerService }) => createSearchTool(pkgseerService),
7943
8085
  search_status: ({ pkgseerService }) => createSearchStatusTool(pkgseerService),
7944
- fetch_code_context: ({ pkgseerService }) => createFetchCodeContextTool(pkgseerService),
8086
+ read_file: ({ pkgseerService }) => createReadFileTool(pkgseerService),
7945
8087
  search_project_docs: ({ pkgseerService, configService, defaultProjectDir }) => createSearchProjectDocsTool({
7946
8088
  pkgseerService,
7947
8089
  configService,
@@ -7952,11 +8094,11 @@ var TOOL_FACTORIES = {
7952
8094
  list_symbols: ({ pkgseerService }) => createListSymbolsTool(pkgseerService),
7953
8095
  symbol_callers: ({ pkgseerService }) => createSymbolCallersTool(pkgseerService),
7954
8096
  symbol_callees: ({ pkgseerService }) => createSymbolCalleesTool(pkgseerService),
7955
- package_imports: ({ pkgseerService }) => createPackageImportsTool(pkgseerService),
8097
+ list_imports: ({ pkgseerService }) => createListImportsTool(pkgseerService),
7956
8098
  call_path: ({ pkgseerService }) => createCallPathTool(pkgseerService),
7957
8099
  trigger_indexing: ({ pkgseerService }) => createTriggerIndexingTool(pkgseerService),
7958
- list_repo_files: ({ pkgseerService }) => createListRepoFilesTool(pkgseerService),
7959
- grep_repo_file: ({ pkgseerService }) => createGrepRepoFileTool(pkgseerService),
8100
+ list_files: ({ pkgseerService }) => createListFilesTool(pkgseerService),
8101
+ grep_file: ({ pkgseerService }) => createGrepFileTool(pkgseerService),
7960
8102
  version_diff: ({ pkgseerService }) => createVersionDiffTool(pkgseerService)
7961
8103
  };
7962
8104
  var PUBLIC_READ_TOOLS = [
@@ -7969,24 +8111,24 @@ var PUBLIC_READ_TOOLS = [
7969
8111
  "fetch_package_doc",
7970
8112
  "search",
7971
8113
  "search_status",
7972
- "fetch_code_context",
8114
+ "read_file",
7973
8115
  "find_symbol",
7974
8116
  "search_symbols",
7975
8117
  "list_symbols",
7976
8118
  "symbol_callers",
7977
8119
  "symbol_callees",
7978
- "package_imports",
8120
+ "list_imports",
7979
8121
  "call_path",
7980
8122
  "trigger_indexing",
7981
- "list_repo_files",
7982
- "grep_repo_file",
8123
+ "list_files",
8124
+ "grep_file",
7983
8125
  "version_diff"
7984
8126
  ];
7985
8127
  var PROJECT_READ_TOOLS = ["search_project_docs"];
7986
8128
  var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
7987
8129
  function createMcpServer(deps) {
7988
8130
  const { pkgseerService, configService, config, fileSystemService } = deps;
7989
- const server = new McpServer({ name: "pkgseer", version: "0.1.0" }, { instructions: PKGSEER_INSTRUCTIONS });
8131
+ const server = new McpServer({ name: "pkgseer", version: "0.5.0" }, { instructions: PKGSEER_INSTRUCTIONS });
7990
8132
  const defaultProjectDir = fileSystemService.getCwd();
7991
8133
  const enabledToolNames = config.enabled_tools ?? ALL_TOOLS;
7992
8134
  const toolsToRegister = enabledToolNames.filter((name) => ALL_TOOLS.includes(name));
@@ -8052,13 +8194,13 @@ function registerMcpCommand(program) {
8052
8194
  When run interactively (TTY), shows setup instructions.
8053
8195
  When run via stdio (non-TTY), starts the MCP server.
8054
8196
 
8055
- Available tools (21):
8197
+ Available tools (22):
8056
8198
  Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
8057
- Browse files: list_repo_files, grep_repo_file, fetch_code_context
8199
+ Browse files: list_files, grep_file, read_file
8058
8200
  Search: search, search_project_docs
8059
8201
  Docs: list_package_docs, fetch_package_doc
8060
8202
  Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
8061
- Utility: trigger_indexing, search_status, package_imports`).action(async () => {
8203
+ Utility: trigger_indexing, search_status, list_imports`).action(async () => {
8062
8204
  const deps = await createContainer();
8063
8205
  if (process.stdout.isTTY && process.stdin.isTTY) {
8064
8206
  showMcpSetupInstructions(deps);