用MCP把智能家居无缝接入大模型,自动控温、控光,太酷了

2025年6月28日

我感觉最近到处都在讨论 MCP(模型上下文协议),可说到底,很多人还是搞不清楚它到底是什么。所以,让我们通过一个简单的用例和实际操作,一起探索这个协议。希望读完这篇文章,MCP 能成为你解决 AI 和 LLM(大型语言模型) 相关问题的新工具!本文将通过一个真实世界的例子,为你讲解 MCP 如何在服务器端发挥作用。

真实世界的 MCP 用例:Claude + 智能家居

我们先从即将探讨的用例说起。我的好朋友兼同事 Jan 家里有很多设备,可以测量温度、人员存在、光照等数据。他搭建了一个服务器,里面有 API,可以响应请求并返回这些信息。不过,Jan 不想每次都打开枯燥的网页查看无聊的图表,他希望可以直接通过一个智能、时尚的 LLM 来询问家里的情况。

此外,Jan 不喜欢从头开始开发,他更喜欢使用现成的、可下载的桌面版 LLM 客户端。但问题来了:我们怎么把所有这些指标信息告诉 LLM 呢?

目前有很多种技术可以为 AI 对话 提供更多上下文和数据,例如:

  • RAG(检索增强生成)
  • 系统提示词(System-Prompt)
  • 工具调用(Tool-Calls)

然而,这些方法似乎都无法真正满足我们的需求。它们要么不够动态,要么需要运行我们无法实现的代码。而 MCP 正是在这里发挥作用。

什么是模型上下文协议(MCP)?

"模型上下文协议"听起来很花哨,但我们可以把它分解开来理解:

  • 协议(Protocol):一套标准化的方式
  • 上下文(Context):传递额外信息
  • 模型(Model):与 LLM 进行对话

这样听起来,是不是就不那么复杂了?

MCP 为什么很"酷"?

试想一个没有标准化硬件规格的世界,每个螺栓都可以是任意尺寸。那样一来,每个机械项目你都需要定制工具!LLM 目前的状况就有点像这样。

即便你为 AI 编写了一个很棒的工具,却没有主流的方式可以与他人共享。当然,你可以共享代码,然后别人在自己的系统中重新实现,但这就像是在传递蓝图,而不是直接传递工具!

有了 MCP,你就可以创建一个 服务器。这个服务器可以访问像温度计这样的 资源。接着,你可以把这个服务器提供给你的 客户端。就这样,大功告成!

得益于标准化,并将其转变为"协议",你的客户端会清楚地知道如何提问以及能得到什么回复!你现在可以将相同的链接分享给其他客户端,它们也知道如何使用!这相当方便。

顺便说一下,我在刚才的解释中,悄悄地融入了 MCP 的基本架构:客户端 — 服务器 — 资源。

理论就说到这里,我们来动手制作一些服务器吧!

从 MCP 入门

MCP 由 Anthropic 公司构思并发布,他们还为此准备了一个很棒的文档网站。

作为客户端,我们将使用 Claude Desktop,因为它已经支持 MCP。

作为服务器,我们将使用 Node.js。当收到请求时,它会向所有设备查询参数。

我们的目标是:向 Claude 询问 Jan 家里的情况,然后它能给出回应。

准备服务器基础代码

在拜访 Jan 并完成项目之前,我想先准备一些基础代码,避免阅读文档等繁琐的开销。按照文档中的步骤,我们搭建了一个简单的 Node 项目。

index.ts 文件中,我们初始化服务器:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// 创建服务器实例
const server = new McpServer({
  name: "jans-crib",
  version: "1.0.0",
  capabilities: {
    resources: {},
    tools: {},
  },
});

接着,我们注册一个简单的工具。目前,我们只会告知 Jan 家里的每个房间都"很冷"!

// 注册天气工具
server.tool(
  "get-home-status",
  "获取 Jan 家里的状态",
  {
    room: z.enum(["kitchen", "living room", "bedroom", "bathroom", "office"]),
  },
  async ({ room }) => {
    return {
      content: [
        {
          type: "text",
          text: `${room} 很冷`,
        },
      ],
    };
  },
);

