待办事项管理MCP服务器

一个基于Bun运行时和MCP协议的待办事项管理服务器,通过VS Code Copilot聊天代理模式提供任务增删改查功能。

  • by TomasHubelbauer
  • TypeScript
  • 本地部署
  • 5 星标
  • 更新于
在 GitHub 查看 TomasHubelbauer/bun-mcp

使用说明

Bun MCP

此存储库的目标是原型化 MCP(模型上下文协议) 服务器使用 包子 运行时并通过VS使用其工具 代码复制聊天代理模式。

我首先阅读了模型上下文协议文档。 在MCP文档的命名中,我们将使用以下元素:

  • 主机与客户端:VS Code与Copilot在代理模式下聊天
  • 服务器:此存储库中实现的脚本

对于此设置,文档有一个特定的学习路径:

面向服务器开发人员

MCP服务器通过公开类似于REST端点和LLM的工具来工作 如果MCP客户端确定用户提示,则可以调用这些工具 可以从该工具能够提供的数据中受益。

文档页面提供了一个示例天气服务MCP服务器,这是一个 这是一个很好的例子,因为LLM不能提供天气信息 天气预报是实时数据,因此无法通过 LLM

我将构建一个能够管理MarkDown文件中待办事项列表的MCP服务器。 MCP服务器的目标是为用户提供创建和 通过允许他们添加、切换和删除待办事项来维护此文档。

值得一提的是,MCP服务器可以提供不同类型的数据 对于MCP客户端:

  • 资源:文件和数据blob的内容
  • 工具:LLM调用和使用以下结果的方法
  • 提示:预定义的提示,帮助改进用户提示以获得最佳结果

与文档页面中一样,我的MCP服务器将只专注于提供工具。

与文档页面不同,我将使用Bun而不是Node。 尽管如此,我可能仍然能够从参考中受益 实施 这里.

教程页面包括一个基于SDK包的服务器实现。 我会先走这条路,但最后,我想建立一个服务器 从头开始,实现原始协议。

据我所知,这应该不是很难,因为服务器有能力 通过标准I/O和服务器发送的事件进行通信,这两者都是基本的 无需任何依赖即可实现。

  • []删除SDK包,使用直接MCP协议重建服务器

在他们之前,我将首先添加 @modelcontextprotocol/sdk 包裹 作为依赖使用 bun add @modelcontextprotocol/sdk.

Bun将创建 package.json 与我所有的个人项目一样,我 我正在将版本更改为 latest 这样项目就不会陷入困境 旧版本。

package.json:

{
  "dependencies": {
    "@modelcontextprotocol/sdk": "latest"
  }
}

我还添加了一个 .gitignore 文件并忽略 node_modules 和 bun.lock. 我不做依赖性销售,也不需要锁文件,因为所有 无论发生什么,依赖项都应该始终安装在最新版本。

服务器的肉和土豆将存储在一个名为的新文件中 index.ts. 我假设在客户端配置中,我将能够通过 命令和参数,如果是这样的话,将使它变得非常容易 只是指定 bun .作为命令和参数对。

我的脚本将是ESM,不会像往常一样有构建步骤。 它将通过Bun的原生TypeScript支持使用TypeScript,并且不会覆盖 Bun的默认TypeScript配置。

此基本MCP SDK import 服务器清单规范如下:

index.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

const server = new McpServer({
  name: "to-do",
  version: "0.0.0",
  capabilities: {
    tools: {},
  },
});

下一步是注册MCP服务器要公开的工具。 我将从一个开始- list-todos 现在它将返回硬编码数据。

server.tool("list-todos", "Lists all to-do items in the TODO.md file", () => {
  return {
    content: [
      {
        type: "text",
        text: "- [ ] Do the dishes\n- [ ] Go grocery shopping\n- [ ] Plan the weekend trip",
      },
    ],
  };
});

