MCP servers 仓库 Everything Server 项目结构详解:目录布局、模块职责与源码级实现导读
本文基于 src/everything/docs/structure.md 这份官方结构文档展开,逐目录、逐文件地讲解 MCP "Everything" 参考服务器的项目组织方式:入口与传输选择、文档体系、prompts / resources / tools 三大原语的注册编排、server 工厂与 transport 层的落地实现。读完之后,你可以快速定位任意功能对应的源码文件,理解各模块之间的调用关系,并按照仓库既有模式为该服务器新增工具、资源、提示词或传输方式。
总体目录布局
structure.md 首先给出了一份完整的目录树,这是理解整个 Everything Server 的骨架:
src/everything
├── index.ts
├── AGENTS.md
├── package.json
├── docs
│ ├── architecture.md
│ ├── extension.md
│ ├── features.md
│ ├── how-it-works.md
│ ├── instructions.md
│ ├── startup.md
│ └── structure.md
├── prompts
│ ├── index.ts
│ ├── args.ts
│ ├── completions.ts
│ ├── simple.ts
│ └── resource.ts
├── resources
│ ├── index.ts
│ ├── files.ts
│ ├── session.ts
│ ├── subscriptions.ts
│ └── templates.ts
├── server
│ ├── index.ts
│ ├── logging.ts
│ └── roots.ts
├── tools
│ ├── index.ts
│ ├── echo.ts
│ ├── get-annotated-message.ts
│ ├── get-env.ts
│ ├── get-resource-links.ts
│ ├── get-resource-reference.ts
│ ├── get-roots-list.ts
│ ├── get-structured-content.ts
│ ├── get-sum.ts
│ ├── get-tiny-image.ts
│ ├── gzip-file-as-resource.ts
│ ├── simulate-research-query.ts
│ ├── toggle-simulated-logging.ts
│ ├── toggle-subscriber-updates.ts
│ ├── trigger-elicitation-request.ts
│ ├── trigger-elicitation-request-async.ts
│ ├── trigger-long-running-operation.ts
│ ├── trigger-sampling-request.ts
│ ├── trigger-sampling-request-async.ts
│ └── trigger-url-elicitation.ts
└── transports
├── sse.ts
├── stdio.ts
└── streamableHttp.ts
从目录树可以清楚看到分层思路:prompts/、resources/、tools/ 分别承载 MCP 协议三大原语,每个目录内部都是"一个 index.ts 编排器 + 每个功能一个文件"的模式;server/ 负责组装服务器实例;transports/ 负责三种通信方式(stdio、SSE、Streamable HTTP);docs/ 则是随构建一起打包进发行产物的文档集。同一套文档导航中还包括 架构说明、扩展指南、功能清单、工作原理 与 启动流程,结构文档与它们互为补充。
入口层:index.ts、AGENTS.md 与 package.json
index.ts:基于第一个 CLI 参数选择传输
index.ts 是整个服务器的启动入口,逻辑非常克制:
- 读取
process.argv,取第一个参数作为传输名,缺省为stdio; - 通过
switch分支动态import对应的传输模块(./transports/stdio.js、./transports/sse.js、./transports/streamableHttp.js),从而保证只有被请求的传输模块会被加载和执行,避免其他模块在未被使用时就完成初始化; - 遇到未知参数时打印使用说明(
node ./index.js [stdio|sse|streamableHttp])并以退出码 1 结束。
对应到 npm scripts 上,就是 package.json 中的三个启动命令:
"start:stdio": "node dist/index.js stdio",
"start:sse": "node dist/index.js sse",
"start:streamableHttp": "node dist/index.js streamableHttp"
AGENTS.md:面向 Agent 的编码规范
AGENTS.md 是写给 Agent / LLM 的开发者指南,规定了构建与运行命令、代码风格(ES 模块 + .js 导入后缀、严格类型、zod schema 校验、2 空格缩进、camelCase / PascalCase / kebab-case 的命名约定等),以及扩展服务器的规则:新工具、资源、提示词分别放在对应目录,导出 registerX(server) 函数,再接入中心 index.ts 编排。它相当于把"如何正确地扩展这个服务器"固化成了可被机器读取的约束。
package.json:元数据、脚本与依赖
package.json 声明了包名 @modelcontextprotocol/server-everything(当前版本 2.0.0),bin 字段将 dist/index.js 暴露为 mcp-server-everything 可执行命令,files 只发布 dist 目录。关键脚本为:
"build": "tsc && shx cp -r docs dist/ && shx chmod +x dist/*.js",
"watch": "tsc --watch",
"test": "vitest run --coverage"
build 脚本做了三件事:TypeScript 编译到 dist/、把 docs/ 原样复制到 dist/(这就是 server/index.ts 启动时能读到 instructions.md 的前提)、标记编译后的入口脚本可执行。依赖方面,运行时依赖 @modelcontextprotocol/sdk、express、cors、zod、jszip;开发依赖含 typescript、vitest、prettier、shx。
docs/ 文档体系
docs/ 目录在结构文档中被逐一列出,每个文件承担明确职责:
| 文件 | 职责 |
|---|---|
| architecture.md | 描述服务器架构:传输层、会话初始化、原语注册 |
| extension.md | 讲解如何扩展新工具、提示词、资源或传输 |
| features.md | 完整的功能参考:所有 prompts、resources、tools 与协议行为 |
| how-it-works.md | SSE 与 Streamable HTTP 传输的搭建方式与 session 管理 |
| instructions.md | 人类可读的使用指引,启动时被服务器读取并在 initialize 交互中返回给客户端 |
| startup.md | 启动时序、环境检查与初始化 |
| structure.md | 即本文所依据的结构文档 |
其中 instructions.md 有特殊的运行时身份:readInstructions() 会在服务器创建时把它读入内存。从 resources/index.ts 的 readInstructions 实现可以看到,它按相对路径 docs/instructions.md 读取文件,读取失败时返回一条错误说明字符串而不是抛异常——这解释了为什么构建脚本必须把 docs/ 复制到 dist/ 中一起发布。
prompts/ 提示词目录
prompts/ 的 index.ts 提供 registerPrompts(server) 编排函数,把注册工作委托给各个提示词文件:
simple.ts:注册simple-prompt,无参数,返回单条用户消息;args.ts:注册args-prompt,带两个参数(city必填、state可选),用于演示参数化消息拼装;completions.ts:注册completable-prompt,参数使用 SDK 的completable(...)助手支持服务器驱动的补全(如department以及上下文相关的name补全);resource.ts:导出registerEmbeddedResourcePrompt(server),注册resource-prompt——接受resourceType("Text" 或 "Blob")与resourceId(整数),在返回消息中嵌入一个动态生成的指定类型资源。它内部直接复用resources/templates.ts暴露的构造函数,是"资源与提示词跨模块协作"的典型示例。
resources/ 资源目录
resources/ 实际包含五个文件,index.ts 中的编排器只做两件事:
export const registerResources = (server: McpServer) => {
registerResourceTemplates(server);
registerFileResources(server);
};
templates.ts:两个动态模板资源
templates.ts 通过 ResourceTemplate 注册两个模板驱动的动态资源:
- 文本:
demo://resource/dynamic/text/{resourceId}(MIMEtext/plain) - 二进制:
demo://resource/dynamic/blob/{resourceId}(MIMEapplication/octet-stream,Base64 载荷)
结构文档称该路径变量为 {index},其约束是必须为有限的正整数;源码中的 parseResourceId(templates.ts)正是这样校验的——非正整数或未知 URI 会抛出 Unknown resource 错误。内容在请求时才生成,并带当前时间戳。此外还注册了 resourceId 的模板补全函数,只接受正整数字符串。
该文件还对外暴露四个辅助函数,供其他模块(尤其是 resource-prompt)直接构造动态资源:
textResource(uri, resourceId) // 生成文本型动态资源
textResourceUri(resourceId) // 生成 demo://resource/dynamic/text/{id}
blobResource(uri, resourceId) // 生成 Blob 型动态资源
blobResourceUri(resourceId) // 生成 demo://resource/dynamic/blob/{id}
files.ts:静态文件资源
files.ts 为 docs/ 目录下每个文件注册一个静态资源,URI 遵循 demo://resource/static/document/<filename> 模式;MIME 类型按扩展名映射:.md → text/markdown、.txt → text/plain、.json → application/json,其余默认 text/plain。
session.ts 与 subscriptions.ts
结构文档对这两个文件的描述较简略,但它们承担会话级能力:
session.ts:提供按会话注册/查找临时资源的机制。gzip-file-as-resource工具就用它把压缩后的 Blob 注册为会话资源,URI 形如demo://resource/session/<name>、mimeType: application/gzip,生命周期仅限当前会话;subscriptions.ts:server/index.ts 从这里导入setSubscriptionHandlers与stopSimulatedResourceUpdates,前者为服务器挂接资源订阅处理,后者在会话清理时停止模拟的资源更新检查(配合toggle-subscriber-updates工具触发)。
server/ 服务器组装
index.ts:服务器工厂
server/index.ts 导出 createServer() 工厂函数,返回 { server, cleanup }:
- 通过
readInstructions()载入服务器指令; - 创建
InMemoryTaskStore与InMemoryTaskMessageQueue,以支持实验性 Tasks 能力; - 构造
McpServer,声明能力包括tools.listChanged、prompts.listChanged、resources.subscribe/listChanged、logging,以及tasks(list、cancel 与tools.call请求); - 依次调用
registerTools(server)、registerResources(server)、registerPrompts(server),再挂接setSubscriptionHandlers(server); - 注册
oninitialized钩子:在客户端能力已知后注册条件工具(见下文 tools 一节),并在 350ms 延迟后调用syncRoots同步 roots(注释说明延迟是为了避免在notifications/initialized处理完成前发出请求导致丢失,见 server/index.ts); cleanup(sessionId)负责会话结束时的收尾:停止模拟日志(stopSimulatedLogging)、停止模拟资源更新、清理 task store 定时器、清除初始化超时。
传输层在客户端断开时调用 cleanup(),这是"服务器状态与传输生命周期解耦"的关键设计。
logging.ts 与 roots.ts
logging.ts:实现模拟日志——按随机间隔向客户端会话发送不同级别的日志消息,由toggle-simulated-logging工具按需启停;roots.ts:提供syncRoots,在初始化后向客户端请求 roots 列表并缓存,供get-roots-list工具返回"客户端最近一次发送的 roots"。
tools/ 工具目录:两级注册机制
结构文档将 tools/index.ts 描述为 registerTools(server) 编排器。深入 tools/index.ts 源码可以看到,实际存在两级注册:
export const registerTools = (server: McpServer) => {
registerEchoTool(server);
registerGetAnnotatedMessageTool(server);
// ... 共 13 个无条件工具
};
export const registerConditionalTools = (server: McpServer) => {
registerGetRootsListTool(server);
registerTriggerElicitationRequestTool(server);
// ... 其余依赖客户端能力的工具
};
第一级在 createServer() 中立即执行,注册与客户端能力无关的工具;第二级 registerConditionalTools 在 server.server.oninitialized 中执行,因为 roots、elicitation、sampling、Tasks 等工具依赖客户端在 initialize 阶段声明的能力。这一分层在 server/index.ts 中有对应调用,是理解该服务器启动时序的重要细节。
各工具的职责(沿用结构文档描述,并对照源码印证):
echo.ts:接收消息并返回Echo: {message};get-annotated-message.ts:演示内容级注解——按messageType("error" | "success" | "debug")输出带priority、audience注解的主文本消息,includeImage为 true 时附带一张小型 PNG 图片;该服务器所有工具均带工具级注解(readOnlyHint、destructiveHint、idempotentHint、openWorldHint);get-env.ts:以格式化 JSON 返回当前进程环境变量,便于调试配置;get-resource-links.ts:返回一段引导text块加多个resource_link项;get-resource-reference.ts:返回选定动态资源的引用;get-roots-list.ts:返回客户端最近一次发送的 roots 列表;get-structured-content.ts:演示structuredContent结构化响应;get-sum.ts:Zod 输入 schema,求a、b之和;get-tiny-image.ts:返回一张小型 PNG(MCP 徽标)image内容及说明文本;trigger-long-running-operation.ts:按duration(秒)与steps数模拟长时任务,客户端提供progressToken时发送notifications/progress进度通知;toggle-simulated-logging.ts/toggle-subscriber-updates.ts:分别启停当前会话的模拟日志与模拟资源订阅更新检查;trigger-elicitation-request.ts:向客户端/LLM 发起elicitation/create并返回结果;trigger-elicitation-request-async.ts:演示双向 Tasks——带任务元数据发起 elicitation 请求,随后轮询客户端tasks/get端点获取完成状态再取最终结果;trigger-sampling-request.ts/trigger-sampling-request-async.ts:同步与基于双向任务的sampling/createMessage请求演示;trigger-url-elicitation.ts:发送带外 URL 模式(mode: "url",含elicitationId请求路径)的 elicitation 请求,或抛出UrlElicitationRequiredError(错误码-32042)走客户端处理路径;错误路径携带的前置 elicitation 指向不同 URL(https://modelcontextprotocol.io),客户端满足后重试同一调用时忽略errorPath改走请求路径,避免客户端在同一错误上死循环;simulate-research-query.ts:基于 MCP Tasks(SEP-1686)的任务型工具,模拟带进度更新的多阶段研究操作;当查询被标记为含糊且客户端支持 elicitation 时,会在执行中途暂停并通过elicitation/create请求澄清,使用server.experimental.tasks.registerToolTask()且execution: { taskSupport: "required" };gzip-file-as-resource.ts:抓取 URL 或 data URI 内容并 gzip 压缩,默认返回指向会话级资源的resource_link,也可返回内联resource(含 gzip 数据);该会话资源在会话期间可通过resources/list发现。它受三个环境变量控制:GZIP_MAX_FETCH_SIZE(字节,默认 10 MiB)GZIP_MAX_FETCH_TIME_MILLIS(毫秒,默认 30000)GZIP_ALLOWED_DOMAINS(逗号分隔的域名白名单;留空表示允许所有域名)
transports/ 传输目录
三种传输模块各自是一个可独立执行的 Express/Node 入口:
stdio.ts
启动 StdioServerTransport,通过 createServer() 创建服务器并连接;处理 SIGINT 以优雅关闭,并在退出前调用 cleanup() 清理所有活动 interval。
sse.ts
基于 Express 暴露两个端点:
GET /sse:为每个会话建立一条 SSE 连接;POST /message:接收客户端消息。
通过 transport 映射表管理多个并发客户端;每次新连接时创建 SSEServerTransport,再经 createServer() 建服务器并连接;断开时调用 cleanup()。
streamableHttp.ts
streamableHttp.ts 用单个 /mcp 端点承载 POST(JSON-RPC)、GET(SSE 流)与 DELETE(会话终止),底层使用 SDK 的 StreamableHTTPServerTransport。源码印证了结构文档的三点描述:
- 自定义的
InMemoryEventStore(streamableHttp.ts)实现storeEvent/replayEventsAfter,支持 SSE 断线后的事件重放,即"可恢复会话"; - 以
sessionId为键维护transports: Map<string, StreamableHTTPServerTransport>,收到携带mcp-session-id头的 POST 时复用既有传输,无 session 时初始化请求则新建createServer()实例并连接; - 启用宽松 CORS(
origin: "*",注释明确这是为 Inspector 直连调试所用),并暴露mcp-session-id、last-event-id、mcp-protocol-version响应头。
测试验证与扩展路径
src/everything/__tests__/ 下有五组测试,与目录结构一一对应:registrations.test.ts、tools.test.ts、prompts.test.ts、resources.test.ts、server.test.ts,通过 npm run test(vitest + 覆盖率)运行。其中 registrations.test.ts 直接验证了 registerResources 对 mock 服务器的注册调用,为本文所述的"编排器 + 单文件工厂"模式提供了可执行的验证依据。
当你要为这个服务器新增功能时,结构文档指出的扩展约定是:跟随所在目录的既有模式,导出一个 registerX(server) 函数,再接入对应的中心 index.ts(tools/index.ts、resources/index.ts 或 prompts/index.ts);更完整的扩展说明见 extension.md 与 AGENTS.md。
小结
Everything Server 的结构可以概括为一条清晰的链条:index.ts 按 CLI 参数选择传输 → 传输模块调用 createServer() 工厂 → 工厂声明能力并依次执行 registerTools / registerResources / registerPrompts 三个编排器 → 初始化完成后按客户端能力补充条件工具 → 会话结束时以 cleanup() 统一回收定时器等资源。每个功能独立成文件、以 kebab-case 命名、由 register* 函数注入,使得目录布局、注册时序与测试边界三者高度一致。对于想学习 MCP 服务器工程化组织,或想参考"如何在单一参考实现中覆盖全部协议特性"的开发者,这套结构本身就是最有价值的部分。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00