Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
440 changes: 440 additions & 0 deletions 01-tutorials/02-AgentKit-Gateway/01_create_mcp_service.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,358 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c6fbd39f",
"metadata": {},
"source": [
"# 转换 API 服务到 MCP 服务\n",
"\n",
"AgentKit 网关支持将现有 API 服务一键转换为 MCP 服务。通过上传 Swagger 或 OpenAPI 3 格式的 API 文档,AgentKit 网关支持批量将存量系统的 API 服务转换为 MCP 服务。在这一过程中,你无需改动任何代码,AgentKit 可以帮助你快速提升大模型与存量系统的交互能力。部署 MCP 服务时,AgentKit 网关可以访问你的函数服务中的 API 服务,也可以通过固定域名的形式访问外部的 API 服务。AgentKit 网关支持入站认证和出站认证,在认证入站请求的同时,为出站请求添加身份凭据,兼容多种系统的认证策略。\n",
"\n",
"在本教程中,我们将演示如何将 API 服务转换为 MCP 服务,你将学会\n",
"\n",
"1. 如何在 AgentKit 网关中将 API 服务转换为 MCP 服务。\n",
"\n",
"在开始本教程之前,请确保你已经**正确配置了凭证**。\n",
"\n",
"> **注意**:如果你还没有配置凭证,请先学习 [`01-tutorials/01-runtime/00_configuration_and_credentials.ipynb`](../01-runtime/00_configuration_and_credentials.ipynb) 教程完成配置。"
]
},
{
"cell_type": "markdown",
"id": "203f636e",
"metadata": {},
"source": [
"## 1. 转换 API 服务到 MCP 服务\n",
"\n",
"AgentKit 网关支持通过 Swagger 或 OpenAPI 3 格式的 API 文档,将存量系统的 API 服务转换为 MCP服务。你可以选择函数服务或者固定域名类型的 API 服务,通过 AgentKit 网关转换为 MCP 服务。当 MCP 请求抵达 AgentKit 网关时,AgentKit 网关将判断 MCP 请求的类型主动回复响应或是转换请求交由后端处理。对于 MCP `tools/list` 请求,AgentKit 网关将直接返回 API 定义中的各种操作。对于 MCP `tools/call` 请求,AgentKit 网关将 MCP 请求中的报文转换为 API 请求并发送到后端服务器中。\n",
"\n",
"AgentKit 网关支持从 MCP 请求中将请求内容转换为 API 请求的 URL 参数(Query)、请求头、Cookie,以及表单(Form)或 JSON 类型的请求体。AgentKit 网关支持从 JSON 类型的 API 响应中响应体转换为 MCP 响应的响应内容。你可以阅读[如何上传正确的 MCP 配置文件](https://www.volcengine.com/docs/6569/1816086#OA4azxgS)获得更多关于服务转换的条件和细节。\n",
"\n",
"[Postman Echo](https://postman-echo.com/) 是 Postman 提供的样例应用,它提供了一组用于测试 HTTP 客户端的调试 API。例如,当你通过 `curl` 调用 GET Request 接口时,你将会收到对应的返回。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "66251c9e",
"metadata": {},
"outputs": [],
"source": [
"!curl \"https://postman-echo.com/get\""
]
},
{
"cell_type": "markdown",
"id": "c2b6eec9",
"metadata": {},
"source": [
"我们还需要为 Postman Echo 服务准备 Swagger 或 OpenAPI 3 格式的 API 文档。\n",
"\n",
"如果你有 Postman Collection,通过 [Postman to OpenAPI](https://www.postman.com/postman/postman-public-workspace/collection/1blkypo/postman-to-openapi) 可以方便的从 Postman Collection 转换为 OpenAPI 3 文档。如果你的应用通过 `Spring Boot`、`NestJS` 和 `FastAPI` 等框架构建,你也可以通过相关工具快速生成 Swagger 或 OpenAPI 3 文档。\n",
"\n",
"最终,我们得到了 Postman Echo 服务的 OpenAPI 3 文档(为了方便阅读本教程,我们对一部分内容进行了裁剪)。AgentKit 网关支持 JSON 和 YAML 格式的 API 文档。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bd06f07a",
"metadata": {},
"outputs": [],
"source": [
"api_config = \"\"\"\n",
"openapi: 3.0.3\n",
"info:\n",
" title: Postman Echo\n",
" description: >-\n",
" Postman Echo is a service you can use to test your REST clients and make\n",
" sample API calls. It provides endpoints for `GET`, `POST`, `PUT`, various\n",
" auth mechanisms and other utility endpoints.\n",
"\n",
"\n",
" The documentation for the endpoints as well as example responses can be\n",
" found at\n",
" [https://postman-echo.com](https://postman-echo.com/?source=echo-collection-app-onboarding)\n",
" version: 1.0.0\n",
"servers:\n",
" - url: https://postman-echo.com\n",
" - url: postman-echo.com\n",
"paths:\n",
" /get:\n",
" get:\n",
" summary: GET Request\n",
" description: >-\n",
" The HTTP `GET` request method is meant to retrieve data from a server.\n",
" The data\n",
"\n",
" is identified by a unique URI (Uniform Resource Identifier).\n",
"\n",
"\n",
" A `GET` request can pass parameters to the server using \"Query String\n",
"\n",
" Parameters\". For example, in the following request,\n",
"\n",
"\n",
" >\n",
" [http://example.com/hi/there?hand=wave](http://example.com/hi/there?hand=wave)\n",
"\n",
"\n",
" The parameter \"hand\" has the value \"wave\".\n",
"\n",
"\n",
" This endpoint echoes the HTTP headers, request parameters and the\n",
" complete\n",
"\n",
" URI requested.\n",
" operationId: getRequest\n",
" parameters:\n",
" - name: foo1\n",
" in: query\n",
" schema:\n",
" type: string\n",
" example: bar1\n",
" - name: foo2\n",
" in: query\n",
" schema:\n",
" type: string\n",
" example: bar2\n",
" responses:\n",
" '200':\n",
" description: GET Request Woops\n",
" content:\n",
" application/json:\n",
" schema:\n",
" type: object\n",
" properties:\n",
" args:\n",
" type: object\n",
" properties:\n",
" foo1:\n",
" type: string\n",
" example: bar1\n",
" foo2:\n",
" type: string\n",
" example: bar2\n",
" headers:\n",
" type: object\n",
" url:\n",
" type: string\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"id": "025db000",
"metadata": {},
"source": [
"接下来,我们将为 Swagger Petstore 服务创建 MCP 服务。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0197ced2",
"metadata": {},
"outputs": [],
"source": [
"from agentkit.sdk.mcp.client import AgentkitMCPClient\n",
"from agentkit.sdk.mcp.types import (\n",
" CreateMCPServiceRequest,\n",
" ProtocolForCreateMCPService,\n",
" ProtocolHttpApiForCreateMCPService,\n",
" NetworkForCreateMCPService,\n",
" InboundAuthorizerForCreateMCPService,\n",
" InboundAuthorizerAuthorizerForCreateMCPService,\n",
" InboundAuthorizerAuthorizerKeyAuthForCreateMCPService,\n",
" InboundAuthorizerAuthorizerKeyAuthApiKeysItemForCreateMCPService,\n",
" BackendForCreateMCPService,\n",
" BackendCustomForCreateMCPService,\n",
")\n",
"import base64\n",
"import uuid\n",
"\n",
"id = str(uuid.uuid4())[-8:]\n",
"\n",
"client = AgentkitMCPClient()\n",
"request = CreateMCPServiceRequest(\n",
" Name=f\"mcp-service-{id}\",\n",
" # 转换 API 服务到 MCP 服务时,`ProtocolType` 为 `HTTP`。\n",
" ProtocolType=\"HTTP\",\n",
" ProtocolConfiguration=ProtocolForCreateMCPService(\n",
" HttpApiConfiguration=ProtocolHttpApiForCreateMCPService(\n",
" Configuration=f\"{base64.b64encode(api_config.encode()).decode()}\",\n",
" )\n",
" ),\n",
" Path=\"/mcp\",\n",
" NetworkConfiguration=NetworkForCreateMCPService(\n",
" EnablePublicNetwork=True,\n",
" EnablePrivateNetwork=False,\n",
" ),\n",
" InboundAuthorizerConfiguration=InboundAuthorizerForCreateMCPService(\n",
" AuthorizerType=\"ApiKey\",\n",
" Authorizer=InboundAuthorizerAuthorizerForCreateMCPService(\n",
" KeyAuth=InboundAuthorizerAuthorizerKeyAuthForCreateMCPService(\n",
" ApiKeys=[\n",
" InboundAuthorizerAuthorizerKeyAuthApiKeysItemForCreateMCPService(\n",
" Name=f\"mcp-service-api-key-{id}\",\n",
" ),\n",
" ],\n",
" ),\n",
" ),\n",
" ),\n",
" BackendType=\"Domain\",\n",
" BackendConfiguration=BackendForCreateMCPService(\n",
" CustomConfiguration=BackendCustomForCreateMCPService(\n",
" Domain=\"postman-echo.com\",\n",
" ProtocolType=\"HTTP\",\n",
" Port=80,\n",
" )\n",
" ),\n",
" ProjectName=\"default\",\n",
")\n",
"\n",
"mcp_service_id = \"\"\n",
"try:\n",
" response = client.create_mcp_service(request)\n",
" mcp_service_id = response.mcp_service_id\n",
" print(f\"MCP service created successfully! MCP service ID: {mcp_service_id}\")\n",
"except Exception as e:\n",
" print(f\"An error occurred: {e}\")\n",
" raise e"
]
},
{
"cell_type": "markdown",
"id": "8c7962f0",
"metadata": {},
"source": [
"AgentKit Gateway 部署 MCP 服务需要一段时间。在部署完成后,我们可以检查一下 API 服务 转换的 MCP 服务是否可用。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6083fc95",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"from agentkit.sdk.mcp.types import (\n",
" GetMCPServiceRequest,\n",
")\n",
"\n",
"request = GetMCPServiceRequest(\n",
" MCPServiceId=mcp_service_id,\n",
")\n",
"\n",
"endpoint = \"\"\n",
"api_key = \"\"\n",
"try:\n",
" while True:\n",
" response = client.get_mcp_service(request)\n",
" if response.mcp_service.status == \"Ready\":\n",
" endpoint = response.mcp_service.network_configurations[0].endpoint\n",
" api_key = response.mcp_service.inbound_authorizer_configuration.authorizer.key_auth.api_keys[0].key\n",
" break\n",
" if response.mcp_service.status != \"Creating\":\n",
" print(f\"The MCP service is in {response.mcp_service.status}\")\n",
" raise RuntimeError()\n",
" time.sleep(2)\n",
"except Exception as e:\n",
" print(f\"An error occurred: {e}\")\n",
" raise e\n",
"\n",
"url = f\"{endpoint}/mcp\"\n",
"print(f\"MCP service URL: {url}\")\n",
"print(\n",
" f'MCP service API key: {api_key}\\n (Hint: Add a \"Authorization: Bearer {api_key}\" request header to access the MCP service)'\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9e31b756",
"metadata": {},
"outputs": [],
"source": [
"!pip install fastmcp --quiet"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75cecd8a",
"metadata": {},
"outputs": [],
"source": [
"from fastmcp import Client\n",
"from fastmcp.client.transports import StreamableHttpTransport\n",
"import json\n",
"from mcp.types import TextContent\n",
"\n",
"transport = StreamableHttpTransport(\n",
" url=url,\n",
" headers={\n",
" \"Authorization\": f\"Bearer {api_key}\",\n",
" }\n",
")\n",
"mcp_client = Client(transport)\n",
"\n",
"async with mcp_client:\n",
" result = await mcp_client.call_tool(\"getRequest\", {\n",
" \"foo1\": \"bar1\",\n",
" \"foo2\": \"bar2\"\n",
" })\n",
" text: TextContent = result.content[0]\n",
" print(f\"The MCP server responds with {json.dumps(json.loads(text.text), indent=2)}.\")"
]
},
{
"cell_type": "markdown",
"id": "a698a8d6",
"metadata": {},
"source": [
"恭喜!你已经使用 AgentKit 网关转换 API 服务到 MCP 服务,这个 MCP 服务包含一个名为 `getRequest` 的工具。"
]
},
{
"cell_type": "markdown",
"id": "369967bf",
"metadata": {},
"source": [
"## 总结\n",
"\n",
"恭喜你!现在你已经掌握了转换 API 服务到 MCP 服务的方法,\n",
"\n",
"1. 通过 Swagger 或 OpenAPI 3 文档转换 API 服务到 MCP 服务。\n",
"\n",
"你可以继续尝试为 [Swagger Petstore](https://petstore3.swagger.io/)(OpenAPI 3) 和 [HTTPBin](https://httpbin.org/)(Swagger)等样例项目生成 MCP 服务。\n",
"\n",
"现在,请继续学习其他教程。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv (3.12.12)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading