MCP健康检查工具

为MCP(Model Context Protocol)服务器提供程序化的健康和活跃性探测,支持多种传输方式,适用于自动化环境和监控场景。

  • by SiluPanda
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 SiluPanda/mcp-healthcheck

使用说明

mcp健康检查

MCP(模型上下文协议)服务器的程序化健康和活性探针。


描述

mcp-healthcheck 通过任何支持的传输(stdio、Streamable HTTP或传统SSE)连接到MCP服务器,执行协议握手,枚举服务器的功能(工具、资源、提示),测量每个操作的延迟,并返回结构化的健康报告。它被设计为在自动化环境中无头运行——Kubernetes活性/就绪性探针、CI管道门、监控仪表板——在这些环境中,交互式调试工具是不可行的。

该包提供了用于编程的TypeScript/JavaScriptneneneba API,以及用于终端和shell脚本的CLI。API返回结构化 HealthReport 具有每次检查状态、延迟和错误详细信息的对象。CLI打印人类可读或JSON输出,并使用常规代码退出(0表示健康,1表示不健康,2表示配置错误,3表示降级)。

唯一的运行时依赖关系是 @modelcontextprotocol/sdk.


安装

npm install mcp-healthcheck @modelcontextprotocol/sdk

@modelcontextprotocol/sdk 是对等依赖,必须与此软件包一起安装。

仅用于CLI而不在本地安装:

npx mcp-healthcheck --stdio 'node ./server.js'

快速开始

程序化(TypeScript)

import { checkHealth } from 'mcp-healthcheck';

const report = await checkHealth({
  transport: {
    type: 'stdio',
    command: 'node',
    args: ['./my-mcp-server.js'],
  },
  timeout: 10_000,
});

console.log(report.status);  // 'healthy' | 'unhealthy' | 'degraded'
console.log(report.totalMs); // 342
console.log(report.checks);  // individual check results

命令行界面

# stdio transport
mcp-healthcheck --stdio 'node ./server.js'

# Streamable HTTP transport
mcp-healthcheck --url https://mcp.example.com/mcp --header 'Authorization:Bearer sk-...'

# Legacy SSE transport
mcp-healthcheck --sse http://localhost:3000/sse

# JSON output for scripting
mcp-healthcheck --stdio 'node ./server.js' --format json

# Quiet mode (exit code only)
mcp-healthcheck --url http://localhost:3000/mcp --quiet

特性

  • 三种运输方式 --stdio(子进程)、流式HTTP和传统SSE。
  • 完整的MCP生命周期验证 --传输连接、协议握手和功能枚举(工具、资源、提示)。
  • 每次检查延迟测量 --每次检查都使用高分辨率计时 performance.now().
  • 可配置阈值 --最小/最大工具计数、最小资源/提示计数和每次检查的最大延迟。
  • 自定义检查 --用户定义的异步函数,用于接收连接的MCP Client 例如,针对特定领域的断言。
  • 超时执行 --每次检查超时和总超时,并自动清理剩余的检查。
  • 中止信号支持 --通过标准进行外部取消 AbortSignal 界面。
  • 自动跳过 --对于服务器未声明的功能的检查将自动跳过,并传递结果。
  • 结构化健康报告 --机器可读 HealthReport 具有状态、每次检查结果、摘要计数和服务器信息的对象。
  • HTTP处理程序工厂 --在Express、Koa、Fastify或raw中挂载健康端点 http.createServer 只需一次函数调用。
  • 具有确定性退出代码的CLI --0(健康),1(不健康),2(配置错误),3(降级)。
  • 环境变量配置 --所有CLI标志都具有容器和CI环境的环境变量等效值。
  • 子流程清理 --stdio传输总是终止(SIGTERM,然后是5秒后的SIGKILL),以防止僵尸进程。
  • 从不投掷 -- checkHealth() 总是返回a HealthReport,捕获报告结构中的所有错误。

API 参考

checkHealth(options: HealthCheckOptions): Promise<HealthReport>

主要API。连接到MCP服务器,运行所有健康检查,并返回结构化报告。此函数从不抛出;所有错误都记录在返回的报告中。

import { checkHealth } from 'mcp-healthcheck';

const report = await checkHealth({
  transport: {
    type: 'stdio',
    command: 'npx',
    args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
  },
});

