mcporter — 安装部署及使用完全指南(四)

十、MCP 桥接模式

mcporter serve 将守护进程管理的 keep-alive 服务器重新暴露为一个统一的 MCP 服务器,让不支持 HTTP 的客户端也能使用。

10.1 stdio 桥接

bash 复制代码
mcporter serve --stdio

适用于 Claude CodeCodex 等仅支持 stdio 的客户端。所有 keep-alive 服务器的工具以 server__tool 的命名空间形式暴露。

10.2 HTTP 桥接

bash 复制代码
mcporter serve --http 3000
端点 说明
http://127.0.0.1:3000/mcp 聚合端点,工具名:chrome-devtools__list_pages
http://127.0.0.1:3000/mcp/<server> 单服务器端点,保留原始工具名

10.3 桥接架构

#mermaid-svg-D6fFgHhukuLI5huJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-D6fFgHhukuLI5huJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-D6fFgHhukuLI5huJ .error-icon{fill:#552222;}#mermaid-svg-D6fFgHhukuLI5huJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-D6fFgHhukuLI5huJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-D6fFgHhukuLI5huJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-D6fFgHhukuLI5huJ .marker.cross{stroke:#333333;}#mermaid-svg-D6fFgHhukuLI5huJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-D6fFgHhukuLI5huJ p{margin:0;}#mermaid-svg-D6fFgHhukuLI5huJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-D6fFgHhukuLI5huJ .cluster-label text{fill:#333;}#mermaid-svg-D6fFgHhukuLI5huJ .cluster-label span{color:#333;}#mermaid-svg-D6fFgHhukuLI5huJ .cluster-label span p{background-color:transparent;}#mermaid-svg-D6fFgHhukuLI5huJ .label text,#mermaid-svg-D6fFgHhukuLI5huJ span{fill:#333;color:#333;}#mermaid-svg-D6fFgHhukuLI5huJ .node rect,#mermaid-svg-D6fFgHhukuLI5huJ .node circle,#mermaid-svg-D6fFgHhukuLI5huJ .node ellipse,#mermaid-svg-D6fFgHhukuLI5huJ .node polygon,#mermaid-svg-D6fFgHhukuLI5huJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-D6fFgHhukuLI5huJ .rough-node .label text,#mermaid-svg-D6fFgHhukuLI5huJ .node .label text,#mermaid-svg-D6fFgHhukuLI5huJ .image-shape .label,#mermaid-svg-D6fFgHhukuLI5huJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-D6fFgHhukuLI5huJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-D6fFgHhukuLI5huJ .rough-node .label,#mermaid-svg-D6fFgHhukuLI5huJ .node .label,#mermaid-svg-D6fFgHhukuLI5huJ .image-shape .label,#mermaid-svg-D6fFgHhukuLI5huJ .icon-shape .label{text-align:center;}#mermaid-svg-D6fFgHhukuLI5huJ .node.clickable{cursor:pointer;}#mermaid-svg-D6fFgHhukuLI5huJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-D6fFgHhukuLI5huJ .arrowheadPath{fill:#333333;}#mermaid-svg-D6fFgHhukuLI5huJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-D6fFgHhukuLI5huJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-D6fFgHhukuLI5huJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D6fFgHhukuLI5huJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-D6fFgHhukuLI5huJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D6fFgHhukuLI5huJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-D6fFgHhukuLI5huJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-D6fFgHhukuLI5huJ .cluster text{fill:#333;}#mermaid-svg-D6fFgHhukuLI5huJ .cluster span{color:#333;}#mermaid-svg-D6fFgHhukuLI5huJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-D6fFgHhukuLI5huJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-D6fFgHhukuLI5huJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-D6fFgHhukuLI5huJ .icon-shape,#mermaid-svg-D6fFgHhukuLI5huJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D6fFgHhukuLI5huJ .icon-shape p,#mermaid-svg-D6fFgHhukuLI5huJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-D6fFgHhukuLI5huJ .icon-shape .label rect,#mermaid-svg-D6fFgHhukuLI5huJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D6fFgHhukuLI5huJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-D6fFgHhukuLI5huJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-D6fFgHhukuLI5huJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🌉 mcporter serve
🖥️ MCP 客户端
👻 Keep-Alive 守护进程
Chrome DevTools
Playwright
Linear API
Claude Code