定义了工具后,是时候配置服务器传输了,以便 客户端知道如何与服务器通信。 这需要一个新的 import 在文件顶部,我选择使用标准 I/O用于此。

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

// …

const transport = new StdioServerTransport();
await server.connect(transport);

此时,是时候测试MCP服务器了。 文档页面演示了如何使用Claude完成此操作,因此我将推迟 在其他地方学习如何在VS Code中配置它。

MCP上的VS Code文档列出了几个选项: https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-mcp服务器

我更喜欢工作区配置选项,所以我创建了一个空的 .vscode/mcp.json 此存储库的工作区中的文件,并在 新的VS代码选项卡。

VS Code识别此特殊路径,并在以下位置显示一个名为“添加服务器”的按钮 文件编辑器区域的右下角。

我单击了按钮并选择了Command(stdio)选项。

在这一点上,必须进行一些摆弄和实验。 我首先尝试的命令只是 bun,但我没有意识到这种流动会 不要要求我为这个命令辩护。 它询问的另一件事是服务器名称,我把它放在哪里 to-do.

服务器启动失败,在MCP的输出窗格中:待办事项通道I 可以理解为什么-VS Code主机执行了命令并开始解释 其标准I/O流用于传输。

但由于命令只是 bun,当否时,它会打印默认输出 提供或发现脚本。 这些行未能解析为MCP消息,因此连接失败 成立。

这是不正确的配置:

{
  "servers": {
    "to-do": {
      "type": "stdio",
      "command": "bun",
      "args": []
    }
  }
}

此时,我开始调整JSON代码本身,而不是依赖于 VS代码UI流。

我想一个简单的修复方法是将命令更改为 bun . 因此,Bun 调用并尝试启动 index.ts.

我点击了VS code放在服务器条目的重启代码镜头。 这再次导致了一个错误。

似乎定义为命令的MCP服务器没有在 工作区目录。 为了验证这一点,我将命令更改为 pwd 并重新运行它。 此打印 /Users/tom 证实了我的怀疑。

从这里有多种选择。 我不想硬编码脚本的完整路径作为Bun的参数, 所以我想我可以依靠VS代码配置替换: https://code.visualstudio.com/docs/reference/variables-reference

我将命令更改为 echo '${workspaceFolder}' 看看它是否会打印出来 在“输出”窗口中输入变量的值,然后再次单击“重新启动”。

这打印出了预期的目录! 当然,服务器还没有启动,但此时我知道了最终的结果 命令必须是 bun ${workspaceFolder}. 我惊讶地发现这也不起作用,但我很快意识到我应该通过考试 这 workspaceFolder 变量作为参数 args 取而代之的是现场。

我将命令更改为 echo 再次确保一切正常 按预期工作:

{
  "servers": {
    "to-do": {
      "type": "stdio",
      "command": "echo",
      "args": ["${workspaceFolder}"]
    }
  }
}

此打印 [warning] Failed to parse message: "/Users/tom/Desktop/bun-mcp\n" 让我知道变量替换和命令传递有效。

我可以改变 command 向 bun 现在,让服务器启动。 服务器入口顶部的代码镜头变为“正在运行…”,我看到一阵骚动 输出选项卡中的活动:

[info] Connection state: Starting
[info] Starting server from LocalProcess extension host
[info] Connection state: Starting
[info] Connection state: Running
[info] Discovered 1 tools

这意味着我的MCP服务器及其唯一工具被发现,我可以尝试提示 这应该会在代理模式下在VS Code GitHub Copilot聊天窗格中触发它。

我使用命令右侧的Copilot图标打开了GitHub Copilot聊天 VS Code窗口顶部中心的栏。

它以询问模式启动,所以我将该开关切换到代理。 这为聊天编辑器带来了一些新图标:开始语音聊天,选择工具 以及发现可用工具/新工具(如果不适用,则隐藏)。

我点击了“选择工具”按钮,并查看了打开的列表 to-do 服务器已列出并与其一起检查 list-todos 工具!

