NeuralOS
GuideAdvanced

用 FastMCP 在 TypeScript 里构建你自己的 MCP 服务器

到今天为止,你一直是租客:你安装别人写的 MCP,你的 AI 使用它们。挺好。但总有一刻,这不再够用——你有一个内部 API、一个数据库、一段只有你懂的脚本,而你想让 Claude 直接碰它,而不是把输出复制粘贴到聊天里。就在那里,你从消费转向发布。一个 MCP 服务器就是那个标准插座:你把你的工具描述一次,任何讲这门协议的 AI 都能像调用自己的一样调用它们。FastMCP 是那个包裹官方 MCP SDK(Anthropic 开源的那个)的 TypeScript 框架,它替你卸下样板代码的负担——就像 Express 在 Node 的 http 模块之上给你的那一跃。在这份指南里,我们从十五分钟里一个走 stdio 的 'add' 工具,走到带 Zod schema、自我校验的工具、暴露数据的 resources、可复用的 prompts,最后是真正的生产:认证、HTTP streaming、会话和 edge。到最后,你会拥有一个 Claude Code 真会调用的、属于你自己的 MCP——不是一个 demo,是一根连着你世界的、属于你的管道。

Jul 19, 202616 min
这份内容写给谁?
写给你——一个已经会消费 MCP 的人。你装了 GitHub 的、Playwright 的,也许还有 agent-browser,你的 AI 每天都在用它们。现在你手上有个它们都没覆盖的东西:一个内部 API、一个装着你客户数据的数据库、一个跑着你业务里那点古怪魔法的脚本。你想让 Claude 直接调用它,而不是像个跑腿的把输出粘到聊天里。这份指南就是过河的那一步:从别人 MCP 的租客,变成你自己 MCP 的作者。你懂一点 TypeScript,不必是专家。一个下午,你就能拥有一个 Claude Code 真正会调用的服务器。

那个时刻:当消费不再够用

你已经把 AI 连着各种工具用了好几周。你让它打开浏览器,它就开;你让它读个仓库,它就读。这些全都是别人写的 MCP——某人发布、你安装的标准插座。它们能用,是因为大家讲一门共同语言:Model Context Protocol,一个开放标准,让任何 AI 都能发现并调用外部工具,而不必和其中任何一个耦合。

那个时刻会在你需要的东西不存在为 MCP 时到来。你有个内部端点会返回订单状态。一张只有你会读的电子表格。一段 40 行、算着你领域里某个特定东西的脚本。今天,每次你想让 AI 用它,你都得跳一遍跑腿舞:你自己执行,复制输出,粘到聊天里,等待。做一次没问题。到第十次,你会开始纳闷,为什么 AI 不自己来。

插座的类比
在标准插座出现之前,每个电器都自带一根焊死在墙上的线。你一搬家,什么都对不上。插座解决了这件事:一个接口,一千种电器。一个 MCP 服务器对 AI 来说正是如此。你用协议把你的工具描述一次,任何会讲这门语言的客户端——Claude Desktop、Claude Code,或其他——都能插上它,而完全不需要了解你内部的代码。你不再焊线了。

这份资源合上了一个闭环。在 agent-browser 里,你学会了给 AI 一种外部能力去消费世界——看页面、点击、抽取。这里,你把镜头转过来:你学会发布你自己的能力,让别的 AI 去消费。从用户到作者。同一个协议,只是从电线的另一头看过去。

那个痛点:官方 SDK 很强,但不友好

当你第一次打开官方 MCP SDK,那种感觉就像掀开一辆赛车的引擎盖:一切都在那儿,一切都正确,但没有一样是显而易见的。你得手动注册 handler,映射协议的 request,把响应序列化成客户端期望的确切格式,管理连接周期,自己解析输入参数并校验。就为了暴露一个把两个数字相加的工具,你要在真正做加法那一行之前,写下几十行管道代码。

这份痛从哪来?来自官方 SDK 有意做成低层。它是构建之上的基座,不是最终的人体工学——就像 Node 的 http 模块虽然正确,但没人会直接拿它写 Web 服务器,大家用 Express。SDK 给你对协议的完全掌控;代价是所有样板代码都压在你身上。对构建框架的人来说这没问题。对只想插上自己 API 的人来说,它并不友好。

