> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 开发一个MCP协议客户端
- URL: https://www.hubwiz.com/blog/build-a-mcp-client/
- Published: 2025-03-07T15:27:36.000Z
- Updated: 2025-03-07T15:27:36.000Z
- Description: MCP并不局限于Claude桌面，它可以用任何支持它的其他LLM客户端使用。考虑到这一点，我们决定构建一个MCP CLI客户端来展示这一点。这个MCP客户端可以更快速地测试MCP服务器。
- Author: admin
- Tags: APPLICATION, AGENT, MCP, CLAUDE, #Import 2026-10-14 14:41

模型上下文协议（MCP）在AI领域持续获得关注，自从[Neon MCP服务器](https://neon.tech/blog/let-claude-manage-your-neon-databases-our-mcp-server-is-here?ref=hubwiz.com)发布以来（大约两周前），社区已经在广泛的领域内构建了数十个这些服务器[\[链接\]](https://github.com/modelcontextprotocol/servers/?ref=hubwiz.com#-third-party-servers)。然而，Claude桌面应用程序已经成为默认的MCP客户端，大多数服务器都有专门的说明来指导如何与该客户端集成。

但MCP并不局限于Claude桌面，它可以用任何支持它的其他LLM客户端使用。考虑到这一点，我们决定构建一个MCP CLI客户端来展示这一点。这个MCP客户端可以更快速地测试MCP服务器。

## 1、如何构建MCP客户端

所有MCP客户端都基于相同的原理并遵循相同的协议。对于工具使用（我们的用例），需要实现的主要概念如下：

### 1.1 MCP服务器连接

第一步是连接到MCP服务器，以便它可以发现和使用服务器上的工具。

```
const mcpClient = new Client(
  { name: 'cli-client', version: '1.0.0' },
  { capabilities: {} },
);

// 此函数将MCP客户端连接到MCP服务器
await mcpClient.connect(new StdioClientTransport(serverConfig));

```

### 1.2 工具列表

我们需要从MCP服务器获取可用工具。这允许LLM知道在交互过程中可以使用哪些工具

```
// 此函数将返回MCP服务器上可用工具的列表
const toolsAvailable = await this.mcpClient.request(
  { method: 'tools/list' },
  ListToolsResultSchema,
);

```

### 1.3 工具使用

一旦LLM决定使用哪个工具，我们需要调用MCP服务器上的工具处理程序。

```
// 此函数将在MCP服务器上调用工具处理程序
const toolResult = await this.mcpClient.request(
  {
    method: 'tools/call',
    params: {
      name: toolName,
      arguments: toolArgs,
    },
  },
  CallToolResultSchema,
);

```

### 1.4 LLM集成

这是一个多步骤的过程，将LLM连接到可用工具：

1. 向LLM发送初始提示
2. 等待LLM响应工具使用
3. 在MCP服务器上调用工具处理程序
4. 将工具结果注入LLM的上下文中
5. 向LLM发送下一个提示

由于我们正在使用来自Anthropic API的[工具API](https://docs.anthropic.com/en/docs/build-with-claude/tool-use?ref=hubwiz.com)，如果仅仅依赖他们的[官方SDK](https://github.com/anthropics/anthropic-sdk-typescript?ref=hubwiz.com)，则会简单得多。

```
// 1- 发送初始提示
const response = await this.anthropicClient.messages.create({
  messages: [
    {
      role: 'user',
      content: 'Can you list my Neon projects?',
    },
  ],
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 8192,
  tools: this.tools,
});

for (const content of response.content) {
	// 2- 等待LLM响应工具使用
  if (content.type === 'tool_use') {
    const toolName = content.name;
    const toolArgs = content.input;
    // 3- 在MCP服务器上调用工具处理程序
    const toolResult = await this.mcpClient.request(
      {
        method: 'tools/call',
        params: {
          name: toolName,
          arguments: toolArgs,
        },
      },
      CallToolResultSchema,
    );
    
    // 4- 将工具结果注入LLM的上下文中
    const contextWithToolResult = [
        ...previousMessages,
        { role: 'user', content: toolResult.content },
     ];

		// 5- 向LLM发送下一个提示
    const nextResponse = await this.anthropicClient.messages.create({
      messages: contextWithToolResult,
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 8192,
    });
  }
}

```

## 2、构建CLI客户端

一旦我们有了所有核心组件，我们只需要构建一个酷炫的CLI客户端，可以用来与MCP服务器交互。

### 2.1 LLM处理

处理LLM消息和工具使用。重要的是我们要在每次交互之间保留消息，以便可以将工具结果注入LLM的上下文中。

```
private async processQuery(query: string) {
  try {
    // 1 - 向LLM发送用户的查询
    this.messages.push({ role: 'user', content: query });
    const response = await this.anthropicClient.messages.create({
      messages: this.messages,
      model: 'claude-3-5-sonnet-20241022',
      tools: this.tools,
    });

    // 2 - 处理LLM响应
    for (const content of response.content) {
      if (content.type === 'text') {
        process.stdout.write(content.text);
      }

      // 3 - 处理工具使用
      if (content.type === 'tool_use') {
        const toolResult = await this.mcpClient.request({
          method: 'tools/call',
          params: {
            name: content.name,
            arguments: content.input,
          }
        });

        // 4 - 将工具结果添加到对话中
        this.messages.push({
          role: 'user',
          content: JSON.stringify(toolResult)
        });

        // 5 - 获取LLM对工具结果的响应
        const nextResponse = await this.anthropicClient.messages.create({
          messages: this.messages,
          model: 'claude-3-5-sonnet-20241022'
        });

        // 6 - 显示LLM的响应
        if (nextResponse.content[0].type === 'text') {
          process.stdout.write(nextResponse.content[0].text);
        }
      }
    }
  } catch (error) {
    console.error('Error during query processing:', error);
  }
}

```

### 2.2 聊天循环

创建一个聊天循环，用于向LLM发送消息并处理响应。

```
private async chat_loop() {
    while (true) {
      try {
        const query = (await this.rl.question(styles.prompt)).trim();
        // 处理查询
        await this.processQuery(query);
      } catch (error) {
        console.error(styles.error('\\\\nError:'), error);
      }
    }
}

```

### 2.3 入口点

设置客户端的主入口点，初始化MCP客户端，获取工具并启动聊天循环

```
  // 这是客户端的主入口点
  async start() {
    try {
      console.log(styles.info('🤖 Interactive Claude CLI'));
      console.log(
        styles.info(`Type your queries or "${EXIT_COMMAND}" to exit`),
      );

      // 1 - 将MCP客户端连接到MCP服务器
      await this.mcpClient.connect(this.transport);

      // 2 - 获取MCP服务器上可用的工具
      await this.initMCPTools();

      // 3 - 启动聊天循环
      await this.chat_loop();
    } catch (error) {
      console.error(styles.error('Failed to initialize tools:'), error);
      process.exit(1);
    } finally {
      this.rl.close();
      process.exit(0);
    }
  }

```

### 2.4 运行

现在我们已经构建了一个通用的MCP客户端，可以通过传递MCP服务器URL和其他所需参数来运行它。

```
const cli = new InteractiveCLI({
  command: '../dist/index.js',
  args: ['start', process.env.NEON_API_KEY!],
});
cli.start();

```

### 2.5 改进

这个简单实现有两个主要缺点：

- **流式传输**：这个客户端不支持流式传输，因此从用户角度来看，响应可能会显得慢一些。
- **多次工具调用**：这个客户端不会跟进多次工具调用，它总是在第一次工具调用后停止。

幸运的是，这两个问题已经在我们在Neon构建的[MCP客户端CLI](https://github.com/neondatabase/mcp-server-neon/tree/main/mcp-client?ref=hubwiz.com)中得到了解决。

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcsWAhsks5tljrL3RRv42QdKU20ZNqW9WNOOrSrpp1aXEOJFwZiqafNnK2UI3iyUbnbpqalpcjLaUh80z9I6u0IirHuTjEAEIBvCjLwTOeqsABOvZ3ajo7C_u6VDvMon60aDrAsHg?key=K0Nt6EMocrmafUcahI3hR3ZI)

## 3、结束语

使用此工具与任何MCP服务器一起查看其工作方式，或将其作为基础来构建自己的MCP客户端。您可以查看我们的GitHub [仓库](https://github.com/neondatabase/mcp-server-neon/tree/main/mcp-client?ref=hubwiz.com)，并在[我们的Discord服务器](https://neon.tech/discord?ref=hubwiz.com)上提供反馈！

---

原文链接：[Building a CLI Client For Model Context Protocol Servers](https://neon.tech/blog/building-a-cli-client-for-model-context-protocol-servers?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处