(stdio)
自定义 Agent

(HTTP)
--stdio
--http 3000

10.4 仅暴露指定服务器

bash 复制代码
mcporter serve --http 3000 --servers chrome-devtools,playwright

10.5 Chrome DevTools 扩展中继

当使用 chrome-devtools-mcp --autoConnect 时,Chrome 的远程调试握手可能每次会话都弹出 "Allow remote debugging?" 对话框。如果同一主机上配对了 OpenClaw Chrome 扩展中继,mcporter 可以使用扩展支持的 Chrome 控制路径代替。

配置选项

策略 行为
prefer(默认) 优先使用 v2 扩展中继,失败时回退到原始 Chrome --autoConnect
require 强制使用 v2 扩展中继,任何失败都直接报错
off 禁用中继探测,使用原始 auto-connect
jsonc 复制代码
{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "chrome-devtools-mcp@latest", "--autoConnect"],
      "lifecycle": "keep-alive",
      "chromeDevtoolsRelay": "require"
    }
  }
}

十一、代理技能模式

11.1 核心理念

🎯 推荐为每个 MCP 服务器或工作流编写一个小型技能文件,而非一个通用技能。

一个通用技能必须教会代理如何发现、选择和调用每个配置的服务器------这重现了 mcporter 试图避免的大型 Schema 上下文问题。per-server 技能保持精简,让技能作者描述该服务器的安全、有用的工作流。

11.2 推荐工作流

#mermaid-svg-nSsaJwq6uWwVSht1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nSsaJwq6uWwVSht1 .error-icon{fill:#552222;}#mermaid-svg-nSsaJwq6uWwVSht1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nSsaJwq6uWwVSht1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nSsaJwq6uWwVSht1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nSsaJwq6uWwVSht1 .marker.cross{stroke:#333333;}#mermaid-svg-nSsaJwq6uWwVSht1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nSsaJwq6uWwVSht1 p{margin:0;}#mermaid-svg-nSsaJwq6uWwVSht1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster-label text{fill:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster-label span{color:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster-label span p{background-color:transparent;}#mermaid-svg-nSsaJwq6uWwVSht1 .label text,#mermaid-svg-nSsaJwq6uWwVSht1 span{fill:#333;color:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 .node rect,#mermaid-svg-nSsaJwq6uWwVSht1 .node circle,#mermaid-svg-nSsaJwq6uWwVSht1 .node ellipse,#mermaid-svg-nSsaJwq6uWwVSht1 .node polygon,#mermaid-svg-nSsaJwq6uWwVSht1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nSsaJwq6uWwVSht1 .rough-node .label text,#mermaid-svg-nSsaJwq6uWwVSht1 .node .label text,#mermaid-svg-nSsaJwq6uWwVSht1 .image-shape .label,#mermaid-svg-nSsaJwq6uWwVSht1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-nSsaJwq6uWwVSht1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nSsaJwq6uWwVSht1 .rough-node .label,#mermaid-svg-nSsaJwq6uWwVSht1 .node .label,#mermaid-svg-nSsaJwq6uWwVSht1 .image-shape .label,#mermaid-svg-nSsaJwq6uWwVSht1 .icon-shape .label{text-align:center;}#mermaid-svg-nSsaJwq6uWwVSht1 .node.clickable{cursor:pointer;}#mermaid-svg-nSsaJwq6uWwVSht1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nSsaJwq6uWwVSht1 .arrowheadPath{fill:#333333;}#mermaid-svg-nSsaJwq6uWwVSht1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nSsaJwq6uWwVSht1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nSsaJwq6uWwVSht1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nSsaJwq6uWwVSht1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nSsaJwq6uWwVSht1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nSsaJwq6uWwVSht1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster text{fill:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 .cluster span{color:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nSsaJwq6uWwVSht1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nSsaJwq6uWwVSht1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-nSsaJwq6uWwVSht1 .icon-shape,#mermaid-svg-nSsaJwq6uWwVSht1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nSsaJwq6uWwVSht1 .icon-shape p,#mermaid-svg-nSsaJwq6uWwVSht1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nSsaJwq6uWwVSht1 .icon-shape .label rect,#mermaid-svg-nSsaJwq6uWwVSht1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nSsaJwq6uWwVSht1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nSsaJwq6uWwVSht1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nSsaJwq6uWwVSht1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. 添加/导入 MCP 服务器
2. 检查工具表面
3. 编写小型技能文件
4. 调用相关工具
5. 需要分享?生成专用 CLI