这意味着我的提示现在应该可以使用这个工具了。 我问Copilot:

我的清单上有什么待办事项?

它要么不够聪明,要么太聪明,因为它使用了复选框列表 在这个README文件中(该文件作为参考自动包含在聊天中 如提示输入区域顶部的项目所示),并通过列出 其中的待办事项复选框。

我点击了旁边的眼睛图标 readme.md 删除当前文件引用 从提示上下文中重新运行相同的提示。

这次,Copilot Chat问我是否要允许 to-do MCP服务器 运行 list-todos 该工具具有“继续”和“取消”按钮。 我选择了“继续”按钮旁边的V形图标,并选择了“始终允许进入” 此工作区允许我的MCP服务器在 从现在开始使用此存储库目录。

Copilot聊天更改为表示它运行了 list-todos 我的工具 to-do 服务器并返回:

您当前的待办事项列表包含以下项目: <input disabled="" type="checkbox"> 洗碗 <input disabled="" type="checkbox"> 去杂货店购物 <input disabled="" type="checkbox"> 计划周末旅行 如果您想添加、删除或更新任何这些任务,请告诉我!

有趣的是,MarkDown复选框不会在Copilot聊天UI中呈现,所以我 我想我将不得不使用表情符号,当我改变工具不返回 硬编码数据。

此外,尽管我有MCP服务器,Copilot相信它可以帮助我编辑此列表 还没有公开这样做的工具。 我会把这归结为幻觉/不够聪明的提示 MCP服务器交互。

下一步,我将添加一个用于创建新待办事项和更改的工具 现有的列出待办事项的工具可以使用内存存储,这样我 可以添加并列出此新待办事项。

当涉及到使用参数注册工具时,MCP SDK似乎是绑定的 Zod用于MCP工具参数结构的模式验证。 我不喜欢这样,在我未来的实施中,我会实施MCP 通过手动协议,我将放弃对Zod的依赖,但现在我会遵守并 使用它:

bun add zod

package.json:

{
  "dependencies": {
    "@modelcontextprotocol/sdk": "latest",
    "zod": "lates"
  }
}

我是这样改变的 index.ts 为了实现这一点:

import { z } from "zod";

// …

const todos: { name: string; isChecked: boolean }[] = [];

server.tool("list-todos", "Lists all to-do items in the TODO.md file", () => {
  return {
    content: [
      {
        type: "text",
        text: todos
          .map((todo) => `${todo.isChecked ? "✅" : "❎"} ${todo.name}`)
          .join("\n"),
      },
    ],
  };
});

server.tool(
  "add-todo",
  "Adds a new to-do item to the TODO.md file",
  {
    name: z.string().describe("The name of the to-do item"),
  },
  ({ name }) => {
    const newTodo = { name, isChecked: false };
    todos.push(newTodo);

    return {
      content: [
        {
          type: "text",
          text: `Added new to-do item: ${newTodo.name}`,
        },
      ],
    };
  }
);

// …

做出这些更改后,我去了 mcp.json 再次单击选项卡并按下 重新启动代码镜头操作以使更改生效。

另一个代码镜头项目更改为“2个工具”,表示更改了 确实发生了,并得到了“输出”窗格日志的进一步证实 MCP:待办事项通道,现在添加了以下行:

[info] Stopping server to-do
[info] Connection state: Stopped
[info] Starting server to-do
[info] Connection state: Starting
[info] Starting server from LocalProcess extension host
[info] Connection state: Starting
[info] Connection state: Running
[info] Discovered 2 tools

我将当前的文件引用保存在Copilot聊天上下文之外,并询问 它为我添加了一个新的待办事项:

添加待办事项以购买晚餐杂货

系统再次提示我继续或取消 to-do MCP服务器呼叫, 这一次为 add-todo 工具,我觉得很惊讶,我想这 检查是按每个工具而不是按服务器进行的 最初预计。

