开发工具MCP Clients调试器【免费下载链接】inspectorVisual testing tool for MCP servers项目地址https://gitcode.com/gh_mirrors/inspector1/inspector点击查看免费下载MCP Inspector 的 Web 形态是该项目三大客户端Web / CLI / TUI中功能最完整的一个一个纯展示层的Vite React Mantine单页应用SPA配上一个轻量的NodeHono后端。本文以 clients/web/README.md 为骨架结合仓库源码逐层讲解其双半区架构、构建产物、组件分层、自动化契约deep-link 与>npm run dev # Vite dev server Hono /api 中间件带 HMR该命令直接在当前客户端目录下运行。launcher 驱动的 prod/dev 流程npm run web/web:dev运行的是已构建的 launcher需先构建。构建npm run build # tsc -b → vite build → build:runner对应 clients/web/package.json 中的脚本链。构建产出两个工件都会随发布包一起发布dist/—— 浏览器 SPAvite build的产物由生产后端静态托管build/—— Node 生产服务器 runnerbuild:runnertsup --config tsup.runner.config.ts把server/inspector/core打包成一个 ESM 文件并 externalize npm 依赖。如果只需要新鲜的dist/build:client只跑vite build那一步。值得注意的构建细节vite.config.ts中内置了browserExternalizedBuiltinGate()插件apply: build且用applyToEnvironment限定在浏览器client环境它把 Vite 对 Node 内置模块的警告升级为硬错误——Vite 8 默认只警告并注入module.exports {}桩会让坏 bundle 以绿色状态构建通过所以该门禁把警告记录在onLog、在buildEnd抛出从而在构建期就拦截问题详见 clients/web/vite.config.ts。组件分层与lib/utils划分规则四层组件体系组件位于src/components/下从小到大分为四层层级数量内容elements/~31叶子展示件徽章、按钮、开关封装 Mantine 原语groups/~63复合件卡片、面板、弹窗、控制条screens/~11完整标签页Tools、Resources、Servers、监控屏……views/1InspectorView—— 组装各屏的顶层布局每个 screen 和 element 都配有*.stories.tsx见下文 Storybook 章节。样式遵循 AGENTS.md 中 Mantine-first 规则——优先用主题变体与组件 props而非 CSS用--inspector-*CSS 变量而非原始颜色。非组件代码src/libvssrc/utils两个杂货目录按一条规则切分utils 做计算的函数lib 实例化、适配或触碰环境的东西。凡是做 I/O 或包装某个子系统的归lib凡是纯变换的归utils。src/utils/—— 纯函数、无副作用无 DOM/window/sessionStorageI/O、不持有子系统无需 mock 即可单测。示例jsonUtils、schemaUtils、toolUtils、maskSecrets、inspectorTabs、deepLink、mcpNetworkHeaders。两个豁免保留在utils诊断日志console.warn/console.error不算副作用从inspector/coreimport—— 无论是 type-only import 还是 re-export core 的纯函数/常量都不构成子系统依赖让一个模块成为lib的是包装 core 的有状态运行时纯领域类型 构造函数customHeaders——lib/utils内不再细分types/子桶。src/lib/—— 基础设施/有状态适配器组合子系统、包装inspector/core运行时、或产生副作用的模块。示例environmentFactory、remoteOAuthStorage、oauthResumesessionStorage、browserTabVisibilityDOM 监听、clearServerOAuthState、downloadFile。顶层的src/types/是独立兄弟目录——存放 ambient.d.ts模块桩不是新领域类型的地方。需要说明的是没有任何机制强制这条边界——没有路径别名依赖它vite.config.ts的 coverageinclude同时列出两个目录所以在两者之间移动文件不影响覆盖率。它是一条给人阅读的 import 时信号。完整规则含白名单注意事项——放在components/lib/utils/server之外的模块会掉出 ≥90 门禁见 AGENTS.md。MCP Apps 屏自动化契约Apps 屏暴露了一小组稳定的data-testid/data-*属性使自动化驱动deep-link 自动打开、CI 审查 harness可以waitForSelector一个确定性信号而不是 sleep。这些属性是公开契约——驱动依赖它们保持稳定属性位置含义data-testidapps-formApps 内容卡片承载下面 status/error 属性的容器data-app-statusapps-form上渲染器生命周期idle未运行→loadingbridge 构建 /ui/initialize进行中→ready视图触发了notifications/initialized→errorbridge 工厂抛出/拒绝。轮询直到readydata-app-errorapps-form上当data-app-statuserror时的失败原因字符串如无已连接客户端否则不存在data-testidapps-error错误面板应用加载失败工厂 throw/reject时渲染在 frame 下方展示原因避免静默空白 framedata-testidopen-appOpen App 按钮启动选中的应用data-testidapps-stageStage-partial 按钮快照当前表单值用于渐进式渲染测试data-testidapps-messagesmessages 面板运行中视图提交的ui/messagedata-testidapps-logsapp-logs 面板notifications/message日志条目默认展开渲染器生命周期本身是AppRendererStatusloading|ready|error由AppRenderer的onAppStatusChange上报screen 将其映射为data-app-status。资源读取失败畸形/404 的 UI resource通过 bridge 工厂的onResourceError以 toast 形式暴露由于此时应用永远到不了ready驱动会在data-app-status上超时然后读取 toast。Deep-link 自动连接launcher、CLI--print-handoff、CI 审查 harness 等驱动可以用一次导航直达一个已连接的 inspector——把目标编码进 URL 查询串即可。解析 安全门控实现在src/utils/deepLink.tsparseDeepLink返回的DeepLink即证明链接通过了校验http://127.0.0.1:6274/?serverUrlurltransporthttp|sseautoConnecttoken参数含义serverUrlMCP 服务器 URL。限定http:/https:构造的javascript:/data:/file:值会被拒绝。通过URL.href规范化使其与 OAuth store 的键形式一致transporthttpstreamable-HTTP默认或sse。未知值回退到httpautoConnectCSRF 门禁。必须等于本次启动的MCP_INSPECTOR_API_TOKEN。token 每次启动随机、只有启动服务器的一方知道因此第三方铸造的链接无法满足校验——这与既有?MCP_INSPECTOR_API_TOKEN参数的暴露面相同。不匹配则链接被忽略从源码看clients/web/src/utils/deepLink.tsparseDeepLink只有在serverUrl与autoConnect都存在且 token 匹配时才继续解析transport走白名单集合{http,sse}未知值一律落到http生成streamable-http类型的MCPServerConfig。validateServerUrl只放行 http/https 协议并返回URL.href规范化结果——这正是 OAuth store 记录 URL 的形式保证 Web 保存的 token 能被 CLI 的--use-stored-auth找到反之亦然。appArgs的解码则把 base64url 转回 base64 后JSON.parse任何畸形值都安全回退为{}。deep link 会 upsert 一条稳定的deep-link目录行重载时重连到同一行而不是累积重复项再连接。连接级结果以机器可读契约暴露在AppShell.Header上驱动无需抓取易失的 toast 即可waitForSelector读取失败原因属性位置含义data-testidconnection-statusheader承载下面属性的元素data-statusconnection-status上实时ConnectionStatusdisconnected→connecting→connected/error。轮询直到connecteddata-error-messageconnection-status上上次连接失败的原因握手错误、OAuth 启动失败、deep-link 自动化失败无错误时不存在data-deeplinkconnection-status上parsed有效 deep link 驱动了本次加载、rejected存在 deep-link 参数但 token/serverUrl 门控失败、或none。让驱动区分没有 deep link与被拒绝——两者在data-status上看起来都是 idle直达已渲染的应用另外三个参数把 deep link 扩展为预选——并可选自动打开——一个 MCP App让驱动零点击直达渲染后的 widget…openApptoolNameappArgsbase64url(JSON)autoOpentoken参数含义openAppapp-tool 名称。连接建立且工具出现在 app 列表后inspector 切到 Apps 标签页并预选它appArgsbase64url(JSON)的表单值对象。叠加在工具 schema 默认值之上collectSchemaDefaults避免必填且有默认值的字段留空——那会禁用 Open App。畸形/非对象值回退为{}autoOpen与autoConnect相同的 CSRF 门禁——必须等于会话 token。设置后 Open App 自动触发从 URL 发起一次工具调用因此 token 门禁是强制的。不匹配则应用只预选不打开应用侧的渲染生命周期可以通过上文 MCP Apps screen automation contract 观测data-app-statusready因此驱动可以对整条connect → open → ready链路做确定性的waitForSelector。主题体系src/theme/每个自定义过的 Mantine 组件都有一个ThemeName.ts文件Button.ts、Text.ts……约 21 个导出一个ThemeName常量barrel 文件index.ts统一 re-exporttheme.ts组装成MantineProvider主题。主题文件持有应用级默认值与变体扁平 CSS-in-JS只有伪选择器、嵌套子选择器、keyframes 和原生 HTML 样式才属于App.css。元素组件从mantine/coreimport永不从theme/import——主题层由 provider 透明应用。测试体系三个 Vitest projects测试在三个 Vitestproject下运行配置见 clients/web/vite.config.ts各用合适的环境Project环境范围脚本unithappy-dom组件、hooks、utils源码旁的*.test.tsxnpm testintegrationnodeinspector/core transports authspawn 真实的 stdio 测试服务器src/test/integration/**npm run test:integrationstorybook真实 ChromiumStoryplay functions作为交互测试npm run test:storybooknpm test跑快速的unitprojecthappy-domtest:watch用于循环开发。Integration测试跑在真实 Node 环境无 happy-dom30 秒超时并把test-servers/build/test-server-stdio.js作为子进程 spawn所以pretest/coverage 脚本需要先构建测试服务器test-servers:build对应 package.json 中的pretest钩子。npm run test:coverage在 v8 插桩下同时跑 unit 与 integration并强制每个文件 ≥90%lines/statements/functions/branches的门禁——与 CI 跑的门禁一致。真正不可达的分支用有理由的/* v8 ignore … */注释标注而不是放水。Integration 测试位于src/test/integration/镜像core/的布局放在其中的任何东西都会自动被integrationproject 拾取。渲染组件请用renderWithMantineclients/web/src/test/renderWithMantine.tsx以获得项目主题。Storybook一等公民npm run storybook # :6006 上的 dev server npm run build:storybook # 静态构建 npm run test:storybook # 在无头 Chromium 中运行每个 story 的 play functionStorybook 在这里是一等公民因为组件是展示型的——每个组件都针对 fixture props 渲染。Play functions 兼作交互测试通过vitest/browser-playwrightstorybook/addon-viteststorybookVitest project在真实 Chromium 中无头运行。它们是npm run ci的一部分ci 会先安装 Chromium 二进制但由于需要浏览器被排除在快速的validate循环之外。鉴权 token开发/生产后端用x-mcp-remote-auth: Bearer MCP_INSPECTOR_API_TOKEN保护每个/api/*路由。浏览器按优先级恢复 token见App.tsx的getAuthToken()window.__INSPECTOR_API_TOKEN__全局变量——每次页面加载时注入index.htmlclients/web/server/inject-auth-token.ts?MCP_INSPECTOR_API_TOKEN…查询参数sessionStorage。从源码看注入逻辑把 token 用JSON.stringify序列化并额外转义\u003c防止用户提供的 token 含字面/script时提前闭合标签脚本被放在/head前兜底/body前或直接前置保证在应用 bundle 执行前全局变量已就位。DANGEROUSLY_OMIT_AUTH禁用鉴权时注入是 no-op页面原样返回、不定义全局变量。生产服务器clients/web/server/server.ts对/与所有 SPA fallback 路径如/oauth/callback返回的index.html都做注入并带Cache-Control: no-store避免浏览器/代理在服务器重启换 token 后继续缓存携带旧 token 的页面。主机绑定与来源白名单生产后端web-server-config.ts与开发 Vite servervite.config.ts都通过同一个共享守卫server/resolve-bind-host.ts解析绑定主机。它默认绑定localhost并拒绝所有网卡主机0.0.0.0、::、空值及一切等价拼写——0、0x0、0.0、::0、::ffff:0.0.0.0……都会被折叠为通配符并拒绝——那会把进程衍生型后端暴露给整个网络正是 DNS-rebinding 攻击瞄准的暴露面——除非设置DANGEROUSLY_BIND_ALL_INTERFACEStrue。Docker 镜像设置了这个标志容器必须绑定0.0.0.0才能通过-p被访问其他任何地方的裸HOST0.0.0.0都会以可操作的错误信息退出。后端的/api/*路由还强制一个来源白名单allowedOrigins作为 DNS-rebinding 防护。默认情况下在 loopback 主机上它会展开为该端口三种可互换的 loopback 来源形式——http://localhost:PORT、http://127.0.0.1:PORT、http://[::1]:PORT——因为localhost可能解析为 IPv4 或 IPv6 loopback且 Node/Vite 可能绑定 IPv6 形式所以浏览器可能合法地到达http://[::1]:PORT。设置ALLOWED_ORIGINS逗号分隔可覆盖条目会被规范化new URL(o).origin因此尾斜杠/大写主机/显式:80仍然匹配。每条必须包含 scheme——http://localhost:6274而不是localhost:6274无 scheme 的值会被丢弃并告警。ALLOWED_ORIGINS替换默认列表不合并所以把你浏览会用到的每个 origin 都列全包括仍需要的 loopback 形式http://localhost:PORT、http://127.0.0.1:PORT、http://[::1]:PORT——否则本地访问会失效。空的ALLOWED_ORIGINS不会禁用检查——它回退到默认fail closed没有任何环境变量能关掉 origin 校验。从web-server-config.ts的源码看白名单解析会对每个条目做new URL(o).origin规范化并明确拒绝三类会削弱防护的输入opaque originorigin null无 scheme 条目如localhost:6274会被解析成 scheme、含*的通配条目、以及非 http(s) scheme浏览器在任何请求——包括 WebSocket 握手——上的Origin都是页面自身的 http(s) originws://条目永远不可能匹配。当配置结果为空时回退到defaultAllowedOrigins()绝不是[]——后者在 origin 中间件里被解释为允许一切会静默关掉防护。defaultAllowedOrigins按绑定主机分支loopback 三连、通配符0.0.0.0绑定额外加http://0.0.0.0:PORT与http://[::]:PORT、或特定主机时输出该主机唯一规范化 origin。部署到网络上守卫只拦截通配符所有网卡地址。绑定特定IP 或主机名无需 opt-in——那是单一、有意的暴露不同于一次绑定所有网卡的通配符DNS-rebinding 利用的模式。要把 Inspector 服务到局域网或公网绑定特定地址。HOST192.168.1.50LAN IP或公网 IP 直接可用默认 origin 白名单跟随绑定主机allowedOrigins变为http://该主机:PORT浏览器访问该地址无需额外配置即可通过。主机按浏览器方式规范化——HOST127.1会广播为http://127.0.0.1:PORTIPv6 绑定主机会加方括号http://[2001:db8::1]:PORThttp 默认端口:80时省略——与浏览器实际发送的一致。在 TLS 或反向代理后面浏览器的Origin变成公共 origin如https://inspector.example.com通常无端口无法匹配自动推导的http://bind-host:PORT。把ALLOWED_ORIGINS设为真实公共 originALLOWED_ORIGINShttps://inspector.example.com。使用0.0.0.0通配符通过DANGEROUSLY_BIND_ALL_INTERFACEStrueopt-inDocker 镜像即如此通配符绑定同样服务 loopback因此默认白名单是 loopback 三连加规范通配符 originhttp://0.0.0.0:PORT、http://[::]:PORT本地访问开箱即用——docker run -p 127.0.0.1:6274:6274后在http://localhost:6274浏览无需额外配置。但在非 loopback地址LAN IP、公共主机名访问仍需ALLOWED_ORIGINS——由于它替换默认如果还要本地浏览请把 loopback 形式保留在列表中ALLOWED_ORIGINShttp://localhost:PORT,http://127.0.0.1:PORT,http://192.168.1.50:PORT,https://inspector.example.com。绑定主机守卫与ALLOWED_ORIGINS白名单同时作用于生产服务器和--dev。注意在--dev下 Vite dev server额外执行自己的server.allowedHostsHost 头检查其默认接受 loopback 和 IP 字面量主机。你绑定的主机自动放行Vite 会把解析后的server.host——本配置中来自HOST——加入白名单所以HOSThostname在--dev下也开箱即用。需要显式server.allowedHosts条目的是以不同于绑定名的名字访问 dev server——例如通配符绑定后用主机名访问或反向代理域名。这种情况建议优先用生产服务器mcp-inspector --web或把主机加进server.allowedHosts。MCP Apps 注意事项。MCP Apps 沙箱运行在独立端口MCP_SANDBOX_PORT默认动态分配。要在 loopback 之外使用 Apps 标签页该沙箱端口必须能从浏览器独立到达——用MCP_SANDBOX_PORT固定它并同样暴露/转发Docker 镜像只EXPOSE了6274。在0.0.0.0通配符绑定下沙箱 URL 被广播为localhost这是可达的——通配符绑定服务 loopback——所以只需处理端口。此外沙箱 iframe 受frame-ancestorsCSP 约束带方括号的 IPv6 字面量不是合法的 CSP host-source——所以 MCP Apps 要求以名字或 IPv4 浏览应用localhost、127.0.0.1、主机名、LAN IPv4不能用裸http://[::1]:…地址。最后沙箱 URL 永远是http://——因此在TLS 之后https://应用页面浏览器会以混合内容为由阻止http://…/sandboxiframeMCP Apps 无法渲染目前 Apps 标签页需要纯http的应用 origin。每种情况下把 Inspector 暴露到 loopback 之外都意味着能访问它的人就能驱动它的后端——请保持鉴权开启不要设置DANGEROUSLY_OMIT_AUTH并优先绑定特定地址而非通配符。HTTP 代理支持Web 后端通过共享的 Node transportcore/mcp/node/transport.ts连接远程 MCP 服务器该 transport 遵循常规代理环境变量HTTPS_PROXY/HTTP_PROXY及其小写形式选择代理NO_PROXY豁免主机。路由由undici。小结MCP Inspector Web Client 的设计可以浓缩为三个关键词展示层 SPA 状态后端浏览器只渲染、Node 只接线、面向自动化的机器可读契约deep-link 参数、data-testid/data-*属性、以及默认收紧的安全姿态localhost-only 绑定、origin 白名单、per-launch API token 的 CSRF 门禁。理解了src/与server/的分工、构建双产物的意义、以及ALLOWED_ORIGINS与绑定主机的联动规则就能在本地开发、CI 自动化、乃至 LAN/Docker 部署三个场景下自如驾驭这套体系。赞分享开发工具MCP Clients调试器【免费下载链接】inspectorVisual testing tool for MCP servers项目地址https://gitcode.com/gh_mirrors/inspector1/inspector点击查看免费下载相关推荐WLED PWM Outputs 用户插件实战在 ESP32 上扩展通用 PWM 输出与 JSON 控制接口WLED PWM Outputs 用户插件实战在 ESP32 上扩展通用 PWM 输出与 JSON 控制接口 本篇指南基于 WLED 仓库中 PWM outp开发工具MCP Clients调试器组件测试必查项组件测试必查项 渲染正确性默认状态、加载状态、空状态、错误状态 交互响应点击、输入、选择等用户操作 状态管理props变化、context变化、状态更开发工具MCP Clients调试器Czkawka 免费磁盘清理教程一条命令扫描重复文件与 14 类冗余快速释放硬盘空间Czkawka 免费磁盘清理教程一条命令扫描重复文件与 14 类冗余快速释放硬盘空间 把几百 GB 素材备份到磁盘后系统突然提示空间不足却分不清哪些文件后端MCP 服务MCP ClientsAI Agent人工智能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
