这是为理解这些工具背后的核心概念而创建的类似MCP服务器的自定义实现。这是在不到3个小时的时间内完成的,所以,没有关注代码质量或其他任何事情。这纯粹是为了学习(和实验)。
聊天运行示例
日志级别设置为info,而不是debug,因此不会显示背景消息。
搜索最新的美国政治新闻
> custom-mcp-server-implementation@1.0.0 example_chat
> node src/example_chat.js
Query (exit/quit/bye to exit)...search for latest US politics news
info: [Final Answer]
[{"type":"ORGANIC","link":"https://www.cnn.com/politics","description":"The IRS is drafting plans to cut as much as half of its 90,000-person workforce, sources say � Trump says US has apprehended 'top terrorist' responsible for�...","title":"Politics - CNN"},{"type":"ORGANIC","link":"https://www.nbcnews.com/politics","description":"Find the latest political news stories, photos, and videos on NBCNews.com. Read breaking headlines covering Congress, Democrats, Republicans, and more. � � � ","title":"Politics: Latest news and headlines | NBC News"},{"type":"ORGANIC","link":"https://www.nytimes.com/international/section/politics","description":"Breaking news and analysis on U.S. politics, including the latest coverage of the White House, Congress, the Supreme Court and more. � � � ","title":"U.S. Politics - The New York Times International"},{"type":"ORGANIC","link":"https://www.theguardian.com/us-news/us-politics","description":"President Donald Trump addresses a joint session of Congress at the US Capitol. Trump touts renewal of rightwing policies in lengthy speech as Democrats jeer,�...","title":"US politics | The Guardian"},{"type":"ORGANIC","link":"https://www.politico.com/politics","description":"Protesters rally in support of Ukraine outside the U.S. Capitol. Trump: Zelenskyy says Ukraine is ready for peace. By DASHA BURNS. 03/�... � � ","title":"Latest and breaking political news today - POLITICO"},{"type":"ORGANIC","link":"https://abcnews.go.com/Politics","description":"Trump orders a 'pause' on military aid to Ukraine. The move followed a fiery Oval Office meetup of the U.S. and Ukraine leaders. March 03. � � ","title":"Breaking Political News, Video & Analysis-ABC News"},{"type":"ORGANIC","link":"https://www.bbc.com/news/topics/cwnpxwzd269t","description":"7 hours ago � The president declares \"America is back\" as he soaks up Republican ovations and spars with Democrats. Just now. World.","title":"US politics - BBC News"},{"type":"ORGANIC","link":"https://www.independent.co.uk/news/world/americas/us-politics","description":"US politics � Truth behind the US economy and where it's heading after Trump tariffs � Stock markets drop as Trump's tariffs with Mexico and Canada begin. � � ","title":"US Politics | Latest news, comment and analysis - The Independent"},{"type":"ORGANIC","link":"https://www.politico.com/","description":"Democrats Are Serious About a Shutdown � Republicans squirm as Trump's tariffs come for their states � Zelenskyy says it is 'time to make things right' after Oval�... � � � ","title":"Politics, Policy, Political News - POLITICO"}]
Query (exit/quit/bye to exit)...服务器CPU计数
> custom-mcp-server-implementation@1.0.0 example_chat
> node src/example_chat.js
Query (exit/quit/bye to exit)...tell me server cpu count
info: [Final Answer]
8
Query (exit/quit/bye to exit)...没有工具调用,然后是页面抓取工具调用
> custom-mcp-server-implementation@1.0.0 example_chat
> node src/example_chat.js
Query (exit/quit/bye to exit)...how are you doing today?
info: [Final Answer]
I'm just a computer program, so I don't have feelings, but I'm here and ready to help you with whatever you need! How can I assist you today?
Query (exit/quit/bye to exit)...extract this page content: https://example.com/
info: [Final Answer]
# Example Domain
This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.
[More information...](https://www.iana.org/domains/example)
Query (exit/quit/bye to exit)...quit安装和运行
- 设置qdrant矢量存储。请参阅下文(将Qdrant设置为矢量存储)
- 克隆仓库
- 复制
.env.example向.env并填写所需的值。FIRECRAWL_KEY只有当你想使用页面抓取工具时才需要它。还需要其他人。 - 集
CHAT_LOG_LEVEL向debug暂时。 - 启动服务器(确保
qdrant正在默认运行所有内容):npm run server. - 在另一个窗口中,启动示例聊天循环,该循环透明地使用此类似MCP的服务器进行工具调用:
npm run example_chat. - 首先尝试使用不需要调用任何工具的简单消息:
how are you doing. - 现在,让我们测试一下工具调用。中提供了一些工具
functions目录。看看他们。 - 类型:
search for latest US politics news。控制台上会出现很多消息。这些是调试消息。最终结果前缀为Final Answer。您还可以将日志级别设置为info只看到最终的答案。 - 另一个:
tell me server cpu count. - FireCrawl测试(注册免费密钥):
extract this page content: https://example.com/. - 令人困惑的一个:
Add these numbers: 10, 20。为什么这令人困惑?因为对于这种简单的添加,LLM不需要依赖于工具调用。因此,这并没有使用任何工具调用。 - 让我们强制工具调用这个:
Add these numbers: 10, 20 using tool call这一次,我们的工具:functions/add_numbers.js被称为。启用debug随时记录以查看幕后消息。
将Qdrant设置为矢量存储
docker run -p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrant_storage:/qdrant/storage \
qdrant/qdrant用户界面位于:http://localhost:6333/dashboard
了解幕后发生的事情
- 广义上讲,MCP公开了两个端点:第一个端点用于查询已注册的函数/工具,第二个端点用于使用参数执行所选函数。
- LLM执行此功能选择。
- 如果你看看我们的 聊天代码,您将看到,在开始时,我们使用变量定义了两个这样的函数/工具:
toolsServerTools. - 这些正好对应于两个 服务器 端点:
/api/functions/search和/api/functions/execute. - 聊天循环基本上将这两个工具调用定义添加到每个用户聊天消息中。
- 然后,它依赖于LLM决定当前问题是否可以本机回答(不依赖于任何外部工具),或者它需要工具的帮助来正确回答用户的问题。
- 重要的是要记住:截至现在(第一条用户聊天消息),它确实 非 对已注册的工具/功能有任何了解。它只是知道有一个
tool它可以用来search对于函数(或多个工具),其中一个可能能够回答用户的问题。 - 这是第一个注册的工具
toolsServerTools开始发挥作用。 - 现在,LLM在其响应中返回工具调用。这被example_chat循环捕获:
let content = result?.choices?.[0]?.message?.content;
let toolCalls = result?.choices?.[0]?.message?.tool_calls;
if(content) {
logger.info(`[Final Answer]\n${typeof content === 'object' ? JSON.stringify(content) : content}`);
} else {
// ... tool call caught here
}- 现在,
handleToolCall方法在提取函数/工具名称及其对应参数后被调用。由于这是第一次工具调用,因此这实际上是searchFunctions对应于我们的工具调用/api/functions/search终点。 - 我们使用LLM给出的参数调用此端点,作为回报,接收最适用的函数(目前为前3个)。然后将这些添加到现有
toolsServerTools变量:
for(const availableTool of toolCallResult?.result) {
toolsServerTools.push({
"type": "function",
"function": availableTool?.definition
});
}- 现在,原始消息再次发送,但这次,我们的LLM
already可以访问最可能的功能finally,回答用户的问题(因为我们添加了如上所示的搜索功能)。 - 现在,LLM以最终的工具调用和相应的参数进行响应。我们打电话
handleToolCall方法再一次,但这一次,最后elsecase与正确的注册函数匹配,并将相应的参数传递给它。 - 此工具由我们的服务器在
/api/functions/execute终点。 - 此函数/工具/服务器api调用的结果是显示给用户的最终答案。
- 请注意,此聊天循环不会保留聊天历史记录。这只是一次聊天。
各种输入的示例流程
how are you doing=>用户->llm->完成。search for latest US politics news=>用户->llm->工具调用(searchFunctions)=>\[前3个匹配函数\]=>将它们添加到工具调用定义中=>再次调用LLM=>工具调用(googleSearch)=>最终结果=>用户。extract this page content: https://example.com/=>流程与上述类似,但第二个工具调用是extractPageContent.