if (report.status === 'healthy') {
  console.log(`${report.summary.passed}/${report.summary.total} checks passed in ${report.totalMs}ms.`);
} else {
  for (const check of report.checks.filter(c => !c.passed)) {
    console.error(`FAIL: ${check.name} -- ${check.error?.message}`);
  }
}

isHealthy(options: HealthCheckOptions): Promise<boolean>

运行的便利功能 checkHealth 并返回 true 仅当状态为 'healthy'.退货 false 对两者 'unhealthy' 和 'degraded'.

import { isHealthy } from 'mcp-healthcheck';

const healthy = await isHealthy({
  transport: { type: 'stdio', command: 'node', args: ['./server.js'] },
});

if (!healthy) {
  process.exit(1);
}

createHttpHandler(options: HealthCheckOptions): (req: IncomingMessage, res: ServerResponse) => void

创建一个公开健康检查端点的HTTP请求处理程序。适用于安装在任何Node.js HTTP框架或原始 http.createServer.

  • 获取 请求:运行 checkHealth(options) 并作出回应 200 OK (健康或退化)或 503 Service Unavailable (不健康),与 Content-Type: application/json 和那个 HealthReport 作为响应体。
  • 任何其他方法:回复如下 405 Method Not Allowed.
import http from 'node:http';
import { createHttpHandler } from 'mcp-healthcheck';

const handler = createHttpHandler({
  transport: { type: 'stdio', command: 'node', args: ['./server.js'] },
  timeout: 10_000,
});

const server = http.createServer(handler);
server.listen(8080);

类型

HealthCheckOptions

传递给的主配置对象 checkHealth, isHealthy,以及 createHttpHandler.

属性 类型 默认值 描述
transport TransportConfig 必需的 用于连接到MCP服务器的传输配置。
timeout number 30000 整个健康检查的总超时时间(毫秒)。
checkTimeout number 10000 每次检查超时(毫秒)。
skip Array<'tools' | 'resources' | 'prompts'> [] 选中以跳过。 connect 和 initialize 不能跳过。
thresholds Thresholds {} 通过/失败评估的阈值断言。
customChecks Array<{ name: string; fn: CustomCheckFn; required?: boolean }> [] 在标准检查后运行的自定义检查功能。
clientInfo { name: string; version: string } { name: 'mcp-healthcheck', version: '<pkg version>' } MCP中发送的客户端信息 initialize 请求。
signal AbortSignal undefined AbortSignal用于外部取消。

TransportConfig

三种运输配置的区别性结合:

StdioTransportConfig

属性 类型 默认值 描述
type 'stdio' -- 运输鉴别器。
command string 必需的 要执行的命令(例如。, 'node', 'python', 'npx').
args string[] [] 要传递给命令的参数。
env Record<string, string> process.env 子流程的环境变量。已合并 process.env.
cwd string process.cwd() 子流程的工作目录。

HttpTransportConfig

属性 类型 默认值 描述
type 'http' -- 运输鉴别器。
url string 必需的 MCP服务器的流式HTTP端点的URL。
headers Record<string, string> undefined 其他HTTP标头(例如授权)。

SseTransportConfig

属性 类型 默认值 描述
type 'sse' -- 运输鉴别器。
url string 必需的 SSE端点的URL。
headers Record<string, string> undefined 其他HTTP标头。

Thresholds

属性 类型 描述
maxLatencyMs number 任何单个检查的最大允许延迟(ms)。超过此值将整体状态设置为 'degraded'.
minTools number 服务器必须公开的最小工具数。
maxTools number 服务器可以公开的最大工具数。
minResources number 服务器必须公开的最小资源数。
minPrompts number 服务器必须公开的最小提示数。

CustomCheckFn

type CustomCheckFn = (client: Client) => Promise<CustomCheckResult>;

用户定义的异步函数,用于接收连接的MCP Client 实例并返回a CustomCheckResult.

CustomCheckResult

属性 类型 描述
passed boolean 检查是否通过。
message string 结果的人类可读描述。
details Record<string, unknown> 可选的任意元数据要包含在报告中。

HealthReport

返回的完整健康报告 checkHealth.