如果你不过这条河会怎样(诚实,不夸张)
你继续当消费者,什么也不会坏。你装好的那些 MCP 照常工作。但你会撞上一个天花板:你的 AI 只能碰别人已经打包好的东西。你的内部 API、你的数据库、你的业务逻辑——这一切都留在玻璃的另一侧,而你当那个跑腿的,粘着输出。这不是什么严重事故。这是一种能力,你日复一日把它留在桌上,直到某个竞争对手把它捡走。

FastMCP 的存在正是为了抹掉那些样板代码。它是一个 TypeScript 框架,包裹着官方 MCP SDK——不是取代它,而是站在它之上——给你一套声明式 API:你描述工具、它的 schema 和它的函数,剩下的 FastMCP 全包(注册、序列化、连接周期、校验)。那个相加的工具,从那团管道代码缩到十来行出头。而且都是重要的那几行:真正做加法的那些。

punkpeye/fastmcp
REPO

用于构建 MCP 服务器、免去样板代码的 TypeScript 框架。它站在官方 MCP SDK(@modelcontextprotocol/sdk,Anthropic 开源的那个)之上,加上了带 schema 校验的工具(Zod 及其他 Standard Schema)、resources、prompts、认证、HTTP streaming、会话,以及一个开发用的 CLI。这是从一个想法走到 Claude 真正会调用的 MCP 服务器最快的方式。

TypeScriptMITView on GitHub

习惯:在哪些时刻你该发布一个 MCP

发布一个 MCP 服务器不是那种做一次就忘的事。它是一种在特定时刻被触发的反射。学会识别它们,你就永远知道,什么时候值得花那点时间去构建它。

呼唤一个属于你自己 MCP 的时刻
你在重复跑腿舞。 如果你第三次手动执行某件事、再把输出粘到聊天里,那件事就想成为一个工具。
你有个内部 API,AI 本该能碰它。 订单状态、指标、你自己的一套 CRUD——包一次,从任何客户端都能用。
你想让多个 agent 共享一种能力。 一个 MCP 就是一个公共插座:写一次,你所有的 agent 都能插上。
你的业务逻辑活在一段脚本里。 那个只有你懂的古怪计算,值得成为一个有名字、有 schema 的工具,而不是一段复制粘贴。
你需要的是上下文数据,而不是动作。 那里不该放工具:该放一个 resource(我们会讲到)。文档、日志、AI 会读的配置。
你在重复同一份 prompt 模板。 MCP 的一个 prompt 把它打包,用一个名字提供给任何客户端。
第三次复制粘贴法则
你第一次把输出粘到聊天里,那是探索。第二次,是巧合。第三次是个信号。 当你察觉自己第三次在某个自己的工具和 AI 之间当人肉桥梁时,停下。那已经不是一次性活儿了:那是一个等着诞生的工具。你花在包装它上的那点时间,第一周就回本了。

备好场地(2 分钟)

FastMCP 像任何 npm 包一样安装。它跑在现代 Node 上,带 TypeScript。一个最小的新项目,一个文件夹里三个文件就够了。

bash
# En una carpeta nueva para tu servidor
mkdir mi-mcp && cd mi-mcp
npm init -y

# FastMCP + Zod (para los esquemas de entrada) + tsx (para correr TS sin compilar)
npm install fastmcp zod
npm install -D tsx typescript
为什么用 Zod
Zod 是那个描述每个工具输入数据形状的库:a 是数字,email 是符合邮箱格式的字符串,edad 是可选的整数。FastMCP 拿着这个 schema,免费帮你做两件事:(1) 告诉客户端你的工具期望哪些参数,好让 AI 把它们填对;(2) 在输入到达你代码之前就校验它。如果 AI 发来垃圾,拦下它的是 schema,不是你的函数。它是门口一个你不必自己写的守卫。(FastMCP 也接受同一标准下的其他校验器——ArkType、Valibot——但 Zod 是走得最多的那条路。)

你的第一个服务器:'add' 工具(15 分钟)

我们从 MCP 的“hello world”开始:一个只有一个工具、把两个数字相加的服务器。它故意很蠢——重点不是加法,而是看清整条电线:定义服务器、注册一个带 schema 的工具、把它启动起来,并让 Claude 调用它。一旦你有了这副骨架,其余一切都是变体。

typescript
// server.ts
import { FastMCP } from "fastmcp";
import { z } from "zod";

const server = new FastMCP({
  name: "Mi Servidor",
  version: "1.0.0",
});

