mcp-raw
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-rawwhat's the current time?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-raw
一个手写的MCP服务器和客户端——零依赖,不用 @modelcontextprotocol/sdk,不用TypeScript构建步骤。目的不是做成生产可用,而是让你看清楚MCP client和server通信时线上到底传了什么——这些东西被SDK的 McpServer/server.tool() 全部藏起来了。这里实现了两种transport:stdio和Streamable HTTP,协议逻辑(rpc.js)完全共用,只有"消息怎么进、响应怎么出"这一层不一样。
运行stdio版本:
npm run demo这会把 server.js 作为子进程spawn起来,驱动它走完一整个session,把每条发出(>>>)和收到(<<<)的消息都打印出来。
运行Streamable HTTP版本:
npm run demo:http这会把 http-server.js 起在 localhost:3100 上,用 http-client.js 发真实HTTP请求驱动同一套流程,把每次请求/响应的method、header、body都打出来。
一段话讲完整个协议
MCP就是通过某种transport交换JSON-RPC 2.0消息。Transport只负责搬运字节——stdio和Streamable HTTP是两种不同的搬运方式。不管用哪种transport,协议本身是一样的:固定的生命周期(initialize → notifications/initialized → 正常调用)加上几个方法(tools/list、tools/call……)。这也是为什么 rpc.js 里的 handleMessage() 不知道自己是被stdio还是HTTP调用的——协议逻辑本该和transport无关。SDK做的所有事情——zod schema、session管理、McpServer.registerTool()——都只是在这层协议之上加的便利封装。
Related MCP server: node-mcp-poc
消息的四种形态
区分依据是有没有 id,以及是请求还是响应:
// 请求 —— 发送方期待一个响应
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }
// 通知 —— 完全没有 "id"。永远不会有响应。看server.js里对
// notifications/initialized 的处理:直接return,什么都不发回去。
{ "jsonrpc": "2.0", "method": "notifications/initialized", "params": {} }
// 成功响应
{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } }
// 错误响应
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32601, "message": "Method not found: bogus" } }分帧方式(stdio上消息怎么分隔)
一行一条JSON消息,换行结尾,stdout上不能有别的任何东西。看 server.js 里的 send()——每次写入都是 JSON.stringify(message) + "\n"。这就是stdio传输的全部分帧协议了,没有长度前缀header(那是LSP的做法,MCP的stdio传输长得像它但不是同一个协议)。
踩了会让一切崩掉的一条规矩: stdout专门留给协议消息用。任何混进这条流里的 console.log 都会污染它——对方那边下一次 JSON.parse 就会失败,或者更糟,悄悄解析错。这也是为什么 server.js 里所有日志都走 console.error(stderr)而不是stdout。
生命周期,一步一步来
Client → Server:
initialize请求。 Client提议一个协议版本,介绍自己(clientInfo)。Server回应自己的protocolVersion、capabilities(支持哪些能力——这里只有{ tools: {} })和serverInfo。对应server.js里的handleInitialize。Client → Server:
notifications/initialized。 一条通知(没有id),确认client接受了这次握手。Server只是记录一下——不发任何响应,因为通知本来就不该有响应。正常操作阶段。 现在
tools/list和tools/call才被允许调用。server.js用一个initialized标志强制这个顺序——初始化完成前发别的方法(除了initialize本身)都会被拒绝,返回-32002 Server not initialized。真实的server也会强制同样的顺序;这个demo只是把它显式写出来了,而不是默默假设client会守规矩。tools/list。 Server返回工具的元信息:name、description、inputSchema——纯 JSON Schema,不是zod。你在mcp-starter项目里写的z.string(),SDK在发出去之前会转换成{ "type": "string" }。这个demo因为没有zod做这个转换,就直接手写了这个JSON Schema(见tools.js)。tools/call。 Server按params.name找到对应工具,跑handler(params.arguments),把返回值包成{ content: [{ type: "text", text: ... }] }。如果handler抛异常,结果会带上isError: true,而不是让整次RPC调用失败——工具执行失败是一个合法的结果,不是协议层的错误。可以试试:demo最后特意用非数字参数调用add,打印出了那个isError: true的响应。
Streamable HTTP:和stdio比多了什么
stdio里"一个进程=一个session",进程本身就是天然的隔离边界。HTTP里一个server进程要同时服务多个client,所以协议要求显式管理session,这就是http-server.js比server.js多出来的部分:
单一端点,三种方法。 都是
/mcp:POST发消息(这个demo的主路径),GET开一条独立SSE流给server主动推送通知(这个demo没有需要推送的场景,直接返回405并说明原因,没有假装支持),DELETE终止session。Mcp-Session-Idheader。initialize请求是唯一允许不带这个header发的请求——因为session还不存在。Server在initialize的响应头里把新生成的session id带回去(http-server.js里的randomUUID()),之后client每次请求都要原样带上它。带了无效session id → 404;该带却没带 → 400。跑npm run demo:http能看到这几种情况全部触发一遍,包括最后DELETE之后再请求拿到404。一次POST,两种响应形态。
initialize和tools/list直接回一个JSON对象(Content-Type: application/json);tools/call走的是text/event-stream(SSE),哪怕这里的工具都是同步瞬时返回、流里只有一个data: ...事件——这么写是为了展示协议允许的另一条路径:真实场景里,一次耗时的调用可以在给出最终结果前,在同一条连接上先推送若干进度事件。通知的响应是202,不是"没有响应". 协议规定:POST body如果只包含通知(没有id),server必须回
202 Accepted、空body,而不是完全不回应——HTTP请求总要有个响应,只是这个响应不携带JSON-RPC语义上的"结果"。
文件说明
rpc.js—— 和transport无关的协议核心:session状态、initialize/tools/list/tools/call的处理逻辑、错误码。stdio和HTTP都调这一份。server.js—— stdio transport:把消息一行行读进来,调rpc.js,把响应一行行写出去http-server.js—— Streamable HTTP transport:单端点/mcp,session管理,JSON/SSE两种响应形态tools.js—— 三个demo工具(get_current_time、echo、add),都是{ name, description, inputSchema, handler }这种普通对象client.js—— spawn起server.js,走stdio驱动它完整走一遍生命周期,打印每条消息http-client.js—— spawn起http-server.js,用node:http发真实HTTP请求走一遍同样的生命周期,打印每次请求/响应的method、header、body
和 mcp-starter 对比
mcp-starter 项目(同级目录)走的是同一套协议,但通过 @modelcontextprotocol/sdk 实现:用 McpServer.registerTool() 代替手写的 switch(method),用 zod schema代替手写的JSON Schema,用 StreamableHTTPServerTransport(内部靠@hono/node-server)代替这里的 http.createServer()。等这两个demo的流程看明白了,再看那个项目的 src/index.ts,应该就能读成"同样这几步,只是交给了一个库去做记账"。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceA demonstration MCP server supporting both Stdio and SSE transports, providing example tools (echo, add, time, UUID generation) and resources for learning and testing MCP implementations.6MIT
- Flicense-qualityCmaintenanceA minimal MCP server that exposes tools for addition, echoing text, time lookup, and URL fetching, with support for HTTP and stdio transports.
- Flicense-qualityCmaintenanceMCP server providing time retrieval and echo tools, running as an independent network process over Streamable HTTP.
- Flicense-qualityCmaintenanceA model-agnostic MCP server exposing example tools (add1, multiply2, greet) for learning purposes, working with any LLM through stdio transport.
Related MCP Connectors
Streamable HTTP MCP server for Google Calendar and Sheets with OAuth login.
A basic MCP server to operate on the Postman API.
MCP (Model Context Protocol) server for Appwrite
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Cynthiaflora/mcp-raw'
If you have feedback or need assistance with the MCP directory API, please join our Discord server