> ## 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/what-mcp-abstracts/
- Published: 2025-04-11T02:46:37.000Z
- Updated: 2025-04-11T02:46:37.000Z
- Description: 如何构建一个简单的包装函数让我们得出了MCP服务器的概念
- Author: admin
- Tags: MCP, APPLICATION, #Import 2026-10-14 14:41

你可能在博客文章中见过这个图表：

![](https://www.hubwiz.com/blog/content/images/2025/04/image-164.png)

但问题是：*每个人都在教你如何使用MCP*。

没有人解释它抽象了什么——以及为什么现在它突然变得重要了。所以让我们停止理论化，开始编码。

## 1、传统Web UI：按钮时代

假设我们在构建一个带有两个按钮的Web UI：

```html
<button id="btn-create-user">创建用户</button>  
<button id="btn-get-revenue">获取收入</button>

```

以下是背后的JavaScript代码：

```javascript
document.getElementById("btn-create-user").addEventListener("click", () => {  
 fetch("/api/createUser")  
  .then(res => res.json())  
  .then(data => renderUserCard(data));  
});document.getElementById("btn-get-revenue").addEventListener("click", () => {  
 fetch("/api/getRevenue")  
  .then(res => res.json())  
  .then(data => renderGraph(data));  
});

```

我们在做什么？

1. 我们在编写获取逻辑。
2. 我们在编写路由逻辑（调用哪个API）。
3. 我们在编写后处理逻辑以适应UI。

每个操作都是硬编码的。输出需要与UI结构完全匹配。

## 2、让我们干掉重复代码：一个事件处理器

```javascript
function handleClick(actionName) {  
 switch (actionName) {  
   case "createUser":  
     fetch("/api/createUser")  
       .then(res => res.json())  
       .then(data => renderUserCard(data));  
   break;  
   case "getRevenue":  
     fetch("/api/getRevenue")  
       .then(res => res.json())  
       .then(data => renderGraph(data));  
   break;  
 }  
}

```

这是我们所有人都使用过的模式：

1. switch语句。
2. 每个动作的逻辑。
3. 与UI形状紧密耦合。

![](https://www.hubwiz.com/blog/content/images/2025/04/image-165.png)

![](https://www.hubwiz.com/blog/content/images/2025/04/image-166.png)

## 2、现在进入基于聊天的UI：文本输入，文本输出

UI不再是按钮和图表。

它是自然语言输入，由LLM驱动。因此现在你的

1. 前端说：“*给我用户A的收入*”
2. LLM提取一个工具（*getRevenue*）和一些工具输入（*User A*）

所以你用以下内容替换了之前的路由逻辑：

```javascript
invokeTool("getRevenue", { name: "User A" });

```

不再需要后处理。LLM只需要一个JSON字符串：

```json
{result:[ {productName: 'XyZ', yearly: 34B, },{productName: 'Z', yearly: 32B}]}

```

![](https://www.hubwiz.com/blog/content/images/2025/04/image-167.png)

## 3、一个函数处理所有工具调用

那么让我们写一个包装器

```javascript
function invokeTool(toolName, toolInput) {  
 switch (toolName) {  
   case "createUser":  
     return fetch("/api/createUser", {  
         method: "POST",  
         body: JSON.stringify(toolInput)  
       }).then(res => res.text());   
    case "getRevenue":  
      return fetch("/api/getRevenue", {  
         method: "POST",  
         body: JSON.stringify(toolInput)  
       }).then(res => res.text());  
     }  
}  
  
// 包装函数   
function getToolDataForLLM(toolName, toolInput){  
  return invokeTool(toolName,toolInput)  
}  

```

> 嘿，一个函数处理所有工具调用。

## 4、让我们将其作为服务公开

既然这工作得很好，我们想：“*嘿，让我们将这个包装器作为服务提供给组织中的其他团队。*”所以我们做了：

```
// 内部组织URL  
POST /invoke   
{  
 "toolName": "getRevenue",  
 "toolInput": { "month": "January" }  
}

```

我们的包装器成为此内部工具调用API的后端。每个人都赢了——其他人不需要再编写自己的逻辑。

![](https://www.hubwiz.com/blog/content/images/2025/04/image-168.png)

## 5、然后……添加了一个新工具

后端团队添加了一个新端点：*getTopCustomers*。现在我们必须：

```
case "getTopCustomers":  
 return fetch("/api/getTopCustomers", …)

```

1. 更新我们的switch块
2. 再次部署
3. 告知所有人我们改变了行为

突然间，这个漂亮的抽象变成了技术债务。

## 6、等等——我们为什么要这样做？

> “*如果我们数据提供者拥有这些工具，为什么我们要维护这个逻辑？*”

我们已经证明UI不关心数据形状。  
LLM只需要一个字符串。那么为什么我们要坐在这中间？

之前，你必须这样做——因为UI期望不同的形状数据。但现在？

1. UI***不关心形状***
2. LLM***不关心端点***
3. 你***只关心字符串输出***

## 7、所以我们将包装器移到数据提供者那里

我们将invokeTool逻辑移到数据提供者那里。

![](https://www.hubwiz.com/blog/content/images/2025/04/image-169.png)

```
// 外部数据提供者URL  
POST /invoke  
{  
 "toolName": "getRevenue",  
 "toolInput": { "month": "January" }  
}

```

后端执行：

1. 路由
2. 获取
3. 输出格式化

然后我们得到JSON字符串

```
// JSON字符串  
{  
 "toolOutput": "一月份的收入是8000美元"  
}

```

## 8、你刚刚移到后端的包装器？

**那是MCP服务器。**

![](https://www.hubwiz.com/blog/content/images/2025/04/image-170.png)

## 9、使用MCP SDK构建它

后端使用：

```
//伪SDK代码   
const { registerTool, startMCPServer } = require("mcp-sdk");  
  
registerTool("getRevenue", async (input) => {  
 const data = await fetchRevenue(input);  
 return `一月份的收入是$${data.total}`;  
});  
registerTool("create", async (input) => {  
 const data = await createUser(input);  
 return `用户已创建`;  
});  
  
startMCPServer();

```

完成。

1. 没有手动路由。
2. 没有客户端逻辑。
3. 没有UI布线。

那么MCP客户端呢？只有一行代码

```
//伪MCP客户端代码  
await invokeTool("getRevenue", { month: "January" });  
// 返回："一月份的收入是8000美元"

```

MCP客户端处理：

1. 传输
2. 负载结构
3. 工具调用

![](https://www.hubwiz.com/blog/content/images/2025/04/image-171.png)

## 10、结束语

为什么以前不可能做到这一点？

![](https://www.hubwiz.com/blog/content/images/2025/04/image-172.png)

这种灵活性使**MCP抽象成为可能**。

> 从一个简单的switch块开始，它变成了一个可重用的包装器。然后我们将其作为服务公开。然后我们将其交给数据提供者。这就是通往MCP服务器的旅程。

1. 它不是一个框架。
2. 它不是一种传输规范。
3. ***它是一种所有权的转变。***

它关乎将**路由**和**格式化逻辑**从*消费者转移到提供者*。如果你正在构建基于LLM的应用程序，你不需要为每个工具重新发明粘合代码。

> 你需要一个接口。 你需要一个协议。 你需要MCP。

---

原文链接：[Everyone Shows What MCP Does — But Nobody Tells You What It Abstracts](https://pub.towardsai.net/everyone-shows-what-mcp-does-but-nobody-tells-you-what-it-abstracts-91432a79e416?ref=hubwiz.com)

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