server.addTool({
  name: "add",
  description: "Suma dos números",
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return String(args.a + args.b);
  },
});

server.start({
  transportType: "stdio",
});

从上到下读一遍,因为这个模式会在你构建的一切里重复。new FastMCP 用名字和版本创建服务器——那就是 Claude 会在连接列表里看到的。addTool 注册一个工具:一个名字(AI 用它来调用)、一段描述(AI 读它来决定何时使用——写好它,这是面向机器的定向营销)、作为 Zod schema 的 parameters,以及 execute,那个真正运行的函数。你返回一个字符串,FastMCP 帮你把它包进协议格式。

stdio:本地插座
transportType: "stdio" 意思是服务器通过标准输入和输出说话——就是终端程序接收和发出文本的那同一个通道。它是最简单的传输方式:客户端(Claude Code)把你的服务器当作一个子进程启动,并通过那根管子和它对话。零网络,零端口,零配置。非常适合你自己的本地工具。当你想把它暴露到互联网上时,你会把这个传输换成 HTTP——但作为开头,stdio 就是你需要的全部。

连接之前先测它:FastMCP 的 CLI

在把它插到 Claude 之前,先隔离测它。FastMCP 自带一个 CLI,能启动你的服务器并让你和它对话,外加官方的 MCP Inspector,让你在可视化界面里看它。这是你的开发循环:改代码,在这里测,只有当它能用时才接到真正的客户端上。

bash
# Arranca tu servidor en modo desarrollo (interactúas con los tools)
npx fastmcp dev server.ts

# Ábrelo en el MCP Inspector (interfaz visual para inspeccionar tools/resources/prompts)
npx fastmcp inspect server.ts
黄金循环
别每改一个逗号就连一次 Claude。那样又慢又污染测试。把 npx fastmcp dev 当你的工作台:在那儿你能看到原始的报错、确切的输出、你服务器发布出来的 schema 本身。只有当工具做到你想要的样子时,你才迈出把它连到客户端那一步。就像你不会为了测一个 if 而部署到生产——先在本地测。

把它连到 Claude Code(让它真的调用起来)

就在这里,它从一次练习变成真事。一个 MCP 客户端(Claude Desktop、Claude Code)把你的服务器当子进程启动,并通过 stdio 和它说话。它只需要知道怎么启动它:什么命令、什么参数。这活在一个配置文件里,里面是 MCP 服务器的清单。

json
{
  "mcpServers": {
    "mi-servidor": {
      "command": "npx",
      "args": ["tsx", "/ruta/absoluta/a/mi-mcp/server.ts"]
    }
  }
}

command 是启动你服务器的可执行文件,args 是它的参数——这里我们用 npx tsx 直接跑 TypeScript,不必编译。用绝对路径:客户端不知道你从哪个文件夹启动它。保存并重启客户端后,你的服务器就出现在列表里,当你让 Claude “把 128 和 45 相加”,你会看到它调用你的 add 工具,而不是自己心算。那个时刻——你第一个工具被 AI 自己调用——就是让人上瘾的那一刻。

相对路径:经典错误
连本地 MCP 时的头号失误,是在 args 里放了相对路径(./server.ts)。客户端从它自己的工作目录启动子进程,不是你的,所以 ./server.ts 指向虚无,服务器起不来——通常还是无声无息。如果你的 MCP 没出现或连接失败,先查这个:绝对路径,永远。

升级:会自我校验的 Zod schema

add 工具用 Zod 只做了最起码的事。但真正的力量,出现在真实工具上——那里输入有形状、有规则。想象一个创建用户的工具:email 必须符合邮箱格式,年龄必须是正整数,角色只能是一个列表里的某一个。用 Zod,你把这一切描述出来,FastMCP 会在无效输入触碰你代码之前把它拒掉。你永远不用写一句 if (!email.includes('@'))。schema 就是那个守卫。