属性 类型 描述
status HealthStatus 总体健康状况: 'healthy', 'unhealthy',或 'degraded'.
totalMs number 整个健康检查的挂钟总时间(毫秒)。
timestamp string 执行健康检查的ISO 8601时间戳。
checks CheckResult[] 按执行顺序显示每个单独检查的结果。
summary { total: number; passed: number; failed: number; skipped: number } 摘要很重要。
server { name: string; version: string; protocolVersion: string } 服务器信息,成功后填充 initialize 检查。

HealthStatus

type HealthStatus = 'healthy' | 'unhealthy' | 'degraded';
  • healthy --所有必需的检查均已通过,所有阈值均已满足。
  • unhealthy --一个或多个必需的检查失败。
  • degraded --所有必需的检查都通过了,但可选检查或延迟阈值失败。

CheckResult

属性 类型 描述
name string 检查名称(例如。, 'connect', 'initialize', 'tools').
passed boolean 检查是否通过。
durationMs number 此检查所用的时间(毫秒)。
message string 人类可读的结果描述。
error { code: string; message: string; stack?: string } 检查失败时的错误详细信息。对成功没有定义。
details Record<string, unknown> 查看具体细节(见下文)。

专业检查结果详情:

检查 详细信息形状
connect { transportType: 'stdio' | 'http' | 'sse' }
initialize { protocolVersion: string; serverName: string; serverVersion: string; capabilities: { tools?: boolean; resources?: boolean; prompts?: boolean; logging?: boolean } }
tools { toolCount: number; toolNames: string[] }
resources { resourceCount: number; resourceUris: string[] }
prompts { promptCount: number; promptNames: string[] }

配置

默认值

选项 默认值 描述
timeout 30000 整个健康检查的总超时时间(毫秒)。
checkTimeout 10000 每次检查超时(ms)。
skip [] 没有跳过检查。
thresholds {} 没有阈值断言。
customChecks [] 没有自定义检查。
clientInfo.name 'mcp-healthcheck' 客户端名称已发送至 initialize 请求。
clientInfo.version 包版本 发送的客户端版本 initialize 请求。

检查顺序

检查按此固定顺序运行。每次检查都取决于之前要求的检查是否成功。

订单 检查 可以跳过吗? 取决于 验证
1 connect 否 -- 传输级连接
2 initialize 没有 connect MCP协议握手
3 tools 是的 initialize tools/list 成功,达到阈值
4 resources 是的 initialize resources/list 成功,达到阈值
5 prompts 是的 initialize prompts/list 成功,达到阈值
6+ 自定义 不适用 initialize 用户定义逻辑

如果 connect 或 initialize 如果失败,则跳过所有后续检查。

如果服务器没有声明能力(例如。, resources),相应的检查将自动跳过 passed: true.

超时策略

超时在两个层面上执行:

  • 每次检查超时 (checkTimeout):每张支票都包裹在 Promise.race 有一个超时。如果检查超出此范围,则失败并返回错误代码 CHECK_TIMEOUT.
  • 总体超时 (timeout):主计时器为整个时间运行 checkHealth() 电话。如果它在所有检查完成之前触发,则跳过剩余的检查并返回错误代码 OVERALL_TIMEOUT.

两个超时级别都使用 AbortController 在内部与提供的任何来电者进行沟通 signal.


错误处理

checkHealth() 从不投掷。所有错误都在返回的 HealthReport未通过的检查包括 error 带有分类代码、消息和可选堆栈跟踪的对象。

错误代码

代码 来源 含义
TRANSPORT_ERROR 传输层 无法建立传输连接(ECONNREFUSED、DNS故障、TLS错误、子进程崩溃)。
SPAWN_ERROR stdio传输 生成子进程失败(ENOENT 未找到命令, EACCES 拒绝许可)。
HANDSHAKE_ERROR MCP协议 initialize 握手失败(JSON-RPC错误、版本不匹配、响应格式错误)。
PROTOCOL_ERROR MCP协议 A tools/list, resources/list,或 prompts/list 请求返回JSON-RPC错误。
CHECK_TIMEOUT 超时系统 超过单个检查 checkTimeout.
OVERALL_TIMEOUT 超时系统 超过整个健康检查 timeout;跳过了其余的检查。
ABORTED 外部信号 呼叫者的 AbortSignal 被触发。
THRESHOLD_VIOLATION 阈值评估 阈值断言失败(例如,工具计数低于 minTools).
CUSTOM_CHECK_ERROR 自定义检查 自定义检查函数抛出异常。
UNKNOWN_ERROR 回退 与任何已知分类都不匹配的意外错误。

