# https://github.com/fstubner/npm-run-mcp-server 项目说明书

生成时间：2026-06-02 03:15:54 UTC

## 目录

- [项目概述](#page-overview)
- [快速开始](#page-quickstart)
- [安装与环境](#page-installation)
- [配置文件指南](#page-configuration)
- [输入模式与脚本参数](#page-input-schema)
- [命令行界面](#page-cli-usage)
- [系统架构](#page-architecture)
- [包管理器检测](#page-package-manager)
- [工具注册机制](#page-tool-registration)
- [文件监视与热重载](#page-file-watching)

<a id='page-overview'></a>

## 项目概述

### 相关页面

相关主题：[快速开始](#page-quickstart), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
</details>

# 项目概述

npm-run-mcp-server 是一个基于 Model Context Protocol (MCP) 的服务器项目，它能够将项目中的 `package.json` 脚本自动暴露为可供 AI 代理使用的 MCP 工具。通过这种方式，AI 助手（如 Claude、Cursor、GitHub Copilot）可以直接调用项目定义的 npm 脚本进行构建、测试、部署等操作，无需人工介入。

---

## 项目定位与核心价值

### 设计目标

该项目的核心目标是消除 AI 代理与项目构建流程之间的壁垒。传统的 AI 编程助手虽然能够理解代码，但执行构建、测试等操作时往往需要用户手动复制粘贴命令。npm-run-mcp-server 通过 MCP 协议将 `package.json` 中的脚本转换为结构化的工具定义，使 AI 能够：

- **自动发现**项目脚本，无需手动配置
- **理解脚本语义**，包括参数、描述等信息
- **安全执行**脚本，支持细粒度的权限控制
- **跨平台兼容**，支持 npm、pnpm、yarn、bun 四种主流包管理器

### 技术定位

| 维度 | 描述 |
|------|------|
| 协议层 | Model Context Protocol (MCP) 标准实现 |
| 运行模式 | Stdio 传输，进程间通信 |
| 目标用户 | AI 编程助手及其使用者 |
| 集成方式 | 即插即用，通过 npx 或全局安装 |
| 最低 Node 版本 | 18.18.0 |

资料来源：[package.json:29]()

---

## 系统架构

### 整体架构图

```mermaid
graph TD
    subgraph "AI 客户端层"
        Claude[Claude Desktop]
        Cursor[Cursor IDE]
        Copilot[GitHub Copilot]
        VSCode[VS Code]
    end

    subgraph "MCP 协议层"
        MCP_SDK[@modelcontextprotocol/sdk]
        StdioTransport[Stdio Transport]
    end

    subgraph "npm-run-mcp-server 核心"
        ConfigLoader[配置加载器]
        PackageDetector[包管理器检测]
        ScriptExecutor[脚本执行器]
        ToolBuilder[工具构建器]
    end

    subgraph "项目层"
        PackageJson[package.json]
        ConfigFile[npm-run-mcp.config.json]
    end

    subgraph "包管理器层"
        NPM[npm]
        PNPM[pnpm]
        Yarn[yarn]
        Bun[bun]
    end

    Claude --> StdioTransport
    Cursor --> StdioTransport
    Copilot --> StdioTransport
    VSCode --> StdioTransport

    StdioTransport --> MCP_SDK
    MCP_SDK --> ConfigLoader
    MCP_SDK --> ToolBuilder

    ConfigLoader --> PackageJson
    ConfigLoader --> ConfigFile

    PackageDetector --> PackageJson
    ScriptExecutor --> PackageDetector

    ToolBuilder --> ScriptExecutor

    ScriptExecutor --> NPM
    ScriptExecutor --> PNPM
    ScriptExecutor --> Yarn
    ScriptExecutor --> Bun
```

### 核心组件说明

| 组件名称 | 职责 | 源码位置 |
|----------|------|----------|
| 配置加载器 | 解析项目配置文件和 CLI 参数 | src/index.ts |
| 包管理器检测 | 自动识别项目使用的包管理器 | src/index.ts |
| 脚本执行器 | 在正确目录下执行 npm 脚本 | src/index.ts |
| 工具构建器 | 将脚本转换为 MCP 工具定义 | src/index.ts |

资料来源：[src/index.ts:1-200]()

---

## 核心功能特性

### 1. 自动包管理器检测

服务器启动时会自动检测项目使用的包管理器，优先级如下：

1. **显式指定**：通过 `--pm` CLI 参数指定
2. **packageManager 字段**：检查 `package.json` 中的 `packageManager` 字段
3. **锁文件检测**：按以下顺序检测锁文件

| 锁文件 | 对应包管理器 |
|--------|--------------|
| `pnpm-lock.yaml` | pnpm |
| `yarn.lock` | yarn |
| `bun.lockb` / `bun.lock` | bun |
| (无锁文件) | npm (默认) |

资料来源：[src/index.ts:PackageJson 定义处]()

### 2. 工作目录自动识别

服务器能够智能识别项目根目录，支持多种环境变量：

| 环境变量 | 说明 | 适用场景 |
|----------|------|----------|
| `WORKSPACE_FOLDER_PATHS` | Cursor 设置的分号分隔路径列表 | Cursor IDE |
| `VSCODE_WORKSPACE_FOLDER` | VS Code 工作区文件夹 | VS Code |
| `CURSOR_WORKSPACE_FOLDER` | Cursor 工作区文件夹 | Cursor IDE |
| `--cwd` 参数 | CLI 显式指定 | 命令行调用 |

资料来源：[src/index.ts:工作目录识别逻辑]()

### 3. 脚本到工具的转换

每个 `package.json` 中的脚本都会自动转换为 MCP 工具：

```mermaid
graph LR
    A[package.json scripts] --> B[脚本名称规范化]
    B --> C[工具元数据生成]
    C --> D[MCP Tools]
    
    E[test:unit] --> F[test_unit]
    G[build:prod] --> H[build_prod]
    I[dev --watch] --> J[dev]
```

- 脚本名称中的冒号替换为下划线（如 `test:unit` → `test_unit`）
- 非字母数字字符转换为下划线
- 工具描述包含实际执行的命令（如 `vitest run`）

### 4. 配置文件支持

从 v0.2.10 开始支持 per-project 配置文件：

| 配置文件名 | 优先级 |
|------------|--------|
| `npm-run-mcp.config.json` | 高 |
| `.npm-run-mcp.json` | 低 |
| `--config` CLI 参数 | 覆盖以上两者 |

配置支持 JSONC 格式，允许添加注释和尾随逗号。

资料来源：[README.md:配置文件章节]()

---

## 依赖关系

### 生产依赖

| 依赖包 | 版本 | 用途 |
|--------|------|------|
| @modelcontextprotocol/sdk | ^1.25.1 | MCP 协议 SDK |
| cross-spawn | ^7.0.5 | 跨平台进程执行 |
| jsonc-parser | ^3.3.1 | JSONC 配置文件解析 |
| zod | ^3.23.8 | Schema 验证与转换 |

资料来源：[package.json:15-19]()

### 开发依赖

| 依赖包 | 版本 | 用途 |
|--------|------|------|
| typescript | ^5.4.0 | TypeScript 编译 |
| @types/node | ^20.14.9 | Node.js 类型定义 |
| @types/cross-spawn | ^6.0.6 | cross-spawn 类型定义 |

资料来源：[package.json:21-24]()

---

## 构建与发布配置

### NPM 发布配置

| 配置项 | 值 |
|--------|-----|
| 发布范围 | public |
| 仓库地址 | https://registry.npmjs.org |
| 入口文件 | dist/index.js |
| 发布前脚本 | npm run build |

资料来源：[package.json:37-40]()

### 发布文件清单

```json
{
  "files": [
    "dist/index.js",
    "dist/index.d.ts",
    "dist/index.d.ts.map",
    "npm-run-mcp.config.schema.json"
  ]
}
```

资料来源：[package.json:10-14]()

### MCP 注册配置

```json
{
  "name": "io.github.fstubner/npm-run-mcp-server",
  "description": "An MCP server that exposes package.json scripts as tools for agents.",
  "version": "0.2.13"
}
```

资料来源：[server.json:1-8]()

---

## 版本演进

| 版本 | 主要变更 |
|------|----------|
| v0.1.0 | 初始版本，基础 MCP 工具暴露功能 |
| v0.2.10 | 添加 per-project 配置文件支持、JSONC 解析、配置 JSON Schema 发布 |
| v0.2.13 | 依赖版本更新（qs: 6.14.0→6.14.1, express: 5.1.0→5.2.1） |

资料来源：[社区上下文版本记录]()

---

## 使用场景

### 与 Claude Desktop 集成

```json
{
  "mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

### 与 Cursor IDE 集成

```json
{
  "mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

### 与 VS Code GitHub Copilot 集成

```json
{
  "github.copilot.chat.mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

资料来源：[README.md:集成指南章节]()

---

## 命令行接口

| 参数 | 说明 | 示例 |
|------|------|------|
| `--cwd <path>` | 设置工作目录 | `--cwd /path/to/project` |
| `--pm <npm|pnpm|yarn|bun>` | 指定包管理器 | `--pm pnpm` |
| `--config <path>` | 指定配置文件路径 | `--config ./config.json` |
| `--verbose` | 输出调试日志 | `--verbose` |
| `--list-scripts` | 仅列出可用脚本 | `--list-scripts` |

资料来源：[README.md:CLI 章节]()

---

## 安全考虑

### 脚本暴露控制

为防止 AI 意外执行危险脚本（如 `publish`、`eject`），支持两种控制机制：

1. **白名单模式**（推荐）：仅暴露指定脚本
2. **黑名单模式**：排除指定脚本

```json
{
  "include": ["test", "lint", "build"],
  "exclude": ["publish", "eject"]
}
```

### 执行上下文

- 脚本始终在检测到的项目根目录执行
- 继承父进程环境变量
- 默认超时时间：5 分钟

---

## 总结

npm-run-mcp-server 通过 MCP 协议桥接了 AI 助手与项目构建系统，其设计体现了以下原则：

- **零配置优先**：开箱即用，自动检测项目环境
- **渐进式增强**：支持配置文件进行精细控制
- **多平台兼容**：支持四种主流包管理器
- **安全可控**：提供脚本暴露的白名单/黑名单机制
- **标准化实现**：遵循 MCP 协议规范

该项目作为 AI 编程助手的工具扩展层，使 AI 能够更自然地参与项目的完整开发周期。

---

<a id='page-quickstart'></a>

## 快速开始

### 相关页面

相关主题：[项目概述](#page-overview), [配置文件指南](#page-configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
</details>

# 快速开始

npm-run-mcp-server 是一个基于 Model Context Protocol (MCP) 的服务器，它能够自动将项目的 `package.json` 中的脚本转换为 AI 助手可调用的工具。通过这种设计，AI 代理可以直接执行项目的构建、测试、部署等操作，无需人工介入。

## 功能概述

该工具的核心价值在于消除 AI 代理与项目脚本之间的隔阂。传统的 AI 助手虽然能够理解代码，但在执行实际操作时往往需要手动复制粘贴命令或依赖用户手动操作。npm-run-mcp-server 通过将 `package.json` 中的脚本暴露为标准化的 MCP 工具，解决了这一痛点。

项目的关键特性包括：自动检测当前目录的 `package.json` 文件；智能识别并支持 npm、pnpm、yarn、bun 四种主流包管理器；通过配置文件实现脚本的白名单和黑名单控制；支持为每个脚本定义输入参数模式和描述，帮助 AI 准确理解何时以及如何调用这些脚本；最后，项目开箱即用，零配置即可工作，同时在需要时提供丰富的自定义选项。

## 环境要求

根据 `package.json` 中的定义，该项目要求 Node.js 版本不低于 18.18.0。这一版本要求主要是因为项目使用了 ES Modules 模块系统（`"type": "module"`）和 `@modelcontextprotocol/sdk` 依赖，这些都依赖于较新版本的 Node.js 运行时特性。

## 支持的 AI 客户端

npm-run-mcp-server 遵循 MCP 协议的 stdio 传输标准，可以与多种 AI 客户端集成。项目已在 README.md 中明确测试并支持以下客户端：

Claude Desktop 是首个官方支持的客户端。用户需要在 `claude_desktop_config.json` 配置文件中添加 MCP 服务器配置，配置内容包括服务器类型为 `command`、命令为 `npx`、参数为 `["-y", "npm-run-mcp-server"]`。这种配置方式使得 Claude Desktop 能够在启动时自动加载并使用 npm-run-mcp-server。

Cursor 是另一个主要支持的客户端。用户可以通过 Settings > Features > MCP Servers 界面添加新服务器，或者使用项目提供的一键安装链接。配置文件位于 `.vscode/settings.json`，使用 `github.copilot.chat.mcpServers` 键进行配置。

VS Code (GitHub Copilot) 同样支持该 MCP 服务器，配置方式与 Cursor 类似，也需要在 `.vscode/settings.json` 中添加相应的配置项。

## 快速配置步骤

### 基本配置

对于大多数用户而言，无需任何配置即可开始使用。只需确保目标项目的 `package.json` 中定义了脚本，AI 客户端就能自动识别并暴露这些脚本作为可调用工具。

基本的集成配置取决于所使用的 AI 客户端。对于 Claude Desktop，需要编辑 `claude_desktop_config.json` 文件；对于 Cursor 和 VS Code，则需要编辑工作区的 `.vscode/settings.json` 文件。无论哪种情况，核心配置结构都保持一致。

### 配置文件

项目支持通过 `npm-run-mcp.config.json` 或 `.npm-run-mcp.json` 文件进行细粒度控制。配置文件应放置在项目根目录，与 `package.json` 同级。

配置文件的 JSON Schema 定义在 `npm-run-mcp.config.schema.json` 中，支持以下顶层字段：`include` 用于指定要暴露的脚本名称数组；`exclude` 用于指定要隐藏的脚本名称数组；`scripts` 用于为特定脚本提供详细的元数据覆盖。

```json
{
  "include": ["test", "lint", "build"],
  "exclude": ["eject", "publish"],
  "scripts": {
    "test": {
      "description": "运行测试套件",
      "inputSchema": {
        "properties": {
          "watch": { "type": "boolean", "description": "监视文件变更" }
        }
      }
    }
  }
}
```

配置文件的解析支持 JSONC 格式，这意味着可以在文件中添加注释和尾随逗号，这与 TypeScript 的配置习惯保持一致。

### CLI 参数

除了配置文件，还可以通过命令行参数进行控制。主要参数包括：`--cwd <path>` 用于手动设置工作目录；`--pm <npm|pnpm|yarn|bun>` 用于强制指定包管理器；`--config <path>` 用于指定配置文件路径；`--verbose` 用于启用详细日志输出。

使用 `--verbose` 参数时，服务器会向 stderr 输出诊断信息，包括当前工作目录、检测到的工作区文件夹、使用的 package.json 路径以及检测到的包管理器类型。这些信息对于调试配置问题非常有用。

## 工作流程

当 npm-run-mcp-server 启动时，它会按照特定的优先级顺序确定工作目录。优先级从高到低依次是：`--cwd` 命令行参数、`WORKSPACE_FOLDER_PATHS` 环境变量（Cursor 设置）、`VSCODE_WORKSPACE_FOLDER` 环境变量、`CURSOR_WORKSPACE_FOLDER` 环境变量。如果以上都没有设置，服务器会尝试在当前目录及上级目录中查找 `package.json` 文件。

找到 `package.json` 后，服务器会调用 `detectPackageManager` 函数确定使用哪个包管理器。检测逻辑首先检查配置文件中是否有 `--pm` 参数覆盖，然后检查 `package.json` 中的 `packageManager` 字段，最后根据 lockfile 文件的存在与否进行推断。pnpm 使用 `pnpm-lock.yaml`，Yarn 使用 `yarn.lock`，Bun 使用 `bun.lockb` 或 `bun.lock`，如果都不存在则默认使用 npm。

脚本名称会经过 `sanitizeScriptName` 函数处理，转换为有效的工具名称。该函数将所有字符转换为小写，并将非字母数字字符替换为下划线，确保生成的工具名称符合 MCP 协议的要求。

## 工具调用机制

每个暴露的脚本都会创建一个 MCP 工具，工具的定义包括名称、描述和输入模式。输入模式默认包含两个字段：`_` 用于传递额外的字符串参数数组，`args` 用于传递自由格式的参数字符串。

如果脚本在配置文件中定义了 `inputSchema`，服务器会使用 `jsonSchemaToZod` 函数将其转换为 Zod 验证模式。该函数支持多种 JSON Schema 类型，包括 string、boolean、number、integer、array、object 以及 enum 类型。转换后的 schema 会用于验证 AI 传递的参数，确保参数类型正确。

当 AI 调用工具时，服务器会执行以下流程：首先从参数中提取配置定义的选项和 `args` 字段；然后使用 `buildCliFlags` 函数将参数转换为命令行标志；接着调用 `buildRunCommand` 生成最终的命令和参数；最后通过 `runProcess` 函数执行脚本。

`runProcess` 函数使用 Node.js 的 `spawn` 函数创建子进程，支持的最大输出捕获量为 120000 字符。如果输出超过限制，会自动截断并添加提示信息。脚本执行的默认超时时间为 5 分钟，如果超时则会被终止。

## 包管理器检测

包管理器检测逻辑的实现位于 `src/index.ts` 中的 `detectPackageManager` 函数。函数首先检查是否有显式的参数覆盖，然后检查 `package.json` 中的 `packageManager` 字段（该字段通常在 Corepack 启用的项目中出现），最后根据 lockfile 文件进行推测。

```typescript
function detectPackageManager(projectDir: string, pkg: PackageJson, override?: PackageManager): PackageManager {
  if (override) return override;
  if (pkg.packageManager) {
    const pm = pkg.packageManager.split('@')[0] as PackageManager;
    if (pm === 'npm' || pm === 'pnpm' || pm === 'yarn' || pm === 'bun') return pm;
  }
  if (existsSync(resolve(projectDir, 'pnpm-lock.yaml'))) return 'pnpm';
  if (existsSync(resolve(projectDir, 'yarn.lock'))) return 'yarn';
  if (existsSync(resolve(projectDir, 'bun.lockb')) || existsSync(resolve(projectDir, 'bun.lock'))) return 'bun';
  return 'npm';
}
```

命令执行则由 `buildRunCommand` 函数处理，该函数根据选定的包管理器生成对应的命令格式。例如，对于 npm 执行 `npm run <script>`，对于 pnpm 执行 `pnpm run <script>`，以此类推。

## 常见问题排查

如果 AI 助手无法看到脚本，首先检查项目根目录是否存在有效的 `package.json` 文件，且其中包含 `scripts` 字段。可以使用 `--list-scripts` 参数直接列出所有可用的脚本进行验证。

如果脚本执行失败，检查 AI 传递的参数是否符合配置的 `inputSchema` 要求。可以通过 `--verbose` 参数启用详细日志，查看服务器接收到的具体参数值和执行命令。

如果服务器启动后没有任何工具注册，可能是工作目录设置不正确。在 verbose 模式下，服务器会输出检测到的工作目录信息，确保该目录包含有效的 `package.json` 文件。

关于包管理器选择，如果服务器选择了错误的包管理器，可以通过 `--pm` 参数显式指定正确的包管理器，或者在配置文件中使用 `packageManager` 字段声明项目使用的包管理器。

## 下一步

完成基本配置后，可以进一步探索高级配置选项，例如为特定脚本定义详细的描述和输入模式。也可以查看项目的 GitHub 仓库获取最新版本和更新日志。版本 v0.2.13 是当前的稳定版本，包含了对 qs 和 express 依赖的安全更新。

---

<a id='page-installation'></a>

## 安装与环境

### 相关页面

相关主题：[项目概述](#page-overview)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
</details>

# 安装与环境

## 概述

`npm-run-mcp-server` 是一个基于 Model Context Protocol (MCP) 的服务器，用于将项目 `package.json` 中的脚本暴露给 AI 助手。该工具的核心价值在于零配置开箱即用，同时支持高度定制化的安装和环境配置方案。

本页面详细介绍该工具的系统要求、安装方式、CLI 参数配置以及各种 AI 客户端（Claude Desktop、Cursor、VS Code）的集成方法。

---

## 系统要求

### Node.js 版本要求

根据 `package.json` 中的 `engines` 字段，该工具要求 Node.js 版本不低于 **18.18.0**。

```json
"engines": {
  "node": ">=18.18.0"
}
```

资料来源：[package.json:39]()

Node.js 18.18.0 是 LTS 版本，引入了完整的 ESM 模块支持和稳定的 `fetch` API，这是该工具正常运行的基础保障。

### 运行时依赖

| 依赖包 | 版本 | 用途 |
|--------|------|------|
| `@modelcontextprotocol/sdk` | ^1.25.1 | MCP 协议 SDK 实现 |
| `cross-spawn` | ^7.0.5 | 跨平台脚本执行 |
| `jsonc-parser` | ^3.3.1 | JSONC 配置文件解析（支持注释和尾随逗号） |
| `zod` | ^3.23.8 | 输入参数验证（打包依赖） |

资料来源：[package.json:43-46]()

---

## 安装方式

### 方式一：npx 临时运行（推荐）

最简洁的安装方式，无需全局安装，直接通过 `npx` 临时下载运行：

```bash
npx -y npm-run-mcp-server
```

这种方式适用于快速测试和临时使用场景。每次运行时会自动下载最新版本。

资料来源：[README.md:1]()

### 方式二：全局安装

适用于需要在任何目录下频繁使用的场景：

```bash
npm install -g npm-run-mcp-server
```

全局安装后，可直接执行命令：

```bash
npm-run-mcp-server --list-scripts
```

### 方式三：项目本地安装

作为开发依赖安装到特定项目中：

```bash
npm install --save-dev npm-run-mcp-server
```

---

## 构建与发布配置

### 构建流程

该工具使用自定义构建脚本，在发布前会将 TypeScript 源码编译为 JavaScript：

```json
"scripts": {
  "build": "node scripts/build.cjs",
  "start": "node ./dist/index.js",
  "prepublishOnly": "npm run build"
}
```

资料来源：[package.json:28-33]()

`prepublishOnly` 脚本确保每次发布到 npm 时都经过构建流程。

### 发布配置

```json
"publishConfig": {
  "access": "public",
  "registry": "https://registry.npmjs.org"
}
```

资料来源：[package.json:57-60]()

发布配置表明该包以公共包形式发布到官方 npm registry。

### 发布文件清单

| 文件 | 说明 |
|------|------|
| `dist/index.js` | 编译后的入口文件 |
| `dist/index.d.ts` | TypeScript 类型声明 |
| `dist/index.d.ts.map` | Source map 文件 |
| `npm-run-mcp.config.schema.json` | 配置文件 JSON Schema |

资料来源：[package.json:24-27]()

---

## CLI 命令行参数

### 完整参数列表

| 参数 | 说明 | 示例 |
|------|------|------|
| `--cwd <path>` | 手动设置工作目录 | `--cwd /path/to/project` |
| `--pm <npm\|pnpm\|yarn\|bun>` | 强制指定包管理器 | `--pm pnpm` |
| `--config <path>` | 指定配置文件路径 | `--config ./custom-config.json` |
| `--verbose` | 启用调试日志输出到 stderr | `--verbose` |
| `--list-scripts` | 仅列出检测到的脚本，不启动服务器 | `--list-scripts` |

资料来源：[src/index.ts:1-500]()、[README.md:1]()

### 详细参数说明

#### --cwd 工作目录

```bash
npx npm-run-mcp-server --cwd /path/to/project
```

当指定 `--cwd` 时，工具会在指定目录下查找 `package.json` 并执行脚本。如果不指定，则自动检测当前工作目录或 AI 客户端提供的 workspace 路径。

#### --pm 包管理器

```bash
npx npm-run-mcp-server --pm pnpm
```

可用的包管理器选项：

- `npm` - Node.js 默认包管理器
- `pnpm` - 高效的磁盘空间管理器
- `yarn` - Facebook 开发的包管理器
- `bun` - 极速 JavaScript 运行时和工具链

资料来源：[src/index.ts:10-18]()

#### --config 配置文件

```bash
npx npm-run-mcp-server --config ./custom-config.json
```

指定自定义配置文件路径，支持 JSONC 格式（允许注释和尾随逗号）。

#### --verbose 调试模式

```bash
npx npm-run-mcp-server --verbose
```

启用后会在 stderr 输出详细的调试信息，包括：

- 当前工作目录
- 检测到的 workspace 路径
- `package.json` 文件路径
- 检测到的包管理器
- 服务器版本信息

```typescript
if (verbose) {
  console.error(`[mcp] server starting: cwd=${startCwd}`);
  console.error(`[mcp] detected workspace: ${process.env.VSCODE_WORKSPACE_FOLDER || process.env.CURSOR_WORKSPACE_FOLDER || 'none'}`);
}
```

资料来源：[src/index.ts:100-115]()

#### --list-scripts 脚本列表

```bash
npx npm-run-mcp-server --list-scripts
```

仅列出 `package.json` 中检测到的脚本，不启动 MCP 服务器。适用于调试配置。

---

## Workspace 自动检测

### 检测优先级

该工具会按以下顺序检测 workspace 路径：

```mermaid
graph TD
    A[开始] --> B{--cwd 参数指定?}
    B -->|是| C[使用 --cwd 路径]
    B -->|否| D{WORKSPACE_FOLDER_PATHS 环境变量?}
    D -->|是| E[使用第一个路径<br/>并处理 WSL Windows 路径转换]
    D -->|否| F{VSCODE_WORKSPACE_FOLDER?}
    F -->|是| G[使用 VSCODE_WORKSPACE_FOLDER]
    F -->|否| H{CURSOR_WORKSPACE_FOLDER?}
    H -->|是| I[使用 CURSOR_WORKSPACE_FOLDER]
    H -->|否| J[使用当前目录向上查找 package.json]
```

资料来源：[src/index.ts:200-280]()

### 环境变量映射

| 环境变量 | 来源 | 说明 |
|----------|------|------|
| `WORKSPACE_FOLDER_PATHS` | Cursor | 分号分隔的多 workspace 路径列表 |
| `VSCODE_WORKSPACE_FOLDER` | VS Code | 单个 workspace 路径 |
| `CURSOR_WORKSPACE_FOLDER` | Cursor | 单个 workspace 路径 |

资料来源：[src/index.ts:220-250]()

### WSL 路径转换

当运行在 Linux 环境但 workspace 路径为 Windows 格式时（如 `H:\path\to\project`），工具会自动转换为 WSL 路径格式（`/mnt/h/path/to/project`）：

```typescript
if (process.platform === 'linux' && workspacePath.match(/^[A-Za-z]:\\/)) {
  const drive = workspacePath[0].toLowerCase();
  const path = workspacePath.slice(3).replace(/\\/g, '/');
  workspacePath = `/mnt/${drive}${path}`;
}
```

资料来源：[src/index.ts:225-230]()

---

## 包管理器自动检测

### 检测策略

该工具采用三级检测策略确定项目使用的包管理器：

```mermaid
graph TD
    A[检测包管理器] --> B{--pm 参数强制指定?}
    B -->|是| C[返回强制指定的包管理器]
    B -->|否| D{package.json<br/>packageManager 字段?}
    D -->|是| E[解析 packageManager<br/>提取包管理器名称]
    D -->|否| F{检测 lockfile 文件}
    F --> G{pnpm-lock.yaml?}
    G -->|存在| H[pnpm]
    G -->|不存在| I{yarn.lock?}
    I -->|存在| J[yarn]
    I -->|不存在| K{bun.lockb 或 bun.lock?}
    K -->|存在| L[bun]
    K -->|不存在| M[npm 默认]
```

资料来源：[src/index.ts:10-25]()

### 支持的包管理器

| 包管理器 | 标识 | lockfile 检测 |
|----------|------|---------------|
| npm | `npm` | `package-lock.json` |
| pnpm | `pnpm` | `pnpm-lock.yaml` |
| yarn | `yarn` | `yarn.lock` |
| bun | `bun` | `bun.lockb` 或 `bun.lock` |

### 命令构建

检测到包管理器后，工具会构建相应的运行命令：

```typescript
function buildRunCommand(
  pm: PackageManager,
  scriptName: string,
  extraArgs: string[]
): { command: string; args: string[] } {
  const command = pm;
  const baseArgs = ['run', scriptName];
  const args = extraArgs.length > 0 ? [...baseArgs, '--', ...extraArgs] : baseArgs;
  return { command, args };
}
```

资料来源：[src/index.ts:27-33]()

---

## AI 客户端集成配置

### Claude Desktop

1. 找到 Claude Desktop 的配置文件 `claude_desktop_config.json`
2. 添加 MCP 服务器配置：

```json
{
  "mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

资料来源：[README.md:1]()

### Cursor

1. 打开 **Settings** > **Features** > **MCP Servers**
2. 点击 **+ Add New MCP Server**
3. 配置服务器参数：
   - **Type**: `command`
   - **Name**: `npm-scripts`
   - **Command**: `npx`
   - **Args**: `-y npm-run-mcp-server`

资料来源：[README.md:1]()

或者直接添加配置到 `.vscode/settings.json`：

```json
{
  "github.copilot.chat.mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

### VS Code (GitHub Copilot)

在 `.vscode/settings.json` 中添加配置：

```json
{
  "github.copilot.chat.mcpServers": {
    "npm-scripts": {
      "command": "npx",
      "args": ["-y", "npm-run-mcp-server"]
    }
  }
}
```

资料来源：[README.md:1]()

---

## 配置文件

### 配置文件路径

工具按以下顺序查找配置文件：

1. CLI 参数 `--config` 指定的路径
2. 项目根目录下的 `npm-run-mcp.config.json`
3. 项目根目录下的 `.npm-run-mcp.json`

```typescript
const configPaths = ['npm-run-mcp.config.json', '.npm-run-mcp.json'];
for (const name of configPaths) {
  const candidate = resolve(projectDir, name);
  if (existsSync(candidate)) {
    // 使用该配置文件
  }
}
```

资料来源：[src/index.ts:300-350]()

### 配置文件 Schema

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/fstubner/npm-run-mcp-server/main/npm-run-mcp.config.schema.json",
  "title": "npm-run-mcp-server config",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "include": {
      "type": "array",
      "items": { "type": "string" },
      "description": "精确包含的脚本名称列表"
    },
    "exclude": {
      "type": "array",
      "items": { "type": "string" },
      "description": "精确排除的脚本名称列表"
    },
    "scripts": {
      "type": "object",
      "description": "每个脚本的工具元数据配置"
    }
  }
}
```

资料来源：[npm-run-mcp.config.schema.json:1-30]()

### 配置示例

```json
{
  "include": ["test", "lint", "build", "start"],
  "exclude": ["publish", "eject"],
  "scripts": {
    "test": {
      "toolName": "run_tests",
      "description": "运行测试套件",
      "argsDescription": "传递给测试框架的参数",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "监视文件变化"
          },
          "coverage": {
            "type": "boolean",
            "description": "生成覆盖率报告"
          }
        }
      }
    }
  }
}
```

---

## 常见问题

### Q: npm 发布失败怎么办？

根据社区反馈，v0.2.10 版本发布时遇到 NPM token 过期/撤销导致发布工作流失败的问题。如遇此问题，请检查：

- npm 账户的访问令牌是否有效
- `.npmrc` 配置文件中的 registry 设置是否正确
- 工作流中的 `NPM_TOKEN` secrets 是否配置正确

### Q: 如何调试配置问题？

使用 `--verbose` 参数启用详细日志输出：

```bash
npx npm-run-mcp-server --verbose
```

日志会显示：
- 工作目录路径
- 检测到的 workspace
- `package.json` 文件路径
- 使用的包管理器
- 服务器版本信息

### Q: Windows 用户需要注意什么？

工具已内置 WSL 路径转换支持，当在 WSL 环境下检测到 Windows 格式路径时会自动转换。但建议在 Windows 原生环境下使用时，显式使用 `--cwd` 参数指定项目路径。

---

## 验证安装

### 快速验证

运行以下命令验证安装是否成功：

```bash
npx npm-run-mcp-server --list-scripts
```

如果成功，会列出当前项目 `package.json` 中所有可用的脚本。

### 集成测试

项目包含集成测试脚本：

```bash
npm run test
```

该测试会：
1. 列出脚本
2. 执行集成测试脚本
3. 验证 MCP 服务器功能

资料来源：[package.json:34-36]()

---

## 版本信息

| 字段 | 值 |
|------|-----|
| 当前版本 | 0.2.13 |
| MCP 名称 | io.github.fstubner/npm-run-mcp-server |
| 发布日期 | 最新版本包含 qs 和 express 安全更新 |

资料来源：[package.json:3-4]()、[server.json:12]()

---

<a id='page-configuration'></a>

## 配置文件指南

### 相关页面

相关主题：[输入模式与脚本参数](#page-input-schema), [命令行界面](#page-cli-usage), [工具注册机制](#page-tool-registration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
</details>

# 配置文件指南

`npm-run-mcp-server` 提供灵活的配置系统，允许你控制哪些 `package.json` 脚本暴露给 AI 助手，以及如何呈现这些脚本。通过配置文件，你可以实现脚本白名单/黑名单管理、自定义工具名称、详细描述和参数模式定义。

## 快速入门

### 配置文件位置

服务器按以下优先级查找配置文件：

1. **CLI 参数指定**：`--config <path>`
2. **项目根目录**：`npm-run-mcp.config.json`
3. **项目根目录（备选）**：`.npm-run-mcp.json`

```mermaid
graph TD
    A[启动服务器] --> B{指定 --config 参数?}
    B -->|是| C[使用指定路径]
    B -->|否| D{查找 npm-run-mcp.config.json}
    D -->|存在| E[使用该文件]
    D -->|不存在| F{查找 .npm-run-mcp.json}
    F -->|存在| G[使用该文件]
    F -->|不存在| H[使用默认配置<br/>暴露所有脚本]
    C --> I[解析配置并注册工具]
    E --> I
    G --> I
    H --> I
```

### 基础示例

在项目根目录创建 `npm-run-mcp.config.json`：

```json
{
  "include": ["test", "lint", "build", "start"],
  "exclude": ["eject", "publish"],
  "scripts": {
    "test": {
      "description": "运行测试套件。使用 --watch 启用监视模式。",
      "inputSchema": {
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "监视文件变化"
          }
        }
      }
    }
  }
}
```

## 配置选项详解

### 顶层配置项

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `include` | `string[]` | 否 | 白名单脚本名称数组，仅暴露列表中的脚本 |
| `exclude` | `string[]` | 否 | 黑名单脚本名称数组，隐藏列表中的脚本 |
| `scripts` | `object` | 否 | 针对特定脚本的详细配置 |

**配置生效逻辑**：

```mermaid
graph LR
    A[所有 package.json<br/>脚本] --> B{在 include 中?}
    B -->|否且有include| C[排除]
    B -->|是| D{在 exclude 中?}
    D -->|是| C
    D -->|否| E[暴露为MCP工具]
```

### include 和 exclude 规则

- 当 `include` 未指定时，默认暴露**所有**脚本（受 `exclude` 限制）
- 当 `exclude` 未指定时，默认不排除任何脚本
- `include` 和 `exclude` 可同时使用：`include` 优先筛选，再由 `exclude` 排除

```json
{
  "include": ["dev", "build", "test"],
  "exclude": ["build:prod"]
}
```

此配置仅暴露 `dev`、`build` 和 `test` 脚本，即使 package.json 中存在 `build:prod` 也会被排除。

### 脚本级配置 (scripts)

每个脚本名称可映射到一个配置对象：

```json
{
  "scripts": {
    "<脚本名称>": {
      "toolName": "自定义工具名",
      "description": "自定义描述文本",
      "argsDescription": "args 参数的描述",
      "inputSchema": { /* JSON Schema 对象 */ }
    }
  }
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| `toolName` | `string` | 覆盖 AI 看到的工具名称（默认由脚本名 sanitize 而来） |
| `description` | `string` | 自定义工具描述，帮助 AI 理解何时使用 |
| `argsDescription` | `string` | `args` 输入字段的描述文本 |
| `inputSchema` | `object` | JSON Schema 定义的额外参数，会转换为 CLI 标志 |

## inputSchema 高级用法

### 概念

`inputSchema` 使用 [JSON Schema](https://json-schema.org/) 定义工具输入参数。配置中的 `keys` 会被转换为 CLI 标志传递给脚本。

```json
{
  "scripts": {
    "build": {
      "description": "构建生产版本",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "启用监视模式"
          },
          "target": {
            "type": "string",
            "description": "构建目标环境"
          },
          "analyze": {
            "type": "boolean",
            "description": "生成打包分析报告"
          }
        }
      }
    }
  }
}
```

### 支持的 JSON Schema 类型

| Schema type | Zod 类型 | 说明 |
|-------------|----------|------|
| `string` | `z.string()` | 字符串参数 |
| `boolean` | `z.boolean()` | 布尔标志（--flag） |
| `number` | `z.number()` | 数字参数 |
| `integer` | `z.number().int()` | 整数参数 |
| `array` | `z.array()` | 数组参数 |
| `object` | `z.object()` | 嵌套对象 |
| `enum` | `z.union([z.literal(...)])` | 枚举值 |

### 布尔类型自动处理

布尔参数会智能转换为 CLI 标志：

```json
{
  "properties": {
    "watch": {
      "type": "boolean",
      "description": "Watch mode"
    }
  }
}
```

- `watch: true` → `--watch`
- `watch: false` → 不传递任何参数

### 对象和数组类型

```json
{
  "properties": {
    "tags": {
      "type": "array",
      "items": { "type": "string" },
      "description": "过滤标签"
    },
    "options": {
      "type": "object",
      "description": "额外选项",
      "properties": {
        "verbose": { "type": "boolean" },
        "level": { "type": "string" }
      }
    }
  }
}
```

### 必填字段

使用 `required` 数组指定必填字段：

```json
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "env": { "type": "string", "description": "环境名称" }
    },
    "required": ["env"]
  }
}
```

## JSONC 支持

配置文件支持 **JSONC** 格式，即带有注释和尾随逗号的 JSON：

```json
{
  // 开发环境相关脚本
  "include": ["dev", "build", "test"],
  
  "scripts": {
    "dev": {
      "description": "启动开发服务器"
      // 可添加更多注释
    },
  }
}
```

服务器使用 `jsonc-parser` 库解析配置，支持：
- 单行注释：`// comment`
- 多行注释：`/* comment */`
- 尾随逗号：列表最后一项后的逗号

资料来源：[src/index.ts:parseJsonOrJsonc 函数]()

## CLI 配置覆盖

使用 `--config` 参数指定配置文件路径：

```bash
npx npm-run-mcp-server --config ./configs/mcp-dev.json
npx npm-run-mcp-server --config /absolute/path/to/config.json
```

如果指定的文件不存在，服务器会报错并退出：

```
npm-run-mcp-server: Config file not found: /path/to/config.json
```

## 完整配置示例

```json
{
  "include": [
    "dev",
    "build",
    "test",
    "lint",
    "typecheck"
  ],
  "exclude": [
    "postinstall",
    "prepublishOnly",
    "deploy"
  ],
  "scripts": {
    "dev": {
      "toolName": "start_development_server",
      "description": "启动 Vite 开发服务器，带热模块替换",
      "inputSchema": {
        "type": "object",
        "properties": {
          "port": {
            "type": "number",
            "description": "开发服务器端口"
          },
          "open": {
            "type": "boolean",
            "description": "启动后自动打开浏览器"
          }
        }
      }
    },
    "build": {
      "description": "构建生产环境资源",
      "argsDescription": "传递给构建命令的额外参数",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "监视文件变化"
          },
          "analyze": {
            "type": "boolean",
            "description": "生成打包分析"
          }
        }
      }
    },
    "test": {
      "description": "运行 Vitest 测试",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "监视模式"
          },
          "coverage": {
            "type": "boolean",
            "description": "生成覆盖率报告"
          },
          "grep": {
            "type": "string",
            "description": "只运行匹配测试"
          }
        }
      }
    }
  }
}
```

## JSON Schema 验证

项目发布了正式的 JSON Schema 用于配置验证：`npm-run-mcp.config.schema.json`

### 获取 Schema

```bash
# 从项目获取
curl -O https://raw.githubusercontent.com/fstubner/npm-run-mcp-server/main/npm-run-mcp.config.schema.json

# 或在编辑器中引用
# VS Code、JetBrains 等支持 $schema 引用自动补全
```

### 在配置文件中引用 Schema

```json
{
  "$schema": "./node_modules/npm-run-mcp-server/npm-run-mcp.config.schema.json",
  "include": ["test", "lint"]
}
```

### Schema 字段一览

| 字段 | 类型 | 描述 |
|------|------|------|
| `include` | `string[]` | 要包含的脚本名称 |
| `exclude` | `string[]` | 要排除的脚本名称 |
| `scripts` | `object` | 脚本配置映射 |
| `scripts[].toolName` | `string` | 工具名称覆盖 |
| `scripts[].description` | `string` | 工具描述覆盖 |
| `scripts[].argsDescription` | `string` | args 字段描述 |
| `scripts[].inputSchema` | `object` | JSON Schema 格式的参数定义 |

## 常见使用场景

### 场景一：限制危险命令

防止 AI 执行发布或部署命令：

```json
{
  "exclude": ["publish", "deploy", "release", "eject"]
}
```

### 场景二：限制特定环境构建

```json
{
  "include": ["dev", "build", "test", "lint"],
  "exclude": ["build:docker", "deploy:staging", "deploy:production"]
}
```

### 场景三：标准化开发工作流

```json
{
  "include": ["dev", "build", "test", "lint", "typecheck"],
  "scripts": {
    "dev": {
      "description": "启动本地开发服务器",
      "inputSchema": {
        "properties": {
          "port": { "type": "number", "description": "服务器端口" }
        }
      }
    },
    "test": {
      "description": "运行测试（可选：watch 模式）",
      "inputSchema": {
        "properties": {
          "watch": { "type": "boolean", "description": "监视模式" },
          "coverage": { "type": "boolean", "description": "生成覆盖率" }
        }
      }
    }
  }
}
```

### 场景四：多环境配置

在不同目录放置不同配置文件：

```
project/
├── npm-run-mcp.config.json      # 基础配置
├── configs/
│   ├── mcp-dev.json             # 开发配置
│   ├── mcp-ci.json              # CI 配置
│   └── mcp-limited.json         # 受限配置
```

通过 CLI 参数切换：

```bash
# 开发环境
npm-run-mcp-server --config configs/mcp-dev.json

# CI 环境
npm-run-mcp-server --config configs/mcp-ci.json
```

## 调试配置

启用详细日志查看配置加载过程：

```bash
npm-run-mcp-server --verbose
```

输出示例：

```
[mcp] server starting: cwd=/path/to/project
[mcp] using package.json: /path/to/project/package.json
[mcp] loaded server info: npm-run-mcp-server@0.2.13
[mcp] detected package manager: npm
[mcp] using config file: /path/to/project/npm-run-mcp.config.json
[mcp] include list references missing scripts: old_script, deprecated_build
```

## 版本历史

| 版本 | 更新内容 |
|------|----------|
| v0.2.10 | 新增配置文件支持、`--config` 参数、JSONC 解析、发布 JSON Schema |
| v0.2.13 | 依赖版本更新（qs, express） |

## 相关资源

- [官方 README](https://github.com/fstubner/npm-run-mcp-server#readme)
- [MCP 协议文档](https://modelcontextprotocol.io/)
- [JSON Schema 规范](https://json-schema.org/)

---

<a id='page-input-schema'></a>

## 输入模式与脚本参数

### 相关页面

相关主题：[配置文件指南](#page-configuration), [工具注册机制](#page-tool-registration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
</details>

# 输入模式与脚本参数

## 概述

npm-run-mcp-server 提供了灵活且强大的输入模式（Input Schema）系统，允许 AI 代理通过类型安全的接口向 package.json 脚本传递参数。该系统基于 JSON Schema 标准构建，通过 Zod 库实现运行时验证，确保 AI 生成的参数符合脚本预期的格式要求。

### 核心设计目标

本系统的设计遵循以下原则：

1. **类型安全** - 通过 JSON Schema 定义参数结构，Zod 在运行时进行验证
2. **向后兼容** - 基础参数 `_` 和 `args` 始终可用
3. **灵活扩展** - 支持自定义输入字段，映射为 CLI 标志位
4. **容错处理** - 解析失败时提供清晰的错误信息

---

## 基础输入参数

每个 MCP 工具都内置两个基础参数，无论配置文件如何设置，这两个参数始终可用。

### 参数说明

| 参数名 | 类型 | 描述 |
|--------|------|------|
| `_` | `string[]` | 位置参数数组，传递给脚本的额外位置参数 |
| `args` | `string \| string[]` | 自由格式参数，通过 `--` 分隔符追加到命令末尾 |

### 默认 Schema 结构

```typescript
const base = z
  .object({
    _: z.array(z.string()).optional(),
    args: z
      .union([z.string(), z.array(z.string())])
      .optional()
      .describe('Optional arguments appended after -- to the script'),
  })
  .passthrough();
```

资料来源：[src/index.ts:67-77]()

### 使用示例

当 AI 调用脚本时，可以传递以下形式的参数：

```json
{
  "args": "--watch --no-cache"
}
```

这会被转换为：

```bash
npm run dev -- --watch --no-cache
```

---

## 自定义输入模式

通过配置文件中的 `inputSchema` 字段，可以为特定脚本定义结构化的输入参数。

### 配置结构

```json
{
  "scripts": {
    "test": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "coverage": {
            "type": "boolean",
            "description": "Generate coverage report"
          },
          "grep": {
            "type": "string",
            "description": "Filter tests by pattern"
          },
          "maxWorkers": {
            "type": "integer",
            "description": "Maximum parallel workers"
          }
        },
        "additionalProperties": false
      }
    }
  }
}
```

### 支持的类型映射

| JSON Schema 类型 | Zod 类型 | CLI 转换 |
|-----------------|----------|----------|
| `string` | `z.string()` | `--key value` |
| `boolean` | `z.boolean()` | `--key` (值为 true 时) |
| `number` | `z.number()` | `--key value` |
| `integer` | `z.number().int()` | `--key value` |
| `array` (string items) | `z.array(z.string())` | 多个 `--key value` |
| `object` | `z.object(...)` | `--key '{"..."}'` |
| `enum` | `z.enum([...])` | `--key value` |

### 类型转换源码

```typescript
function jsonSchemaToZod(schema: unknown): z.ZodTypeAny {
  if (!isPlainObject(schema)) return z.any();

  // Handle enum types
  if (Array.isArray(schema.enum) && schema.enum.every((v) => typeof v === 'string')) {
    const values = schema.enum as string[];
    const [first, ...rest] = values;
    let base: z.ZodTypeAny = first ? z.literal(first) : z.string();
    for (const v of rest) base = z.union([base, z.literal(v)]);
    return typeof schema.description === 'string' ? base.describe(schema.description) : base;
  }

  const type = schema.type;
  let zod: z.ZodTypeAny;
  switch (type) {
    case 'string':
      zod = z.string();
      break;
    case 'boolean':
      zod = z.boolean();
      break;
    case 'number':
      zod = z.number();
      break;
    case 'integer':
      zod = z.number().int();
      break;
    // ... more cases
  }
}
```

资料来源：[src/index.ts:6-58]()

---

## 参数到 CLI 标志位的转换

### 转换规则

当 AI 提供输入参数时，系统通过 `toolInputToExtraArgs` 函数将其转换为命令行标志位。

```typescript
function toolInputToExtraArgs(input: Record<string, unknown>): string[] {
  const flags: string[] = [];
  const positional: string[] = [];
  const rawArgs: string[] = [];

  // Handle positional arguments
  if (Array.isArray(input._)) {
    positional.push(...input._.map(String));
  }

  // Handle free-form args
  if (typeof input.args === 'string') {
    rawArgs.push(...parseArgString(input.args));
  } else if (Array.isArray(input.args)) {
    rawArgs.push(...input.args.map(String));
  }

  // Convert schema-defined inputs to flags
  for (const [key, value] of Object.entries(input)) {
    if (key === '_' || key === 'args') continue;

    const flag = `--${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`;

    if (value === null || value === undefined) continue;

    if (typeof value === 'boolean') {
      if (value) flags.push(flag);
      continue;
    }

    if (typeof value === 'string') {
      flags.push(flag, value);
      continue;
    }

    if (Array.isArray(value)) {
      for (const item of value) {
        if (item === null || item === undefined) continue;
        if (typeof item === 'boolean') {
          if (item) flags.push(flag);
        } else {
          flags.push(flag, String(item));
        }
      }
      continue;
    }

    if (typeof value === 'object') {
      flags.push(flag, JSON.stringify(value));
      continue;
    }

    flags.push(flag, String(value));
  }

  return [...flags, ...positional, ...rawArgs];
}
```

资料来源：[src/index.ts:140-196]()

### 驼峰命名转换

配置中的 camelCase 键名会被自动转换为 kebab-case CLI 标志位：

| 配置键名 | CLI 标志位 |
|----------|-----------|
| `maxWorkers` | `--max-workers` |
| `noCache` | `--no-cache` |
| `runInBand` | `--run-in-band` |

### 布尔值特殊处理

布尔值参数遵循约定优于配置的原则：

- `true` → 添加标志位（如 `--coverage`）
- `false` → 不添加任何内容

这允许脚本使用 `--no-` 前缀约定来处理否定选项。

---

## 参数字符串解析

### 解析规则

`parseArgString` 函数实现了智能的 shell 风格参数解析：

```typescript
function parseArgString(input: string): string[] {
  const result: string[] = [];
  let current = '';
  let inSingle = false;
  let inDouble = false;
  let escaping = false;
  let tokenActive = false;
  // ... parsing logic
}
```

### 特性

| 特性 | 说明 |
|------|------|
| 双引号包裹 | 允许包含空格，如 `"hello world"` |
| 单引号包裹 | 字面量处理，如 `'$HOME'` |
| 转义字符 | 支持 `\` 转义 |
| 自动分词 | 空格分隔的词法分析 |

### 示例

```
输入: --flag "hello world" --name 'John Doe'
输出: ['--flag', 'hello world', '--name', 'John Doe']
```

---

## 脚本执行与参数传递

### 命令构建流程

```mermaid
graph TD
    A[AI 调用工具] --> B[接收 input 对象]
    B --> C{是否有自定义 inputSchema?}
    C -->|是| D[合并自定义字段到基础 Schema]
    C -->|否| E[仅使用基础 Schema]
    D --> F[Zod 验证输入]
    E --> F
    F --> G{验证通过?}
    G -->|否| H[返回验证错误]
    G -->|是| I[toolInputToExtraArgs 转换参数]
    I --> J[buildRunCommand 构建命令]
    J --> K[spawn 执行子进程]
    K --> L[捕获 stdout/stderr]
    L --> M[返回执行结果]
```

### 执行函数

```typescript
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 分钟

async function runProcess(
  command: string,
  args: string[],
  options: { cwd: string; env: NodeJS.ProcessEnv; timeoutMs?: number }
): Promise<{
  stdout: string;
  stderr: string;
  exitCode: number | null;
  signal: NodeJS.Signals | null;
  totalLength: number;
  timedOut: boolean;
}> {
  // ... spawn implementation with timeout handling
}
```

资料来源：[src/index.ts:204-220]()

### 构建运行命令

```typescript
function buildRunCommand(
  pm: PackageManager,
  scriptName: string,
  extraArgs: string[]
): { command: string; args: string[] } {
  const command = pm;
  const baseArgs = ['run', scriptName];
  const args = extraArgs.length > 0 ? [...baseArgs, '--', ...extraArgs] : baseArgs;
  return { command, args };
}
```

资料来源：[src/index.ts:116-123]()

---

## 配置示例

### 完整配置文件示例

```json
{
  "include": ["dev", "build", "test", "lint"],
  "exclude": ["postinstall", "prepublishOnly"],
  "scripts": {
    "dev": {
      "description": "启动开发服务器",
      "argsDescription": "传递给 Vite 的额外参数",
      "inputSchema": {
        "type": "object",
        "properties": {
          "port": {
            "type": "integer",
            "description": "开发服务器端口"
          },
          "open": {
            "type": "boolean",
            "description": "自动打开浏览器"
          },
          "host": {
            "type": "string",
            "description": "监听的主机地址"
          }
        }
      }
    },
    "test": {
      "description": "运行测试套件",
      "inputSchema": {
        "type": "object",
        "properties": {
          "grep": {
            "type": "string",
            "description": "按模式过滤测试"
          },
          "coverage": {
            "type": "boolean",
            "description": "生成覆盖率报告"
          },
          "watch": {
            "type": "boolean",
            "description": "监视模式"
          }
        },
        "additionalProperties": false
      }
    }
  }
}
```

### 与 CLI 参数结合使用

```json
{
  "scripts": {
    "build": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "analyze": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
```

AI 可以这样调用：

```json
{
  "analyze": true,
  "args": "--entry ./src/main.ts"
}
```

实际执行的命令：

```bash
npm run build -- --analyze --entry ./src/main.ts
```

---

## 错误处理与输出截断

### 验证错误

当输入参数不符合 Schema 时，系统返回详细的验证错误信息：

```json
{
  "content": [
    {
      "type": "text",
      "text": "Invalid input: at \"port\" expected integer"
    }
  ],
  "isError": true
}
```

### 输出截断

对于大量输出，系统自动进行截断处理：

```typescript
function trimOutput(
  out: string,
  limit = 12000,
  totalLength?: number
): { text: string; truncated: boolean } {
  const total = typeof totalLength === 'number' ? totalLength : out.length;
  if (total <= limit) return { text: out, truncated: false };
  return {
    text: out.slice(0, limit) + `\n...[truncated ${total - limit} chars]`,
    truncated: true
  };
}
```

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| 单个输出截断限制 | 12000 字符 | 单个 stdout/stderr 的最大长度 |
| 总捕获限制 | 120000 字符 | 进程生命周期内的总输出上限 |

---

## 最佳实践

### Schema 设计建议

1. **使用精确类型** - 优先使用 `integer` 而非 `number`
2. **添加描述** - 每个字段的 `description` 帮助 AI 理解用途
3. **设置默认值** - 通过 `default` 属性提供合理的默认值
4. **限制额外属性** - 设置 `"additionalProperties": false` 防止意外输入

### 参数命名建议

| 命名风格 | 示例 | 转换后 |
|----------|------|--------|
| camelCase | `maxWorkers` | `--max-workers` |
| PascalCase | `MaxWorkers` | `--max-workers` |
| kebab-case | `max-workers` | `--max-workers` |

### 复杂参数处理

对于需要传递复杂对象的场景：

```json
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "env": {
        "type": "object",
        "description": "环境变量",
        "additionalProperties": { "type": "string" }
      }
    }
  }
}
```

调用时系统会自动将对象序列化为 JSON 字符串：

```bash
npm run script -- --env '{"NODE_ENV":"production"}'
```

---

## 相关配置字段

| 字段 | 类型 | 说明 |
|------|------|------|
| `include` | `string[]` | 白名单脚本列表 |
| `exclude` | `string[]` | 黑名单脚本列表 |
| `scripts[].toolName` | `string` | 覆盖工具名称 |
| `scripts[].description` | `string` | 覆盖工具描述 |
| `scripts[].argsDescription` | `string` | `args` 参数的描述 |
| `scripts[].inputSchema` | `object` | 自定义输入 Schema |

资料来源：[npm-run-mcp.config.schema.json]()

---

<a id='page-cli-usage'></a>

## 命令行界面

### 相关页面

相关主题：[配置文件指南](#page-configuration), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
</details>

# 命令行界面

npm-run-mcp-server 提供了一套完整的命令行界面（CLI），允许用户通过命令行参数控制 MCP 服务器的行为，包括工作目录指定、包管理器选择、配置文件加载和调试模式等核心功能。

## 概述

该工具是 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 的服务器实现，专门将项目 `package.json` 中的 npm scripts 暴露为 MCP 工具供 AI Agent 使用。CLI 层负责环境检测、参数解析和运行时初始化，是整个系统的入口点。

### 核心功能定位

| 功能 | 说明 |
|------|------|
| 工作目录检测 | 自动定位 package.json 或手动指定 |
| 包管理器识别 | 支持 npm、pnpm、yarn、bun 四种主流工具 |
| 配置管理 | 支持 JSONC 格式的本地配置文件 |
| 调试支持 | 详细的运行时日志输出 |

## CLI 参数参考

### 基础参数

| 参数 | 类型 | 说明 |
|------|------|------|
| `--cwd <path>` | string | 手动设置工作目录路径 |
| `--pm <manager>` | npm \| pnpm \| yarn \| bun | 强制使用指定的包管理器 |
| `--config <path>` | string | 指定配置文件路径 |
| `--verbose` | flag | 启用详细调试日志 |
| `--list-scripts` | flag | 仅列出可用脚本并退出 |

资料来源：[src/index.ts:1-300]()

### 环境变量

CLI 支持通过环境变量进行配置，这些变量通常由 IDE 集成时自动设置：

| 环境变量 | 说明 |
|----------|------|
| `MCP_VERBOSE` | 启用详细日志输出 |
| `DEBUG` | 包含 'mcp' 子串时启用日志 |
| `WORKSPACE_FOLDER_PATHS` | Cursor IDE 多工作区路径（分号分隔） |
| `VSCODE_WORKSPACE_FOLDER` | VS Code 工作区文件夹路径 |
| `CURSOR_WORKSPACE_FOLDER` | Cursor 工作区文件夹路径 |

资料来源：[src/index.ts:58-75]()

## 工作目录检测逻辑

服务器启动时按优先级依次检测工作目录：

```mermaid
graph TD
    A[启动] --> B{--cwd 参数?}
    B -->|是| C[使用 --cwd 值]
    B -->|否| D{WORKSPACE_FOLDER_PATHS?}
    D -->|是| E[取第一个路径<br/>处理 Windows→WSL 转换]
    D -->|否| F{VSCODE_WORKSPACE_FOLDER?}
    F -->|是| G[使用该路径]
    F -->|否| H{CURSOR_WORKSPACE_FOLDER?}
    H -->|是| I[使用该路径]
    H -->|否| J[使用 cwd<br/>向上查找 package.json]
    C --> K[查找 package.json]
    E --> K
    G --> K
    I --> K
    J --> K
```

### Windows 到 WSL 路径转换

当检测到运行在 Linux 环境且收到 Windows 格式路径时，系统会自动进行转换：

```typescript
// 输入: H:\path\to\project (Windows)
// 输出: /mnt/h/path/to/project (WSL)
const drive = workspacePath[0].toLowerCase();
const path = workspacePath.slice(3).replace(/\\/g, '/');
workspacePath = `/mnt/${drive}${path}`;
```

资料来源：[src/index.ts:82-87]()

## 包管理器检测

系统支持自动检测和手动覆盖两种方式来确定使用哪个包管理器：

```mermaid
graph TD
    A[检测包管理器] --> B{--pm 参数?}
    B -->|是| C[返回指定值]
    B -->|否| D{package.json<br/>packageManager 字段?}
    D -->|有| E[解析并返回<br/>npm/pnpm/yarn/bun]
    D -->|无| F{lock 文件检测}
    F -->|pnpm-lock.yaml| G[返回 pnpm]
    F -->|yarn.lock| H[返回 yarn]
    F -->|bun.lock/bun.lockb| I[返回 bun]
    F -->|无| J[返回 npm]
```

### 检测优先级

| 优先级 | 来源 | 说明 |
|--------|------|------|
| 1 | `--pm` 参数 | 手动指定，优先级最高 |
| 2 | `package.json.packageManager` | packageManager 字段 |
| 3 | lock 文件 | 按类型检测 |
| 4 | 默认值 | 返回 npm |

资料来源：[src/index.ts:120-135]()

## 配置文件系统

### 配置文件位置

服务器按以下顺序查找配置文件：

1. `--config` 参数指定的路径
2. `npm-run-mcp.config.json`
3. `.npm-run-mcp.json`

### 配置文件结构

```json
{
  "include": ["test", "lint", "build"],
  "exclude": ["eject", "publish"],
  "scripts": {
    "test": {
      "toolName": "run_tests",
      "description": "运行测试套件",
      "argsDescription": "传递给测试的参数",
      "inputSchema": {
        "properties": {
          "watch": { "type": "boolean" }
        }
      }
    }
  }
}
```

### 配置选项说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `include` | string[] | 白名单，仅暴露指定的脚本 |
| `exclude` | string[] | 黑名单，排除指定的脚本 |
| `scripts` | object | 各脚本的详细配置 |

资料来源：[npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)

### JSONC 支持

配置文件支持 JSONC 格式，允许使用 JavaScript 风格注释和尾部逗号：

```json
{
  // 这是一条注释
  "include": ["test", "build", /* 内联注释 */ "lint"],
}
```

## 使用方式

### 直接运行

```bash
# 列出所有可用脚本
npx npm-run-mcp-server --list-scripts

# 指定工作目录
npx npm-run-mcp-server --cwd /path/to/project

# 强制使用 pnpm
npx npm-run-mcp-server --pm pnpm

# 指定配置文件
npx npm-run-mcp-server --config ./custom-config.json

# 启用调试输出
npx npm-run-mcp-server --verbose
```

### 本地开发

```bash
# 构建项目
npm run build

# 运行服务器
npm start

# 运行集成测试
npm run test:integration
```

### MCP 协议启动

标准 MCP 通信通过 Stdio 传输层：

```bash
# 由 MCP Client 启动
npx npm-run-mcp-server
# 服务器通过 stdin/stdout 与客户端通信
```

资料来源：[package.json:12-20]()

## 调试模式

### 启用方式

1. 命令行参数：`--verbose`
2. 环境变量：`MCP_VERBOSE=1`
3. DEBUG 环境变量包含 'mcp'

### 调试输出内容

启用后会输出以下信息：

```
[mcp] server starting: cwd=/path/to/project
[mcp] detected workspace: /path/to/project
[mcp] using package.json: /path/to/project/package.json
[mcp] detected package manager: pnpm
[mcp] loaded server info: npm-run-mcp-server@0.2.13
```

资料来源：[src/index.ts:60-73]()

## 常见问题

### 工作目录找不到 package.json

**症状**：服务器启动但没有暴露任何工具

**排查步骤**：
1. 确认项目目录存在 `package.json`
2. 使用 `--cwd` 参数显式指定路径
3. 确认工作目录有读取权限
4. 启用 `--verbose` 查看检测路径

### 包管理器检测错误

**症状**：使用了错误的包管理器执行脚本

**解决方案**：使用 `--pm` 参数强制指定

```bash
npx npm-run-mcp-server --pm yarn
```

### 配置文件不生效

**排查清单**：
1. 确认文件名正确：`npm-run-mcp.config.json` 或 `.npm-run-mcp.json`
2. 检查 JSON 语法有效性
3. 确认文件在工作目录根目录
4. 使用 `--verbose` 确认配置被加载

### NPM 发布失败

社区反馈：NPM 发布工作流因 token 过期/撤销而失败。需在 GitHub Secrets 中轮换 NPM token。

资料来源：[v0.2.10 Release Notes](https://github.com/fstubner/npm-run-mcp-server/releases/tag/v0.2.10)

## 技术架构

### 入口流程

```mermaid
sequenceDiagram
    participant User
    participant CLI as 命令行解析
    participant Detector as 环境检测
    participant Config as 配置加载
    participant Server as MCP 服务器

    User->>CLI: npm-run-mcp-server --cwd /path
    CLI->>CLI: 解析参数和环境变量
    CLI->>Detector: 检测工作目录
    Detector-->>CLI: 返回项目路径
    CLI->>Config: 加载 MCP 配置
    Config-->>CLI: 返回过滤规则
    CLI->>Server: 初始化 MCP 服务器
    Server->>Server: 注册 npm scripts 为工具
    Server-->>User: MCP Stdio 连接就绪
```

### 依赖关系

| 模块 | 用途 |
|------|------|
| `@modelcontextprotocol/sdk` | MCP 协议实现 |
| `cross-spawn` | 跨平台脚本执行 |
| `jsonc-parser` | JSONC 配置解析 |
| `zod` | 输入验证 |

资料来源：[package.json:25-30]()

## 版本历史

| 版本 | CLI 变更 |
|------|----------|
| v0.2.10 | 新增 `--config` 参数和 JSONC 支持 |
| v0.2.13 | 依赖更新（qs, express） |
| v0.1.0 | 初始版本，包含基础 CLI 功能 |

相关发布说明请参阅 [GitHub Releases](https://github.com/fstubner/npm-run-mcp-server/releases)。

---

<a id='page-architecture'></a>

## 系统架构

### 相关页面

相关主题：[包管理器检测](#page-package-manager), [工具注册机制](#page-tool-registration), [文件监视与热重载](#page-file-watching)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
- [server.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/server.json)
</details>

# 系统架构

## 概述

npm-run-mcp-server 是一个基于 Model Context Protocol (MCP) 的服务器实现，其核心功能是将项目中的 `package.json` 脚本转换为 AI Agent 可调用的 MCP 工具。该项目采用单入口架构，所有核心逻辑集中在 `src/index.ts` 中，通过 MCP SDK 与 AI 客户端（如 Claude Desktop、Cursor、VS Code）进行标准输入输出（stdio）通信。

主要技术栈：

- **运行时**: Node.js (>=18.18.0)，ESM 模块系统
- **MCP 通信**: `@modelcontextprotocol/sdk` v1.25.1
- **配置解析**: `jsonc-parser` (支持 JSONC 注释和尾随逗号)
- **数据验证**: `zod` v3.23.8
- **跨平台执行**: `cross-spawn` v7.0.5

资料来源：[package.json:1-40]()

## 核心组件架构

```mermaid
graph TD
    subgraph "启动层"
        A["CLI 参数解析"] --> B["工作目录检测"]
        B --> C["环境变量检测"]
    end
    
    subgraph "检测层"
        C --> D["package.json 读取"]
        D --> E["包管理器检测"]
        E --> F["MCP 配置读取"]
    end
    
    subgraph "转换层"
        F --> G["脚本名称规范化"]
        G --> H["工具元数据生成"]
        H --> I["Zod Schema 构建"]
    end
    
    subgraph "服务层"
        I --> J["MCP Server 初始化"]
        J --> K["StdioServerTransport"]
        K --> L["工具注册"]
    end
    
    subgraph "执行层"
        L --> M["MCP 工具调用"]
        M --> N["进程 Spawn"]
        N --> O["输出捕获与截断"]
    end
```

## 启动与初始化流程

### 工作目录检测策略

服务器启动时按以下优先级确定工作目录：

1. **CLI 参数**: `--cwd` 显式指定的路径
2. **环境变量**: `WORKSPACE_FOLDER_PATHS` (Cursor 设置，分号分隔)
3. **IDE 环境变量**: `VSCODE_WORKSPACE_FOLDER` 或 `CURSOR_WORKSPACE_FOLDER`
4. **当前目录回退**: 向上遍历查找包含 `package.json` 的目录

```typescript
let startCwd: string = process.cwd();

if (args.cwd) {
  startCwd = resolve(String(args.cwd));
} else if (process.env.WORKSPACE_FOLDER_PATHS) {
  const workspacePaths = process.env.WORKSPACE_FOLDER_PATHS.split(';');
  startCwd = workspacePaths[0];
} else if (process.env.VSCODE_WORKSPACE_FOLDER) {
  startCwd = process.env.VSCODE_WORKSPACE_FOLDER;
} else if (process.env.CURSOR_WORKSPACE_FOLDER) {
  startCwd = process.env.CURSOR_WORKSPACE_FOLDER;
}
```

资料来源：[src/index.ts:89-110]()

### WSL 路径转换

当检测到在 WSL 环境下运行且接收到 Windows 格式路径时，自动转换为 WSL 路径格式：

```typescript
if (process.platform === 'linux' && workspacePath.match(/^[A-Za-z]:\\/)) {
  const drive = workspacePath[0].toLowerCase();
  const path = workspacePath.slice(3).replace(/\\/g, '/');
  workspacePath = `/mnt/${drive}${path}`;
}
```

资料来源：[src/index.ts:95-99]()

## 包管理器检测机制

服务器支持 npm、pnpm、yarn、bun 四种包管理器，检测顺序如下：

```mermaid
graph TD
    A["开始检测"] --> B{"--pm 参数指定?"}
    B -->|是| Z["使用指定包管理器"]
    B -->|否| C{"packageManager 字段?"}
    C -->|是| D{"有效值?"}
    D -->|npm/pnpm/yarn/bun| Z
    D -->|否| E{"lockfile 存在?"}
    C -->|否| E
    E --> F["pnpm-lock.yaml?"]
    F -->|是| G["pnpm"]
    F -->|否| H["yarn.lock?"]
    H -->|是| I["yarn"]
    H -->|否| J["bun.lockb/bun.lock?"]
    J -->|是| K["bun"]
    J -->|否| L["默认 npm"]
    G --> Z
    I --> Z
    K --> Z
    L --> Z
```

### 检测函数实现

```typescript
function detectPackageManager(
  projectDir: string, 
  pkg: PackageJson, 
  override?: PackageManager
): PackageManager {
  if (override) return override;
  
  // 优先使用 packageManager 字段
  if (pkg.packageManager) {
    const pm = pkg.packageManager.split('@')[0] as PackageManager;
    if (pm === 'npm' || pm === 'pnpm' || pm === 'yarn' || pm === 'bun') 
      return pm;
  }
  
  // 基于 lockfile 检测
  if (existsSync(resolve(projectDir, 'pnpm-lock.yaml'))) return 'pnpm';
  if (existsSync(resolve(projectDir, 'yarn.lock'))) return 'yarn';
  if (existsSync(resolve(projectDir, 'bun.lockb')) || 
      existsSync(resolve(projectDir, 'bun.lock'))) return 'bun';
  
  return 'npm';
}
```

资料来源：[src/index.ts:131-151]()

## 配置系统

### 配置文件位置

按以下顺序查找配置文件：

1. `--config` CLI 参数指定的路径
2. 项目根目录的 `npm-run-mcp.config.json`
3. 项目根目录的 `.npm-run-mcp.json`

配置采用 JSONC 格式，支持注释和尾随逗号。

资料来源：[npm-run-mcp.config.schema.json:1-10]()

### 配置 Schema

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "npm-run-mcp-server config",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "include": {
      "type": "array",
      "items": { "type": "string" },
      "description": "精确包含的脚本名称列表"
    },
    "exclude": {
      "type": "array", 
      "items": { "type": "string" },
      "description": "精确排除的脚本名称列表"
    },
    "scripts": {
      "type": "object",
      "description": "每个脚本的元数据覆盖配置"
    }
  }
}
```

资料来源：[npm-run-mcp.config.schema.json:11-40]()

### 脚本过滤逻辑

```mermaid
graph TD
    A["所有脚本名称"] --> B{"include 存在?"}
    B -->|是| C["只保留 include 中的脚本"]
    B -->|否| D{"exclude 存在?"}
    D -->|是| E["移除 exclude 中的脚本"]
    D -->|否| F["返回所有脚本"]
    C --> F
    E --> F
```

## MCP 工具生成

### 工具名称规范化

脚本名称经过以下转换规则：

1. 转小写
2. 非字母数字字符替换为下划线
3. 空名称回退为 `script`

```typescript
function sanitizeToolName(name: string): string {
  const normalized = name.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
  return normalized.length > 0 ? normalized : 'script';
}
```

资料来源：[src/index.ts:175-178]()

### 输入 Schema 构建

每个 MCP 工具的输入包含两个内置字段：

| 字段 | 类型 | 描述 |
|------|------|------|
| `_` | `string[]` | 额外参数数组 |
| `args` | `string \| string[]` | 追加在 `--` 之后的参数 |

额外配置字段可通过 `inputSchema` 定义，JSON Schema 类型到 Zod 的转换支持：

| JSON Schema 类型 | Zod 类型 |
|------------------|----------|
| `string` | `z.string()` |
| `boolean` | `z.boolean()` |
| `number` | `z.number()` |
| `integer` | `z.number().int()` |
| `array` (string items) | `z.array(z.string())` |
| `object` | `z.object()` |

资料来源：[src/index.ts:180-230]()

## 进程执行与输出处理

### 命令构建

```typescript
function buildRunCommand(
  pm: PackageManager,
  scriptName: string,
  extraArgs: string[]
): { command: string; args: string[] } {
  const command = pm;
  const baseArgs = ['run', scriptName];
  const args = extraArgs.length > 0 
    ? [...baseArgs, '--', ...extraArgs] 
    : baseArgs;
  return { command, args };
}
```

资料来源：[src/index.ts:154-163]()

### 输出截断机制

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `outputCaptureLimit` | 120000 | 单次捕获上限（字节） |
| `trimOutput.limit` | 12000 | 返回给客户端的截断限制 |

当输出超过限制时，会返回前 12000 字符并附加截断提示。

```typescript
function trimOutput(out: string, limit = 12000, totalLength?: number): { 
  text: string; 
  truncated: boolean 
} {
  const total = typeof totalLength === 'number' ? totalLength : out.length;
  if (total <= limit) return { text: out, truncated: false };
  return { 
    text: out.slice(0, limit) + `\n...[truncated ${total - limit} chars]`, 
    truncated: true 
  };
}
```

资料来源：[src/index.ts:248-254]()

### 超时控制

| 配置项 | 默认值 |
|--------|--------|
| `DEFAULT_TIMEOUT_MS` | 5 分钟（300000ms） |

## MCP 协议集成

### 服务器注册

```typescript
const server = new McpServer({ 
  name: serverName, 
  version: serverVersion 
});
```

使用 StdioServerTransport 建立连接：

```typescript
const transport = new StdioServerTransport();
await server.connect(transport);
```

### 工具注册流程

```mermaid
sequenceDiagram
    participant Client as MCP Client
    participant Server as npm-run-mcp-server
    participant Package as package.json
    participant Config as npm-run-mcp.config.json
    
    Server->>Package: 读取 scripts
    Server->>Config: 读取 MCP 配置
    Server->>Server: 过滤脚本名称
    Server->>Server: 规范化工具名称
    Server->>Server: 构建 Zod Schema
    Server->>Server: 注册 MCP Tools
    Server->>Client: 连接 stdio transport
    Client->>Server: 工具调用请求
    Server->>Server: 执行 spawn 进程
    Server->>Client: 返回执行结果
```

### 工具调用处理

当 AI 客户端调用工具时：

1. 解析输入参数
2. 根据参数类型生成 CLI flags
3. 构建执行命令
4. Spawn 子进程
5. 捕获 stdout/stderr
6. 处理超时
7. 返回结构化结果

## 依赖关系图

```
@modelcontextprotocol/sdk (MCP SDK)
    ├── 协议通信
    └── 类型定义
cross-spawn
    └── 跨平台进程执行
jsonc-parser
    └── JSONC 配置解析
zod
    └── Schema 验证与转换
```

资料来源：[package.json:18-21]()

## 错误处理与边界情况

### 无 package.json 场景

当未找到 `package.json` 时，服务器启动但不注册任何工具，仅等待 stdio 连接请求。

```typescript
if (!projectDir || !projectPkg) {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  return;
}
```

资料来源：[src/index.ts:118-127]()

### 空脚本列表

```typescript
if (scriptNames.length === 0) {
  console.error(`npm-run-mcp-server: No scripts found in ${pkgJsonPath}`);
}
```

### 过滤后无有效脚本

```typescript
if (filteredScriptNames.length === 0) {
  const hint = mcpConfig.include?.length
    ? 'Check your config "include"/"exclude" settings.'
    : 'Check your package.json "scripts" section.';
  console.error(`npm-run-mcp-server: No scripts selected for exposure. ${hint}`);
}
```

## 调试支持

### Verbose 模式

通过以下任一方式启用：

- CLI 参数: `--verbose`
- 环境变量: `MCP_VERBOSE=1`
- 环境变量: `DEBUG=mcp` (需包含 "mcp" 字符串)

### 调试输出内容

| 信息 | 条件 |
|------|------|
| `cwd` | 启动时 |
| `workspace` | 环境变量检测 |
| `package.json` 路径 | 文件存在时 |
| `server info` | verbose 模式 |
| `package manager` | 检测完成后 |
| `include 列表中的缺失脚本` | 配置了 include 时 |

## 关键文件清单

| 文件路径 | 用途 |
|----------|------|
| `src/index.ts` | 主入口，包含所有核心逻辑 |
| `package.json` | 项目配置与依赖声明 |
| `npm-run-mcp.config.schema.json` | 配置文件 JSON Schema |
| `server.json` | MCP Registry 注册信息 |
| `README.md` | 用户文档 |
| `scripts/build.cjs` | 构建脚本 |
| `scripts/integration-test.mjs` | 集成测试 |

---

<a id='page-package-manager'></a>

## 包管理器检测

### 相关页面

相关主题：[系统架构](#page-architecture), [命令行界面](#page-cli-usage)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
</details>

# 包管理器检测

## 功能概述

包管理器检测是 npm-run-mcp-server 的核心功能之一，负责自动识别项目所使用的 Node.js 包管理器。该模块确保服务器能够使用正确的包管理器命令（如 `npm`、`pnpm`、`yarn` 或 `bun`）来执行 `package.json` 中定义的脚本。

支持自动检测四种主流包管理器：npm、pnpm、yarn 和 bun。

## 检测逻辑

### 优先级策略

包管理器检测采用三级优先级策略，从高到低依次为：

1. **命令行参数覆盖** - 优先级最高，允许用户强制指定特定包管理器
2. **package.json 显式声明** - 检测 `packageManager` 字段
3. **Lockfile 启发式检测** - 通过检测 lockfile 文件推断包管理器
4. **默认回退** - 若以上均无法确定，返回 `npm` 作为默认值

```typescript
function detectPackageManager(projectDir: string, pkg: PackageJson, override?: PackageManager): PackageManager {
  if (override) return override;
  
  if (pkg.packageManager) {
    const pm = pkg.packageManager.split('@')[0] as PackageManager;
    if (pm === 'npm' || pm === 'pnpm' || pm === 'yarn' || pm === 'bun') return pm;
  }
  
  if (existsSync(resolve(projectDir, 'pnpm-lock.yaml'))) return 'pnpm';
  if (existsSync(resolve(projectDir, 'yarn.lock'))) return 'yarn';
  if (existsSync(resolve(projectDir, 'bun.lockb')) || existsSync(resolve(projectDir, 'bun.lock'))) return 'bun';
  
  return 'npm';
}
```

资料来源：[src/index.ts]()

### 检测流程图

```mermaid
graph TD
    A[开始检测] --> B{是否有 --pm 参数?}
    B -->|是| C[使用命令行指定值]
    B -->|否| D{package.json 是否有 packageManager 字段?}
    D -->|是| E{字段值是否有效?}
    D -->|否| F{是否存在 pnpm-lock.yaml?}
    E -->|npm/pnpm/yarn/bun| G[使用 packageManager 值]
    E -->|其他| F
    F -->|是| H[使用 pnpm]
    F -->|否| I{是否存在 yarn.lock?}
    I -->|是| J[使用 yarn]
    I -->|否| K{是否存在 bun.lockb 或 bun.lock?}
    K -->|是| L[使用 bun]
    K -->|否| M[使用 npm 默认值]
    C --> N[返回包管理器]
    G --> N
    H --> N
    J --> N
    L --> N
    M --> N
```

## 支持的包管理器

| 包管理器 | 标识符 | Lockfile 检测 | packageManager 前缀 |
|---------|--------|---------------|---------------------|
| npm | `npm` | 无 | `npm@x.x.x` |
| pnpm | `pnpm` | `pnpm-lock.yaml` | `pnpm@x.x.x` |
| yarn | `yarn` | `yarn.lock` | `yarn@x.x.x` |
| bun | `bun` | `bun.lockb` / `bun.lock` | `bun@x.x.x` |

## 使用方式

### CLI 参数指定

通过 `--pm` 参数强制指定包管理器：

```bash
npx npm-run-mcp-server --pm pnpm
npx npm-run-mcp-server --pm yarn
npx npm-run-mcp-server --pm bun
```

### packageManager 字段

在项目 `package.json` 中声明使用的包管理器：

```json
{
  "packageManager": "pnpm@8.15.0"
}
```

服务器会自动提取 `@` 前的包管理器名称。

### 自动检测

服务器启动时自动执行检测，无需额外配置。检测结果会输出到 stderr（当启用 verbose 模式时）：

```bash
npx npm-run-mcp-server --verbose
# 输出: [mcp] detected package manager: pnpm
```

## 构建运行命令

检测到包管理器后，`buildRunCommand` 函数负责构建实际的执行命令：

```typescript
function buildRunCommand(
  pm: PackageManager,
  scriptName: string,
  extraArgs: string[]
): { command: string; args: string[] } {
  const command = pm;
  const baseArgs = ['run', scriptName];
  const args = extraArgs.length > 0 ? [...baseArgs, '--', ...extraArgs] : baseArgs;
  return { command, args };
}
```

| 参数 | 类型 | 说明 |
|-----|------|------|
| `pm` | `PackageManager` | 检测到的包管理器 |
| `scriptName` | `string` | 要执行的脚本名称 |
| `extraArgs` | `string[]` | 额外参数 |

返回的 `command` 和 `args` 直接用于 `spawn` 调用执行脚本。

## 已知问题

根据社区反馈，NPM 发布工作流曾因 NPM token 过期/撤销而失败，建议用户在实际使用中注意 token 有效期管理。

---

<a id='page-tool-registration'></a>

## 工具注册机制

### 相关页面

相关主题：[系统架构](#page-architecture), [配置文件指南](#page-configuration), [输入模式与脚本参数](#page-input-schema)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
</details>

# 工具注册机制

## 概述

npm-run-mcp-server 的核心功能是将 `package.json` 中定义的 npm scripts 自动转换为 MCP (Model Context Protocol) 工具，使 AI 代理能够直接调用项目脚本。工具注册机制负责将脚本转换为符合 MCP 协议的工具定义，包括输入参数验证、名称规范化、配置过滤等关键步骤。

工具注册流程始于服务器启动阶段，在读取项目 `package.json` 后，系统会根据配置文件（`npm-run-mcp.config.json` 或 `.npm-run-mcp.json`）过滤可暴露的脚本，然后为每个符合条件的脚本生成 MCP 工具定义。 资料来源：[src/index.ts:1-200]()

## 核心流程

```mermaid
graph TD
    A[读取 package.json] --> B[读取 MCP 配置文件]
    B --> C[过滤脚本名称]
    C --> D[生成工具名称映射]
    D --> E[构建输入 Schema]
    E --> F[注册 MCP 工具]
    F --> G[等待工具调用]
```

## 脚本名称规范化

### sanitizeScriptName 函数

脚本名称需转换为符合 MCP 工具命名规范的标识符。`sanitizeScriptName` 函数负责此转换：

```typescript
function sanitizeScriptName(name: string): string {
  const normalized = name.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
  return normalized.length > 0 ? normalized : 'script';
}
```

**转换规则：**

| 输入示例 | 输出结果 | 说明 |
|---------|---------|------|
| `test:unit` | `test_unit` | 冒号替换为下划线 |
| `build:prod` | `build_prod` | 保留下划线和连字符 |
| `lint-fix` | `lint_fix` | 连字符替换为下划线 |
| `clean` | `clean` | 纯字母保持不变 |
| `@scope/pkg` | `_scope_pkg` | 非法字符替换 |

该函数确保所有生成的工具名称仅包含小写字母、数字、下划线和连字符，同时处理空名称的边界情况。 资料来源：[src/index.ts:120-123]()

## 配置过滤机制

### filterScriptNames 函数

在注册工具前，系统根据用户配置决定哪些脚本应被暴露：

```typescript
function filterScriptNames(
  scriptNames: string[],
  mcpConfig: McpConfig
): string[] {
  let filtered = scriptNames;

  if (mcpConfig.include && mcpConfig.include.length > 0) {
    filtered = filtered.filter((name) => mcpConfig.include!.includes(name));
  }

  if (mcpConfig.exclude && mcpConfig.exclude.length > 0) {
    filtered = filtered.filter((name) => !mcpConfig.exclude!.includes(name));
  }

  return filtered;
}
```

**过滤优先级：**

1. **include 优先**：如果配置了 `include` 数组，仅暴露列表中的脚本
2. **exclude 次之**：在 include 结果基础上排除指定脚本
3. **无配置时**：暴露所有脚本

过滤逻辑确保配置冲突时，include 白名单优先于 exclude 黑名单，这在企业项目中用于限制敏感脚本（如 `publish`、`eject`）的访问尤为重要。 资料来源：[src/index.ts:200-215]()

## 工具名称映射

系统维护一个 `toolNameToScripts` 映射表，处理脚本名称转换后的冲突问题：

```typescript
const toolNameToScripts = new Map<string, string[]>();
for (const scriptName of filteredScriptNames) {
  const overrideName = mcpConfig.scripts?.[scriptName]?.toolName;
  const toolName = overrideName ?? sanitizeScriptName(scriptName);
  // 处理同名冲突
}
```

**冲突处理机制：**

当多个脚本经过规范化后产生相同工具名称时，系统通过 `toolNameToScripts` 映射记录所有原始脚本。这确保了每个工具调用能准确定位到对应的脚本命令。

用户可通过配置文件的 `scripts[scriptName].toolName` 字段自定义工具名称，避免自动生成的名称不符合预期：

```json
{
  "scripts": {
    "test:unit": {
      "toolName": "run_unit_tests"
    }
  }
}
```

 资料来源：[src/index.ts:230-245]()

## 输入 Schema 生成

### jsonSchemaToZod 函数

配置文件的 `inputSchema` 使用 JSON Schema 定义工具参数，系统将其转换为 Zod 验证模式：

```typescript
function jsonSchemaToZod(schema: unknown): z.ZodTypeAny {
  if (!isPlainObject(schema)) return z.any();

  // Handle enum types
  if (Array.isArray(schema.enum) && schema.enum.every((v) => typeof v === 'string')) {
    const values = schema.enum as string[];
    let base: z.ZodTypeAny = z.literal(values[0]);
    for (const v of values.slice(1)) {
      base = z.union([base, z.literal(v)]);
    }
    return base;
  }

  // Type-based conversion
  switch (schema.type) {
    case 'string': return z.string();
    case 'boolean': return z.boolean();
    case 'number': return z.number();
    case 'integer': return z.number().int();
    case 'array': {
      const items = schema.items;
      if (isPlainObject(items) && items.type === 'string') {
        return z.array(z.string());
      }
      return z.array(z.any());
    }
    case 'object': {
      const properties = schema.properties || {};
      const requiredSet = new Set(schema.required || []);
      const shape: Record<string, z.ZodTypeAny> = {};
      
      for (const [key, value] of Object.entries(properties)) {
        let prop = jsonSchemaToZod(value);
        if (!requiredSet.has(key)) prop = prop.optional();
        shape[key] = prop;
      }
      
      const obj = z.object(shape);
      return schema.additionalProperties === false ? obj.strict() : obj.passthrough();
    }
    default: return z.any();
  }
}
```

**支持的 Schema 类型映射：**

| JSON Schema Type | Zod Type | 说明 |
|------------------|----------|------|
| `string` | `z.string()` | 字符串输入 |
| `boolean` | `z.boolean()` | 布尔开关 |
| `number` | `z.number()` | 数值类型 |
| `integer` | `z.number().int()` | 整数类型 |
| `array` (string items) | `z.array(z.string())` | 字符串数组 |
| `object` | `z.object({...})` | 嵌套对象 |
| `enum` | `z.union([...])` | 枚举值 |

 资料来源：[src/index.ts:130-175]()

### buildToolInputSchema 函数

每个 MCP 工具的基础输入 Schema 包含两个标准字段：

```typescript
function buildToolInputSchema(configForScript: McpScriptConfig | undefined): z.ZodTypeAny {
  const base = z.object({
    _: z.array(z.string()).optional(),
    args: z
      .union([z.string(), z.array(z.string())])
      .optional()
      .describe(configForScript?.argsDescription ?? 'Optional arguments appended after -- to the script'),
  }).passthrough();

  if (!configForScript?.inputSchema) return base;

  const converted = jsonSchemaToZod(configForScript.inputSchema);
  // ... merge logic
  return mergedSchema;
}
```

**基础 Schema 结构：**

| 字段 | 类型 | 说明 |
|-----|------|------|
| `_` | `string[]` | 位置参数数组（可选） |
| `args` | `string \| string[]` | 追加到 `--` 后的额外参数（可选） |

 资料来源：[src/index.ts:180-200]()

## 参数到 CLI 标志转换

### convertArgsToFlags 函数

当 AI 调用工具时，输入参数需转换为 CLI 标志传给 npm/pnpm/yarn/bun：

```typescript
function convertArgsToFlags(
  args: Record<string, unknown>,
  inputSchema: z.ZodSchema
): string[] {
  const parsed = inputSchema.safeParse(args);
  if (!parsed.success) return [];

  const validArgs = parsed.data;
  const flags: string[] = [];
  const positional: string[] = [];
  const rawArgs = typeof validArgs.args === 'string' 
    ? [validArgs.args] 
    : (validArgs.args || []);

  for (const [key, value] of Object.entries(validArgs)) {
    if (key === '_' || key === 'args') continue;
    
    const flag = key.length === 1 ? `-${key}` : `--${key}`;
    
    if (value === null || value === undefined) continue;
    
    if (typeof value === 'boolean') {
      if (value) flags.push(flag);
      continue;
    }
    
    if (typeof value === 'string') {
      flags.push(flag, value);
      continue;
    }
    
    if (Array.isArray(value)) {
      for (const item of value) {
        if (item !== null && item !== undefined) {
          if (typeof item === 'boolean') {
            if (item) flags.push(flag);
          } else {
            flags.push(flag, String(item));
          }
        }
      }
      continue;
    }
    
    if (typeof value === 'object') {
      flags.push(flag, JSON.stringify(value));
    }
  }

  return [...flags, ...positional, ...rawArgs];
}
```

**转换规则示例：**

| 输入参数 | CLI 标志 |
|---------|---------|
| `{ watch: true }` | `--watch` |
| `{ output: "dist" }` | `--output dist` |
| `{ files: ["a.ts", "b.ts"] }` | `--files a.ts --files b.ts` |
| `{ config: { ts: true } }` | `--config '{"ts":true}'` |
| `{ args: "--verbose" }` | `-- --verbose` |

 资料来源：[src/index.ts:300-360]()

## MCP 服务器集成

### 工具注册到 McpServer

最终的工具注册通过 `@modelcontextprotocol/sdk` 实现：

```typescript
import { McpServer } from '@modelcontextprotocol/sdk';

const server = new McpServer({ name: serverName, version: serverVersion });

// 为每个脚本注册工具
for (const scriptName of filteredScriptNames) {
  const toolName = overrideName ?? sanitizeScriptName(scriptName);
  const description = mcpConfig.scripts?.[scriptName]?.description 
    ?? `${scriptName}: ${scripts[scriptName]}`;
  
  const inputSchema = buildToolInputSchema(mcpConfig.scripts?.[scriptName]);

  server.tool(
    toolName,
    description,
    inputSchema,
    async (args) => {
      const extraArgs = convertArgsToFlags(args, inputSchema);
      const { command, args: cmdArgs } = buildRunCommand(pm, scriptName, extraArgs);
      const result = await runProcess(command, cmdArgs, options);
      return {
        content: [{ type: 'text', text: result.stdout + result.stderr }]
      };
    }
  );
}

// 连接 stdio 传输层
const transport = new StdioServerTransport();
await server.connect(transport);
```

**McpServer.tool 注册参数：**

| 参数 | 类型 | 说明 |
|-----|------|------|
| name | `string` | 工具标识符 |
| description | `string` | 工具功能描述 |
| inputSchema | `z.ZodSchema` | 参数验证 Schema |
| handler | `function` | 工具执行回调 |

 资料来源：[src/index.ts:240-280]()

## 完整执行流程

```mermaid
sequenceDiagram
    participant AI as AI Agent
    participant MCP as MCP Server
    participant PM as Package Manager
    participant Proj as Project Scripts

    AI->>MCP: 调用工具 (run_build)
    MCP->>MCP: 验证输入参数
    MCP->>PM: npm run build -- --mode production
    PM->>Proj: 执行构建脚本
    Proj-->>PM: 输出构建结果
    PM-->>MCP: stdout/stderr
    MCP-->>AI: 返回执行结果
```

## 配置文件结构

工具注册支持完整的 JSON Schema 验证：

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "npm-run-mcp.config.schema.json",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "include": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Exact script names to include"
    },
    "exclude": {
      "type": "array", 
      "items": { "type": "string" },
      "description": "Exact script names to exclude"
    },
    "scripts": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "toolName": { "type": "string" },
          "description": { "type": "string" },
          "argsDescription": { "type": "string" },
          "inputSchema": { "type": "object" }
        }
      }
    }
  }
}
```

**完整配置示例：**

```json
{
  "include": ["dev", "build", "test"],
  "exclude": ["publish", "eject"],
  "scripts": {
    "test": {
      "description": "运行测试套件",
      "argsDescription": "传递给测试框架的参数",
      "inputSchema": {
        "type": "object",
        "properties": {
          "watch": {
            "type": "boolean",
            "description": "监听文件变化"
          },
          "coverage": {
            "type": "boolean", 
            "description": "生成覆盖率报告"
          },
          "grep": {
            "type": "string",
            "description": "只运行匹配的正则表达式"
          }
        }
      }
    }
  }
}
```

 资料来源：[npm-run-mcp.config.schema.json:1-60]()

## 依赖项

工具注册机制依赖以下核心依赖包：

| 包名 | 版本 | 用途 |
|-----|------|------|
| `@modelcontextprotocol/sdk` | ^1.25.1 | MCP 协议实现与工具注册 |
| `zod` | ^3.23.8 | 输入参数验证（bundled） |
| `jsonc-parser` | ^3.3.1 | JSONC 配置解析（支持注释） |

 资料来源：[package.json:1-40]()

## 注意事项

1. **JSONC 支持**：配置文件支持 JavaScript 风格注释和尾随逗号，由 `jsonc-parser` 处理
2. **Windows 路径转换**：在 WSL 环境下运行时，自动转换 Windows 路径格式
3. **超时控制**：默认超时为 5 分钟，可通过环境变量或参数调整
4. **输出截断**：单次输出超过 12000 字符时自动截断并标注

---

<a id='page-file-watching'></a>

## 文件监视与热重载

### 相关页面

相关主题：[系统架构](#page-architecture), [配置文件指南](#page-configuration)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/index.ts](https://github.com/fstubner/npm-run-mcp-server/blob/main/src/index.ts)
- [package.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/package.json)
- [npm-run-mcp.config.schema.json](https://github.com/fstubner/npm-run-mcp-server/blob/main/npm-run-mcp.config.schema.json)
- [README.md](https://github.com/fstubner/npm-run-mcp-server/blob/main/README.md)
</details>

# 文件监视与热重载

## 功能概述

根据对源码的全面分析，**npm-run-mcp-server 当前版本 (v0.2.13) 并不支持文件监视（File Watching）与热重载（Hot Reload）功能**。

该仓库的核心定位是作为 Model Context Protocol (MCP) 服务器，将 `package.json` 中的脚本暴露为 AI 代理可调用的工具，而非开发工作流中的实时监听与自动重载服务。

## 当前架构说明

### 核心功能模块

当前实现主要包含以下功能模块：

| 模块 | 功能描述 | 相关源码位置 |
|------|----------|--------------|
| 包管理器自动检测 | 检测 npm/pnpm/yarn/bun | `src/index.ts:detectPackageManager()` |
| 脚本执行引擎 | 使用 cross-spawn 执行脚本 | `src/index.ts:runProcess()` |
| 配置文件解析 | 支持 JSONC 格式配置 | `src/index.ts:readProjectMcpConfig()` |
| CLI 参数处理 | 支持 --cwd, --pm, --config 等 | `src/index.ts` 入口逻辑 |

### 现有工作流程

当前服务器遵循以下工作模式：

```mermaid
graph TD
    A[MCP Server 启动] --> B[检测工作目录]
    B --> C[查找 package.json]
    C --> D[自动检测包管理器]
    D --> E[加载 MCP 配置文件]
    E --> F[注册脚本为 MCP Tools]
    F --> G[等待 AI Agent 调用]
    G --> H[执行对应 npm 脚本]
    H --> I[返回执行结果]
    I --> G
```

资料来源：[src/index.ts:入口逻辑]()

## 脚本执行机制

### 进程执行与超时控制

脚本执行采用原生 `child_process.spawn` 实现，默认超时时间为 5 分钟：

```typescript
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
```

资料来源：[src/index.ts:DEFAULT_TIMEOUT_MS]()

执行函数返回结构：

```typescript
interface ProcessResult {
  stdout: string;      // 标准输出
  stderr: string;     // 标准错误
  exitCode: number | null;  // 退出码
  signal: NodeJS.Signals | null;  // 中断信号
  totalLength: number;  // 总输出长度
  timedOut: boolean;   // 是否超时
}
```

### 输出截断机制

为防止大量输出导致协议阻塞，服务器实现了自动截断功能：

```typescript
function trimOutput(out: string, limit = 12000, totalLength?: number)
```

默认限制为 12000 字符，超过部分显示为：
```
...[truncated X chars]
```

资料来源：[src/index.ts:trimOutput()]()

## 配置系统

### 配置文件格式

支持 `npm-run-mcp.config.json` 或 `.npm-run-mcp.json`，支持 JSONC 语法（注释和尾随逗号）：

```json
{
  "include": ["test", "lint", "build"],
  "exclude": ["publish", "eject"],
  "scripts": {
    "test": {
      "description": "运行测试套件",
      "inputSchema": {
        "properties": {
          "watch": { "type": "boolean", "description": "监视文件变化" }
        }
      }
    }
  }
}
```

### 配置选项说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `include` | `string[]` | 白名单 - 仅暴露指定的脚本 |
| `exclude` | `string[]` | 黑名单 - 排除指定的脚本 |
| `scripts` | `object` | 单个脚本的详细配置 |

## 缺失功能说明

### 为何当前版本不支持热重载

1. **协议限制**：MCP 协议主要设计为请求-响应模式，而非事件驱动
2. **架构设计**：服务器启动时静态读取 `package.json`，无动态监听机制
3. **依赖关系**：核心依赖 `@modelcontextprotocol/sdk` 未提供文件系统监听接口

### 替代方案建议

如需实现脚本变更监听，可考虑以下方案：

1. **外部脚本封装**：在项目级 `package.json` 中添加 `dev` 脚本使用 `nodemon` 或 `watch` 工具
2. **自定义 MCP 扩展**：基于 SDK 扩展支持 `watch` 模式
3. **IDE 集成**：利用 VS Code/Cursor 的文件监视功能配合 MCP 工具调用

## 版本历史参考

| 版本 | 发布日期 | 相关变更 |
|------|----------|----------|
| v0.2.13 | 最新 | 依赖更新 (qs, express) |
| v0.2.10 | - | 添加配置文件支持 |
| v0.1.0 | - | 初始版本发布 |

资料来源：[社区发布信息](https://github.com/fstubner/npm-run-mcp-server/releases)

## 结论

**npm-run-mcp-server 当前不具备文件监视与热重载功能**。该工具专注于将 npm 脚本可靠地暴露为 AI 可调用的 MCP 工具，强调的是静态配置与明确的工作流程控制，而非动态监听。

如需开发环境热重载，建议使用专门的开发服务器（如 Vite、webpack-dev-server）或任务运行器（如 nodemon、concurrently）配合此 MCP 服务器使用。

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：fstubner/npm-run-mcp-server

摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。

## 1. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | README/documentation is current enough for a first validation pass.

## 2. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | last_activity_observed missing

## 3. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | no_demo; severity=medium

## 4. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | no_demo; severity=medium

## 5. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | issue_or_pr_quality=unknown

## 6. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | mcp_registry:io.github.fstubner/npm-run-mcp-server:0.2.13 | https://registry.modelcontextprotocol.io/v0.1/servers/io.github.fstubner%2Fnpm-run-mcp-server/versions/0.2.13 | release_recency=unknown

<!-- canonical_name: fstubner/npm-run-mcp-server; human_manual_source: deepwiki_human_wiki -->