typescript
server.addTool({
  name: "crear_usuario",
  description: "Crea un usuario en el sistema con validación completa",
  parameters: z.object({
    nombre: z.string().min(2),
    email: z.string().email(),
    edad: z.number().int().positive().optional(),
    rol: z.enum(["admin", "editor", "lector"]),
  }),
  execute: async (args) => {
    // Si llegaste aquí, args YA está validado: email es email, rol es válido.
    const usuario = await miBaseDeDatos.insertar(args);
    return `Usuario ${usuario.id} creado con rol ${args.rol}`;
  },
});
schema 是活的文档
那个 Zod schema 干着三份活。一:它校验——没有无效的东西能进来。二:它记录文档——客户端向 AI 精确展示这个工具期望哪些字段、什么类型,好让 AI 把参数填对而不是瞎猜。三:它做类型——在 execute 里,args 带着 TypeScript 类型进来,还有自动补全。一个代码块,又校验、又文档、又类型。这正是官方 SDK 逼你手写三遍的东西。

Resources:暴露数据,而不只是动作

工具是个动词——AI 执行它来让某件事发生。但有时你不想要一个动作,你想给出上下文:一个日志文件、一份配置文档、一个 README 的内容。为此存在着 resources。它们是你服务器暴露、AI 在需要时可以读取的数据,由一个 URI 标识。把工具想成遥控器上的按钮,把 resources 想成展示信息的屏幕。

typescript
server.addResource({
  uri: "file:///logs/app.log",
  name: "Logs de la Aplicación",
  mimeType: "text/plain",
  async load() {
    const contenido = await fs.readFile("/var/log/app.log", "utf-8");
    return { text: contenido };
  },
});

uri 是 resource 的唯一标识符——客户端用它来请求。mimeType 告诉 AI 内容是什么类型(纯文本、JSON、markdown),好让它正确解读。而 load 是有人请求时把内容取来的那个函数——设计上是惰性的:不到需要时不读文件。对于二进制数据,你返回 base64 的 { blob } 而不是 { text }。一个 resource 是干净地说“AI,这里有新鲜数据,等你需要时来取”的方式,直到那个确切时刻才在 prompt 里消耗它们。

Prompts:打包你可复用的模板

协议的第三种原料是 prompts。如果你有一份一直在用的模板——“根据这个 diff 生成一条 commit 信息”“用这个格式总结这场会议”——MCP 的一个 prompt 就把它连同一个名字和几个参数打包,任何客户端都能调用它。你不再复制粘贴同一长串指令:你把它当作服务器的又一种能力提供出来。

typescript
server.addPrompt({
  name: "git-commit",
  description: "Genera un mensaje de commit a partir de un diff",
  arguments: [
    {
      name: "changes",
      description: "El diff de git o una descripción de los cambios",
      required: true,
    },
  ],
  load: async (args) => {
    return `Genera un mensaje de commit conciso para estos cambios:\n${args.changes}`;
  },
});
Tools、resources、prompts:协议的三个动词
有了这三样,你就能构建任何 MCP 服务器。Tools = AI 执行的动作(创建、搜索、发送)。Resources = AI 读取的数据(日志、文档、配置)。Prompts = AI 复用的模板(格式、反复出现的指令)。你的大部分工作都会是 tools。但知道另外两个的存在,能让你不至于把一个其实是 resource 或 prompt 的东西硬塞进一个 tool 里。

迈向生产:从 stdio 到 HTTP streaming

上面这一切都跑在 stdio 上:本地的、你自己的、你机器上的一个子进程。作为开头很完美。但当你想让别人用你的 MCP——你的团队、一个客户、你自己从好几个地方——你需要把它暴露到互联网上。这时 HTTP streaming 传输就登场了:不再是一根本地管子,你的服务器监听一个端口,通过 HTTP 用事件流响应。你工具的代码一行都不变;你只改它怎么启动。

typescript
server.start({
  transportType: "httpStream",
  httpStream: {
    port: 8080,
    endpoint: "/mcp", // opcional, por defecto es /mcp
  },
});

那就是全部的开关。同样的 tools、同样的 resources、同样的 prompts——现在通过 HTTP 服务在 8080 端口、/mcp 端点上。一个远程客户端指向 https://tu-dominio/mcp 就插上了。就在这里,你的 MCP 从一个个人工具变成了一项服务。也在这里,那个把玩具和产品分开的问题出现了:谁能调用它?

认证:锁 + 管道的信条

一个没有认证、走 HTTP 的 MCP,是一扇敞开的门:任何知道 URL 的人都能调用你的工具、碰你的数据库、耗你的资源。FastMCP 用一个 authenticate 选项解决这个:一个在每次连接时运行的函数,它检视请求(headers、API key、token),决定放不放行。如果放行,它返回一个会话对象,这个对象会在每个工具内部可用。

