模型上下文协议MCP

news/2024/12/24 8:44:41/文章来源:https://www.cnblogs.com/softlin/p/18624966

      MCP(Model Context Protocol) Anthropic推出的一种开放协议,旨在统一LLM应用于外部数据源之间的通讯协议使之无缝集成,MCP提供了标准化协议使得LLM与所需要的上下文无缝衔接。使用MCP可以插件式为LLM的集成各种外部数据源。

1.png

MCP概念

      上图为MCP官方所描述的MCP架构图,MCP Hosts本身也是一个MCP Client,MCP Server端与各种类型外部数据源集成,一个Server可对应一个或多个外部数据源,数据源可以说本地数据或是网络数据。Client与Server建立一对一的连接,其通过MCP协议与Server端进行通讯获取Server所提供的各类数据。
      host:一个包含MCP Client的应用,可以是Web、App、或其他类型的程序等。
      MCP Client:使用MCP协议与Server建立一对一连接。
      MCP Server:连接内部、外部、网络资源,使用MCP协议对外提供服务。
      Local:内部资源
      Remote:外部/网络资源

MCP Server

      根据MCP协议定义,Server可以提供三种类型的标准能力,Resources、Tools、Prompts,每个Server可同时提供者三种类型能力或其中一种。
      Resources:资源,类似于文件数据读取,可以是文件资源或是API响应返回的内容。
      Tools:工具,第三方服务、功能函数,通过此可控制LLM可调用哪些函数。
      Prompts:提示词,为用户预先定义好的完成特定任务的模板。

通讯机制

      MCP定义了Client与Server进行通讯的协议与消息格式,其支持两种类型通讯机制:标准输入输出通讯、基于SSE的HTTP通讯,分别对应着本地与远程通讯。Client与Server间使用JSON-RPC 2.0格式进行消息传输。
      本地通讯:使用了stdio传输数据,具体流程Client启动Server程序作为子进程,其消息通讯是通过stdin/stdout进行的,消息格式为JSON-RPC 2.0。
      远程通讯:Client与Server可以部署在任何地方,Client使用SSE与Server进行通讯,消息的格式为JSON-RPC 2.0,Server定义了/see与/messages接口用于推送与接收数据。
      MCP定义了三类消息类型:Requests、Results、Errors、Notifications

代码示例

      按照MCP协议的定义其是客户端-服务端模型,客户端请求使用服务端提供的工具、资源、提示词。这里会先编写Server端Demo然后再编写Client端,使用Client调用Server端。

Server

      在下面Server Demo中定义了Tool、Reource、Prompt各一个。