可以看到,有了 MCP,我们可以给工具命名、添加描述,并告知客户端它可以向我们发送哪些参数。这就像 Vercel ai-sdk 中的工具,但具有更好的可移植性!

最后,我们提供运行服务器的函数:

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Weather MCP Server running on stdio");
}

main().catch((error) => {
  console.error("main() 函数发生致命错误:", error);
  process.exit(1);
});

现在,我们运行 npm run build,然后进入准备工作的另一部分。这时我感到惊讶的是,这个服务器只负责"提供"上下文。它不暴露任何你可以使用的 HTTP 访问点。所以,你无法通过 localhost 并将 URL 传递给客户端。相反,你的客户端接收的是服务器构建的路径!

准备客户端连接

安装 Claude Desktop 后,我进入"设置 → 开发者 → 编辑配置",添加了服务器的位置:

{
    "mcpServers": {
        "jans-crib": {
            "command": "node",
            "args": [
                "/absolute/path/to/jans-crib/build/index.js"
            ]
        }
    }
}

Claude 竟然会托管它,这让我很吃惊!我最担心的是所有的授权和认证问题,但看起来我可以直接在服务器的函数调用中进行编程。

之后,我重新启动了客户端,结果如下:

经过一番简单的对话,我们可以确认每个房间确实都很冷。

虽然可以使用 HTTP 来连接 MCP 服务器,但在撰写本文时,在 Claude 桌面客户端 上进行设置非常不直观。

将真实的智能家居数据添加到服务器

概念验证准备好后,我去找 Jan,获得了他家私有本地网络上的 API 访问权限。接着,我找到了他智能家居助手 API 的文档,以及关于访问令牌和进行授权请求所需其他头信息。

很快,我们扩展了 MCP 服务器,让 Claude 能够读取房间和室外温度,检查房间里检测到的人数,查看灯光状态,以及更改灯光状态(打开和关闭)。你可以访问代码仓库查看完整代码!

唯一拖慢我们进度的,是 Jan API 的一些奇怪的特性、命名规范等。令人惊讶的是,这与 MCP 本身没有任何关系!

每次更改后,我只需重建服务器并重新启动 Claude 桌面客户端,这使得迭代和测试速度极快。代码虽然有点乱,但我们只是在试验,并没有开发一个成熟的产品。

然而,如果我们提高代码质量,并允许传入自定义实体名称,我们可以轻松地为其他人准备这个服务器!他们所要做的就是获取代码仓库,设置环境变量,构建它,然后将位置传递给他们的客户端。

MCP 是 LLM 客户端的 USB-C 吗?

我听到过一种说法,把 MCP 比作 LLM 客户端的 USB-C。因为它建立了一个通信标准和形式。因此,每个客户端都可以轻松地使用它来扩展自身功能。而且,现在已经有一些网站方便你查找各种服务器,比如 mcp.so 或 mcpmarket.com。

我相信未来会出现其他标准,但目前 MCP 是最广为人知、讨论最多的。

你应该"全力以赴"投入 MCP 吗?

老实说,这不是一个开创性的想法或技术。然而,将大家都在使用的东西转变为协议或标准,会加速创新,并降低很多人的入门门槛。

根据我的经验和测试,MCP 仍有巨大的改进空间。本地运行 MCP 服务器 固然很酷,但我坚信,一旦 HTTP 标准 到位,它的全部潜力才能得到释放。

很可惜,我太年轻了(或者说幸运),没有经历过 RSS 订阅源 的时代,但我发现这些技术之间有很多相似之处。很快,MCP 将会足够成熟,能够与上下文提供商进行全面的集成。

付费账户、MCP 扩展市场、疯狂的集成(比如和你的汽车对话?!为什么不呢?只需让你的客户端将 MCP 服务器 连接到你的汽车数据收集服务器)。我知道这一切都即将到来。

为什么要费力制作一个网站,而不能直接将你的 MCP 服务器 暴露给 MCP 搜索引擎,让客户端直接与你的产品对话呢?

现在,请原谅我的激动。回答我自己的问题:是的,我确实认为 MCP 是 AI / LLM 通信的未来。

生在这个时代,真是太棒了。