11.3 技能文件示例

markdown 复制代码
---
name: docs-mcp
description: Fetch package and framework docs through the configured docs MCP server.
---

# 📚 Docs MCP

Use `npx mcporter call docs.resolve-library-id query=<task> libraryName=<name>` to resolve a package,
then call `npx mcporter call docs.query-docs ...` with the resolved ID and docs query.

11.4 完整步骤示例

bash 复制代码
# 1. 添加 MCP 服务器
npx mcporter config add docs https://mcp.context7.com/mcp --scope home

# 2. 检查工具表面
npx mcporter list docs --brief
npx mcporter list docs --schema

# 3. 编写技能文件(见上方示例)
# 4. 在 Agent 中使用技能文件

# 5. 对于可分享工作流,生成专用 CLI
npx mcporter generate-cli docs --bundle dist/docs-mcp.js

11.5 工具过滤

使用 allowedToolsblockedTools 限制暴露给代理的工具:

jsonc 复制代码
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "allowedTools": ["search_repositories", "get_file_contents"]
    }
  }
}

十二、TypeScript 运行时 API

12.1 创建服务器代理(推荐)

createServerProxy() 将 MCP 工具名映射为 camelCase 方法,自动应用 JSON Schema 默认值,验证必填参数,返回带有 .text().markdown().json().images().content() 辅助方法的 CallResult

typescript 复制代码
import { createServerProxy } from "mcporter";

const proxy = await createServerProxy("linear");

const result = await proxy.createIssue({
  title: "Bug report",
  team: "ENG",
});

// 多种输出格式
console.log(result.text());       // 纯文本
console.log(result.markdown());   // Markdown
console.log(result.json());       // JSON
console.log(result.images());     // 图片数组
console.log(result.content());    // 原始内容

12.2 一次性调用

callOnce() 处理单次调用和清理,适合脚本场景:

typescript 复制代码
import { callOnce } from "mcporter";

const result = await callOnce("linear", "createIssue", {
  title: "Bug report",
  team: "ENG",
});

console.log(result.text());

12.3 底层运行时

createRuntime() 当你需要显式控制服务器定义、连接复用或多个调用时:

typescript 复制代码
import { createRuntime } from "mcporter";

const runtime = await createRuntime({
  servers: [{
    name: "context7",
    command: {
      kind: "http",
      url: new URL("https://mcp.context7.com/mcp")
    }
  }],
});

try {
  const tools = await runtime.listTools("context7");
  console.log(tools.map((tool) => tool.name));
} finally {
  await runtime.close();
}

12.4 API 对比

API 适用场景 连接管理
createServerProxy() 大多数场景,类型友好的方法调用 自动管理
callOnce() 单次调用脚本 自动创建和关闭
createRuntime() 复杂场景,需要精细控制 手动 runtime.close()

十三、日志与诊断

13.1 守护进程日志

bash 复制代码
# 启动守护进程并记录日志
mcporter daemon start --log

# 指定日志文件
mcporter daemon start --log --log-file /path/to/log

# 限制日志范围到特定服务器
mcporter daemon start --log --log-servers chrome-devtools,playwright

13.2 环境变量日志级别

bash 复制代码
# 查看结构化连接决策日志
MCPORTER_LOG_LEVEL=info mcporter list

13.3 调试挂起调用

mcporter call 打印了工具响应但进程永不退出时,通常是 Node 仍有活跃句柄在等待(最常见的是子进程 MCP 服务器保持 stdio 传输存活)。

快速检查清单

  1. 在 tmux 中运行 --- 启动命令在 tmux 中,这样即使 Cursor 或其他代理超时,你也能检查面板内容
  2. 启用挂起诊断 --- 设置 MCPORTER_DEBUG_HANG=1
  3. 检查句柄列表 --- 查找 ChildProcess (pid=...) 条目
  4. 捕获面板输出 --- tmux capture-pane -p -t <session> -S -200
  5. 使用 --timeout --- 如果工具本身挂起,设置超时快速失败
  6. 限制 OAuth 等待 --- --oauth-timeout <ms>MCPORTER_OAUTH_TIMEOUT_MS

示例诊断会话

bash 复制代码
tmux new-session -d -s mcphang   'cd /path/to/project &&    MCPORTER_DEBUG_HANG=1    mcporter call chrome-devtools list_pages'