我再次在“继续”下拉菜单中选择了“始终在此工作区”选项。

副驾驶回答:

你的清单上增加了一个新的待办事项“购买晚餐杂货”。 如果你需要查看、更新或删除任何待办事项,请告诉我!

我扩展了“Ran” add-todo“Copilot响应顶部的框进行深入分析。 它根据提示打印了它制作的输入以及来自的输出 MCP服务器。

输入:

{
  "name": "Buy groceries for dinner"
}

输出:

新增待办事项:购买晚餐杂货

接下来,我问我的清单上有什么待办事项:

我的清单上有什么待办事项?

这一次,我没有被提示允许工具运行,它运行时没有中断, 所以提示似乎真的是针对每个工具的。

副驾驶回答:

您当前的待办事项列表包括: <input disabled="" type="checkbox"> 买食品杂货当晚餐 如果你想添加、删除或更新任何待办事项,请告诉我!

检查工具箱以了解详细信息:

输入:

{}

输出:

❎ 买食品杂货当晚餐

因此,Copilot LLM似乎将此工具响应重新格式化为 MarkDown清单本身就意味着我们与损坏的MarkDown发生了冲突 再次在VS Code Copilot聊天中渲染。

我不确定是否可以使用工具来防止这种情况,但MCP服务器 可能会暴露一个提示,该提示将改写简单的查询 将待办事项列表视图转换为更丰富的查询,指示Copilot将列表格式化为 特定方式,可能使用我在代码中使用的表情符号,而不是 MarkDown检查表。

  • []显示一个提示以丰富用户提示,从而避免MarkDown列表呈现

完成待办事项列表管理流程还剩下两件事:切换 以及删除待办事项。

我添加了一个基于关键字切换待办事项的工具,如下所示:

server.tool(
  "toggle-todo",
  "Toggles the completion status of a to-do item",
  {
    keyword: z
      .string()
      .describe("A keyword in the name of the to-do item to toggle"),
  },
  ({ keyword }) => {
    const todo = todos.find((todo) => todo.name.includes(keyword));
    if (!todo) {
      return {
        content: [
          {
            type: "text",
            text: `To-do item containing "${keyword}" not found.`,
          },
        ],
      };
    }

    todo.isChecked = !todo.isChecked;

    return {
      content: [
        {
          type: "text",
          text: `Toggled to-do item "${todo.name}" to ${
            todo.isChecked ? "completed" : "not completed"
          }.`,
        },
      ],
    };
  }
);

我在VS Code中重启了MCP服务器,并询问Copilot:

把晚餐待办事项划掉

我确认始终在此工作区中 toggle-todo 工具调用并执行此操作 回复:

似乎找不到包含“晚餐”的待办事项。 你能确认一下待办事项的确切措辞吗,或者让我知道 最近是否被更改或删除?

我意识到问题是MCP服务器重新启动时丢失了内存存储 状态,所以实际上还有另一件事要做:坚持。

我计划更换 todos 常数,带I/O助手进行读写 将待办事项放入存储器。

为了实现这些助手,我使用了Bun的I/O方法,这要求我添加 Bun类型到依赖项,因此I/O方法可以在TypeScript中访问:

bun add -D @types/bun

package.json:

{
  "dependencies": {
    "@modelcontextprotocol/sdk": "latest",
    "zod": "latest"
  },
  "devDependencies": {
    "@types/bun": "latest"
  }
}

我使用导入Bun import Bun from "bun"; 并意识到,为了 能够为I/O编写助手,我需要确保脚本知道 要使用的目录路径。

我假设脚本的工作目录是 /Users/tom 因为我们 正在调用 bun VS Code工作区的完整路径正是因为 它从那个目录开始。

我决定仍然通过更改默认值来验证这一点 todos 列出完整 脚本运行所在目录的路径:

