Xiaohei Companion
БесплатноНе проверенMCP server that provides a tool to query the status of an electronic pet named Xiaohei, including mood, hunger level, and time since last played.
Описание
MCP server that provides a tool to query the status of an electronic pet named Xiaohei, including mood, hunger level, and time since last played.
README
写在前面的话
本文由浅入深的介绍了 MCP 的相关内容,不同于技术栈或者工程化知识点的层层递进,本文只是简单介绍,具体应用环节还需要在实战过程中慢慢体会。
本文的代码地址:
时间线
我们先来对齐一下时间线:
| 时间 | 事件 | 说明 |
|---|---|---|
| 2022 年 10 月 | ReAct 现世 | 论文ReAct:Synergizing Reasoning and Acting 发表,确立了推理 + 行动交替的 Agent 范式 |
| 2022 年末 ~ 2023 年中 | Tool Use 现世 | 这一阶段的工具调用靠的是文本的正则解析:Langchain 的 ReAct 式 Agent 把 Action 或者 Action Input 拿出来,随后逐步向 「让 LLM 输出 JSON 迈进」 |
| 2023 年 6 月 13 日 | OpenAI 协议的 Tool Use | OpenAI 正式发布 Function Calling,把工具参数标准化为 JSON Schema |
| 2024 年 11 月 25日 | MCP 现世 | Anthropic 发布 Model Context Protocol ,支持两种传输方式:Stdio & SSE + HTTP |
| 2025 年 3 月 26 日 | Streamable HTTP 协议 MCP | 使用 Streamable 取代 SSE + HTTP |
| 2025 年 10 月 16 日 | Skill 现世 | Anthropic 发布 Agent Skills |
V1:单纯的Function Call
在 V1 中,我们先不涉及到任何 MCP,我们先看看 Function Call 的一个致命痛点。
我们先要定义一个工具,也就是写一个工具函数:
def get_xiaohei_status(detail: str = "all") -> dict:
"""模拟一个数据源:返回小黑此刻的状态。真实项目里这里会查数据库 / 调 API。"""
full = {
"name": "小黑",
"mood": "有点想你", # 心情
"hunger": 72, # 饥饿度 0-100,越高越饿
"last_played_hours": 6, # 距离上次陪它玩过去了几小时
}
if detail == "mood":
return {"name": full["name"], "mood": full["mood"]}
return full
那么,如果要让LLM 能够调用这个函数,需要给这个工具写好描述,也就是:
TOOLS_SCHEMA = [
{
"type": "function",
"function": {
"name": "get_xiaohei_status",
"description": "查询电子宠物小黑此刻的状态,包括心情、饥饿度、距上次陪玩的时间。",
"parameters": {
"type": "object",
"properties": {
"detail": {
"type": "string",
"enum": ["all", "mood"],
"description": "all=返回全部状态;mood=只返回心情",
}
},
"required": [],
},
},
}
]
也就是以规定的格式来描述一下我们的 Tool,然后,把注册好的工具给到 LLM,让 LLM 知道工具的作用以及使用方法:
response = client.chat.completions.create(
model=MODEL,
messages=messages,
tools=TOOLS_SCHEMA, # 关键:把 schema 交给 LLM
)
最后用户Prompt进来之后,LLM判断要调用此工具,那么就在调用之后将工具返回的结果和用户Prompt一起给到LLM,得到最终回复。
这是一个成功完成Tool Use 也就是Function Call的过程,这其中有一个很致命的点:
如果别人要用这个工具,该怎么办?
我们工具函数和工具说明书都是自己来定的,注册方式也写到了代码中,完全无法拆开,这也就是真正的痛点,我们将在V2中解决它。
V2:Tool = MCP Sever
还是一样的工具函数,这里的一个关键点是我们在工具函数的前面添加了mcp的装饰器 @mcp.tool()
from mcp.server.fastmcp import FastMCP
# 给这个 Server 起个名字。Client 连上来 initialize 时会看到它。
mcp = FastMCP("xiaohei-companion")
@mcp.tool()
def get_xiaohei_status(detail: str = "all") -> dict:
"""查询电子宠物小黑此刻的状态,包括心情、饥饿度、距上次陪玩的时间。
Args:
detail: all=返回全部状态;mood=只返回心情。
"""
# 注意:这段函数体和 v1 几乎一字不差——真正搬家的只是"它住在哪/怎么被找到"。
# schema 不用手写了,FastMCP 会读上面的类型注解(detail: str)和 docstring 自动生成。
full = {
"name": "小黑",
"mood": "有点想你",
"hunger": 72,
"last_played_hours": 6,
}
if detail == "mood":
return {"name": full["name"], "mood": full["mood"]}
return full
这个装饰器的作用有两个:
- 把函数的备注抄成description
- 添加 MCP 的类型判断
先说第一个,我们把这个函数的注释写在了函数头的下面,已经封装好的 MCP 会直接把这一段注释当成这个Tool 的 Description
至于第二个,被封装在了 FastMCP 内部,FastMCP 会自己来校验工具函数入参的类型,比如这里只支持字符串,那么如果在传入参数时,不是字符串,就会被拦在外面,不会进入到工具函数内容不。
我们可以通过下面的代码来获取到工具的相关信息:
session.initialize()
tools = await session.list_tools()
print("📋 Server 自报的工具列表(schema 是 Server 自动生成的):")
for t in tools.tools:
print(f" - {t.name}: {t.description}")
print(f" inputSchema: {t.inputSchema}")
获取到的信息如下所示:
📋 Server 自报的工具列表(schema 是 Server 自动生成的):
- get_xiaohei_status: 查询电子宠物小黑此刻的状态,包括心情、饥饿度、距上次陪玩的时间。
Args:
detail: all=返回全部状态;mood=只返回心情。
inputSchema: {'properties': {'detail': {'default': 'all', 'title': 'Detail', 'type': 'string'}}, 'title': 'get_xiaohei_statusArguments', 'type': 'object'}
到这里,我们就解决了 V1 的痛点,工具函数 当然还是要自己来写,但是描述和格式校验可以有统一的标准了,我们要在 V3 中来详细聊聊调用的过程了。
V3:MCP Client + LLM
这里就进入到 MCP 的使用环节了,核心伪代码如下:
连接(Server): # ① 建立会话
mcp_tools = Server.list_tools() # ② 问 Server 有哪些工具
llm_tools = [翻译(t) for t in mcp_tools] # ③ MCP格式 → function calling 格式
messages = [system, user问题]
答复 = LLM(messages, tools=llm_tools) # ④ 第一次问 LLM
while 答复.要调工具: # ⑤ LLM 说"我要调工具"
for 调用 in 答复.tool_calls:
结果 = Server.call_tool(调用.名字, 调用.参数) # ⑥ Client 替 LLM 去 Server 执行
messages.append(结果) # ⑦ 把结果塞回对话
答复 = LLM(messages, tools=llm_tools) # ⑧ 再问一次 LLM
return 答复.文字 # ⑨ 没有要调工具了 → 自然语言回复
这个过程无数人讲烂了已经,我就不再赘述了,我想讲几个点,首先是协议的问题
首先,MCP协议只有一种那就是 JavaScipt Object Notation - Remote Procedure Call ,简称为 JSON-RPC协议
它的核心很简单,就是想调用本地的函数一样,去调用另一台机器上的函数,人话 = 调用接口。
其次,MCP讨论比较高的是传输协议,我们在时间线表格里面梳理过了,MCP一共有三种协议,分别是:Stdio传输,SSE + HTTP 传输,Streamable + HTTP 传输。由于SSE + HTTP已经被废弃了,我们就不在多说,我们聊聊剩下两个。再开始之前,我们先规定好传输协议在哪一层,不然越聊越懵:
--------------------------------------
| MCP 协议层:JSON-RPC 消息 |
| initialize / list_tools / call_tool | -> 永远不变
----------------------------------------
| 传输层,负责吧上面的 Json 从 A 搬到 B | -> Stdio / Streamable + HTTP / ...
|--------------------------------------
Stdio 传输(Standard Input/Output )就像他的名字一样,传输方式是 Cline 当场讲他作为子进程拉起,也就是本地 MCP 的常见调用方式,既不需要端口,也不需要配置,不暴露到外侧。
Streamable + HTTP 的传输方式是,Server 端和 Client 端独立存在,Server 端可以被多个 Client 调用,虽然多了一层 HTTP 的开销,但是他可以解决一些场景下的难题,比如:
- 一个工具要跑三十秒,Server 想中途推进度 -> 一直链接着,进度随时更新
- Server 想反过来回调一下 Clinet -> 支持回调
Установка Xiaohei Companion
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/Nuo-chen-287/MCP-BasisFAQ
Xiaohei Companion MCP бесплатный?
Да, Xiaohei Companion MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Xiaohei Companion?
Нет, Xiaohei Companion работает без API-ключей и переменных окружения.
Xiaohei Companion — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Xiaohei Companion в Claude Desktop, Claude Code или Cursor?
Открой Xiaohei Companion на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Xiaohei Companion with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