sleep 5
tmux capture-pane -p -t mcphang -S -200

典型诊断输出

text 复制代码
[mcporter] [debug] after call (object result): 6 active handle(s), 0 request(s)
[mcporter] [debug] handle => ChildProcess (pid=78480)
[mcporter] [debug] beginning runtime.close()
[mcporter] [debug] after runtime.close: 6 active handle(s), 0 request(s)
[mcporter] [debug] forcibly killed child pid=78480 (runtime.finally)

💡 CLI 默认在清理后强制 process.exit(0),防止 Node 在泄漏句柄上挂起。调试时设置 MCPORTER_NO_FORCE_EXIT=1 保持进程存活。

13.4 Stdio 服务器日志

Stdio 服务器的 stderr 输出默认被抑制。设置以下环境变量查看:

bash 复制代码
MCPORTER_STDIO_LOGS=1 mcporter call <server>.<tool>

当子进程以非零状态退出时,其日志也会自动显示。


十四、最佳实践

14.1 项目 vs 机器层配置

#mermaid-svg-OfQkGLRrN2xRuTgs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OfQkGLRrN2xRuTgs .error-icon{fill:#552222;}#mermaid-svg-OfQkGLRrN2xRuTgs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OfQkGLRrN2xRuTgs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OfQkGLRrN2xRuTgs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OfQkGLRrN2xRuTgs .marker.cross{stroke:#333333;}#mermaid-svg-OfQkGLRrN2xRuTgs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OfQkGLRrN2xRuTgs p{margin:0;}#mermaid-svg-OfQkGLRrN2xRuTgs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster-label text{fill:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster-label span{color:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster-label span p{background-color:transparent;}#mermaid-svg-OfQkGLRrN2xRuTgs .label text,#mermaid-svg-OfQkGLRrN2xRuTgs span{fill:#333;color:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs .node rect,#mermaid-svg-OfQkGLRrN2xRuTgs .node circle,#mermaid-svg-OfQkGLRrN2xRuTgs .node ellipse,#mermaid-svg-OfQkGLRrN2xRuTgs .node polygon,#mermaid-svg-OfQkGLRrN2xRuTgs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OfQkGLRrN2xRuTgs .rough-node .label text,#mermaid-svg-OfQkGLRrN2xRuTgs .node .label text,#mermaid-svg-OfQkGLRrN2xRuTgs .image-shape .label,#mermaid-svg-OfQkGLRrN2xRuTgs .icon-shape .label{text-anchor:middle;}#mermaid-svg-OfQkGLRrN2xRuTgs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OfQkGLRrN2xRuTgs .rough-node .label,#mermaid-svg-OfQkGLRrN2xRuTgs .node .label,#mermaid-svg-OfQkGLRrN2xRuTgs .image-shape .label,#mermaid-svg-OfQkGLRrN2xRuTgs .icon-shape .label{text-align:center;}#mermaid-svg-OfQkGLRrN2xRuTgs .node.clickable{cursor:pointer;}#mermaid-svg-OfQkGLRrN2xRuTgs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OfQkGLRrN2xRuTgs .arrowheadPath{fill:#333333;}#mermaid-svg-OfQkGLRrN2xRuTgs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OfQkGLRrN2xRuTgs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OfQkGLRrN2xRuTgs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OfQkGLRrN2xRuTgs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OfQkGLRrN2xRuTgs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OfQkGLRrN2xRuTgs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster text{fill:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs .cluster span{color:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OfQkGLRrN2xRuTgs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OfQkGLRrN2xRuTgs rect.text{fill:none;stroke-width:0;}#mermaid-svg-OfQkGLRrN2xRuTgs .icon-shape,#mermaid-svg-OfQkGLRrN2xRuTgs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OfQkGLRrN2xRuTgs .icon-shape p,#mermaid-svg-OfQkGLRrN2xRuTgs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OfQkGLRrN2xRuTgs .icon-shape .label rect,#mermaid-svg-OfQkGLRrN2xRuTgs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OfQkGLRrN2xRuTgs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OfQkGLRrN2xRuTgs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OfQkGLRrN2xRuTgs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🔄 CI/CD
📁 项目层(纳入版本控制)
config/mcporter.json
schema 引用 {LINEAR_API_KEY}

