# MCP 注册表（src/openhuman/mcp\_registry/）

`src/openhuman/mcp_registry/` 是 **动态的、面向用户的** OpenHuman 的 Model Context Protocol 客户端支持的一半。它让用户能够浏览 Smithery.ai MCP 注册表、安装所选服务器、将该选择持久化到 SQLite，并且（对于作为本地子进程启动的服务器）监管子进程生命周期。已安装服务器的工具会通过统一工具注册表（`crate::openhuman::tool_registry`).

> **命名说明**：Rust 模块路径是 `mcp_registry`，但出于与现有前端代码和已存储用户状态的向后兼容性，RPC 命名空间和磁盘上的 SQLite 文件名仍然是 `mcp_clients` 。在追踪调用位置时，请同时搜索这两个名称。

该模块与 `src/openhuman/mcp_client/` 配套——即 **传输库** （HTTP + stdio 原语）以及 *静态的、在配置中声明的* 从以下位置读取的服务器集合 `[[mcp_client.servers]]` 位于 `config.toml`中。代理通过通用桥接工具访问该静态集合。该静态集合有意与这个动态注册表分离；这两类最终都会共享来自 `mcp_client`.

```
                 ┌───────────────────────────────────────────────┐
   Smithery.ai ──► registries/ + registry.rs（10 分钟 SQLite 缓存）│
                 └────────────────────┬──────────────────────────┘
                                      │ 浏览 / 安装
                                      ▼
                          ┌──────────────────────┐
   前端（Skills UI） ─►│  ops.rs / schemas.rs │  RPC 控制器
                          └──────────┬───────────┘
                                     │
                                     ▼
                          ┌──────────────────────┐
                          │      store.rs        │  mcp_clients.db（SQLite）
                          │  InstalledServer 行│
                          └──────────┬───────────┘
                                     │ 在启动时
                                     ▼
                          ┌──────────────────────┐
                          │       boot.rs        │  spawn_installed_servers
                          └──────────┬───────────┘
                                     │ 对每个本地启动项
                                     ▼
                          ┌──────────────────────┐
                          │   connections.rs     │  封装 mcp_client::
                          │  （全局注册表）   │  McpStdioClient
                          └──────────┬───────────┘
                                     │ 将工具暴露给
                                     ▼
                          tool_registry（代理）
```

## 服务器传输模型

目前每个 `InstalledServer` 都是一个 **本地子进程** 由 `npx`, `uvx`，或直接二进制文件启动（见 `types::CommandKind`）。连接是 **stdio JSON-RPC**，由 `connections.rs`.

HTTP 远程 MCP 服务器（Smithery 实际列出的绝大多数） **尚未被建模** 为一个 `InstalledServer` 变体。添加远程传输变体是计划中的后续工作；完成后，注册表将同时容纳两种类型，并且 `connections.rs` 将按传输方式进行分发。

## 启动时生成

`boot::spawn_installed_servers` 由 `bootstrap_core_runtime` 调用，因此每个本地启动的服务器都会在核心启动后立即连接。错误会按服务器分别记录日志，并且 **绝不会阻塞启动** ——损坏的 MCP 安装不应阻止桌面应用启动。

## 布局

| 路径                          | 角色                                                                                                                     |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `types.rs`                  | 数据结构： `InstalledServer`, `McpTool`, `ConnStatus`，Smithery DTO 等。                                                       |
| `store.rs`                  | SQLite 持久化—— `mcp_clients.db`，对 `InstalledServer` 行执行 CRUD。                                                            |
| `registry.rs`               | 带有 10 分钟 SQLite 缓存的 Smithery HTTP 客户端，因此重复浏览不会猛击上游注册表。                                                                 |
| `registries/`               | 用于此代码可浏览的上游注册表的适配器（当前为 Smithery）。                                                                                      |
| `connections.rs`            | 全局进程内连接注册表。封装了 `crate::openhuman::mcp_client::McpStdioClient` ——这里没有单独的 stdio 客户端实现。                                   |
| `boot.rs`                   | 启动时生成（`spawn_installed_servers`）由 `bootstrap_core_runtime`.                                                            |
| `setup.rs` / `setup_ops.rs` | “设置代理”支持——这个小型代理会引导用户完成新安装服务器的配置（环境变量、密钥、首次连接）。                                                                        |
| `ops.rs`                    | RPC 处理器实现（安装、卸载、列出、浏览、启用 / 禁用等）。                                                                                       |
| `schemas.rs`                | 控制器 schema + 处理器分发。从 `mod.rs` 重新导出为 `all_mcp_registry_controller_schemas` / `all_mcp_registry_registered_controllers`. |
| `bus.rs`                    | `DomainEvent` 订阅者，用于生命周期日志记录。                                                                                          |

## 公共接口

来自 `mod.rs` 的导出被有意保持得很窄：

```rust
pub use schemas::{
    all_controller_schemas as all_mcp_registry_controller_schemas,
    all_registered_controllers as all_mcp_registry_registered_controllers,
    schemas as mcp_registry_schemas,
};

pub use types::{ConnStatus, InstalledServer, McpTool};
```

其他所有内容—— `boot`, `bus`, `connections`, `store`, `setup`, `setup_ops` ——都是 `pub mod` ，供 crate 内调用方使用，但不会被重新导出。

## 调用到

* `crate::openhuman::mcp_client::McpStdioClient` ——实际的 stdio 传输。
* `crate::openhuman::tool_registry` ——已安装服务器的工具会落到这里，因此代理可以像看到原生工具一样看到它们。
* `memory_store` / 工作区 SQLite——用于 `mcp_clients.db` 持久化。
* Smithery.ai HTTP——注册表浏览。

## 由

* `bootstrap_core_runtime` 调用（通过 `boot::spawn_installed_servers`).
* 前端 Skills UI——（当前仍是占位实现的）MCP 服务器面板将通过 `ops.rs` 进行分发，基于 `openhuman.mcp_clients_*` RPC 命名空间。
* 位于 `setup_ops.rs` 中的设置代理——用于首次连接引导。

## 测试

单元测试以内联形式与代码放在一起，位于 `#[cfg(test)]` 块中，所在文件为 `store.rs`, `connections.rs`，以及 `setup.rs`。没有专门的 `*_tests.rs` 与每个文件对应的同级文件（该领域中的约定是内联）。

## 相关内容

* [`mcp_registry/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/mcp_registry/mod.rs) ——本页所镜像的权威 rustdoc。
* `src/openhuman/mcp_client/` ——传输库 + 静态配置声明的服务器集合。
* [Agent Harness](/openhuman/zh/kai-fa/architecture/agent-harness.md) ——代理如何最终通过 `tool_registry`.
* [架构概览](https://github.com/tinyhumansai/openhuman/blob/main/gitbooks/developing/architecture.md) ——它在更广泛系统中的位置。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tinyhumans.gitbook.io/openhuman/zh/kai-fa/architecture/mcp-registry.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
