嘿, 我是Mofei!
用 MCP Server 让 AI 能读懂你的网站:快速部署教程 + 示例代码

不得不承认,AI 在解答日常问题方面越来越常被用来取代搜索引擎。在过去的1年内,我自己使用搜索引擎的频率已经降到了冰点。遇到问题的第一时间就是打开ChatGPT然后寻找答案。但随之而来的问题是,现有的AI学习到的知识往往落后于现实世界,对于刚刚更新的事情它并不了解,虽然现在很多AI都多了联网搜索功能,但是差强人意。

比如,当我询问“我的博客有哪些文章”时,GPT 通常会尝试访问网络。但由于网络访问受限,它大概率会失败,最终无法获取有用信息,或者只能以极其缓慢的速度访问到不完整的数据。

image.png

这时候,我们就可以使用MCP包装我们已有的服务,让AI可以自由的访问我们的数据源,并且这个过程非常简单直接,并不需要大量的编码。今天我们就聊聊如何通过MCP Server让自己的服务能被AI所理解。

什么是MCP

Model Context Protocol (MCP) 是一个介于LLM和自定义工具数据之间的一个协议,它定义了一些列的规范,可以让LLM快速知道当前的MCP有哪些工具,以及每个工具是做什么用的,并在特定的上下文情况下自行选择使用哪个工具。

比如在我们这次的案例中,我就为我的博客封装了下面几个工具:

  • list-blog-posts:获取博客文章的标题列表
  • get-blog-article:获取具体某一篇博客文章的内容
  • get-comment-list:获取用户评论列表
  • get-recommend-blog:获取某一篇博客类似的推荐博文列表

MCP Client在首次连接到我们开的MCP Server的时候,就会获取到这些工具的描述,然后当我们询问具体的内容的时候。比如:“我的博客有哪些文章”,MCP Client就会根据上下文自动判断应该调用第一个 list-blog-posts 工具,并自行准备好调用参数来获取最新的文章列表。同理,当我们询问“有哪些评论”的时候,MCP Client也会自动判断应该使用 get-comment-list 来完成任务。

这些工具可以是现有 API 的封装、执行 SQL 查询的函数,或是本地文件读取器。总之,只要代码能实现的逻辑都能被封装为 MCP 工具。

MCP除了工具 Tools 以外,我们还有对应的 Resource , Prompt 等概念,但是这些不是我们本文讨论的重点。

MCP 解决了什么问题

通过上面的例子,你可能对于MCP有了一定的想法。简单来说,MCP(Model Context Protocol)是为了解决 LLM 访问结构化外部数据的难题而诞生的协议。最初,LLM 的知识局限于训练时的数据,对现实世界的变化一无所知。后来,人们尝试赋予它访问互联网的能力,让它通过实时检索来回答问题,但这个方案有两个核心问题:

  1. 稳定性差:访问失败、权限受限、网页结构变化都可能导致获取信息失败。
  2. 信息不完整:比如我问“我的博客有多少篇文章”,但我的博客有 100 页,LLM 不可能每页都访问后再总结,结果常常不准确。

为了解决这个问题,人们也尝试过使用 Function Calling ,让 LLM 可以调用特定函数获取数据。但这依然有问题:

  • 需要为每个服务和每种 LLM 定制 Function schema。
  • 工具发现机制不统一,灵活性有限。

MCP 的出现解决了这些痛点,就像一座桥梁,让 LLM 可以灵活、安全、高效地连接任何外部结构化数据,它的核心思路是:

  • 统一协议:任何 MCP Server 都可以定义一组标准的接口(如 /tools, /resources, /prompts),LLM 在连接时就能知道有哪些工具、它们的用途是什么。
  • 自动工具发现:LLM 无需硬编码,自动发现 MCP Server 提供的功能,并根据上下文自主决定是否调用。
  • 高度扩展性:任何服务(博客、商品系统、地图、留言板等)都可以通过 MCP 封装暴露,成为 AI 可理解的“数据源”。

把自己的服务封装成 MCP 服务,简单么?

结合我自己的实践经验,答案是:非常简单。我仅花了 1–2 个小时,就把自己的博客封装成了一个完整的 MCP Server,并通过 Cloudflare 快速上线,变成了一个真正可供 AI 理解和调用的数据源服务。

