返回市场
整合生成式AI协议-MCP和A2A单服务器解决方案

整合生成式AI协议-MCP和A2A单服务器解决方案

作者:tanaikech2 星标更新:2025-06-19

项目介绍

<a name="top"></a> MIT License

统一生成式AI协议:MCP和A2A的单一服务器解决方案

摘要

一个新的统一的Google Apps Script现在可以同时部署模型上下文协议(MCP)和代理对代理(A2A)网络作为单一服务器,简化了Google Workspace用户的AI模型集成。

引言

生成式AI的快速发展导致了AI模型之间的日益整合,例如模型上下文协议(MCP)和代理对代理(A2A)协议。最近,我发布了MCPApp和A2AApp,它们使用Google Apps Script建立了MCP和A2A网络。参见参见 这种方法为Google Workspace和Google API用户提供了显著的优势,因为它允许无缝授权并直接在应用程序中集成这些资源。

传统上,分别部署MCP和A2A服务器需要设置和开发两个独立的项目。本报告通过提出一个统一脚本解决了这种低效问题,该脚本能够创建一个集成的服务器,同时支持MCP和A2A服务器。这种整合使得MCP和A2A客户端都能够访问同一个服务器,从而简化操作。此外,它还促进了MCP和A2A服务器之间共享通用函数,大大降低了开发成本并提高了整体效率。

流程图

流程图如下所示。

flowchart TD
    subgraph 服务器
        direction TB
        函数[函数] --> mvp[MCP服务器] & a2a[A2A服务器]
    end
    A[MCP客户端] -- MCP协议 --> 服务器
    B[A2A客户端] -- A2A协议 --> 服务器

仓库

https://github.com/tanaikech/Consolidating-Generative-AI-Protocols-A-Single-Server-Solution-for-MCP-and-A2A

使用方法

1. 获取API密钥

为了使用本报告中的脚本,请使用您的API密钥。参见 此API密钥用于访问Gemini API。

2. 复制演示脚本

您可以使用以下Google Apps Script复制演示脚本。请将以下脚本复制并粘贴到Google Apps Script的脚本编辑器中,并运行函数myFunction。这样,演示的Google Apps Script项目就会被复制到您的Google云端硬盘根目录下。

function myFunction() {
  const fileId = "1N1eg3vEgi_eVAiPB1SrPG9NIfEEQ5qohZED9haQQ7VbOKnMfLkPkYkUe";
  const file = DriveApp.getFileById(fileId);
  file.makeCopy(file.getName());
}

当然,您也可以直接从仓库复制并粘贴脚本。GitHub

3. 部署Web应用

为了允许MCP和A2A客户端访问,该项目使用了由Google Apps Script构建的Web应用作为服务器。两个客户端都可以使用HTTP GET和HTTP POST请求访问此服务器。因此,Web应用可以作为一个统一的服务器,集成MCP和A2A的功能。

详细信息可以在官方文档中找到。

请按照以下步骤在脚本编辑器中部署Web应用。

  1. 在脚本编辑器顶部右侧,点击“部署” -> “新建部署”。
  2. 点击“选择类型” -> “Web应用”。
  3. 在“部署配置”下的字段中输入有关Web应用的信息。
  4. 选择“我”作为“执行者”。
  5. 选择“任何人”作为“谁有权访问此应用”。
  6. 点击“部署”。
  7. 在脚本编辑器顶部右侧,点击“部署” -> “测试部署”。
  8. 复制Web应用的URL。它类似于https://script.google.com/macros/s/###/exec。此URL用于MCP客户端和A2A服务器。
  9. 请在复制的脚本中运行函数getRegisteringAgentCardURL(),并在控制台中复制显示的URL。此URL用于A2A客户端。

请注意,当您修改用于Web应用的Google Apps Script时,必须将其作为新版本进行修改。 这确保了修改后的脚本会在Web应用中生效。请务必注意这一点。您还可以在我的报告"重新部署Web应用而不更改Web应用的URL的新IDE"中找到更多细节。

4. 更新复制的脚本

当您复制文件后,请打开它。此时脚本编辑器会被打开。请进行以下修改。

  • 将您的API密钥设置为apiKey
  • 将Web应用的URL如https://script.google.com/macros/s/###/exec设置为agentCard的URL。此时,请添加查询参数accessKey=sample。因此,URL变为https://script.google.com/macros/s/###/exec?accessKey=sample

5. 测试

MCP客户端

作为MCP客户端,使用Claude Desktop。参见 在这种情况下,claude_desktop_config.json配置如下。请将https://script.google.com/macros/s/###/exec替换为您自己的Web应用URL。

{
  "mcpServers": {
    "gas_web_apps": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://script.google.com/macros/s/###/exec?accessKey=sample"
      ]
    }
  }
}

请关闭并重新打开Claude Desktop。结果可以在以下演示中看到。

可以看到,Claude Desktop的MCP客户端可以使用集成了MCP服务器和A2A服务器的Google Apps Script服务器。

A2A客户端

作为A2A客户端,使用@a2a-js/sdk参见 在这种情况下,为了使用@a2a-js/sdk测试脚本,需要修改@a2a-js/sdk。请按如下方式修改node_modules/@a2a-js/sdk/build/src/client/client.js中的_fetchAndCacheAgentCard函数。

为了请求Google Apps Script Web应用的路径/.well-known/agent.json,需要访问令牌参见。此访问令牌用作查询参数。然而,大多数当前的A2A客户端规范不支持这一点。因此,需要进行以下修改。

此外,请求Web应用需要重定向参见。不幸的是,Python的公共A2A客户端不支持重定向。相比之下,Node.js默认支持重定向。出于这些原因,选择了@a2a-js/sdk作为本报告的示例。