const todos: { name: string; isChecked: boolean }[] = [
  {
    name: `Know that the working directory is ${import.meta.dirname}`,
    isChecked: true,
  },
];

我重启了服务器,问Copilot我的待办事项是什么,它说:

您当前的待办事项列表包括: <input checked="" disabled="" type="checkbox"> 知道工作目录是/Users/tom/Destop/bun-mcp 如果你想添加、删除或更新任何待办事项,请告诉我!

因此,令人惊讶的是(对我来说),如果通过目录路径调用脚本,我想它 将工作目录设置为该路径。 这稍微简化了一些事情。

我换了 todos 此代码为常量:

const FILE_PATH = "TODO.md";

async function readTodos() {
  const text = await Bun.file(FILE_PATH).text();
  const lines = text.split("\n").filter((line) => line.trim() !== "");
  return lines.map((line) => {
    const isChecked = line.startsWith("- [x] ");
    const name = line.slice("- [?] ".length).trim();
    return { name, isChecked };
  });
}

async function writeTodos(todos: Awaited<ReturnType<typeof readTodos>>) {
  const content = todos
    .map((todo) => `- [${todo.isChecked ? "x" : " "}] ${todo.name}`)
    .join("\n");
  await Bun.write(FILE_PATH, content);
}

我还更新了现有的三个工具,使它们的回调方法 async 并添加 const todos = await readTodos() 使用 todos 工作 再次并添加 await writeTodos(todos) 每当待办事项被修改为 将更改持久化到文件中。

我重新启动了MCP服务器,并以以下提示开始:

将取出垃圾箱添加到我的待办事项列表中

工具调用的输出如下:

ENOENT:没有这样的文件或目录,请打开“TODO.md”

我不记得了 Bun.file().text 会抛出一个不存在的文件 AFAIK没有提供回退内容的机制,因此我更改了I/O 辅助方法如下:

const FILE = Bun.file("TODO.md");

async function readTodos() {
  const text = (await FILE.exists()) ? await FILE.text() : "";
  const lines = text.split("\n").filter((line) => line.trim() !== "");
  return lines.map((line) => {
    const isChecked = line.startsWith("- [x] ");
    const name = line.slice("- [?] ".length).trim();
    return { name, isChecked };
  });
}

async function writeTodos(todos: Awaited<ReturnType<typeof readTodos>>) {
  const content = todos
    .map((todo) => `- [${todo.isChecked ? "x" : " "}] ${todo.name}`)
    .join("\n");
  await Bun.write(FILE, content);
}

我重新启动了MCP服务器,并按了 聊天编辑器,用于回忆上次发送的消息并重新发送。

GitHub Copilot再次变得过于聪明,因为它创造了 TODO.md 单独和 在不调用我的MCP服务器的情况下向其添加了MarkDown复选框。

我重新编写了提示,希望能击中我的MCP服务器:

在我的待办事项列表中添加一个新的待办事项,用于倒垃圾

这导致了完全相同的事情发生,所以我转而问:

我的待办事项清单上有哪些项目?

MCP服务器正确调用了此功能。

您的待办事项列表当前为空。 如果你想添加一个新项目,请告诉我你想包括什么!

我接着说:

添加一个用于倒垃圾的项目

这也不起作用,所以我再次使用了“选择工具”按钮并取消选中 GitHub Copilot Chat下的Codebase选项希望它能阻止它 能够写入文件,但它不起作用,所以我重新打开了它。

我求助于这个提示:

使用我的待办事项列表MCP服务器添加待办事项以取出垃圾

这正确地调用了正确的工具,但我没有看到 TODO.md 如此创建 我问我的待办事项清单上有哪些文件,得知它是空的。

我还不知道如何调试MCP服务器脚本,所以我求助于更多的调试 通过工具结果走私信息,但这次我意识到我应该 使用过的 process.cwd() 而不是 import.meta.dir 整个时间!

  • []了解如何在VS Code调试器下运行MCP服务器脚本