typescript
const server = new FastMCP({
  name: "Mi Servidor",
  version: "1.0.0",
  authenticate: (request) => {
    const apiKey = request.headers["x-api-key"];
    if (apiKey !== process.env.MCP_API_KEY) {
      throw new Response(null, { status: 401, statusText: "Unauthorized" });
    }
    return { id: 1, role: "user" }; // esto se vuelve la sesión
  },
});

server.addTool({
  name: "sayHello",
  execute: async (args, { session }) => {
    return `Hola, usuario ${session.id}!`; // session viene de authenticate
  },
});
锁与管道
在这里,集成世界里的一条关键信条变得可触:认证是锁,MCP 是管道,而它们相结合。MCP 协议搬运调用(管道)。但谁有权通过那根管道搬东西,由锁来决定——API key、OAuth、authenticate 校验的那个 token。它们不是对手:一个生产级 MCP 是带锁的管道。没有锁,你的管道就是一个谁都能拧开的公共水龙头。
API key 放在环境变量里,绝不放在代码里
注意 process.env.MCP_API_KEY。这个 key 绝不在代码里写死,也不上传到 git——这是密钥那份资源里同一条黄金法则:出仓库,放在环境变量或密钥管理器里。一个把 key 硬编码的 MCP,是一扇门上漆着“已锁”、却根本没有真锁的 MCP。任何看到代码的人,都能进。

会话、进度与流:会呼吸的工具

真实的工具不是瞬时的。一个处理大文件、调用慢 API 或生成内容的工具要花上几秒。FastMCP 在 execute 内部给你一个上下文,带着一些工具,让那个工具呼吸:上报进度、流式发出内容、记录日志,并访问已认证用户的会话。

typescript
server.addTool({
  name: "procesar_lote",
  description: "Procesa un lote reportando progreso en vivo",
  parameters: z.object({ total: z.number() }),
  annotations: { streamingHint: true },
  execute: async (args, { streamContent, reportProgress, log, session }) => {
    log.info(`Iniciando lote para ${session.id}`);
    await streamContent({ type: "text", text: "Empezando..." });
    await reportProgress({ progress: 50, total: 100 });
    // ... trabajo real ...
    return "Completado";
  },
});

reportProgress({ progress, total }) 告诉客户端“我进行到 50% 了”,AI(和人)于是看到一条进度条,而不是一片令人焦虑的沉默。streamContent 随着内容生成一块块地发出输出,而不是等到最后——这是看着文字浮现,和盯着一个转圈圈之间的差别。log 留下结构化的痕迹供调试。而 sessionauthenticate 校验过的那个用户,于是每个工具都知道在调用它。有了这些,你的工具不再是耗时的黑盒,而变成可观察的过程。

那条主 PROMPT:启动你的 MCP 服务器

这就是你唯一需要保存的 prompt。与其手写服务器,你把它描述给你的 AI——它面前已经有了这份指南里 FastMCP 的全部上下文——它就会生成完整的骨架,测试过的、可以直接连接的。用你真实的情况填好方括号,让它去构建。只有一个 prompt,不是五个:这一个就把整个项目启动起来。

MCP 服务器生成器text
扮演一名资深 MCP 工程师。我们要用 FastMCP(那个包裹官方 MCP SDK、Anthropic 开源的那个框架;用 `npm install fastmcp zod` 安装)在 TypeScript 里构建一个 MCP 服务器。

我的服务器:
- 名称:[你服务器的名称,例如 "CRM Interno"]
- 它暴露什么:[用 2 行描述你想让 AI 碰的工具/数据]

我需要的 TOOLS(AI 会执行的动作):
1. [nombre_tool] — [做什么] — 输入:[字段及其类型/规则]
2. [nombre_tool] — [做什么] — 输入:[字段及其类型/规则]

RESOURCES(AI 会读取的数据,如适用):
- [nombre] — [暴露什么数据,例如日志、配置]

模式:[开发时从 "stdio local" 开始 | 之后为了生产迁移到 "httpStream con autenticación por API key"]