依赖失败传播

如果需要检查(connect 或 initialize)如果失败,则跳过所有后续检查,并记录一条指示先前失败的消息。即使早期检查失败,这也提供了一个完整的报告结构。


高级用法

自定义检查

自定义检查在标准检查后运行,并接收连接的MCP Client 例子每个检查都可以标记为 required (失败使状态 'unhealthy')或可选(失败使状态 'degraded',这是默认设置)。

import { checkHealth } from 'mcp-healthcheck';

const report = await checkHealth({
  transport: { type: 'stdio', command: 'node', args: ['./server.js'] },
  customChecks: [
    {
      name: 'has-search-tool',
      required: true,
      fn: async (client) => {
        const { tools } = await client.listTools();
        const hasSearch = tools.some(t => t.name === 'search');
        return {
          passed: hasSearch,
          message: hasSearch ? 'search tool is registered' : 'search tool is missing',
        };
      },
    },
  ],
});

引发异常的自定义检查被视为失败,并带有错误代码 CUSTOM_CHECK_ERROR同步抛出和拒绝的promise都会被处理。

中止信号取消

通过A AbortSignal 要从外部取消健康检查:

import { checkHealth } from 'mcp-healthcheck';

const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);

const report = await checkHealth({
  transport: { type: 'stdio', command: 'node', args: ['./server.js'] },
  signal: controller.signal,
});

中止时,健康检查立即停止,并返回一个包含错误代码的不健康报告 ABORTED.

带阈值的HTTP传输

import { checkHealth } from 'mcp-healthcheck';

const report = await checkHealth({
  transport: {
    type: 'http',
    url: 'https://mcp.example.com/mcp',
    headers: { 'Authorization': 'Bearer sk-...' },
  },
  timeout: 15_000,
  checkTimeout: 5_000,
  thresholds: {
    maxLatencyMs: 2_000,
    minTools: 3,
  },
});

HTTP健康端点

在任何Node.js应用程序中将健康检查作为HTTP端点公开:

import http from 'node:http';
import { createHttpHandler } from 'mcp-healthcheck';

const handler = createHttpHandler({
  transport: { type: 'stdio', command: 'node', args: ['./server.js'] },
  timeout: 10_000,
});

const server = http.createServer(handler);
server.listen(8080);
// GET http://localhost:8080 -> 200 (healthy/degraded) or 503 (unhealthy)

Kubernetes生存性和就绪性探测

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-server
spec:
  template:
    spec:
      containers:
        - name: mcp-server
          image: my-mcp-server:latest
          ports:
            - containerPort: 3000
        - name: healthcheck
          image: node:20-slim
          command: ['sleep', 'infinity']
          livenessProbe:
            exec:
              command:
                - mcp-healthcheck
                - '--url'
                - 'http://localhost:3000/mcp'
                - '--timeout'
                - '5000'
                - '--skip'
                - 'resources'
                - '--skip'
                - 'prompts'
                - '--quiet'
            initialDelaySeconds: 15
            periodSeconds: 30
            timeoutSeconds: 8
            failureThreshold: 3
          readinessProbe:
            exec:
              command:
                - mcp-healthcheck
                - '--url'
                - 'http://localhost:3000/mcp'
                - '--timeout'
                - '5000'
                - '--min-tools'
                - '5'
                - '--quiet'
            initialDelaySeconds: 5
            periodSeconds: 10
            timeoutSeconds: 8
            failureThreshold: 1

CI管道闸门

- name: Wait for MCP server to be healthy
  run: |
    for i in $(seq 1 10); do
      npx mcp-healthcheck \
        --url http://localhost:3000/mcp \
        --timeout 5000 \
        --min-tools 3 \
        --format json \
        && exit 0
      echo "Attempt $i failed, retrying in 2s..."
      sleep 2
    done
    echo "MCP server failed to become healthy"
    exit 1

监控仪表板集成

import { checkHealth } from 'mcp-healthcheck';

const servers = [
  { name: 'search-server', transport: { type: 'http' as const, url: 'https://search.internal/mcp' } },
  { name: 'db-server', transport: { type: 'http' as const, url: 'https://db.internal/mcp' } },
];