我打消了在工具中添加更多信息的想法,转而去了 直接进入终端应用程序并运行 cd ~ 随后 ls.

这让我看到了 TODO.md 我的macOS用户目录中的文件。 我奔跑 cat TODO.md 并在那里看到了新的待办事项。

这意味着文件被正确写入(尽管缺少EOF换行符), 这就提出了一个问题,为什么我在回复中没有看到新的待办事项 向 list-todos.

但是,首先,我需要找到一种方法告诉MCP服务器 工作区目录是,我无法访问 import.meta.dir,因为这个案子 其中是我使用GitHub Copilot的工作区的工作区目录 与我将其开发为特殊工作区的工作区目录相同 这种情况不会适用于其他工作空间。

我换了 args 线路输入 mcp.json 对此:

"args": ["${workspaceFolder}", "${workspaceFolder}"]

这样我就可以使用 process.argv 并获取脚本的唯一参数(暂且不谈) 脚本文件本身),并从中导出工作目录。

MCP服务器的安装方式不理想,因为 工作区目录是显式传递的,它应该能够请求此类型 信息本身,但目前我不知道如何做到这一点,或者如果 甚至在MCP协议中也支持。

从快速的网络搜索来看,答案可能不是。 我发现了一些提及 process.env.WORKSPACE_FOLDER_PATHS 它不在那里 在我的MCP服务器中 process.env 我还发现了一张纸条 . 扩展到 中的工作区根目录 mcp.json args 配置,我测试了 而且它似乎也不起作用。

目前,我将坚持使用双倍-workspaceFolder 在……里面 args.

  • []提交一个VS代码问题,要求将工作区根传递给MCP服务器脚本

我在MCP服务器脚本的顶部添加了一个检查,以指导用户和更改 工作目录(如果提供正确):

if (!process.argv[2]) {
  throw new Error(
    'Register the MCP server with `args` set to `["${workspaceFolder}", "${workspaceFolder}"]`.'
  );
}

process.chdir(process.argv[2]);

有了这些更改,我现在应该能够重新运行特定的提示,要求 创建一个新的todo并查看 TODO.md 文件似乎是由我的MCP服务器创建的,而不是 Copilot特工本身。

我重新启动了服务器并尝试了。

使用我的待办事项列表MCP服务器添加待办事项以取出垃圾

我看见 TODO.md 内容正确:

- [ ] Take out the trash

此时,我意识到这个特定的存储库,因为 TODO.md 文件是测试数据的一部分,本质上,我应该忽略它。 它只应该在发生这种情况的工作区之外的工作区中不被忽视 使用MCP服务器。

.gitignore:

TODO.md

# NPM
node_modules

# Bun
bun.lock

我再次尝试了“我的待办事项列表上有什么?”提示,它回答说: 没有待办事项。 我怀疑 const 随着 Bun.File 实例可能正在缓存 有些东西,我应该在每次通话中重新创建它 readTodos. 当我重新启动MCP服务器时,这种怀疑变得更加强烈 没有更改,待办事项现在已列出。

我更改了I/O助手,如下所示:

const FILE_NAME = "TODO.md";

async function readTodos() {
  const text = (await Bun.file(FILE_NAME).exists())
    ? await Bun.file(FILE_NAME).text()
    : "";

  const lines = text.split("\n").filter((line) => line.trim() !== "");
  return lines.map((line) => {
    const isChecked = line.startsWith("- [x] ");
    const name = line.slice("- [?] ".length).trim();
    return { name, isChecked };
  });
}

async function writeTodos(todos: Awaited<ReturnType<typeof readTodos>>) {
  const content = todos
    .map((todo) => `- [${todo.isChecked ? "x" : " "}] ${todo.name}`)
    .join("\n");
  await Bun.write(FILE_NAME, content);
}

这带来了正确的行为和东西现在工作! 我还可以让聊天记录将待办事项标记为已完成,这是正确的 呼叫 toggle-todo 工具。

  • []向添加选项参数 toggle-todo 强制直接打开/关闭状态

我添加了另一个通过关键字删除待办事项的工具,类似于 切换它们:

server.tool(
  "remove-todo",
  "Removes a to-do item from the TODO.md file",
  {
    keyword: z
      .string()
      .describe("A keyword in the name of the to-do item to remove"),
  },
  async ({ keyword }) => {
    const todos = await readTodos();
    const index = todos.findIndex((todo) => todo.name.includes(keyword));
    if (index === -1) {
      return {
        content: [
          {
            type: "text",
            text: `To-do item containing "${keyword}" not found.`,
          },
        ],
      };
    }

    const removedTodo = todos.splice(index, 1)[0];
    await writeTodos(todos);

    return {
      content: [
        {
          type: "text",
          text: `Removed to-do item "${removedTodo.name}".`,
        },
      ],
    };
  }
);

这就完成了基本行为。 有很多方法可以改进这个玩具MCP服务器,我将 为未来储蓄。


再次回到这个演示后,我发现LLM可以很聪明 有时甚至足以将简短的提示与MCP服务器工具相关联。

我发现这些类型的提示可以很好地调用 to-do MCP与GitHub Copilot在代理模式下聊天,并使用OpenAI GPT-4.1模型。

这些工作没有 .github/copilot-instructions.md(详见下文)

  • “创建新的待办事项…”
  • “为…制定新的待办事项”
  • “提醒我…”
  • “注意…”

我对那些短的感到非常惊讶! 我无法重现绕过MCP服务器的问题 做一个 TODO.md 即使在重置聊天历史记录时,文件本身也是如此。

关于重置聊天历史记录,以了解提示将如何 在没有先前上下文的情况下处理:

使用Cmd+Shift+P命令调色板条目“聊天:清除所有工作区聊天” 重置GitHub Copilot对话,以确保不采用之前的上下文 在输入新的独立提示时,将其添加到帐户中。

我也发现了 .github/copilot-instructions.md 文件 它将额外的存储库级上下文嵌入到每个提示符/GitHub Copilot中 聊天,可用于引导代理走向所需的行为。

我用它来强迫代理人总是用句子大小写来命名项目 在每次突变后列出更新的列表。

更新到此文件后,将在下一个提示下发送到GitHub Copilot,它 只需保存,无需以其他方式刷新。

HTTP流传输

到目前为止,这个存储库已经实现了标准的I/O传输。 要将其转换为HTTP传输 StreamableHTTPServerTransport 可以使用传输实现。 还有 SSEServerTransport 计划使用服务器发送事件时。

我重新修改了代码,但缺少一部分。 需要运行一个单独的HTTP服务器 handleRequest 使用。 其签名仅与Node服务器兼容:

https://nodejs.org/api/http.html#class-http服务器

Bun.serve 不能用作其 request 和 response 类型不是 兼容的:

https://bun.sh/docs/api/http

我让Claude Code实现Node服务器,并以以下形式对其进行测试 这 test-server.sh Bash文件。

我还通过更新手动测试了它 .github/mcp.json 使用基于HTTP的 传输并使用VS Code GitHub Copilot代理询问与TODO相关的问题 不断使用正确的工具并更新内容和验证 TODO.md.

后来我发现 StreamableHTTPServerTransport 默认为SSE,但这 不同于 SSEServerTransport. 我希望JSON传输能够生成用于测试MCP交换的Bash脚本 更容易测试 jq 所以我打开了 enableJsonResponse 从哪个切换 SSE转换为JSON。

我请Claude Code研究SSE在流媒体方面的差异 HTTP传输和SSE传输,并得出结论 SSEServerTransport 是一个被取代的旧标准 StreamableHTTPServerTransport 哪个 仍然默认为SSE,但可以回退到JSON模式,这对 我的测试在这里。