请构建:
1. 完整的 server.ts:带名称和版本的 `new FastMCP`,每个工具用 `addTool`(name、清晰的、面向让 AI 知道何时使用它的 description、作为真正会校验的 Zod schema 的 parameters——该用的地方用 .email()、.int().positive()、.enum(),可选项用 .optional(),以及带类型的 execute)。
2. 如果我要了,用 `addResource` 写 resources(uri、name、mimeType、返回 {text} 或 {blob} 的惰性 load)。
3. 用我选的传输方式写 `server.start`(stdio,或带 port/endpoint 的 httpStream)。
4. 如果我要了生产:`authenticate` 选项,从 `process.env` 读 API key(绝不硬编码),不匹配时抛 `new Response(null, {status: 401})` 并返回会话,外加一个使用 `session` 的工具。
5. 用来把它连到 Claude Code 的 `mcpServers` JSON 块,用 `npx tsx` 和绝对路径。
6. 确切的命令:安装、用 `npx fastmcp dev server.ts` 测试、用 `npx fastmcp inspect server.ts` 检视。

约束:代码里零密钥;工具的描述要写成 让 AI 能很好地决定何时调用它们;用 Zod 校验所有输入,不要手写 if。在代码前用一行向我解释每个工具。
如何使用这个 prompt
别一发就走。从 stdio local 模式、一两个工具开始——用 npx fastmcp dev 能测的最小量。当它能用、Claude 真的会调用它时,再回到同一个 prompt,把模式换成带认证的生产。这样你是分层地、可验证地构建,而不是吐出一个没测过的巨型服务器。并应用一贯的习惯:先给能用的骨架来一个 commit,再来其余的。

最省事的路径:聊天 vs. 网页

发布一个 MCP,根据你站在哪儿有两条路,值得知道各自何时该走。

通过聊天(和你的 AI 一起,生成代码)
从零开始时最理想。 粘上那条主 prompt,描述你的工具,AI 就生成完整的 server.ts,带 Zod、传输方式和配置。
快速迭代时最理想。 “加一个按 id 删除的工具”“把 stdio 换成带 auth 的 httpStream”——在同一个文件上做对话式改动。
连接时最理想。 AI 给你带正确路径的 mcpServers 块,以及 fastmcp dev 的命令,让你在插上之前先测。
通过网页 / 终端(你亲自掌舵)
做真正的部署。 把 HTTP 服务器上到某个 host(edge、一个容器、你的 VPS),配置域名,以及带 API key 的环境变量。
做隔离测试。 npx fastmcp inspect server.ts 打开可视化的 Inspector——在那儿你像客户端一样看到你的 tools、resources 和 prompts。
做版本管理。 在加更多东西之前,给能用的骨架来个 git commit——在 AI 弄坏什么之前先保存的习惯,依然是老大。

完整的弧线:从消费者到作者

退后一步,看看这条路。你从消费别人写的 MCP 开始——你的 AI 用着别人的工具。你用 agent-browser 学会给它一种能力去看、去碰世界。而在这里,用 FastMCP,你把镜头转过来:现在你发布你自己的能力,让任何 AI 去消费。一个十五分钟的 add 工具,变成了带 Zod、resources、prompts、认证和 HTTP 的工具。你合上了用户→作者的弧线。你不再是 MCP 生态的租客:你是一个插座的主人。

在 NeuralOS 里:已经接好线的工具目录
你在这里手工构建的一切——包一个 API、给它上一把锁、把它当管道暴露——正是 NeuralOS 在它的集成里已经替你解决的工作:一个引擎,把每个服务连同它的认证接好线,并把凭证存进一个按租户加密的 Vault,还支持多账户。它是一个已经搭好、已经上锁的工具目录。而 MCP 前线(B8)——今天它还作为界面里的一个愿景存在——指向让那个目录讲你刚学会发布的同一门标准协议。你为你那些古怪的东西写你自己的 MCP;NeuralOS 替你省下那些常见的,已经接好线、上好锁。管道和锁,无需写样板代码。
Agent-browser:别让你的 AI 蒙着眼构建
弧线的另一头:你学会了去消费一种外部能力。这份资源教你去发布你自己的。把它们一起读,看清完整的用户→作者循环。
保护你的应用:RLS、CORS 和 headers
你走 HTTP 的 MCP 是一个暴露的表面。在把它向世界敞开之前,锁(认证)、CORS 和 headers,就是一根安全管道和一个公共水龙头之间的差别。
#MCP#TypeScript#FastMCP#Claude Code#Agentes#Zod
Ready to build?

Start building in
under 3 minutes

Join 4,200+ builders. No credit card. Build your first app with AI in minutes.