@pkgseer/cli 0.4.7 → 0.4.8

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-z0xepgqq.js";
4
+ } from "./shared/chunk-edcjw6wf.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
@@ -5117,16 +5117,39 @@ async function setupCodexViaCli(shellService) {
5117
5117
  }
5118
5118
  function showAvailableTools(hasProject, useColors) {
5119
5119
  console.log(`
5120
- Available MCP tools:`);
5121
- console.log(" • package_summary - Get package overview");
5122
- console.log(" package_vulnerabilities - Check for security issues");
5123
- console.log(" package_quality - Get quality score");
5124
- console.log(" package_dependencies - List dependencies");
5125
- console.log(" compare_packages - Compare multiple packages");
5126
- console.log(" list_package_docs - List documentation pages");
5127
- console.log(" fetch_package_doc - Fetch documentation content");
5128
- console.log(" search_package_docs - Search package documentation");
5129
- console.log(" • search_project_docs - Search docs across project dependencies");
5120
+ Available MCP tools (21):`);
5121
+ console.log("");
5122
+ console.log(" Navigate source:");
5123
+ console.log(" find_symbol - Read source code of functions/classes");
5124
+ console.log(" list_symbols - Browse public API or file symbols");
5125
+ console.log(" search_symbols - Full-text search within package code");
5126
+ console.log(" symbol_callers - Trace what calls a function");
5127
+ console.log(" symbol_callees - Trace what a function calls");
5128
+ console.log(" call_path - Find call path between two functions");
5129
+ console.log("");
5130
+ console.log(" Browse files:");
5131
+ console.log(" • list_repo_files - Explore package file structure");
5132
+ console.log(" • grep_repo_file - Search for patterns in source files");
5133
+ console.log(" • fetch_code_context - Read source by file path and line range");
5134
+ console.log("");
5135
+ console.log(" Search & docs:");
5136
+ console.log(" • search - Search code and docs across packages");
5137
+ console.log(" • search_project_docs - Search docs across project dependencies");
5138
+ console.log(" • list_package_docs - List documentation pages");
5139
+ console.log(" • fetch_package_doc - Fetch documentation content");
5140
+ console.log("");
5141
+ console.log(" Evaluate:");
5142
+ console.log(" • package_summary - Get package overview");
5143
+ console.log(" • package_quality - Get quality score");
5144
+ console.log(" • package_vulnerabilities - Check for security issues");
5145
+ console.log(" • compare_packages - Compare multiple packages");
5146
+ console.log(" • package_dependencies - List dependencies");
5147
+ console.log(" • version_diff - Compare changes between versions");
5148
+ console.log("");
5149
+ console.log(" Utility:");
5150
+ console.log(" • trigger_indexing - Pre-warm package indexes");
5151
+ console.log(" • search_status - Check async search progress");
5152
+ console.log(" • package_imports - See what a package imports");
5130
5153
  if (!hasProject) {
5131
5154
  console.log(dim(`
5132
5155
  Tip: Create pkgseer.yml to enable automatic project detection for search_project_docs.`, useColors));
@@ -6022,27 +6045,51 @@ function generateSkillContent(invocation = "pkgseer") {
6022
6045
  return `---
6023
6046
  name: pkgseer
6024
6047
  version: ${version}
6025
- description: Search code/docs across npm, PyPI, Hex packages. Provides quality scores, security vulnerabilities, dependencies, comparisons. Use when user asks about package security, CVEs, vulnerabilities, code examples, API usage, package comparison, dependency analysis, or which package to use.
6048
+ description: Navigate source code, trace call graphs, and search docs across npm/PyPI/Hex packages. Quality scores, vulnerability checks, dependency analysis, and cross-package comparison. Use when debugging third-party dependencies, understanding how a library works internally, tracing a stack trace into dependency code, evaluating or comparing packages, checking security vulnerabilities, or understanding what changed between versions.
6026
6049
  ---
6027
6050
 
6028
- # PkgSeer - Package Intelligence
6051
+ # PkgSeer - Package Source Code & Intelligence
6029
6052
 
6030
- Search and analyze packages across npm, PyPI, and Hex. All commands support \`--json\`.
6053
+ Navigate dependency source code and analyze packages across npm, PyPI, and Hex. All commands support \`--json\`.
6031
6054
 
6032
- ## Search (Primary Use Case)
6055
+ Use PkgSeer instead of guessing library behavior, cloning repos, or browsing GitHub.
6056
+
6057
+ ## Code Navigation (Debug & Understand Dependencies)
6058
+
6059
+ \`\`\`bash
6060
+ # Read source code of a function/class — use instead of guessing from training data
6061
+ ${invocation} code find express Router --include-code
6062
+ ${invocation} code find pypi:requests Session --include-code
6063
+
6064
+ # Trace what calls a function (find entry points, debug triggers)
6065
+ ${invocation} code callers -r npm -p express -n Router
6066
+
6067
+ # Trace what a function calls (follow execution path)
6068
+ ${invocation} code callees -r npm -p express -n Router
6069
+
6070
+ # Find how function A reaches function B
6071
+ ${invocation} code path -r npm -p express --from-name listen --to-name createServer
6072
+
6073
+ # Search for error messages or patterns in dependency source
6074
+ ${invocation} code search express "ERR_HTTP_HEADERS_SENT"
6075
+ ${invocation} code grep express src/router/index.js "handle"
6076
+
6077
+ # Browse package structure, API, and imports
6078
+ ${invocation} code files express --path-prefix src/
6079
+ ${invocation} code list express --scope exports
6080
+ ${invocation} code imports express --resolved-only
6081
+
6082
+ # Compare versions (detect breaking changes after upgrades)
6083
+ ${invocation} code diff express v4.18.2 v5.0.0
6084
+ \`\`\`
6085
+
6086
+ ## Search Across Packages
6033
6087
 
6034
6088
  \`\`\`bash
6035
- # Search code and docs across packages
6036
6089
  ${invocation} search "<query>" -P lodash,express # npm packages
6037
6090
  ${invocation} search "<query>" -P pypi:requests # PyPI packages
6038
- ${invocation} search "authentication" -P hex:phoenix,hex:plug
6039
-
6040
- # Search modes
6041
6091
  ${invocation} search "<query>" -P <packages> --mode code # Code only
6042
6092
  ${invocation} search "<query>" -P <packages> --mode docs # Docs only
6043
-
6044
- # Docs-only search (shorthand)
6045
- ${invocation} docs search "<query>" -P <packages>
6046
6093
  \`\`\`
6047
6094
 
6048
6095
  ## Package Analysis
@@ -6050,23 +6097,11 @@ ${invocation} docs search "<query>" -P <packages>
6050
6097
  Package format: \`[registry:]name[@version]\`
6051
6098
 
6052
6099
  \`\`\`bash
6053
- # Overview: metadata, versions, quickstart
6054
- ${invocation} pkg info lodash
6055
- ${invocation} pkg info pypi:requests
6056
-
6057
- # Quality score (0-100) with category breakdown
6058
- ${invocation} pkg quality express@4.18.0
6059
- ${invocation} pkg quality pypi:django@4.2
6060
-
6061
- # Security: CVEs, severity, upgrade paths
6062
- ${invocation} pkg vulns lodash@4.17.21
6063
-
6064
- # Dependencies: direct, transitive, tree view
6065
- ${invocation} pkg deps express --transitive
6066
-
6067
- # Compare up to 10 packages
6068
- ${invocation} pkg compare lodash underscore ramda
6069
- ${invocation} pkg compare axios pypi:httpx # cross-registry
6100
+ ${invocation} pkg info lodash # Overview, versions, quickstart
6101
+ ${invocation} pkg quality express@4.18.0 # Quality score (0-100)
6102
+ ${invocation} pkg vulns lodash@4.17.21 # CVEs, severity, upgrade paths
6103
+ ${invocation} pkg deps express --transitive # Dependency tree
6104
+ ${invocation} pkg compare lodash underscore ramda # Side-by-side comparison
6070
6105
  \`\`\`
6071
6106
 
6072
6107
  ## Documentation
@@ -6082,6 +6117,7 @@ ${invocation} docs search "<query>" -P <packages> # Search docs only
6082
6117
  - Package format: \`[registry:]name[@version]\` (e.g., \`pypi:django@4.2\`)
6083
6118
  - Default registry: npm
6084
6119
  - Use \`--json\` for structured output when parsing
6120
+ - Quick start: \`${invocation} code find <package> <function> --include-code\`
6085
6121
  `;
6086
6122
  }