MCP 官方(modelcontextprotocol.io)提供了多种语言的 SDK,比如 TypeScript / NodePython。你只需要根据这些 SDK 提供的规范,将你已有的 API 接口稍作封装,明确每个方法接受的参数和返回的数据结构,就可以快速构建起一个合规的 MCP 服务。

更棒的是,使用 Cloudflare 部署的过程非常简化,无需配置额外业务逻辑,只是把你原本的数据“翻译”成 AI 能理解的结构形式。这种轻量级接入方式,极大降低了门槛,让你的博客、应用甚至一段静态内容都能变成 AI 可用的“知识插件”。

下面是我通过自己的博客 MCP Server 与 LLM 对话的实际截图:

2025-05-22 15.16.38.gif

我们依次提出了以下几个问题:

  • 你能告诉我我的博客有哪些文章么?
  • 我的博客一共有多少篇文章?
  • 你能告诉我第一篇文章的内容么?
  • 第一篇文章有什么评论么?
  • 其他的文章有什么评论么?

可以看到,LLM 的回答准确且详细,对内容掌握程度令人惊讶。

这就是 MCP 的魔力:LLM 不再“盲人摸象”,而是能像数据库客户端一样精确地读取你的数据服务。甚至,AI 对你网站的了解可能比你本人更清楚!

实战

在实战部分,我基于自己博客的多个 API,使用 Cloudflare 提供的模板进行了开发与部署。

相关代码已放到Github:https://github.com/zmofei/mofei-life-mcp,欢迎参考细节。

准备

首先我们看看我们已有的API

  • 第一个是获取博客列表的API /api/blog/list/{page} ,可以接受 page 作为参数,同时我的博客支持多语言,也可以通过 lang 参数指定访问的语言类型
  • 第二个是获取博客具体文章内容的API /api/blog/article/{id} , 接受文章 idlang 作为参数
  • 第三个是获取评论的接口 /api/blog/comment_list/{page} ,接受 pagepageSize 作为参数,实际上我也有获取具体文章的评论接口 /api/blog/comment/{blogID}/{page} ,但是为了省事,这里我们用通用接口
  • 第四个是获取推荐文章的接口 /api/blog/recommend/{id} , 接受 idlang 作为参数

初始化项目

我们使用了Cloudflare的模板创建项目,打开terminal,进入到需要开发的目录,运行下面的命令

$ npm create cloudflare@latest -- my-mcp-server --template=cloudflare/ai/demos/remote-mcp-authless

其中 my-mcp-server 可以换成自己的项目名称,其他的可以不变

初始化项目之后,我们发现Cloudflare已经贴心的把所有的内容都准备好了,并且在 src/index.ts 文件中还给我们准备了一些 tools 的示例。

添加tool

我们可以将每个API定义成一个tool,比如对于第一个,获取博客列表的API /api/blog/list/{page} ,我们就可以定义成 list-blog-posts tool, 在 init() 中我们添加如下代码:

// get blog post
this.server.tool(
  "list-blog-posts",
  {
    page: z.number().describe("The page number to retrieve"),
    lang: z.string().describe("Language code, e.g. 'en' or 'zh'"),
  },
  async ({ page, lang }) => {
    const url = `https://api.mofei.life/api/blog/list/${page}?lang=${lang}`;
    const res = await fetch(url);
    const data = await res.json();
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(data),
        },
      ],
    };
  }
);

这段代码相对直观,下面简单说明其结构,我们为 this.server.tool 传递了3个参数, title , params , callback ,其中:

  • title : 是定义这个tool的名字
  • params : 定义了这个tool接受什么样的参数,LLM会按照这个描述来调用 callback
  • callback : LLM调用这个工具的时候具体执行的内容,在这个案例中,我们直接访问了我的博客的一个API,在实际项目中可以更换成其他的API访问或者写成其他的方法。

我们可以按照同样的方法,把其他3个API也都改写成tool,由于篇幅有限,这里就不赘述了,有兴趣的话可以直接看源码 https://github.com/zmofei/mofei-life-mcp/blob/d8fe414b9d4c340add8f542594a5431aeeebf585/src/index.ts#L16-L112

调试

在我们添加完成tool之后,就可以用 MCP inspector 去调试我们的代码了。