const agentCardUrl = `${this.agentBaseUrl}/.well-known/agent.json`;

const agentCardUrl = ((agentBaseUrl) => {
  /**
   * ### 描述
   * 该方法用于解析包括查询参数的URL。
   * 参见:https://tanaikech.github.io/2018/07/12/adding-query-parameters-to-url-using-google-apps-script/
   *
   * @param {String} url 包括查询参数的URL。
   * @return {Object} 包括基础URL和查询参数的JSON对象。
   */
  function parseQueryParameters(url) {
    if (url === null || typeof url != "string") {
      throw new Error(
        "请提供包括查询参数的URL(字符串)。"
      );
    }
    const s = url.split("?");
    if (s.length == 1) {
      return { url: s[0], queryParameters: null };
    }
    const [baseUrl, query] = s;
    if (query) {
      const queryParameters = query.split("&").reduce(function (o, e) {
        const temp = e.split("=");
        const key = temp[0].trim();
        let value = temp[1].trim();
        value = isNaN(value) ? value : Number(value);
        if (o[key]) {
          o[key].push(value);
        } else {
          o[key] = [value];
        }
        return o;
      }, {});
      return { url: baseUrl, queryParameters };
    }
    return null;
  }

  /**
   * ### 描述
   * 该方法用于向URL添加查询参数。
   * 参见:https://tanaikech.github.io/2018/07/12/adding-query-parameters-to-url-using-google-apps-script/
   *
   * @param {String} url 添加查询参数的基础URL。
   * @param {Object} obj 包括查询参数的JSON对象。
   * @return {String} 包括查询参数的URL。
   */
  function addQueryParameters(url, obj) {
    if (url === null || obj === null || typeof url != "string") {
      throw new Error(
        "请提供URL(字符串)和查询参数(JSON对象)。"
      );
    }
    const o = Object.entries(obj);
    return (
      (url == "" ? "" : `${url}${o.length > 0 ? "?" : ""}`) +
      o
        .flatMap(([k, v]) =>
          Array.isArray(v)
            ? v.map((e) => `${k}=${encodeURIComponent(e)}`)
            : `${k}=${encodeURIComponent(v)}`
        )
        .join("&")
    );
  }

  const urlObj = parseQueryParameters(agentBaseUrl);
  return addQueryParameters(
    `${urlObj.url}/.well-known/agent.json`,
    urlObj.queryParameters
  );
})(this.agentBaseUrl);

A2A客户端的示例脚本如下。请将https://script.google.com/macros/s/###/dev?access_token=###&accessKey=sample替换为您通过复制的脚本中的函数getRegisteringAgentCardURL()获取的URL。

import {
  A2AClient,
  Message,
  MessageSendParams,
  SendMessageResponse,
  SendMessageSuccessResponse,
} from "@a2a-js/sdk";
import { v4 as uuidv4 } from "uuid";

// 请设置您的A2A服务器URL。
const agentBaseUrl = "https://script.google.com/macros/s/###/dev?access_token=###&accessKey=sample";

// 用于测试上述A2A服务器的示例提示。
const prompts = [
  "10日元等于多少美元?",
  "今天中午东京的天气预报是什么?",
];

async function run(prompts: Array<string>) {
  const client = new A2AClient(agentBaseUrl);
  for (let prompt of prompts) {
    const messageId = uuidv4();
    const sendParams: MessageSendParams = {
      message: {
        messageId: messageId,
        role: "user",
        parts: [{ kind: "text", text: prompt }],
        kind: "message",
      },
      configuration: {
        blocking: true,
        acceptedOutputModes: ["text/plain"],
      },
    };
    const sendResponse: SendMessageResponse = await client.sendMessage(
      sendParams
    );
    const result = (sendResponse as SendMessageSuccessResponse).result;
    const messageResult = result as Message;
    messageResult.parts.forEach((e) => {
      if (e.kind == "text") {
        console.log(`提示:${prompt}`);
        console.log(`响应:${e.text}`);
      }
    });
  }
}

run(prompts);

当运行此脚本时,可以获得以下结果。

可以看到,由@a2a-js/sdk创建的A2A客户端可以使用集成了MCP服务器和A2A服务器的Google Apps Script服务器。

重要事项

  • 如果出现错误,请重新部署Web应用以反映最新的脚本。请注意,当您修改用于Web应用的Google Apps Script时,必须将其作为新版本进行修改。 这确保了修改后的脚本会在Web应用中生效。请务必注意这一点。您还可以在我的报告"重新部署Web应用而不更改Web应用的URL的新IDE"中找到更多细节。

总结

  • 开发了一个新的统一的Google Apps Script,可以同时部署模型上下文协议(MCP)和代理对代理(A2A)网络作为单一服务器。
  • 这种整合的方法解决了传统部署的低效问题,后者需要分别为MCP和A2A服务器设置独立的项目。
  • 统一的服务器使得MCP和A2A客户端都能访问同一个服务器,这简化了操作并促进了通用函数的共享,从而降低了开发成本。
  • 服务器使用了由Google Apps Script构建的Web应用来处理来自MCP和A2A客户端的HTTP GET和HTTP POST请求。
  • 使用Claude Desktop作为MCP客户端和@a2a-js/sdk作为A2A客户端的演示成功地展示了,集成的Google Apps Script服务器对于这两种协议都能正确工作。

<a name="licence"></a>

许可证

MIT

<a name="author"></a>

作者

Tanaike

捐赠

<a name="updatehistory"></a>

更新历史

  • v1.0.0 (2025年6月19日)

    1. 初始发布。

TOP