6087
6123
  function extractSkillVersion(content) {
@@ -6214,7 +6250,8 @@ PkgSeer skill ${action} for ${toolName}!`, useColors));
6214
6250
  console.log(`Location: ${highlight(paths.skillPath, useColors)}`);
6215
6251
  console.log(dim(`
6216
6252
  The skill is now available. Try asking:
6217
- ` + ` "Search for authentication examples in express"
6253
+ ` + ` "How does express Router work internally?"
6254
+ ` + ` "What changed between express v4 and v5?"
6218
6255
  ` + ` "Is lodash secure? Check for vulnerabilities"
6219
6256
  ` + ' "Compare axios vs fetch vs got"', useColors));
6220
6257
  }
@@ -6828,8 +6865,9 @@ var argsSchema = {
6828
6865
  function createCallPathTool(pkgseerService) {
6829
6866
  return {
6830
6867
  name: "call_path",
6831
- description: "Find the shortest call path between two symbols in the same package. " + "Uses BFS to trace how function A eventually calls function B through intermediate calls. " + "Returns whether a path was found, with ordered call paths (shortest first) and hop details. " + "For direct callers/callees only, use symbol_callers or symbol_callees instead.",
6868
+ 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.",
6832
6869
  schema: argsSchema,
6870
+ annotations: { readOnlyHint: true },
6833
6871
  handler: async (args, _extra) => {
6834
6872
  return withErrorHandling("find call path", async () => {
6835
6873
  const fromInput = toSymbolReferenceInput(args.from);
@@ -6871,6 +6909,7 @@ function createComparePackagesTool(pkgseerService) {
6871
6909
  name: "compare_packages",
6872
6910
  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"}]',
6873
6911
  schema: argsSchema2,
6912
+ annotations: { readOnlyHint: true },
6874
6913
  handler: async ({ packages }, _extra) => {
6875
6914
  return withErrorHandling("compare packages", async () => {
6876
6915
  const input2 = packages.map((pkg) => ({
@@ -6902,8 +6941,9 @@ var argsSchema3 = {
6902
6941
  function createFetchCodeContextTool(pkgseerService) {
6903
6942
  return {
6904
6943
  name: "fetch_code_context",
6905
- description: "Fetch code content from a repository by file path and line range. " + "Returns full file by default, or a specific line range. " + "For symbol-based lookup, use find_symbol(include_code=true) instead. " + "Requires repo_url, git_ref (tag/commit/branch), and file_path.",
6944
+ 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.",
6906
6945
  schema: argsSchema3,
6946
+ annotations: { readOnlyHint: true },
6907
6947
  handler: async ({ repo_url, git_ref, file_path, start_line, end_line }, _extra) => {
6908
6948
  return withErrorHandling("fetch code context", async () => {
6909
6949
  const result = await pkgseerService.fetchCodeContext(repo_url, git_ref, file_path, {
@@ -6931,6 +6971,7 @@ function createFetchPackageDocTool(pkgseerService) {
6931
6971
  name: "fetch_package_doc",
6932
6972
  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.",
6933
6973
  schema: argsSchema4,
6974
+ annotations: { readOnlyHint: true },
6934
6975
  handler: async ({ page_id }, _extra) => {
6935
6976
  return withErrorHandling("fetch documentation page", async () => {
6936
6977
  const result = await pkgseerService.getDocPage(page_id);
@@ -6971,8 +7012,9 @@ var argsSchema5 = {
6971
7012
  function createFindSymbolTool(pkgseerService) {
6972
7013
  return {
6973
7014
  name: "find_symbol",
6974
- description: "Find functions, methods, or classes by name in a package. " + "Set include_code=true to get full source code inline, avoiding separate fetch_code_context calls. " + "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.",
7015
+ 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.",
6975
7016
  schema: argsSchema5,
7017
+ annotations: { readOnlyHint: true },
6976
7018
  handler: async (args, _extra) => {
6977
7019
  return withErrorHandling("find symbol", async () => {
6978
7020
  const result = await pkgseerService.findSymbol(toGraphQLRegistry(args.registry), args.package_name, {
@@ -7016,8 +7058,9 @@ var argsSchema6 = {
7016
7058
  function createGrepRepoFileTool(pkgseerService) {
7017
7059
  return {
7018
7060
  name: "grep_repo_file",
7019
- description: "Search for a pattern within a file in a package's repository. " + "Case-insensitive substring matching. Returns matching lines with context. " + "Faster than fetch_code_context for large files. " + "Use list_repo_files to discover available file paths.",
7061
+ 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.",
7020
7062
  schema: argsSchema6,
7063
+ annotations: { readOnlyHint: true },
7021
7064
  handler: async (args, _extra) => {
7022
7065
  return withErrorHandling("grep repo file", async () => {
7023
7066
  const result = await pkgseerService.grepRepoFile(toGraphQLRegistry(args.registry), args.package_name, args.file_path, args.pattern, {
@@ -7050,8 +7093,9 @@ var argsSchema7 = {
7050
7093
  function createListPackageDocsTool(pkgseerService) {
7051
7094
  return {
7052
7095
  name: "list_package_docs",
7053
- 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_package_docs to find specific topics.",
7096
+ 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.",
7054
7097
  schema: argsSchema7,
7098
+ annotations: { readOnlyHint: true },
7055
7099
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7056
7100
  return withErrorHandling("list package documentation", async () => {
7057
7101
  const result = await pkgseerService.listPackageDocs(toGraphQLRegistry(registry), package_name, version2);
@@ -7079,8 +7123,9 @@ var argsSchema8 = {
7079
7123
  function createListRepoFilesTool(pkgseerService) {
7080
7124
  return {
7081
7125
  name: "list_repo_files",
7082
- description: "List files in a package's indexed repository. " + "Returns file paths, names, languages, types (source/doc/config), and sizes. " + "Use path_prefix to filter by directory (e.g., 'src/'). " + "Useful for exploring package structure before searching or reading code.",
7126
+ 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.",
7083
7127
  schema: argsSchema8,
7128
+ annotations: { readOnlyHint: true },
7084
7129
  handler: async (args, _extra) => {
7085
7130
  return withErrorHandling("list repo files", async () => {
7086
7131
  const result = await pkgseerService.listRepoFiles(toGraphQLRegistry(args.registry), args.package_name, {
@@ -7122,8 +7167,9 @@ var argsSchema9 = {
7122
7167
  function createListSymbolsTool(pkgseerService) {
7123
7168
  return {
7124
7169
  name: "list_symbols",
7125
- description: "Browse symbols in a package by scope. " + "Use scope='exports' for public API with namespace grouping and optional popularity. " + "Use scope='file' with file_path for all symbols in a specific file. " + "Returns symbols with refs, names, qualified paths, kinds, and file locations. " + "Use find_symbol(name=<symbol>, include_code=true) to get source for any listed symbol.",
7170
+ 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.",
7126
7171
  schema: argsSchema9,
7172
+ annotations: { readOnlyHint: true },
7127
7173
  handler: async (args, _extra) => {
7128
7174
  return withErrorHandling("list symbols", async () => {
7129
7175
  const scope = toListScope(args.scope);
@@ -7245,6 +7291,7 @@ function createPackageDependenciesTool(pkgseerService) {
7245
7291
  name: "package_dependencies",
7246
7292
  description: "Analyze package dependencies. By default returns direct dependencies only. " + "Set include_transitive=true to get the full dependency tree (use max_depth to limit large trees). " + "Returns: dependency names, version constraints, and for transitive deps, a graph with depth levels. " + "Use this to understand complexity before adding a package, or to find nested dependencies.",
7247
7293
  schema: argsSchema10,
7294
+ annotations: { readOnlyHint: true },
7248
7295
  handler: async ({ registry, package_name, version: version2, include_transitive, max_depth }, _extra) => {
7249
7296
  return withErrorHandling("fetch package dependencies", async () => {
7250
7297
  const result = await pkgseerService.getPackageDependencies(toGraphQLRegistry(registry), package_name, version2, include_transitive, max_depth);
@@ -7296,8 +7343,9 @@ var argsSchema11 = {
7296
7343
  function createPackageImportsTool(pkgseerService) {
7297
7344
  return {
7298
7345
  name: "package_imports",
7299
- description: "Get import statements in a package. " + "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.",
7346
+ 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.",
7300
7347
  schema: argsSchema11,
7348
+ annotations: { readOnlyHint: true },
7301
7349
  handler: async (args, _extra) => {
7302
7350
  return withErrorHandling("fetch package imports", async () => {
7303
7351
  const result = await pkgseerService.packageImports(toGraphQLRegistry(args.registry), args.package_name, {
@@ -7330,6 +7378,7 @@ function createPackageQualityTool(pkgseerService) {
7330
7378
  name: "package_quality",
7331
7379
  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.",
7332
7380
  schema: argsSchema12,
7381
+ annotations: { readOnlyHint: true },
7333
7382
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7334
7383
  return withErrorHandling("fetch package quality", async () => {
7335
7384
  const result = await pkgseerService.getPackageQuality(toGraphQLRegistry(registry), package_name, version2);
@@ -7354,6 +7403,7 @@ function createPackageSummaryTool(pkgseerService) {
7354
7403
  name: "package_summary",
7355
7404
  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).",
7356
7405
  schema: argsSchema13,
7406
+ annotations: { readOnlyHint: true },
7357
7407
  handler: async ({ registry, package_name }, _extra) => {
7358
7408
  return withErrorHandling("fetch package summary", async () => {
7359
7409
  const result = await pkgseerService.getPackageSummary(toGraphQLRegistry(registry), package_name);
@@ -7379,6 +7429,7 @@ function createPackageVulnerabilitiesTool(pkgseerService) {
7379
7429
  name: "package_vulnerabilities",
7380
7430
  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.",
7381
7431
  schema: argsSchema14,
7432
+ annotations: { readOnlyHint: true },
7382
7433
  handler: async ({ registry, package_name, version: version2 }, _extra) => {
7383
7434
  return withErrorHandling("fetch package vulnerabilities", async () => {
7384
7435
  const result = await pkgseerService.getPackageVulnerabilities(toGraphQLRegistry(registry), package_name, version2);
@@ -7446,6 +7497,7 @@ function createSearchTool(pkgseerService) {
7446
7497
  name: "search",
7447
7498
  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.",
7448
7499
  schema: argsSchema15,
7500
+ annotations: { readOnlyHint: true },
7449
7501
  handler: async ({ packages, query, mode, limit, waitTimeoutMs }, _extra) => {
7450
7502
  return withErrorHandling("search packages", async () => {
7451
7503
  const normalizedQuery = query.trim();
@@ -7510,8 +7562,9 @@ function createSearchProjectDocsTool(deps) {
7510
7562
  const { pkgseerService, configService, defaultProjectDir } = deps;
7511
7563
  return {
7512
7564
  name: "search_project_docs",
7513
- description: "Searches documentation across all dependencies in a PkgSeer project using search terms and match modes (any/all). Returns ranked results from multiple packages. Use project_directory to specify which project's context to use, or project to search a specific project directly.",
7565
+ description: "Search documentation across all dependencies in a PkgSeer project " + "use when you need to find information but don't know which dependency has it. " + "Requires a pkgseer.yml project config (or pass project name directly). " + "Returns ranked results with snippets from multiple packages. " + "Use project_directory to specify which project's context to use. " + "For single-package doc search, use search(mode='docs') instead.",
7514
7566
  schema: argsSchema16,
7567
+ annotations: { readOnlyHint: true },
7515
7568
  handler: async ({
7516
7569
  project_directory,
7517
7570
  project,
@@ -7566,6 +7619,7 @@ function createSearchStatusTool(pkgseerService) {
7566
7619
  name: "search_status",
7567
7620
  description: "Check the status of an async search and get results if complete. " + "Use after search returns completed=false with a searchRef. Sessions expire after 1 hour. " + "Returns status (PENDING, INDEXING, SEARCHING, COMPLETED, TIMEOUT, FAILED), " + "progress info (packagesReady/packagesTotal), and results when COMPLETED.",
7568
7621
  schema: argsSchema17,
7622
+ annotations: { readOnlyHint: true },
7569
7623
  handler: async ({ searchRef }, _extra) => {
7570
7624
  return withErrorHandling("check search status", async () => {
7571
7625
  const progressResult = await pkgseerService.getSearchProgress(searchRef);
@@ -7631,8 +7685,9 @@ var argsSchema18 = {
7631
7685
  function createSearchSymbolsTool(pkgseerService) {
7632
7686
  return {
7633
7687
  name: "search_symbols",
7634
- description: "Full-text search within package code. " + "Searches across functions, classes, modules, and doc sections. " + "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: use find_symbol(name=<result.name>, include_code=true) to get full source.",
7688
+ 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.",
7635
7689
  schema: argsSchema18,
7690
+ annotations: { readOnlyHint: true },
7636
7691
  handler: async (args, _extra) => {
7637
7692
  return withErrorHandling("search symbols", async () => {
7638
7693
  const result = await pkgseerService.searchSymbols(toGraphQLRegistry(args.registry), args.package_name, {
@@ -7682,8 +7737,9 @@ var argsSchema19 = {
7682
7737
  function createSymbolCalleesTool(pkgseerService) {
7683
7738
  return {
7684
7739
  name: "symbol_callees",
7685
- description: "Find what a symbol calls (its dependencies). " + "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 results. See symbol_callers for the reverse.",
7740
+ 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.",
7686
7741
  schema: argsSchema19,
7742
+ annotations: { readOnlyHint: true },
7687
7743
  handler: async (args, _extra) => {
7688
7744
  return withErrorHandling("find symbol callees", async () => {
7689
7745
  const symbolInput = toSymbolReferenceInput(args.symbol);
@@ -7722,8 +7778,9 @@ var argsSchema20 = {
7722
7778
  function createSymbolCallersTool(pkgseerService) {
7723
7779
  return {
7724
7780
  name: "symbol_callers",
7725
- description: "Find what calls a symbol (its dependents/callers). " + "Returns the target symbol and a list of callers with file locations and call line numbers. " + "Use same_package_only to limit to callers within the same package. " + "Get symbol_ref from find_symbol or list_symbols results. See symbol_callees for the reverse.",
7781
+ 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.",
7726
7782
  schema: argsSchema20,
7783
+ annotations: { readOnlyHint: true },
7727
7784
  handler: async (args, _extra) => {
7728
7785
  return withErrorHandling("find symbol callers", async () => {
7729
7786
  const symbolInput = toSymbolReferenceInput(args.symbol);
@@ -7769,6 +7826,7 @@ function createTriggerIndexingTool(pkgseerService) {
7769
7826
  name: "trigger_indexing",
7770
7827
  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.",
7771
7828
  schema: argsSchema21,
7829
+ annotations: { readOnlyHint: false, idempotentHint: true },
7772
7830
  handler: async (args, _extra) => {
7773
7831
  return withErrorHandling("trigger indexing", async () => {
7774
7832
  const packages = args.packages?.map((p) => ({
@@ -7827,8 +7885,9 @@ var argsSchema22 = {
7827
7885
  function createVersionDiffTool(pkgseerService) {
7828
7886
  return {
7829
7887
  name: "version_diff",
7830
- description: "Compare symbols between two package versions. " + "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.",
7888
+ 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.",
7831
7889
  schema: argsSchema22,
7890
+ annotations: { readOnlyHint: true },
7832
7891
  handler: async (args, _extra) => {
7833
7892
  return withErrorHandling("version diff", async () => {
7834
7893
  const result = await pkgseerService.versionDiff(toGraphQLRegistry(args.registry), args.package_name, args.from_version, args.to_version, {
@@ -7849,6 +7908,28 @@ function createVersionDiffTool(pkgseerService) {
7849
7908
  };
7850
7909
  }
7851
7910
  // src/commands/mcp.ts
7911
+ var PKGSEER_INSTRUCTIONS = `PkgSeer provides source code intelligence for third-party packages across npm, PyPI, Hex, and other registries. All tools are read-only except trigger_indexing (which only queues background work).
7912
+
7913
+ Use PkgSeer when:
7914
+ - A stack trace or error originates in a third-party dependency
7915
+ - You need to understand how a library function works internally
7916
+ - You want to trace call chains through dependency source code
7917
+ - You're evaluating, comparing, or auditing packages
7918
+ - You need to understand what changed between package versions
7919
+
7920
+ Instead of guessing library behavior from training data, use find_symbol(include_code=true) to read actual source.
7921
+ Instead of cloning repos to search code, use search_symbols or grep_repo_file.
7922
+ Instead of manually tracing call chains on GitHub, use symbol_callers and symbol_callees.
7923
+
7924
+ Tool groups:
7925
+ - Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
7926
+ - Browse files: list_repo_files, grep_repo_file, fetch_code_context
7927
+ - Search across packages: search, search_project_docs
7928
+ - Browse docs: list_package_docs, fetch_package_doc
7929
+ - Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
7930
+ - Utility: trigger_indexing, search_status, package_imports
7931
+
7932
+ Quick start: find_symbol(registry="npm", name="<function>", package_name="<pkg>", include_code=true) often answers the question in one call.`;
7852
7933
  var TOOL_FACTORIES = {
7853
7934
  package_summary: ({ pkgseerService }) => createPackageSummaryTool(pkgseerService),
7854
7935
  package_vulnerabilities: ({ pkgseerService }) => createPackageVulnerabilitiesTool(pkgseerService),
@@ -7904,10 +7985,7 @@ var PROJECT_READ_TOOLS = ["search_project_docs"];
7904
7985
  var ALL_TOOLS = [...PUBLIC_READ_TOOLS, ...PROJECT_READ_TOOLS];
7905
7986
  function createMcpServer(deps) {
7906
7987
  const { pkgseerService, configService, config, fileSystemService } = deps;
7907
- const server = new McpServer({
7908
- name: "pkgseer",
7909
- version: "0.1.0"
7910
- });
7988
+ const server = new McpServer({ name: "pkgseer", version: "0.1.0" }, { instructions: PKGSEER_INSTRUCTIONS });
7911
7989
  const defaultProjectDir = fileSystemService.getCwd();
7912
7990
  const enabledToolNames = config.enabled_tools ?? ALL_TOOLS;
7913
7991
  const toolsToRegister = enabledToolNames.filter((name) => ALL_TOOLS.includes(name));
@@ -7920,7 +7998,11 @@ function createMcpServer(deps) {
7920
7998
  for (const toolName of toolsToRegister) {
7921
7999
  const factory = TOOL_FACTORIES[toolName];
7922
8000
  const tool = factory(factoryDeps);
7923
- server.registerTool(tool.name, { description: tool.description, inputSchema: tool.schema }, tool.handler);
8001
+ server.registerTool(tool.name, {
8002
+ description: tool.description,
8003
+ inputSchema: tool.schema,
8004
+ annotations: tool.annotations
8005
+ }, tool.handler);
7924
8006
  }
7925
8007
  return server;
7926
8008
  }
@@ -7969,10 +8051,13 @@ function registerMcpCommand(program) {
7969
8051
  When run interactively (TTY), shows setup instructions.
7970
8052
  When run via stdio (non-TTY), starts the MCP server.
7971
8053
 
7972
- Available tools: package_summary, package_vulnerabilities,
7973
- package_dependencies, package_quality, compare_packages,
7974
- list_package_docs, fetch_package_doc, search_package_docs,
7975
- search_project_docs`).action(async () => {
8054
+ Available tools (21):
8055
+ Navigate source: find_symbol, list_symbols, search_symbols, symbol_callers, symbol_callees, call_path
8056
+ Browse files: list_repo_files, grep_repo_file, fetch_code_context
8057
+ Search: search, search_project_docs
8058
+ Docs: list_package_docs, fetch_package_doc
8059
+ Evaluate: package_summary, package_quality, package_vulnerabilities, compare_packages, package_dependencies, version_diff
8060
+ Utility: trigger_indexing, search_status, package_imports`).action(async () => {
7976
8061
  const deps = await createContainer();
7977
8062
  if (process.stdout.isTTY && process.stdin.isTTY) {
7978
8063
  showMcpSetupInstructions(deps);
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-z0xepgqq.js";
3
+ } from "./shared/chunk-edcjw6wf.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -1,4 +1,4 @@
1
1
  // package.json
2
- var version = "0.4.7";
2
+ var version = "0.4.8";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pkgseer/cli",
3
3
  "description": "CLI companion for PkgSeer - package intelligence for developers and AI assistants",
4
- "version": "0.4.7",
4
+ "version": "0.4.8",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",