实现 MCP Server 开发指南
本文系统性讲解如何基于 tio-boot 从零实现一个符合 MCP(Model Context Protocol) 的 Server,并通过 SSE(Server-Sent Events) 与 MCP Client(如 openai-mcp)完成真实协议交互。文末保留了完整代码与完整抓包协议内容,便于你对照实现细节与运行行为。
一、MCP 协议概览
1. MCP 是什么
MCP(Model Context Protocol) 是一套用于 AI Client ↔ Tool Server 的协议标准,目标是让不同模型/客户端以统一方式发现并调用工具服务。协议核心点:
- 统一会话与能力协商:
initialize - 统一工具发现:
tools/list - 统一工具调用:
tools/call - 统一生命周期结束:
DELETE - 支持流式返回:常用 SSE 将 JSON-RPC 响应以事件流方式写回
2. MCP 的关键约定
| 项 | 说明 |
|---|---|
| 通信协议 | HTTP + JSON-RPC 2.0 |
| 返回形式 | SSE(text/event-stream,常见 Transfer-Encoding: chunked) |
| 会话标识 | mcp-session-id(由 Server 返回,Client 后续携带) |
| 版本协商 | mcp-protocol-version / Mcp-Protocol-Version |
| 生命周期 | initialize → notifications/initialized → tools/list → tools/call → DELETE |
二、交互与通信模型:HTTP + JSON-RPC + SSE
在 MCP 中,请求通常为:
HTTP POST 到
/mcpBody 为 JSON-RPC 2.0 格式(
jsonrpc/method/id/params)Server 对某些方法(如
initialize、tools/list、tools/call)使用 SSE 返回:- 先写出响应头:
Content-Type: text/event-stream - 然后以
event: message+data: {json}形式发送 JSON-RPC 响应 - 连接可保持不断开(用于后续事件/流式)
- 先写出响应头:
而对于 notifications/initialized 这种通知型方法,常见做法是:
- 不走 SSE
- 直接返回
202 Accepted(无 body),表示已接收处理
会话关闭通常通过:
- HTTP DELETE /mcp
- 携带
Mcp-Session-Id、Mcp-Protocol-Version等 header - Server 执行
sessionClosed(...)清理资源
三、基于 tio-boot 的整体架构设计
┌────────────┐
│ MCP Client │ (openai-mcp)
└─────┬──────┘
│ HTTP POST / DELETE
▼
┌──────────────┐
│ tio-boot │
│ HttpServer │
└─────┬────────┘
▼
┌────────────────────────┐
│ McpHandler │ ← 协议解析 / SSE
└─────┬──────────────────┘
▼
┌────────────────────────┐
│ McpServer / McpCoder │ ← 业务逻辑
│ ToolRegistry │
└────────────────────────┘
核心分工:
McpHandler:协议入口层
- 解析 HTTP 请求与 JSON-RPC
- 管理
mcp-session-id与protocolVersion - 对需要 SSE 的方法写出 SSE header,并以 chunk 形式推送事件数据
- 调用真正的业务 Server(
IMcpServer)
McpCoderServer:业务实现层
- 声明 Server 信息(name/version)
- 注册 Tools(schema + handler)
- 实现工具执行逻辑(run_shell / run_python / ai_search 等)
四、核心实现:McpHandler(协议解析与 SSE 输出)
1. 关键职责
McpHandler 实现了 tio-boot 的 HttpRequestHandler,负责:
从 request header 中读取:
mcp-session-idmcp-protocol-version
若未提供 sessionId,则生成一个并写回 response header
根据 HTTP method:
DELETE:执行 sessionClosedPOST:解析 JSON-RPC 并按 method 分派
对
initialize/tools/list/tools/call:- 写出 SSE header(
text/event-stream、chunked、keep-alive) - 通过
SseEmitter.pushSSEChunk(...)推送event: message+data: ...
- 写出 SSE header(
对
notifications/initialized:- 调用业务方法并返回
202
- 调用业务方法并返回
2. SSE 的 tio-boot 实现方式
在 tio-boot 里,关键点是:
- 先构造
HttpResponse - 调用
httpResponse.addServerSentEventsHeader()设置 SSE 必要头 - 再设置 chunk 传输、keep-alive
- 立刻把 header 发出去(
Tio.bSend(channelContext, httpResponse)) - 同时
httpResponse.setSend(false),避免 tio 再次自动发送并关闭连接 - 后续用
SseEmitter.pushSSEChunk(...)不断写入事件数据
这样可以实现 MCP 所需的“建立 SSE 通道并发送 JSON-RPC 响应”。
五、业务实现:McpCoderServer(Tool 注册与执行)
McpCoderServer 继承 McpServer,主要做三件事:
- 声明 MCP Server 的 name/version
- 注册工具(
registry.register(...)) - 提供工具 handler(Map args → List<McpContent>)
1. Tool schema 的价值
每个 Tool 注册时都定义了:
- name/title/description
- inputSchema(参数类型、required、默认值等)
- handler(执行逻辑)
MCP Client 在 tools/list 时会拿到工具清单 + schema,从而自动生成调用结构。
2. 示例工具
run_shell:执行 Linux shell 命令,返回 stdout/stderr/exit_coderun_python:执行 python 代码,返回 stdout/stderr/exit_codeai_search:示例 AI 搜索服务(Google + 模型整合),用于演示扩展能力
六、路由挂载与启动方式
tio-boot 中把 handler 挂到 /mcp:
McpCoderServer mcpCoderServer = new McpCoderServer();
McpHandler mcpCoderHandler = new McpHandler(mcpCoderServer);
r.add("/mcp", mcpCoderHandler);
当 openai-mcp 访问 POST /mcp 或 DELETE /mcp 时,就会进入 McpHandler.handle(...)。
七、完整请求 / 响应流程复盘(结合真实抓包)
下面按抓包顺序解释一次典型会话:
Client 发起 initialize
POST /mcpBody:
{"jsonrpc":"2.0","method":"initialize","id":1,...}Server:
生成或确认
mcp-session-id写出 SSE header(200 + text/event-stream)
SSE 推送:
event: messagedata: {"jsonrpc":"2.0","id":1,"result":{...}}
Client 发送 notifications/initialized
POST /mcpBody:
{"method":"notifications/initialized","jsonrpc":"2.0"}Server:
- 调用
notificationsInitialized - 返回
202 Accepted,content-length 0
- 调用
Client 请求 tools/list
POST /mcpBody:
{"method":"tools/list","jsonrpc":"2.0","id":1}Server:
- 写出 SSE header
- SSE 推送 tools 清单(含 schema)
Client 调用 tools/call(抓包里未展示,但逻辑已实现)
POST /mcpBody:
{"method":"tools/call","id":X,"params":{name,args}}Server:
- 执行对应 handler
- SSE 推送 result(contents)
Client 结束会话 DELETE
DELETE /mcpServer:
- 调用
sessionClosed - 返回 200,content-length 0
- 调用
八、常见注意事项与排错建议
SSE header 必须先发送 如果没在
initialize/tools/list/tools/call里先Tio.bSend(...),后续pushSSEChunk可能无法写入或连接已关闭。httpResponse.setSend(false)很关键 不然 tio 可能把 response 当作普通 HTTP 响应处理,发送后关闭连接,SSE 失效。Header 大小写与取值 抓包里 Client 用的是
Mcp-Session-Id、Mcp-Protocol-Version,代码读取的是mcp-session-id、mcp-protocol-version。多数 HTTP 框架会做大小写不敏感处理,但如果遇到取不到 header,需要确认底层是否规范化了 header 名称。notifications/initialized 返回 202 是合理的 它是通知型 method,不要求 SSE 流。
超时与 keep-alive
Keep-Alive: timeout=60只是声明,实际还受服务端/代理(如 Cloudflare)影响。生产环境要结合反代/网关配置。
附录 A:完整代码(原样保留)
1)McpHandler
package com.litongjava.kit.handler;
import java.util.Map;
import com.alibaba.fastjson2.util.TypeUtils;
import com.litongjava.mcp.context.McpRequestContext;
import com.litongjava.mcp.exception.McpRpcException;
import com.litongjava.mcp.model.JsonRpcRequest;
import com.litongjava.mcp.model.JsonRpcResponse;
import com.litongjava.mcp.model.McpInitializeParams;
import com.litongjava.mcp.model.McpInitializeResult;
import com.litongjava.mcp.model.McpMethod;
import com.litongjava.mcp.model.McpToolsCallParams;
import com.litongjava.mcp.model.McpToolsCallResult;
import com.litongjava.mcp.model.McpToolsListResult;
import com.litongjava.mcp.model.RpcError;
import com.litongjava.mcp.server.IMcpServer;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.core.ChannelContext;
import com.litongjava.tio.core.Tio;
import com.litongjava.tio.http.common.HeaderName;
import com.litongjava.tio.http.common.HeaderValue;
import com.litongjava.tio.http.common.HttpMethod;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.common.utils.HttpIpUtils;
import com.litongjava.tio.http.server.handler.HttpRequestHandler;
import com.litongjava.tio.http.server.util.SseEmitter;
import com.litongjava.tio.utils.UUIDUtils;
import com.litongjava.tio.utils.hutool.StrUtil;
import com.litongjava.tio.utils.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class McpHandler implements HttpRequestHandler {
private IMcpServer mcpServer;
public McpHandler(IMcpServer mcpServer) {
this.mcpServer = mcpServer;
}
@Override
public HttpResponse handle(HttpRequest httpRequest) {
HttpResponse httpResponse = TioRequestContext.getResponse();
ChannelContext channelContext = httpRequest.getChannelContext();
String mcpSessionId = httpRequest.getHeader("mcp-session-id");
String protocolVersion = httpRequest.getHeader("mcp-protocol-version");
if (mcpSessionId == null) {
mcpSessionId = UUIDUtils.random();
}
httpResponse.addHeader("mcp-session-id", mcpSessionId);
String realIp = HttpIpUtils.getRealIp(httpRequest);
Map<String, String> headers = httpRequest.getHeaders();
if (httpRequest.getMethod().equals(HttpMethod.DELETE)) {
McpRequestContext mcpRequestContext = new McpRequestContext(mcpSessionId, protocolVersion, realIp, headers);
mcpServer.sessionClosed(mcpRequestContext);
return httpResponse;
}
String bodyString = httpRequest.getBodyString();
if (StrUtil.isBlank(bodyString)) {
return httpResponse;
}
JsonRpcRequest rpcRequest = JsonUtils.parse(bodyString, JsonRpcRequest.class);
if (rpcRequest == null) {
return httpResponse;
}
String method = rpcRequest.getMethod();
Object id = rpcRequest.getId();
log.info("method:{}", method);
if (McpMethod.INITIALIZE.equals(method)) {
sendHttpResponseHeader(httpResponse, channelContext);
Map<String, Object> params = rpcRequest.getParams();
McpInitializeParams mcpInitializeParams = TypeUtils.cast(params, McpInitializeParams.class);
if (protocolVersion == null) {
protocolVersion = mcpInitializeParams.getProtocolVersion();
}
McpRequestContext mcpRequestContext = new McpRequestContext(mcpSessionId, protocolVersion, realIp, headers);
McpInitializeResult initialize;
try {
initialize = mcpServer.initialize(mcpInitializeParams, mcpRequestContext);
JsonRpcResponse<McpInitializeResult> resp = new JsonRpcResponse<>();
resp.setId(id).setResult(initialize);
sendSSEData(channelContext, resp);
} catch (McpRpcException e) {
log.error(e.getMessage(), e);
JsonRpcResponse<?> resp = new JsonRpcResponse<>();
RpcError rpcError = new RpcError();
rpcError.setMessage(e.getMessage());
resp.setId(id).setError(rpcError);
sendSSEData(channelContext, resp);
}
} else if (McpMethod.NOTIFICATIONS_INITIALIZED.equals(method)) {
McpRequestContext mcpRequestContext = new McpRequestContext(mcpSessionId, protocolVersion, realIp, headers);
try {
mcpServer.notificationsInitialized(mcpRequestContext);
httpResponse.setStatus(202);
} catch (McpRpcException e) {
log.error(e.getMessage(), e);
httpResponse.setStatus(500);
}
} else if (McpMethod.TOOLS_LIST.equals(method)) {
sendHttpResponseHeader(httpResponse, channelContext);
McpRequestContext mcpRequestContext = new McpRequestContext(mcpSessionId, protocolVersion, realIp, headers);
McpToolsListResult result;
try {
result = mcpServer.listTools(mcpRequestContext);
JsonRpcResponse<McpToolsListResult> resp = new JsonRpcResponse<>();
resp.setId(id).setResult(result);
sendSSEData(channelContext, resp);
} catch (McpRpcException e) {
log.error(e.getMessage(), e);
JsonRpcResponse<?> resp = new JsonRpcResponse<>();
RpcError rpcError = new RpcError();
rpcError.setMessage(e.getMessage());
resp.setId(id).setError(rpcError);
sendSSEData(channelContext, resp);
}
} else if (McpMethod.TOOLS_CALL.equals(method)) {
sendHttpResponseHeader(httpResponse, channelContext);
McpRequestContext mcpRequestContext = new McpRequestContext(mcpSessionId, protocolVersion, realIp, headers);
Map<String, Object> params = rpcRequest.getParams();
McpToolsCallParams toolCallparams = TypeUtils.cast(params, McpToolsCallParams.class);
McpToolsCallResult result;
try {
result = mcpServer.callTool(toolCallparams, mcpRequestContext);
JsonRpcResponse<McpToolsCallResult> resp = new JsonRpcResponse<>();
resp.setId(id).setResult(result);
sendSSEData(channelContext, resp);
} catch (McpRpcException e) {
log.error(e.getMessage(), e);
JsonRpcResponse<?> resp = new JsonRpcResponse<>();
RpcError rpcError = new RpcError();
rpcError.setMessage(e.getMessage());
resp.setId(id).setError(rpcError);
sendSSEData(channelContext, resp);
}
}
return httpResponse;
}
private void sendSSEData(ChannelContext channelContext, JsonRpcResponse<?> resp) {
String data = JsonUtils.toSkipNullJson(resp);
// 发送数据
SseEmitter.pushSSEChunk(channelContext, "message", data);
// 手动移除连接
// SseEmitter.closeChunkConnection(channelContext);
}
private void sendHttpResponseHeader(HttpResponse httpResponse, ChannelContext channelContext) {
// 设置sse请求头
httpResponse.addServerSentEventsHeader();
httpResponse.addHeader(HeaderName.Transfer_Encoding, HeaderValue.from("chunked"));
httpResponse.addHeader(HeaderName.Keep_Alive, HeaderValue.from("timeout=60"));
// 手动发送消息到客户端,因为已经设置了sse的请求头,所以客户端的连接不会关闭
Tio.bSend(channelContext, httpResponse);
httpResponse.setSend(false);
}
}
2)McpCoderServer
package com.litongjava.kit.mcp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.litongjava.kit.service.GoogleGeminiSearchService;
import com.litongjava.kit.utils.CmdInterpreterUtils;
import com.litongjava.kit.utils.PythonInterpreterUtils;
import com.litongjava.mcp.model.McpContent;
import com.litongjava.mcp.model.McpServerInfo;
import com.litongjava.mcp.server.McpToolRegistry;
import com.litongjava.mcp.server.RegisteredTool;
import com.litongjava.model.result.ResultVo;
import com.litongjava.tio.utils.commandline.ProcessResult;
import com.litongjava.tio.utils.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
/**
* 你的具体服务器:只需提供名称/版本。 如需添加或覆盖工具,可覆写 registerAdditionalTools() 或单独覆盖某个 handler。
*/
@Slf4j
public class McpCoderServer extends McpServer {
private GoogleGeminiSearchService aiSearchService = new GoogleGeminiSearchService();
public McpCoderServer() {
super();
}
@Override
protected McpServerInfo getMcpServerInfo() {
return new McpServerInfo("Coder Server", "1.15.0");
}
@Override
protected void registerTools() {
// run_shell
RegisteredTool runShell = McpToolRegistry.builder("run_shell").title("run shell")
.description("执行 Linux Shell 命令并返回 stdout/stderr/exit_code,支持联网").addStringProperty("command", "Command", true)
.addIntegerProperty("timeout", "Timeout", 30, false).addNullableProperty("cwd", "Cwd", "string", null, false)
.addNullableObjectProperty("env", "Env", true, null, false).handler(this::handleRunShell).build();
registry.register(runShell);
// run_python
RegisteredTool runPython = McpToolRegistry.builder("run_python").title("run python")
.description("在子进程中执行一段 donghua代码,返回 stdout/stderr/exit_code,支持联网").addStringProperty("code", "Code", true)
.addIntegerProperty("timeout", "Timeout", 30, false)
.addNullableProperty("stdin", "Stdin", "string", null, false)
.addBooleanProperty("use_isolated", "Use Isolated", true, false).handler(this::handleRunPython).build();
registry.register(runPython);
// ai_search(留一个简单的缺省实现,子类可覆盖 handler 或重载注册)
RegisteredTool aiSearch = McpToolRegistry.builder("ai_search").title("AI Search")
.description("智能搜索服务。会将问题拆分成多个关键字,通过 Google 搜索获取数据,然后结合模型进行回答,延迟20s.")
//
.addStringProperty("question", "Question", true).handler(this::handleAiSearch).build();
registry.register(aiSearch);
}
/** 公共:run_shell 处理逻辑 */
protected List<McpContent> handleRunShell(Map<String, Object> args) {
List<McpContent> contents = new ArrayList<>();
Object command = args.get("command");
if (command instanceof String) {
ProcessResult result = CmdInterpreterUtils.executeCmd((String) command);
String text = JsonUtils.toSkipNullJson(result);
contents.add(McpContent.buildText(text));
} else {
String json = JsonUtils.toSkipNullJson(ResultVo.fail("command must be a string"));
contents.add(McpContent.buildText(json));
}
return contents;
}
/** 公共:run_python 处理逻辑 */
protected List<McpContent> handleRunPython(Map<String, Object> args) {
List<McpContent> contents = new ArrayList<>();
Object code = args.get("code");
if (code instanceof String) {
ProcessResult result = PythonInterpreterUtils.executeCode((String) code);
String text = JsonUtils.toSkipNullJson(result);
contents.add(McpContent.buildText(text));
} else {
String json = JsonUtils.toSkipNullJson(ResultVo.fail("code must be a string"));
contents.add(McpContent.buildText(json));
}
return contents;
}
/** 公共:ai_search 的缺省实现(示例占位,可被子类替换) */
protected List<McpContent> handleAiSearch(Map<String, Object> args) {
List<McpContent> contents = new ArrayList<>();
Object question = args.get("question");
if (question instanceof String) {
log.info("keyword: {}", question);
try {
String text = JsonUtils.toSkipNullJson(aiSearchService.search((String) question));
contents.add(McpContent.buildText(text));
} catch (Exception e) {
log.error(e.getMessage(), e);
String json = JsonUtils.toSkipNullJson(ResultVo.fail(e.getMessage()));
contents.add(McpContent.buildText(json));
}
} else {
String json = JsonUtils.toSkipNullJson(ResultVo.fail("question must be a string"));
contents.add(McpContent.buildText(json));
}
return contents;
}
}
3)路由挂载
McpCoderServer mcpCoderServer = new McpCoderServer();
McpHandler mcpCoderHandler = new McpHandler(mcpCoderServer);
r.add("/mcp", mcpCoderHandler);
附录 B:完整协议交互内容(原样保留)
mcp协议解析
1.initialize and tool list
1.1.initialize
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 159
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 135.237.133.53
Cf-Ipcountry: US
Cf-Ray: 98726897cbd96ffe-IAD
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Traceparent: 00-68db9731000000000467bf121d36614a-71b754436da77584-00
Tracestate: dd=s:-1;p:2bdd09f56afbf331;t.dm:-3
X-Datadog-Parent-Id: 8977988190380532902
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db973100000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 317432383273328970
X-Forwarded-For: 135.237.133.53, 172.70.174.64
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"openai-mcp","version":"1.0.0"}}}
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:39:15 GMT
server: t-io
cache-control: no-cache, no-transform
connection: keep-alive
content-type: text/event-stream
mcp-session-id: 7e7ab8b566ad4c629abebf920d0cf45b
x-accel-buffering: no
Transfer-Encoding: chunked
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"ExecServer","version":"1.15.0"}}}
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 159
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 135.237.133.50
Cf-Ipcountry: US
Cf-Ray: 9872689bae0dd705-IAD
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Traceparent: 00-68db9731000000000467bf121d36614a-328ea6fbd6588e2e-00
Tracestate: dd=s:-1;p:2bdd09f56afbf331;t.dm:-3
X-Datadog-Parent-Id: 6233387827860711166
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db973100000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 317432383273328970
X-Forwarded-For: 135.237.133.50, 172.71.194.46
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"openai-mcp","version":"1.0.0"}},"jsonrpc":"2.0","id":0}
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:39:16 GMT
server: t-io
cache-control: no-cache, no-transform
connection: keep-alive
content-type: text/event-stream
mcp-session-id: 478f1dc036fd49d8ab69a693846acfb6
x-accel-buffering: no
Transfer-Encoding: chunked
event: message
data: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-06-18","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"ExecServer","version":"1.15.0"}}}
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 54
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 135.237.133.56
Cf-Ipcountry: US
Cf-Ray: 9872689f3aa0c56b-IAD
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: 478f1dc036fd49d8ab69a693846acfb6
Traceparent: 00-68db9731000000000467bf121d36614a-452f89cdbeb4c92e-00
Tracestate: dd=s:-1;p:2bdd09f56afbf331;t.dm:-3
X-Datadog-Parent-Id: 17731699559690821652
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db973100000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 317432383273328970
X-Forwarded-For: 135.237.133.56, 172.68.15.217
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"method":"notifications/initialized","jsonrpc":"2.0"}
HTTP/1.1 202 Accepted
date: Tue, 30 Sep 2025 08:39:16 GMT
server: t-io
content-type: application/json
mcp-session-id: 478f1dc036fd49d8ab69a693846acfb6
content-length: 0
1.2.tools/list
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 46
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 135.237.133.57
Cf-Ipcountry: US
Cf-Ray: 987268a1cf66d62d-IAD
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: 478f1dc036fd49d8ab69a693846acfb6
Traceparent: 00-68db9731000000000467bf121d36614a-9699cb18b322256d-00
Tracestate: dd=s:-1;p:2bdd09f56afbf331;t.dm:-3
X-Datadog-Parent-Id: 13673633483892079410
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db973100000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 317432383273328970
X-Forwarded-For: 135.237.133.57, 172.70.35.191
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"method":"tools/list","jsonrpc":"2.0","id":1}
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:39:17 GMT
server: t-io
cache-control: no-cache, no-transform
connection: keep-alive
content-type: text/event-stream
mcp-session-id: 478f1dc036fd49d8ab69a693846acfb6
x-accel-buffering: no
Transfer-Encoding: chunked
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"run_shell","title":"run_shell","description":"...... Linux Shell ............... stdout/stderr/exit_code","inputSchema":{"properties":{"command":{"title":"Command","type":"string"},"timeout":{"default":30,"title":"Timeout","type":"integer"},"cwd":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Cwd"},"env":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"title":"Env"}},"required":["command"],"title":"run_shellArguments","type":"object"}},{"name":"run_python","title":"run_python","description":"........................... Python ............... stdout/stderr/exit_code","inputSchema":{"properties":{"code":{"title":"Code","type":"string"},"timeout":{"default":30,"title":"Timeout","type":"integer"},"stdin":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Stdin"},"use_isolated":{"default":true,"title":"Use Isolated","type":"boolean"}},"required":["code"],"title":"run_pythonArguments","type":"object"}}]}}
1.3.Delete
DELETE /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 135.237.133.56
Cf-Ipcountry: US
Cf-Ray: 987268a3cfc3c943-IAD
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: 478f1dc036fd49d8ab69a693846acfb6
Traceparent: 00-68db9731000000000467bf121d36614a-8554ddea46198512-00
Tracestate: dd=s:-1;p:2bdd09f56afbf331;t.dm:-3
X-Datadog-Parent-Id: 9121804070330067398
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db973100000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 317432383273328970
X-Forwarded-For: 135.237.133.56, 172.68.245.99
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:39:17 GMT
server: t-io
content-type: application/json
mcp-session-id: 478f1dc036fd49d8ab69a693846acfb6
content-length: 0
2.tool call
2.1.notifications/initialized
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 54
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 57.154.187.40
Cf-Ipcountry: US
Cf-Ray: 987280c19b39173b-SJC
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: c362f6dd171c4c0b9ee5d230ba011060
Traceparent: 00-68db9b0a00000000e8fb2ae346302db7-6ad9b9d3762b8813-00
Tracestate: dd=s:-1;p:11a91123b3c77b78;t.dm:-3
X-Datadog-Parent-Id: 8650946564966287682
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db9b0a00000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 16788059191577161143
X-Forwarded-For: 57.154.187.40, 172.69.135.128
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"method":"notifications/initialized","jsonrpc":"2.0"}
HTTP/1.1 202 Accepted
date: Tue, 30 Sep 2025 08:55:45 GMT
server: t-io
content-type: application/json
mcp-session-id: c362f6dd171c4c0b9ee5d230ba011060
content-length: 0
2.2.tools/call
POST /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Content-Length: 450
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 57.154.187.36
Cf-Ipcountry: US
Cf-Ray: 987280c27b2467f2-SJC
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: c362f6dd171c4c0b9ee5d230ba011060
Traceparent: 00-68db9b0a00000000e8fb2ae346302db7-b23a3a53d8b444cc-00
Tracestate: dd=s:-1;p:11a91123b3c77b78;t.dm:-3
X-Datadog-Parent-Id: 13928377909303532074
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db9b0a00000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 16788059191577161143
X-Forwarded-For: 57.154.187.36, 172.69.135.128
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
{"method":"tools/call","params":{"_meta":{"openai/userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","openai/locale":"en-US","openai/userLocation":{"city":"Honolulu","region":"Hawaii","country":"US","timezone":"Pacific/Honolulu","latitude":"21.28870","longitude":"-157.80060"}},"name":"run_python","arguments":{"code":"import sys; print(sys.version)"}},"jsonrpc":"2.0","id":1}
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:55:45 GMT
server: t-io
cache-control: no-cache, no-transform
connection: keep-alive
content-type: text/event-stream
mcp-session-id: c362f6dd171c4c0b9ee5d230ba011060
x-accel-buffering: no
Transfer-Encoding: chunked
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\n \"exit_code\": 0,\n \"stdout\": \"3.11.13 | packaged by Anaconda, Inc. | (main, Jun 5 2025, 13:03:15) [MSC v.1929 64 bit (AMD64)]\\r\\n\",\n \"stderr\": \"\"\n}"}],"isError":false}}
2.3.Delete
DELETE /mcp HTTP/1.1
Host: mcp.litong.xyz
User-Agent: openai-mcp/1.0.0
Accept: application/json, text/event-stream
Accept-Encoding: gzip, br
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 57.154.187.41
Cf-Ipcountry: US
Cf-Ray: 987280c3bbc467be-SJC
Cf-Visitor: {"scheme":"https"}
Content-Type: application/json
Mcp-Protocol-Version: 2025-06-18
Mcp-Session-Id: c362f6dd171c4c0b9ee5d230ba011060
Traceparent: 00-68db9b0a00000000e8fb2ae346302db7-76b11a326432944c-00
Tracestate: dd=s:-1;p:11a91123b3c77b78;t.dm:-3
X-Datadog-Parent-Id: 1605897049399514698
X-Datadog-Sampling-Priority: -1
X-Datadog-Tags: _dd.p.tid=68db9b0a00000000,_dd.p.dm=-3
X-Datadog-Trace-Id: 16788059191577161143
X-Forwarded-For: 57.154.187.41, 172.69.22.186
X-Forwarded-Host: mcp.litong.xyz
X-Forwarded-Proto: http
HTTP/1.1 200 OK
date: Tue, 30 Sep 2025 08:55:45 GMT
server: t-io
content-type: application/json
mcp-session-id: c362f6dd171c4c0b9ee5d230ba011060
content-length: 0
