提示：McpClientProvider 内部有长链接，适合用单例方式（或者用完显示调用 close 关闭）。

---

McpClientProvider（Mcp 客户端提供者），同时也提供 Tool、Prompt、Resource 三种内容。支持心跳机制和“断线重连”机制。对应的配置属性实体为 McpClientProperties。

配置属性 McpClientProperties：


| 属性                          | 默认值                            | 说明              |
| ----------------- | -------------------- | ----------- |
| name                                    | `Solon-Mcp-Client`     | 客户端名称     |
| version                                  | `1.0.0`                        | 客户端版本号   |
| channel                                  |                                | 通讯方式（或通道），三种可选   |
| cacheSeconds                        |  `30`                           | 缓存秒数（int）   |
|   | | |
| :: for http | |  |
| url                                         |                                 | 接口完整地址   |
| headers                                 |                                 | 请求头信息      |
| timeout                                  | `30s`                         | mcp 所有超时的默认值         |
| httpTimeout.connectTimeout    |                                 | http 连接超时  |
| httpTimeout.writeTimeout        |                                  | http 写超时     |
| httpTimeout.readTimeout         |                                  | http 读超时（如果为0，表示不超时）      |
| requestTimeout                       |                                 | mcp 请求等待超时         |
| initializationTimeout                 |                                  | mcp 初始化等待超时      |
| heartbeatInterval                      | `15s`                          | 心跳间隔（null 或 0s 为关闭）      |
|  | |  |
| httpProxy                                |                                  | http 代理（要通过接口配置）      |
| httpSsl                                    |                                  | http 证书（要通过接口配置）      |
| httpFactory                              |                                  | http 工厂（要通过接口配置）      |
|   | | |
| :: for stdio  | | |
| command                    |                                   |  stdio 命令                     | 
| args                            |                                   |  stdio 参数（list 型）      | 
| env                             |                                   |  stdio 环镜（map 型）     | 




McpClientProvider 实现的接口有：




| 接口                        | 说明                                                              | 
| ---------------- | ------------------------------------- | 
| ToolProvider             | 工具提供者接口（可以获取工具清单）                | 
| ResourceProvider     | 资源提供者接口（可以获取资源清单）                 | 
| PromptProvider        | 提示语提供者接口（可以获取提示语清单）           | 
| Closeable                | 关闭接口（关闭后，会释放资源且不再自动重连）   | 


McpClientProvider 主要方法：

| 方法          | 说明          | 
| -------- | -------- | 
| `getClient()`                                      | 获取客户端（基础能力）     | 
| | | 
| `close()`                                            | 关闭     | 
| `reopen()`                                          | 重新打开     | 
| | | 
| `callTool(name, args)`                         | 调用工具    | 
| `callToolRequest(name, args)`              | 发起工具调用请求     | 
| `getTools()`                                        | ToolProvider 接口的实现     | 
| `getTools(cursor)`                               | 根据游标，获取一批工具描述     | 
| | | 
| `readResource(uri)`                              | 读取资源     | 
| `readResourceRequest(uri)`                   | 发起资源读取请求     | 
| `getResources()`                                  | ResourceProvider 接口的实现     | 
| `getResources(cursor)`                         | 根据游标，获取一批资源描述     | 
| | | 
| `getPrompt(name, args)`                       | 获取提示语     | 
| `getPromptRequest(name, args)`            | 发起提示语获取请求     | 
| `getPrompts()`                                     | PromptProvider 接口的实现     | 
| `getPrompts(cursor)`                            | 根据游标，获取一批资源描述     | 



支持直接实例化或构造模式

```java
//直接实例化
new McpClientProvider(Properties clientProps);
new McpClientProvider(String url);
new McpClientProvider(McpClientProperties clientProps);

//构造模式（示例）
McpClientProvider.builder()
    .channel(...)
    .url(...)
    .build();
```

### 1、配置或构建

* 可注入环境的构建方式

```yaml
solon.ai:
  mcp:
    client:
       demo:
          channel: "streamable"
          url: "http://localhost:8080/mcp"
       gitee:
          channel: "sse"
          url: "http://ai.gitee.demo/sse"
```

```java
import org.noear.solon.ai.mcp.client.McpClientProvider;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

@Configuration
public class McpClientConfig {
    @Bean("mcp-demo")
    public McpClientProvider clientWrapper(@Inject("${solon.ai.mcp.client.demo}") McpClientProvider clientProvider) {
        return clientProvider;
    }

    @Bean("mcp-gitee")
    public McpClientProvider clientWrapper2(@Inject("${solon.ai.mcp.client.gitee}") McpClientProvider clientProvider) {
        return clientProvider;
    }
}
```



* Java 原生环境构建方式

```java
//使用代码构建
McpClientProvider clientProvider = McpClientProvider.builder()
                .channel(McpChannel.STREAMABLE)
                .url("http://localhost:8080/mcp")
                .build();
                
//使用配置构建
McpClientProvider clientProvider = Utils.loadProps("classpath:mcp/gitee.yml")
                                        .getProps("solon.ai.mcp.client.demo") //对上配置前缀
                                        .toBean(McpClientProvider.class);
```


### 2、客户端使用

McpClientProvider 已实现 Chat Tool 相关的接口（相当于 Tool Rpc Client），可以直接调用，也可以直接给 ChatModel 使用。

* 直接调用

```java
public void case1() {
    McpClientProvider clientProvider = McpClientProvider.builder()
                .channel(McpChannel.STREAMABLE)
                .url("http://localhost:8080/mcp")
                .build();

    String rst = clientProvider.callTool("getWeather", Map.of("location", "杭州"))
                               .getContent();
}
```

### 3、客户端与模型（ChatModel）集成使用

* 绑定给模型使用（结合配置与注入）

```yaml
solon.ai:
  chat:
    demo:
      apiUrl: "http://127.0.0.1:11434/api/chat"
      provider: "ollama"
      model: "qwen2.5:1.5b"
  mcp:
    client:
        demo:
          channel: "streamable"
          url: "http://localhost:8080/mcp"
```

```java
import org.noear.solon.ai.chat.ChatConfig;
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.mcp.client.McpClientProvider;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

@Configuration
public class McpClientConfig {
    @Bean
    public McpClientProvider mcpClient(@Inject("${solon.ai.mcp.client.demo}") McpClientProvider clientProvider) {
        return clientProvider;
    }

    @Bean
    public ChatModel chatModel(@Inject("${solon.ai.chat.demo}") ChatConfig chatConfig, McpClientProvider clientProvider) {
        return ChatModel.of(chatConfig)
                .defaultToolsAdd(clientProvider) //添加默认工具
                .defaultToolsAdd(...) //可以添加多套工具（只是示意下，可以删掉）
                .build();
    }
    
    @Bean
    public void case2( McpClientProvider clientProvider, ChatModel chatModel) {
        ChatResponse resp = chatModel.prompt("杭州今天的天气怎么样？")
                .options(options -> {
                    //转为工具集合用于绑定 //如果有 defaultToolsAdd，这里就不需要了
                    //options.toolsAdd(clientProvider);
                })
                .call();
    }
}
```