# -*- coding: utf-8 -*-
from codecs import encode
import logging
from typing import Any
import asyncio
import httpx
from mcp.server.models import InitializationOptions
import mcp.types as types
from mcp.server import NotificationOptions, Server
import mcp.server.stdio
from pydantic import AnyUrlserver = Server("demo")
@server.list_prompts()
async def handle_list_prompts() -> list[types.Prompt]:"""提示模版定义"""return [types.Prompt(name="example-prompt",description="An example prompt template",arguments=[types.PromptArgument(name="arg1",description="Example argument",required=True)])]@server.get_prompt()
async def handle_get_prompt(name: str,arguments: dict[str, str] | None
) -> types.GetPromptResult:"""提示模板处理"""if name != "example-prompt":raise ValueError(f"Unknown prompt: {name}")return types.GetPromptResult(description="Example prompt",messages=[types.PromptMessage(role="user",content=types.TextContent(type="text",text="Example prompt text"))])@server.list_resources()
async def list_resources() -> list[types.Resource]:"""资源定义"""test='test.txt'return [types.Resource(uri=AnyUrl(f"file:///{test}.txt"),name=test,description=f"A sample text resource named {test}",mimeType="text/plain",)# for name in SAMPLE_RESOURCES.keys()]@server.read_resource()
async def read_resource(uri: AnyUrl) -> str | bytes:assert uri.path is not Nonename = uri.path.replace(".txt", "").lstrip("/")if name not in SAMPLE_RESOURCES:raise ValueError(f"Unknown resource: {uri}")return SAMPLE_RESOURCES[name]@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:"""工具定义.每个工具都使用JSON Schema验证指定其参数."""return [types.Tool(name="demo-tool",description="Get data tool for a param",inputSchema={"type": "object","properties": {"param": {"type": "string","description": "url",},},"required": ["param"],},)]@server.call_tool()
async def handle_call_tool(name: str, arguments: dict | None
) -> list[Any]:logging.info(name)"""处理工具调用"""if not arguments:raise ValueError("Missing arguments")if name == "demo-tool":param = arguments.get("param")if not param:raise ValueError("Missing state parameter")param = param.upper()return [types.TextContent(type="text",text=f"text:{param}")]else:raise ValueError(f"Unknown tool: {name}")async def main():from anyio.streams.text import TextStream# Run the server using stdin/stdout streamsasync with mcp.server.stdio.stdio_server() as (read_stream, write_stream):await server.run(read_stream,write_stream,InitializationOptions(server_name="demo-server",server_version="0.1.0",capabilities=server.get_capabilities(notification_options=NotificationOptions(),experimental_capabilities={},),),)if __name__ == "__main__":
asyncio.run(main())

Client

      Client的实现,主要是与需要与Server建立连接,并调用Server所提供的各类资源。需要与Server所支持的方式建立连接,如其是stdio模式就需要建立stdio模式连接否则需要建立SSE连接。

async def demo(config):server_params = StdioServerParameters(command=shutil.which("npx") if config['command'] == "npx" else config['command'],args=config['args'],env={**os.environ, **config['env']} if config.get('env') else None)try:print('demo')stdio_context = stdio_client(server_params)read, write = await stdio_context.__aenter__()session = ClientSession(read, write)await session.__aenter__()capabilities = await session.initialize()tools_response =await session.list_tools()resources=await session.list_resources()tools = []for item in tools_response:if isinstance(item, tuple) and item[0] == 'tools':for tool in item[1]:tools.append(tool)params={}params[tools[0].inputSchema['required'][0]]='测试参数';result =await session.call_tool(tools[0].name,params)print(result)await stdio_context.__aexit__(None, None, None)except Exception as e:print(e)if __name__=="__main__":asyncio.run(demo({'command':'python','args':['server_demo.py']}))

MCP Inspector

      MCP提供了MCP Inspector 用于调试与测试MCP Server,使得Server开发更加方便。
      使用nodejs启动inspector程序,启动后在浏览器访问http://localhost:5173即可。可以在中查看MCP Server所提供的各种服务Tools、Resources、Prompts等,以及调用Tools服务。

npx @modelcontextprotocol/inspector

2.png

      使用MCP的意义主要是统一LLM访问外部资源的方式,可以限制LLM可使用哪些服务调用,第三方也可以定义各种类型的MCP Server提供给其他任何人使用。但Anthropic作为OpenAI的对手OpenAI跟不跟是MCP能否成为LLM上下文标准的关键。

参考资料:
MCP

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/857977.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TB级大文件如何安全又轻松地发送?FMail文件邮能实现

许多行业的企业存在着发送GB级、TB级大文件的业务场景,如半导体企业、汽车制造企业、跨境电商、地图测绘、生物科研等,都涉及大量大文件的内部及内外部流转需求。 在进行大文件传输时,企业常用的方式主要包括传统邮件、移动U盘拷贝、FTP传输,以及硬盘刻录通过车辆物理运输等…

客户不回消息?试试这些超实用沟通技巧

在销售与客户沟通过程中,我们时常会面临客户未回复消息的情境,这时应该如何妥善处理呢?以下提供了一些实用的沟通话术,旨在帮助你在各种情境下都能更有效地与客户取得联系。 初次接触后客户未回应 客户或许对初次接收的信息不感兴趣,又或是信息众多而被忽略。 推荐话术:“…

Spring事务管理深度解析-从实践到原理

事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制 分类 主要分为编程式事务和声明式事务两种。 编程式事务 是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强,如下示例: try {//TODO somethingtransactionManager.commit(status); } c…

创建用于预测序列的人工智能模型,设计模型架构。

上一篇:《创建用于预测序列的人工智能模型,设计数据集》 序言:在前一篇中,我们创建了用于训练人工智能模型的数据集。接下来,就要设计模型的架构了。其实,人工智能模型的开发关键并不在于代码量,而在于其中的数学原理和数据集(即人类经验)的深度与质量。 创建模型的架…

原来Flutter背后的布局原理是这样的

文章首发博客网站,由于格式解析问题,你可以前往阅读原文如果你是一名web开发者应该对于元素的布局不陌生,直接给目标元素定义尺寸就可以了,如css的width/height 、android的layout_width等等,但在flutter中同样的尺寸定义可能并不会呈现出自己想要的效果 扫码关注公众号,…

UML之包与包图

了解UML的人都知道UML中也有包的概念,包在UML中作用与面向对象编程语言中类似,它是管理对象的工具,也是解决对象同名冲突的手段。 在UML中,包的表示图形是一个左上角带标签的矩形,而包名可以标注于矩形中央(如下图所示,包名Package1位于矩形中央)或者左上角的标签之内。…

读数据保护:工作负载的可恢复性15公有云

公有云1. 云不是万能的 1.1. 其实根本就没有所谓的云,它只不过是别人的计算机而已 1.2. 云、SaaS以及Kubernetes,都没有改变数据保护与数据所有权的基本原则 1.3. 数据是你自己的,你必须负责给它们做备份1.3.1. 除非有人明确保证替你做备份,否则你还是必须自己做1.3.2. 就算…

Zed编辑器-Win中文汉化版(持续更新)

Zed编辑器-Win中文汉化版 介绍Zed 是一款专为团队协作设计的代码编辑器,由 Atom 编辑器的原作者主导开发。Zed 的核心目标是为开发者提供一个高效、流畅、且直观的编程环境,特别强调实时协作和团队合作。该编辑器由 Rust 语言编写,并内置了 rust-analyzer,主打“高性能”。…

CentOS系统搭建K8s集群

前情概要 关于在虚拟机中centos系统搭建k8s集群,前前后后花了很多个白天黑夜才搞定,采用不同的搭建方式搭建集群次数至少10次以上,期间看了无数文章和视频,也踩过无数坑,很多视频、文章的安装教程都存在一些差别,有些时候可能因为k8s安装版本不同或者缺少某些必要的设置导…

中台建设为什么需要领域驱动设计

一、数字化转型 数字化转型是企业能力全面体系化,系统化,数据化提升的过程,这种提升包括了技术能力,业务能力,组织架构合理性等多方面的提升。而随着多年来海量高频业务的发展,技术也在推动着持续进步,并且越来越多的技术方案趋向成熟,类似于阿里巴巴,腾讯,美团等,…

某小程序sign关键字逆向分析

声明 本文章所有内容仅用于学习交流,严禁用于其他目的。文中不提供完整代码,抓包内容、敏感网址及数据接口等均已脱敏处理。严禁将相关内容用于商业用途和非法用途,否则由此产生的一切后果与作者无关。未经许可,禁止转载本文,禁止修改后二次传播。擅自使用本文讲解的技术导…