首先我们需要运行我的项目,进入项目根目录:

$ npm start

然后打开一个新的terminal:

$ npx @modelcontextprotocol/inspector@latest

这时候,访问 http://localhost:5173 就能打开调试工具了。

我们在调试工具中输入我们之前启动的本地服务的sse地址 http://localhost:8787/sse 然后点击连接 ToolsList Tools ,就能看见我们定义的工具列表了。

image.png

如果你点开下面的History的列表中的小箭头,你还能看到LLM接收到的Tools list是什么样的,比如,我们之前创建的4个工具的描述就是下面这样子的:

{
  "tools": [
    {
      "name": "list-blog-posts",
      "inputSchema": {
        "type": "object",
        "properties": {
          "page": {
            "type": "number",
            "description": "The page number to retrieve"
          },
          "lang": {
            "type": "string",
            "description": "Language code, e.g. 'en' or 'zh'"
          }
        },
        "required": [
          "page",
          "lang"
        ],
        "additionalProperties": false,
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get-blog-article",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the blog article, e.g. '665ad9f8136fb3b8b96dd685'"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "zh"
            ],
            "default": "en",
            "description": "Language code: 'en' or 'zh'"
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false,
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get-comment-list",
      "inputSchema": {
        "type": "object",
        "properties": {
          "page": {
            "type": "string",
            "default": "1"
          },
          "pageSize": {
            "type": "string",
            "default": "20"
          }
        },
        "additionalProperties": false,
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    },
    {
      "name": "get-recommend-blog",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the blog article, e.g. '665ad9f8136fb3b8b96dd685'"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "zh"
            ],
            "default": "en",
            "description": "Language code: 'en' or 'zh'"
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false,
        "$schema": "http://json-schema.org/draft-07/schema#"
      }
    }
  ]
}

我们还可以点击具体的tool,然后尝试运行它

image.png

按照需要,逐一调试所有的tool

部署

调试完成,可以运行

$ npx wrangler@latest deploy

把自己的代码部署到Cloudflare上,部署完成之后,你会获得一个url(我在调试的时候,把域名设置成了https://mcp.mofei.life/sse),你可以通过这个url来使用你的MCP

比如在Claude中,我们可以配置Claude的MCP为下面内容

{
  "mcpServers": {
    "mofei": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://mcp.mofei.life/sse"
      ]
    }
  }
}

在Cursor中我可以这样配置

{
  "mcpServers": {
    "mofei-blog": {
      "url": "https://mcp.mofei.life/sse"
    }
  }
}

验证

我们以Cursor为例,配置完成之后,我们尝试询问“Mofei的博客都有哪些内容?”

image.png

可以看到Cursor会自动调用 list-blog-posts 工具,然后自行决定传入 page=1 , lang=zh 的参数。如果我们尝试用英文去询问,Cursor也能智能的尝试使用 lang=en 去获得答案

image.png

接着我们可以继续通过自然语言提问,验证其他接口是否正常工作,比如“最近的评论都有哪些?”

image.png

总结

通过这次实践,我们可以看到:MCP Server 是一种极其轻量、灵活、易扩展的方式,可以将任何结构化数据源暴露给 AI 客户端使用。无论是博客、商品系统、评论区还是地图服务,只要你有 API,就可以用 MCP 快速封装,并被 ChatGPT、Claude、Cursor 等 LLM 工具即时调用。

与传统的联网搜索相比,MCP 提供了一种更可控、更高效的数据访问路径。不仅部署成本低,而且对现有服务改动极小,特别适合中小团队或个人开发者将自己的内容产品开放给 AI 使用

目前我已经将博客完整接入 MCP,未来也计划继续探索如何将其与 LangChain、Agents、RAG 等机制结合,构建出更智能、更私有的知识应用。

📌 如果你也希望让 AI 读懂你的数据,不妨试试 MCP,也欢迎参考这篇文章提及的代码:https://github.com/zmofei/mofei-life-mcp

THE END

更多你可能感兴趣的文章

关于文章中的内容,有任何见解都可以告诉我哦!

avatar

Mofei's Friend (点击编辑)

听说在这里留言会很酷。

HI. I AM MOFEI!

NICE TO MEET YOU!