环境变量占位符
🖥️ 机器层(不纳入版本控制)
~/.mcporter/mcporter.json
OAuth 令牌

~/.mcporter/credentials.json
~/.mcporter/local.json

机器特定配置
--config config/mcporter.json

14.2 配置管理清单

实践 说明
✅ 版本控制 config/mcporter.json 纳入版本控制
✅ 敏感数据 使用环境变量(${LINEAR_API_KEY})而非内联密钥
✅ 预注册 OAuth 配置中存储公开的 oauthClientId,使用 oauthClientSecretEnv 指向本地环境变量
✅ 机器特定配置 放在 ~/.mcporter/local.json,使用 --config 指定
✅ CI 环境 始终传递 --config config/mcporter.json 确保确定性行为
❌ 不提交令牌 OAuth 令牌保留在 ~/.mcporter/...XDG_*_HOME/mcporter/...绝不纳入仓库

14.3 安全建议

  1. 非 HTTPS 端点 :仅在内网使用 --allow-http,生产环境始终使用 HTTPS
  2. Stdio 命令确认:首次遇到新 stdio 命令时,mcporter 会打印确认摘要,仔细审查
  3. 工具白名单 :对于暴露敏感操作的服务器,使用 allowedTools 限制可用工具
  4. 令牌刷新 :使用 refreshable_bearer 自动管理令牌生命周期,避免手动更新

十五、故障排除

15.1 常见问题速查

问题 原因 解决方案
🔴 环境占位符缺失 配置中使用了 ${VAR} 但环境变量未设置 添加环境变量,或使用 ${VAR:-fallback} 提供默认值
🔴 配置来源不明 不确定服务器从哪个配置文件加载 mcporter config get <name> 显示服务器来源和完整路径
🔴 导入冲突 多个编辑器配置了同名服务器 重新排序 imports 数组,或设为 [] 禁用所有导入
🔴 OAuth 问题 浏览器流程失败或无头环境 mcporter auth <name> --no-browser 在无头环境完成认证
🔴 守护进程问题 连接状态异常 mcporter daemon status 查看状态,mcporter daemon restart 重启
🔴 调用挂起 子进程未正确退出 使用 --timeout,或 MCPORTER_DEBUG_HANG=1 诊断
🔴 EADDRINUSE 端口 localhost:3334 被占用 检查是否有其他 mcporter 实例在运行

15.2 诊断命令速查

bash 复制代码
# 查看 mcporter 版本
mcporter --version

# 查看服务器来源和配置
mcporter config get <server-name>

# 查看守护进程状态
mcporter daemon status

# 启用挂起诊断
MCPORTER_DEBUG_HANG=1 mcporter call <server>.<tool>

# 查看 stdio 服务器日志
MCPORTER_STDIO_LOGS=1 mcporter call <server>.<tool>

# 结构化日志输出
MCPORTER_LOG_LEVEL=info mcporter list

# 验证配置
mcporter config doctor
相关推荐
手写码匠1 小时前
华为云Flexus+DeepSeek征文|Dify 多 Agent 评测实战:用 DeepSeek-R1 当裁判,打造多智能体系统的自动化质量保障体系
人工智能·深度学习·算法·aigc
MartinYeung51 小时前
[论文学习]JBShield:通过激活概念分析与操纵防御大语言模型越狱攻击
人工智能·学习·语言模型
ZJU_统一阿萨姆1 小时前
【推理优化】KV Cache 量化:在不牺牲质量的前提下压榨更多内存
人工智能·语言模型·系统架构·vllm
安逸sgr1 小时前
Dropout 和正则化:深度学习如何缓解过拟合?
人工智能·ai·大模型·agent·智能体
weixin_446260851 小时前
Intern-S2-Preview:面向科学智能的智能体基础大模型
人工智能
汽车仪器仪表相关领域1 小时前
SIRIUS R1DB/R2DB便携式一体化数据采集系统
大数据·人工智能·功能测试·深度学习·压力测试
MartinYeung51 小时前
[论文学习]SMSR:带平滑检索的签名记忆——针对持久化LLM智能体系统运行时内存投毒的认证防御
人工智能·学习
147API1 小时前
蒸馏模型数据漂移怎么监控,从输入变化到回归验证
人工智能·数据挖掘·回归
Co_zy1 小时前
从Manus看AI Agent云端沙箱:技术演进与底层实现解析
agent·沙箱·sandbox·manus