1. 项目概述:快速构建云端AI工具平台
最近在折腾AI编程助手,特别是Cursor,发现它的Agent功能虽然强大,但很多时候需要调用外部API或执行特定任务。传统的做法是写本地脚本,或者配置复杂的本地MCP服务器,过程繁琐,还得一直开着本地进程。这让我开始思考,有没有一种更优雅、更“云原生”的方式,能让AI助手直接调用部署在云端的工具函数,就像调用一个普通的API一样简单?
这就是create-mcp这个CLI工具要解决的问题。它的核心目标非常明确:让你只专注于用TypeScript写工具函数,然后一键将这些函数部署为云端服务,并自动集成到你的Cursor Agent中,成为它可以直接调用的“工具”。整个过程,从零到拥有一个可用的云端工具,可能只需要几分钟。
简单来说,它帮你搭建了一个桥梁。桥的一边是你用几行TypeScript写的业务逻辑(比如查询天气、调用某个SaaS的API、处理一段文本),桥的另一边是Cursor里的AI Agent。create-mcp负责把这座桥修好、通电、并告诉Agent怎么过桥。而你,只需要关心桥面上跑什么车(也就是你的业务函数)。
为什么我觉得这个思路很对味?因为它抓住了几个关键痛点:
- 部署简化:无需关心服务器运维、网络配置、安全证书。Cloudflare Workers提供了无服务器环境,部署就是一条命令的事。
- 开发体验极致:采用“约定大于配置”的理念。你不需要学习复杂的MCP协议细节,只需要按照固定的格式(JSDoc注释)写函数,工具自动帮你生成协议所需的元数据。
- 即时可用:部署后,工具链接会自动复制到剪贴板,直接粘贴到Cursor的设置里即可生效,实现了“编码-部署-使用”的快速闭环。
接下来,我会带你深入拆解这个工具,从原理、实操到避坑,完整走一遍用create-mcp打造个人AI工具链的旅程。
2. 核心原理与架构设计解析
要理解create-mcp的价值,得先弄明白它涉及的几个关键技术栈是如何串联起来的。
2.1 Model Context Protocol 是什么?
MCP,即模型上下文协议,你可以把它想象成AI模型(或AI助手)的“USB标准接口”。在没有MCP之前,每个AI应用想要扩展功能,都需要自己定义一套与模型交互的私有协议,混乱且不通用。MCP的目标是建立一个开放标准,让任何兼容MCP的AI应用(如Cursor Agent、Claude Desktop)都能通过同一套方式,发现、描述并调用外部工具或访问外部数据源。
一个MCP服务器本质上是一个遵循特定JSON-RPC协议的WebSocket或HTTP服务。它向客户端(如Cursor)宣告:“我这里有哪些工具(Tools),每个工具需要什么参数(Input Schema),以及如何调用它们(执行函数)。” 客户端拿到这个清单后,就可以在需要时,根据当前对话上下文,决定调用哪个工具,并传递相应参数。
传统上,搭建一个MCP服务器需要你手动处理:
- 协议层的WebSocket连接管理。
- 按照标准格式实现
tools/list、tools/call等RPC方法。 - 将你的业务逻辑函数映射到这些RPC调用上。
- 处理错误和响应格式。
这对于只想快速暴露几个API函数的开发者来说,学习成本和模板代码都太多了。
2.2 create-mcp 的“魔法”:从函数到工具
create-mcp的巧妙之处在于,它通过代码转换和约定,把上述复杂过程全部隐藏了。它基于一个预设的Cloudflare Workers模板项目。这个Worker本身就是一个MCP服务器实现。但它的核心“魔法”发生在构建时。
当你运行bun create mcp时,CLI工具会为你创建一个基于此模板的新项目。你的主要工作区在src/index.ts里。这里导出了一个MyWorker类。你的每一个类方法,只要附上了正确的JSDoc注释,就会被自动识别并转换。
转换过程解析:
- 静态代码分析:项目使用TypeScript编译器API或类似的工具,在构建阶段解析
src/index.ts文件。 - 提取元数据:工具会寻找
MyWorker类中的所有方法。对于每个方法,它会解析其上方的JSDoc注释块。- 第一行注释(
/** 描述... */)会被提取为工具的description。 @param标签定义了工具的输入参数。例如@param name {string} the person's name.会被解析为:参数名name,类型string,描述the person's name。这些信息用于生成JSON Schema,定义调用工具时必须传入的字段。@return标签描述了工具的返回值类型和说明。
- 第一行注释(
- 生成MCP清单:提取出的元数据会被生成为一个符合MCP协议的工具清单。当Cursor Agent连接到此服务器时,服务器返回的就是这个自动生成的清单。
- 路由映射:同时,构建过程会为每个方法生成一个对应的HTTP路由或RPC处理函数。当Cursor发起
tools/call请求,指定要调用sayHello工具并传入{“name”: “World”}时,Worker的请求处理逻辑会根据工具名,路由到MyWorker实例的sayHello(“World”)方法上执行,并将结果按照MCP协议格式包装返回。
这个过程实现了声明式编程:你声明函数的功能和接口,框架负责处理所有通信和协议细节。这极大地提升了开发效率。
2.3 为什么选择 Cloudflare Workers?
原文提到了“Vibes, great DX, and blazing fast deployments”,这虽然是半开玩笑的说法,但确实点出了几个关键优势:
- 无服务器与全球网络:Cloudflare Workers跑在Cloudflare庞大的边缘网络上。你的工具一旦部署,就在全球数百个节点生效,延迟极低。对于AI工具调用这种即时交互场景,低延迟体验至关重要。你不需要租用服务器,按请求付费,成本极低甚至免费(在免费额度内)。
- 极致的开发部署体验:Wrangler CLI工具链非常成熟,
wrangler deploy命令通常在几秒到十几秒内就能完成全球部署。这与MCP工具“快速迭代、即时测试”的需求完美契合。create-mcp封装了bun run deploy,进一步简化。 - 免运维:你完全不用操心服务器的扩容、安全补丁、运行监控。Cloudflare全包了。作为工具开发者,你可以100%聚焦在业务逻辑上。
- 内置的WebSocket支持:MCP协议可以通过HTTP或WebSocket通信。Cloudflare Workers对WebSocket有很好的支持,使得实现全双工、长连接的MCP服务器成为可能,虽然当前
create-mcp的模板可能基于更简单的HTTP调用。
注意:选择Cloudflare Workers也意味着你将项目绑定在了Cloudflare的生态上。如果你的工具需要访问特定的云服务(如AWS DynamoDB)或需要更复杂的后端运行时环境(如长时间运行的进程),可能需要评估Workers的限制(如CPU时间限制、无状态特性)。但对于绝大多数轻量级、无状态的API封装和工具函数,Workers是绝佳选择。
3. 从零开始:完整实操指南
理论说得再多,不如亲手做一遍。我们从头开始,创建一个能查询当前时间的MCP工具,并集成到Cursor中。
3.1 环境准备与初始化
首先,确保你的系统满足所有先决条件。
1. 安装 Bun 运行时create-mcp使用 Bun作为包管理和运行工具。Bun相比Node.js在启动速度和工具链集成上有优势。
# 在macOS或Linux上 curl -fsSL https://bun.sh/install | bash # 或者在Windows上通过PowerShell powershell -c "irm bun.sh/install.ps1 | iex"安装后,重启终端,运行bun --version确认安装成功。
2. 安装并登录 Wrangler CLIWrangler是Cloudflare Workers的官方命令行工具。
# 使用npm或bun全局安装 npm install -g wrangler # 或 bun add -g wrangler安装后,需要登录你的Cloudflare账户,授权Wrangler管理你的Workers。
wrangler login这会打开浏览器,引导你完成Cloudflare账户的授权。确保你拥有一个Cloudflare账户,并且打算使用Workers服务(有免费额度)。
3. 安装 Claude Desktop (目前暂时需要)根据项目说明,目前还需要Claude Desktop应用。这是因为初始的MCP服务器配置可能会被自动添加到Claude Desktop中,作为配置流程的一部分。未来这个依赖可能会被移除。你可以从Anthropic官网下载并安装。
4. 创建你的第一个MCP服务器项目环境就绪后,创建项目非常简单。
# 进入你希望创建项目的目录 cd ~/projects # 运行创建命令,可以指定项目名 bun create mcp --name my-time-tools如果你不指定--name,CLI会交互式地询问你项目名称。这里我们创建了一个名为my-time-tools的项目。
执行过程解读:当你运行上述命令后,CLI会执行一系列操作:
- 克隆模板:从远程仓库(通常是GitHub上的一个模板仓库)克隆项目代码到
./my-time-tools目录。 - 安装依赖:进入项目目录,运行
bun install,安装所有必要的npm包,包括@cloudflare/workers-types,wrangler以及MCP协议相关的库。 - 初始化Git:在项目目录内执行
git init,帮你初始化版本控制。 - 首次部署:自动运行部署脚本,将模板中的“Hello World”示例部署到你的Cloudflare账户。你会在终端看到部署进度和最终生成的
.dev.vars等文件。 - 配置客户端:尝试将新部署的MCP服务器配置添加到Claude Desktop应用中。
- 复制连接命令:最关键的一步,它将一条形如
npx @modelcontextprotocol/server-cloudflare-workers https://your-worker.your-account.workers.dev的命令复制到你的系统剪贴板。这条命令就是你的MCP服务器地址。
3.2 编写你的第一个工具函数
项目创建并部署成功后,用你喜欢的代码编辑器打开my-time-tools目录。核心文件是src/index.ts。
打开它,你会看到类似以下内容的模板:
import { Hono } from 'hono'; // ... 其他导入 export class MyWorker { // ... 可能有一些构造函数或初始化逻辑 /** * A warm, friendly greeting from your new Workers MCP server. * @param name {string} the name of the person we are greeting. * @return {string} the contents of our greeting. */ sayHello(name: string) { return `Hello from an MCP Worker, ${name}!`; } } // ... 底层的服务器配置和Hono应用初始化代码你的所有工具都将作为MyWorker类的方法来添加。现在,让我们添加一个获取当前时间的工具。
在sayHello方法下方,添加一个新的方法:
/** * 获取当前的日期和时间信息。 * 该工具无需任何输入参数,将返回服务器所在时区的当前时间。 * @return {object} 包含当前日期、时间、时间戳和时区的对象。 */ getCurrentTime() { const now = new Date(); return { date: now.toISOString().split('T')[0], // YYYY-MM-DD time: now.toTimeString().split(' ')[0], // HH:MM:SS timestamp: now.getTime(), // Unix时间戳(毫秒) timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, // 例如 "Asia/Shanghai" display: now.toLocaleString('zh-CN') // 本地化格式显示 }; }代码解析与注意事项:
- JSDoc注释是核心:
/** ... */里的描述会成为Cursor Agent识别工具功能的依据。描述应清晰、简洁,说明工具的作用。 @return标签:这里我们返回一个对象。注释中说明了返回值的类型是object,并描述了其结构。虽然MCP协议最终会序列化为JSON,但清晰的返回描述能帮助AI更好地理解和使用返回的数据。- 函数实现:函数体就是普通的TypeScript/JavaScript代码。我们创建了一个Date对象,然后构造了一个包含多种时间格式的对象。Cloudflare Workers运行在UTC时区,但我们可以通过
IntlAPI获取运行时环境的时间区域信息,或者展示ISO格式。 - 无需
@param:因为这个工具不需要输入参数,所以我们没有写@param标签。
实操心得:工具设计的“提示工程”给工具函数写JSDoc注释时,要像给AI写提示词(Prompt)一样思考。注释的第一行和
@param、@return的描述,直接决定了AI是否能在正确的场景下想起并正确使用这个工具。例如,“获取当前的日期和时间信息”就比“getTime”要好得多。清晰的参数描述(如“@param city {string} 城市名称,例如‘北京’或‘New York’”)能极大提高AI调用工具的准确率。
3.3 部署更新与在Cursor中集成
编写完工具函数后,需要将其部署到云端,并在Cursor中启用。
1. 部署更改在项目根目录下,运行:
bun run deploy这个命令封装了wrangler deploy。你会看到构建和上传的过程,最终输出你的Worker的URL,格式如https://my-time-tools.<your-subdomain>.workers.dev。
2. 在Cursor中配置MCP服务器这是最关键的一步,让你的Agent能“看见”新工具。
- 打开Cursor编辑器。
- 进入设置(Settings)。通常在左下角找到齿轮图标或通过命令面板(Cmd/Ctrl + Shift + P)搜索“Settings”。
- 在设置中,找到“Cursor Agent”或“MCP Servers”相关配置项。不同版本的Cursor位置可能略有不同。
- 在MCP服务器配置区域,你需要添加一个新的服务器配置。这时,请粘贴之前
create-mcp初始化完成后复制到你剪贴板的那条命令。它看起来像这样:npx @modelcontextprotocol/server-cloudflare-workers https://my-time-tools.<your-subdomain>.workers.dev重要提示:有些配置界面可能只需要URL部分(
https://...),而有些则需要完整的命令。请根据Cursor的界面提示操作。如果之前剪贴板命令丢失了,你可以在项目根目录的README.md或package.json的脚本中找找,或者直接使用Worker的URL尝试。
3. 测试你的工具配置完成后,你需要完全重启Cursor(关闭所有窗口再重新打开),或者按照其提示“重新加载Agent配置”,以确保新的MCP服务器被加载。
重启后,打开一个聊天窗口(与Cursor Agent对话的界面)。现在,你可以尝试让Agent使用新工具。例如,输入:
“请帮我看看现在几点了。”
如果一切配置正确,Cursor Agent应该会理解你的请求,并在后台调用getCurrentTime工具,然后将返回的结果组织成自然语言回复给你,比如:“当前时间是2023年10月27日下午3点30分(北京时间),时间戳是1698399000000。”
3.4 进阶:创建带参数的复杂工具
让我们创建一个更实用的工具:一个简单的单位转换器。这个工具需要输入参数。
在src/index.ts的MyWorker类中添加新方法:
/** * 进行常见的单位转换。 * 支持长度(米/英尺)、重量(公斤/磅)、温度(摄氏度/华氏度)的转换。 * @param value {number} 需要转换的数值。 * @param fromUnit {string} 原始单位。可选值:'meters', 'feet', 'kilograms', 'pounds', 'celsius', 'fahrenheit'。 * @param toUnit {string} 目标单位。可选值同上,但需与fromUnit属于同一类别(长度、重量或温度)。 * @return {object} 包含转换结果和单位的对象。如果转换失败,会返回错误信息。 */ unitConverter(value: number, fromUnit: string, toUnit: string) { // 定义转换函数 const converters = { // 长度转换:1米 = 3.28084英尺 length: { meters_to_feet: (val: number) => val * 3.28084, feet_to_meters: (val: number) => val / 3.28084, }, // 重量转换:1公斤 = 2.20462磅 weight: { kilograms_to_pounds: (val: number) => val * 2.20462, pounds_to_kilograms: (val: number) => val / 2.20462, }, // 温度转换 temperature: { celsius_to_fahrenheit: (val: number) => (val * 9/5) + 32, fahrenheit_to_celsius: (val: number) => (val - 32) * 5/9, }, }; // 确定转换类别和键 const lengthUnits = ['meters', 'feet']; const weightUnits = ['kilograms', 'pounds']; const tempUnits = ['celsius', 'fahrenheit']; let category: keyof typeof converters | null = null; let converterKey: string | null = null; if (lengthUnits.includes(fromUnit) && lengthUnits.includes(toUnit)) { category = 'length'; converterKey = `${fromUnit}_to_${toUnit}`; } else if (weightUnits.includes(fromUnit) && weightUnits.includes(toUnit)) { category = 'weight'; converterKey = `${fromUnit}_to_${toUnit}`; } else if (tempUnits.includes(fromUnit) && tempUnits.includes(toUnit)) { category = 'temperature'; converterKey = `${fromUnit}_to_${toUnit}`; } // 执行转换或返回错误 if (category && converterKey && converters[category][converterKey]) { const result = converters[category][converterKey](value); return { original: { value, unit: fromUnit }, converted: { value: parseFloat(result.toFixed(4)), unit: toUnit }, // 保留4位小数 note: `转换公式已应用。` }; } else { // 返回清晰的错误信息,帮助AI理解问题所在 return { error: true, message: `无法从'${fromUnit}'转换到'${toUnit}'。请确保它们属于同一类别(长度、重量或温度),且单位名称正确。`, supportedCategories: { length: lengthUnits, weight: weightUnits, temperature: tempUnits } }; } }部署并测试:
- 再次运行
bun run deploy。 - 在Cursor中,你可以这样询问:
“把10米转换成英尺是多少?” “20摄氏度相当于多少华氏度?”
Agent应该能正确解析你的问题,调用unitConverter工具,并给出答案。
避坑指南:参数设计与AI理解
- 类型明确:JSDoc中的
{string}、{number}对AI选择参数值有指导作用。尽量使用基础类型。- 枚举值提示:对于像
fromUnit这样的参数,在描述中列出所有可选值('meters', 'feet'...)非常有用。这相当于给了AI一个选项列表,能显著提高调用准确性。- 错误处理友好:工具函数内部要做好错误处理,并返回结构化的错误信息。例如,上面的例子中,如果单位不匹配,返回的JSON对象中包含了
error: true和详细的message,甚至列出了支持的单位。这能帮助AI向用户解释哪里出了问题,而不是得到一个晦涩的异常。
4. 项目模板深度剖析与定制
create-mcp使用的模板项目是一个精心设计的起点。理解它的结构,有助于你进行高级定制和故障排查。
4.1 项目目录结构解析
初始化后的项目通常包含以下核心文件和目录:
my-time-tools/ ├── src/ │ └── index.ts # 核心文件,你的工具函数都在这里定义 ├── public/ # 静态资源目录(如果有前端界面的话) ├── tests/ # 测试文件目录 ├── package.json # 项目依赖和脚本定义 ├── wrangler.toml # Cloudflare Workers 配置文件 ├── tsconfig.json # TypeScript 配置 └── README.md # 项目说明src/index.ts:这是你的主战场。除了MyWorker类,文件底部通常包含Cloudflare Worker的入口点配置,使用Hono(一个轻量级Web框架)来设置路由和处理MCP协议请求。你一般不需要修改这部分,除非你有特殊的路由或中间件需求。wrangler.toml:这是Cloudflare Workers的配置文件。里面定义了你的Worker名称、兼容日期、触发路由等。create-mcp初始化时已经根据你的项目名配置好了。name = "my-time-tools" main = "src/index.ts" compatibility_date = "2024-01-01" [[migrations]] tag = "v1" new_classes = ["MyWorker"][[migrations]]部分可能与Durable Objects或其他高级特性相关,对于基础工具服务器,可以暂时不用深究。package.json:注意里面的脚本命令。"scripts": { "deploy": "wrangler deploy", "dev": "wrangler dev", "typecheck": "tsc --noEmit" }bun run deploy实际执行的就是wrangler deploy。wrangler dev命令非常有用,它会在本地启动一个开发服务器,并模拟Cloudflare Workers环境,你可以本地测试你的工具函数,而无需每次修改都部署到云端。
4.2 使用本地开发服务器进行测试
在将代码部署到云端之前,强烈建议先在本地进行测试。
启动本地开发服务器:
bun run dev终端会输出一个本地URL,通常是
http://localhost:8787。测试MCP端点:MCP服务器有特定的端点。你可以用
curl或 Postman 来测试tools/list端点,查看你的工具列表是否被正确生成。curl http://localhost:8787/tools/list你应该会收到一个JSON响应,其中包含了
sayHello、getCurrentTime和unitConverter这三个工具的完整定义,包括名称、描述和参数schema。模拟工具调用:你也可以测试
tools/call端点(注意,这通常是一个POST请求)。curl -X POST http://localhost:8787/tools/call \ -H "Content-Type: application/json" \ -d '{ "name": "unitConverter", "arguments": { "value": 10, "fromUnit": "meters", "toUnit": "feet" } }'如果一切正常,你会收到转换结果:
{"original": {...}, "converted": {"value": 32.8084, "unit": "feet"}, ...}。
本地测试的价值:
- 快速迭代:无需等待云端部署,修改代码后保存,开发服务器通常支持热重载。
- 调试方便:可以在代码中打
console.log,日志会直接输出在wrangler dev的终端里。 - 验证协议:确保你的工具函数和JSDoc被正确解析为MCP协议格式。
4.3 添加外部依赖与调用第三方API
真正的工具威力在于连接外部世界。让我们创建一个调用公共API的工具:获取指定城市的天气信息。这需要用到HTTP请求。
1. 安装HTTP客户端库Cloudflare Workers环境推荐使用内置的fetchAPI,它全局可用,无需安装。但为了更好的类型提示和错误处理,我们可以使用hono框架已经集成的能力,或者保持使用fetch。这里我们直接使用fetch。
2. 编写天气查询工具在src/index.ts的MyWorker类中添加以下方法。我们将使用一个免费的天气API(例如 open-meteo.com)作为示例。
/** * 获取指定城市的当前天气情况。 * 该工具通过公共天气API查询,返回温度、天气状况、风速等基本信息。 * @param city {string} 城市名称,例如“London”或“北京”。对于非英文城市名,API可能支持有限,建议同时提供经纬度。 * @param countryCode {string} [可选] 国家代码(ISO 3166-1 alpha-2),例如“GB”、“CN”。用于更精确地定位城市。 * @return {object} 包含城市、温度、天气描述、风速等信息的对象。如果查询失败,返回错误信息。 */ async getWeather(city: string, countryCode?: string) { // 注意:这是一个示例,实际使用时你需要注册一个免费的天气API服务(如OpenWeatherMap)并获取API密钥。 // 这里我们使用不需要密钥的Open-Meteo API,但它需要经纬度,而不是城市名。 // 因此,在实际项目中,你可能需要先调用一个地理编码API将城市名转换为经纬度。 // 为了示例的简单性,我们这里模拟一个固定城市的响应,并说明实际集成步骤。 // 实际步骤1: 地理编码 (例如使用 Nominatim / OpenStreetMap) // const geoUrl = `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(city)}&format=json&limit=1`; // const geoResponse = await fetch(geoUrl, { headers: { 'User-Agent': 'YourAppName' } }); // Nominatim要求设置User-Agent // const geoData = await geoResponse.json(); // if (!geoData || geoData.length === 0) { return { error: `未找到城市: ${city}` }; } // const { lat, lon } = geoData[0]; // 实际步骤2: 调用天气API (例如 Open-Meteo) // const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`; // const weatherResponse = await fetch(weatherUrl); // const weatherData = await weatherResponse.json(); // 模拟数据返回(在实际开发中,请替换为上述真实API调用) console.log(`[Weather Tool] Requested weather for: ${city} ${countryCode ? `(${countryCode})` : ''}`); // 模拟API响应延迟 await new Promise(resolve => setTimeout(resolve, 100)); // 返回模拟数据 const mockWeatherData = { city: city, country: countryCode || 'N/A', temperature: 22.5, // 摄氏度 condition: 'Partly cloudy', windSpeed: 12.3, // km/h humidity: 65, // 百分比 lastUpdated: new Date().toISOString(), note: '这是模拟数据。实际集成需要调用地理编码和天气API,并处理API密钥。' }; return mockWeatherData; }3. 处理异步操作与错误注意,我们使用了async关键字,因为fetch是异步操作。MCP服务器模板应该已经处理好了异步方法的返回。在函数内部,务必用try...catch包裹可能出错的网络请求或逻辑,并返回友好的错误信息,而不是让异常抛出导致整个请求失败。
4. 关于API密钥等敏感信息如果你需要调用需要认证的API(如OpenWeatherMap),绝对不要将API密钥硬编码在代码中。Cloudflare Workers提供了安全存储机密信息的方式。
使用
wrangler secret命令:wrangler secret put OPENWEATHER_API_KEY然后在命令行中输入你的API密钥。在你的代码中,通过
process.env.OPENWEATHER_API_KEY或环境变量来访问它。在wrangler.toml中也可以定义环境变量,但对于密钥,使用secret更安全。在代码中访问:
const apiKey = process.env.OPENWEATHER_API_KEY; const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric`;
安全警告:永远不要在客户端(如浏览器)或可公开访问的代码(如GitHub公共仓库)中暴露API密钥。Cloudflare Workers的Secret功能确保了密钥只保存在Cloudflare的安全环境中,不会出现在你的代码仓库或客户端请求里。
5. 故障排查、优化与最佳实践
在实际使用中,你可能会遇到各种问题。这里汇总了一些常见情况及解决方案。
5.1 常见问题与解决方案速查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
运行bun create mcp失败 | 1. Bun未正确安装。 2. 网络问题无法克隆模板。 3. Wrangler未登录。 | 1. 运行bun --version确认Bun已安装。2. 检查网络连接,尝试手动访问模板仓库。 3. 运行 wrangler whoami确认登录状态,未登录则运行wrangler login。 |
部署失败 (bun run deploy报错) | 1.wrangler.toml配置错误。2. TypeScript编译错误。 3. Cloudflare账户配额不足或名称冲突。 | 1. 检查wrangler.toml语法,特别是name是否合法(仅小写字母、数字、连字符)。2. 先运行 bun run typecheck或tsc --noEmit检查类型错误。3. 登录Cloudflare Dashboard,查看Workers页面是否有错误提示,或尝试修改Worker名称。 |
| Cursor Agent 找不到/不调用新工具 | 1. MCP服务器配置未正确添加或未重启Cursor。 2. 工具函数JSDoc格式错误,导致MCP清单生成失败。 3. 部署后Worker URL有变化,但Cursor中配置未更新。 4. 工具描述不够清晰,AI无法理解适用场景。 | 1. 确认Cursor设置中的MCP服务器配置已保存,并完全重启Cursor。 2. 本地运行 bun run dev,用curl测试/tools/list端点,看你的工具是否出现在返回的JSON中。3. 重新部署后,使用新的Worker URL更新Cursor配置。 4. 优化工具函数的JSDoc描述,使其更贴近自然语言提问。例如,“获取天气”比“weatherFetch”更好。 |
| 工具被调用但返回错误 | 1. 工具函数内部逻辑有bug,抛出异常。 2. 参数类型不匹配或缺失。 3. 异步函数未正确处理。 | 1. 查看Cloudflare Worker的日志(在Dashboard的Workers详情页)。本地开发时查看wrangler dev终端输出。2. 检查JSDoc中 @param定义的类型是否与函数实际参数类型一致。确保AI传递的参数能正确解析。3. 确保异步函数使用了 async/await并妥善处理了Promise拒绝。 |
| 工具调用速度慢 | 1. Worker冷启动。 2. 工具函数内部有耗时的同步操作或网络请求。 | 1. Cloudflare Workers冷启动通常很快(毫秒级)。频繁调用可避免冷启动。 2. 优化工具函数逻辑,将耗时操作异步化。对于依赖外部API的,考虑其响应时间。 |
| 想使用其他部署平台 | 项目模板紧密耦合Cloudflare Workers。 | 1. 理解MCP协议,手动或用其他框架构建MCP服务器,部署到Vercel、AWS Lambda等。 2. 寻找社区其他 create-mcp类似模板,可能支持多平台。 |
5.2 性能与成本优化建议
- 减少依赖包大小:定期检查
package.json,移除未使用的依赖。精简的依赖包能加快Worker的冷启动速度。 - 使用环境变量和KV存储:对于配置信息和频繁读取的静态数据,使用Cloudflare KV命名空间存储,比在代码中硬编码或每次从外部API获取更快、更经济。
- 合理设计工具粒度:避免创建“巨无霸”工具函数。一个工具最好只做一件事。这样AI更容易理解和调用,也便于你维护和复用。例如,将“获取用户信息并发送邮件”拆分成“获取用户信息”和“发送邮件”两个独立工具。
- 利用免费额度:Cloudflare Workers每日有10万次免费请求,对于个人或小规模使用完全足够。但仍需关注用量,避免意外超支。可以在Cloudflare Dashboard设置用量警报。
5.3 维护与迭代最佳实践
- 版本控制:
create-mcp已经帮你初始化了Git仓库。务必频繁提交,特别是添加新工具或重大修改时。良好的提交信息有助于回溯。 - 编写测试:虽然快速原型阶段可能忽略,但对于核心工具函数,编写单元测试(放在
tests/目录下)能保证其可靠性。可以使用bun test来运行测试。 - 文档化你的工具集:在项目
README.md中维护一个工具清单表格,列出每个工具的名称、描述、参数和示例。这不仅帮助未来的你,也方便与其他开发者协作。 - 监控与日志:在工具函数的关键节点添加
console.log或console.error语句。这些日志可以在Cloudflare Worker的实时日志中查看,对于排查生产环境问题至关重要。 - 克隆与复用社区工具:
create-mcp支持--clone参数,你可以直接克隆并部署别人已经写好的MCP服务器(如示例中的Neon、Vercel API等)。这是学习和快速获得功能的绝佳途径。研究他人的代码,理解他们如何设计工具和调用第三方API。
通过create-mcp,你将复杂的MCP服务器开发、部署和集成流程,简化为“写函数 -> 部署 -> 使用”的三步曲。它极大地降低了为AI助手扩展能力的门槛,让你能快速将想法转化为Agent可用的实际工具。无论是封装内部系统API,还是连接各种SaaS服务,这个模式都提供了一个高效、云原生的起点。