const results = await Promise.all(
  servers.map(async (s) => ({
    name: s.name,
    report: await checkHealth({ transport: s.transport, timeout: 10_000 }),
  })),
);

for (const { name, report } of results) {
  console.log(`${name}: ${report.status} (${report.totalMs}ms)`);
}

CLI参考

mcp-healthcheck [options]

Transport (exactly one required):
  --stdio <command>          Spawn an MCP server via stdio transport.
  --url <url>                Connect via Streamable HTTP transport.
  --sse <url>                Connect via legacy SSE transport.

Transport options:
  --header <key:value>       Add an HTTP header (repeatable). For --url and --sse only.
  --cwd <path>               Working directory for --stdio subprocess.
  --env <key=value>          Environment variable for --stdio subprocess (repeatable).

Check options:
  --timeout <ms>             Overall timeout in milliseconds. Default: 30000.
  --check-timeout <ms>       Per-check timeout in milliseconds. Default: 10000.
  --skip <check>             Skip a check (repeatable). Values: tools, resources, prompts.
  --min-tools <n>            Minimum expected tool count.
  --max-tools <n>            Maximum expected tool count.
  --min-resources <n>        Minimum expected resource count.
  --min-prompts <n>          Minimum expected prompt count.
  --max-latency <ms>         Maximum allowed latency per check.

Output options:
  --format <format>          Output format: human, json. Default: human.
  --quiet                    Suppress all output except the exit code.
  --verbose                  Show detailed check information.

Meta:
  --version                  Print version and exit.
  --help                     Print help and exit.

退出代码

代码 含义
0 健康。所有检查均已通过,所有阈值均已满足。
1 不健康。一个或多个必需的检查失败。
2 配置错误。标志无效、缺少传输或传输配置无效。
3 降级。所有必需的检查都通过了,但可选阈值或自定义检查失败。

环境变量

所有CLI标志都可以通过环境变量设置。显式CLI标志覆盖环境变量。

环境变量 等效标志
MCP_HEALTHCHECK_STDIO --stdio
MCP_HEALTHCHECK_URL --url
MCP_HEALTHCHECK_SSE --sse
MCP_HEALTHCHECK_TIMEOUT --timeout
MCP_HEALTHCHECK_CHECK_TIMEOUT --check-timeout
MCP_HEALTHCHECK_FORMAT --format
MCP_HEALTHCHECK_MIN_TOOLS --min-tools
MCP_HEALTHCHECK_MAX_TOOLS --max-tools
MCP_HEALTHCHECK_MIN_RESOURCES --min-resources
MCP_HEALTHCHECK_MIN_PROMPTS --min-prompts
MCP_HEALTHCHECK_MAX_LATENCY --max-latency
MCP_HEALTHCHECK_SKIP --skip (逗号分隔)

人类可读输出示例

$ mcp-healthcheck --stdio 'node ./server.js' --min-tools 2

  mcp-healthcheck v0.2.0

  Target: stdio -- node ./server.js
  Status: healthy

  PASS  connect         12ms   stdio transport connected
  PASS  initialize      45ms   protocol v2025-06-18, server: my-server v1.0.0
  PASS  tools           28ms   5 tools: search, create, update, delete, list
  PASS  resources       15ms   2 resources
  PASS  prompts          8ms   1 prompt

  Summary: 5/5 passed in 108ms

TypeScript

这个包是用TypeScript编写的,并附带了类型声明(dist/index.d.ts).所有公共类型都从主入口点导出:

import {
  checkHealth,
  isHealthy,
  createHttpHandler,
  // Types
  type HealthCheckOptions,
  type HealthReport,
  type HealthStatus,
  type CheckResult,
  type ConnectCheckResult,
  type InitializeCheckResult,
  type ToolsCheckResult,
  type ResourcesCheckResult,
  type PromptsCheckResult,
  type CustomCheckCheckResult,
  type TransportConfig,
  type StdioTransportConfig,
  type HttpTransportConfig,
  type SseTransportConfig,
  type Thresholds,
  type CustomCheckFn,
  type CustomCheckResult,
} from 'mcp-healthcheck';

需要TypeScript 5.0或更高版本。该包使用CommonJS模块编译为ES2022。


许可证

麻省理工学院