返回市场
谷歌ADK服务器多工系统

谷歌ADK服务器多工系统

作者:ammilam3 星标更新:2025-07-25

项目介绍

MCP服务器与Google ADK多工具系统

系统概述

该系统由两个主要组件构成:

  1. MCP服务器:一个使用TypeScript/Express构建的服务器,提供文件操作、API调用、会话数据管理和天气信息等工具。
  2. Google ADK代理:一个使用Python编写的代理,连接到MCP服务器并通过webhook接口使用其工具。

通信流程如下:

  • Google ADK代理接收用户请求
  • 代理确定要使用的工具
  • 代理向MCP服务器的webhook端点发送请求
  • MCP服务器处理请求并执行操作
  • MCP服务器将结果返回给代理
  • 代理为用户格式化响应

运行整个系统

本指南将帮助您设置并运行MCP服务器和Google ADK代理系统,包括添加新的工具到系统中。

前提条件

  • 对于MCP服务器,需要Node.js(v16+)
  • 对于Google ADK代理,需要Python(v3.9+)
  • 安装Google ADK SDK(pip install google-adk
  • 启用了Vertex AI的Google项目
  • Google ADK代理访问Vertex AI所需的IAM权限
  • 用于MCP服务器访问仓库的GitHub或GitLab访问令牌作为环境变量

设置环境

  1. 设置MCP服务器和Google ADK代理

    # 在项目的根目录下运行此命令以设置MCP服务器和Google ADK代理
    ./scripts/setup.sh
    gcloud auth application-default login
    
  2. 配置环境变量

    • 对于MCP服务器,请确保mcp/中的.env包含以下内容:
      # 服务器配置
      PORT=9000
      BASE_DIR=./data
      
      # 仓库访问令牌,允许MCP服务器访问私有仓库
      GITHUB_ACCESS_TOKEN=your_github_token_here
      GITLAB_ACCESS_TOKEN=your_gitlab_token_here
      
      # 可选配置
      REPO_DIR=./repos
      MAX_EVENT_LISTENERS=100
      
    • 对于Google ADK代理,请确保mcp_agent/中的.env包含以下内容:
      GOOGLE_CLOUD_PROJECT="your-google-project-id"
      GOOGLE_CLOUD_LOCATION="us-central1"
      GOOGLE_GENAI_USE_VERTEXAI="True"
      MCP_SERVER_URL=http://localhost:9000
      
  3. 运行MCP服务器

    # 在项目的根目录下运行此命令以启动MCP服务器和Google ADK代理
    ./scripts/run-mcp.sh
    
  4. 运行Google ADK代理

    # 在此仓库的根目录下运行此命令以启动Google ADK代理
    
    # 将以web模式启动
    ./scripts/run-agent.sh web
    
    # 将以终端模式启动
    ./scripts/run-agent.sh run
    
  5. 打开web界面并选择mcp_agent

    • 在浏览器中访问http://localhost:8000
    • 从下拉菜单中选择mcp_agent
    • 与代理聊天以确保其正常工作
  6. 测试现有工具

在Kubernetes中运行Google ADK代理

要在Kubernetes中运行Google ADK代理,请按照以下步骤操作:

  1. 构建Docker镜像
    docker build -t mcp-agent:latest -f mcp_agent/Dockerfile .
    
  2. 将镜像推送到Google Artifact Registry
    # 构建并标记镜像
    gcloud builds submit \
        --tag $GOOGLE_CLOUD_LOCATION-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/mcp-agent-repo/mcp-agent:latest \
        --project=$GOOGLE_CLOUD_PROJECT \
        .
    
    # 验证镜像是否已推送
    gcloud artifacts docker images list \
        $GOOGLE_CLOUD_LOCATION-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/mcp-agent-repo \
        --project=$GOOGLE_CLOUD_PROJECT \
        --format=json
    
  3. 创建Kubernetes部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mcp-agent
  template:
    metadata:
      labels:
        app: mcp-agent
    spec:
      serviceAccount: mcp-agent-sa
      containers:
      - name: mcp-agent
        imagePullPolicy: Always
        image: us-central1-docker.pkg.dev/your-gar-registry/mcp-agent-repo/mcp-agent:latest
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
            ephemeral-storage: "1Gi"
          requests:
            memory: "256Mi"
            cpu: "250m"
            ephemeral-storage: "512Mi"
        ports:
        - containerPort: 8000
        env:
          - name: PORT
            value: "8000"
          - name: GOOGLE_CLOUD_PROJECT
            value: "your-google-project-id"
          - name: GOOGLE_CLOUD_LOCATION
            value: "us-central1"
          - name: GOOGLE_GENAI_USE_VERTEXAI
            value: "True"
          # 使用服务名称或外部访问方法来访问MCP服务器
          - name: MCP_SERVER_URL
            value: "http://mcp-server-service:9000"
        volumeMounts:
        - name: credentials
          mountPath: "/app/credentials"
          readOnly: true
      volumes:
      - name: credentials
        secret:
          secretName: mcp-agent-credentials
---
apiVersion: v1
kind: Service
metadata:
  name: mcp-agent
spec:       
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 8000
  selector:
    app: mcp-agent

向MCP服务器和Google ADK代理系统添加新工具

本逐步指南将引导您完成向MCP服务器添加新工具的整个过程,并使其对Google ADK代理可用。下面的指南将以图像生成工具为例进行说明。

3. 向MCP服务器添加新工具

让我们在MCP服务器上添加一个图像生成工具。我们将逐步介绍所有必要的更改。

步骤1:在MCP服务器上实现工具

首先,让我们将核心图像生成功能添加到MCP服务器。将其添加到mcp/app.ts中的app.ts文件:

// 1. 添加图像生成操作的新类型
type ImageGenerationOptions = {
  prompt: string;
  width?: number; 
  height?: number;
  style?: string;
  format?: 'png' | 'jpeg' | 'webp';
  negativePrompt?: string;
};

// 2. 添加图像生成工具的实现
const imageGenerationTool = async (options: ImageGenerationOptions): Promise<{success: boolean; data?: any; error?: string}> => {
  try {
    // 验证参数
    if (!options.prompt) {
      return { success: false, error: '图像提示是必需的' };
    }
    
    // 为缺失选项设置默认值
    const width = options.width || 512;
    const height = options.height || 512;
    const format = options.format || 'png';
    const style = options.style || 'photorealistic';
    
    console.log(`正在为提示:“${options.prompt}”生成图像,风格:${style},尺寸:${width}x${height}`);
    
    // 在这个示例中,我们只是模拟图像生成
    // 在实际实现中,您可能会调用Stable Diffusion或DALL-E之类的API
    const mockImageData = {
      prompt: options.prompt,
      imageUrl: `https://example.com/generated_images/${Date.now()}.${format}`,
      width,
      height,
      style,
      format,
      generatedAt: new Date().toISOString()
    };
    
    // 在实际实现中,您可能会存储图像文件
    // 为了模拟目的,写入元数据文件
    const metadataPath = validatePath(`images/metadata_${Date.now()}.json`);
    const dir = path.dirname(metadataPath);
    await fs.mkdir(dir, { recursive: true });
    await fs.writeFile(metadataPath, JSON.stringify(mockImageData, null, 2), 'utf-8');
    
    return {
      success: true,
      data: mockImageData
    };
  } catch (error: any) {
    console.error('图像生成错误:', error);
    return {
      success: false, 
      error: error.message || '图像生成过程中出现未知错误'
    };
  }
};

步骤2:为Google ADK Webhook添加处理函数

在MCP服务器上添加此处理函数以处理来自Google ADK代理的请求:

// 添加到处理函数部分
async function handleImageGenerationTool(parameters: any, sessionId: string) {
  // 验证必需参数
  if (!parameters.prompt) {
    return { 
      success: false, 
      error: '缺少必需参数:prompt' 
    };
  }
  
  // 创建图像生成工具的选项对象
  const options: ImageGenerationOptions = {
    prompt: parameters.prompt,
    width: parameters.width || 512,
    height: parameters.height || 512,
    style: parameters.style || 'photorealistic',
    format: parameters.format || 'png',
    negativePrompt: parameters.negativePrompt
  };
  
  return await imageGenerationTool(options);
}

步骤3:更新ADK Webhook中的Switch语句

现在,在/api/adk-webhook路由处理器中的switch语句中添加一个新的case:

// 在app.post('/api/adk-webhook', ...)中找到switch语句
switch (toolName) {
  case 'file_system':
    result = await handleFileSystemTool(parameters, mcpSessionId);
    break;
  case 'api_call':
    result = await handleApiTool(parameters, mcpSessionId);
    break;
  case 'session_data':
    result = await handleSessionDataTool(parameters, mcpSessionId);
    break;
  case 'weather':
    result = await handleWeatherTool(parameters, mcpSessionId);
    break;
  // 为图像生成添加新的case
  case 'image_generation':
    result = await handleImageGenerationTool(parameters, mcpSessionId);
    break;
  default:
    result = {
      success: false,
      error: `未知工具名:${toolName}`
    };
}

步骤4:添加直接访问的端点

为直接访问图像生成工具添加专用端点:

// 将此路由添加到app
app.post('/api/session/:sessionId/image', async (req, res) => {
  const { sessionId } = req.params;
  const session = getSessionAndUpdate(sessionId);

  if (!session) {
    return res.status(404).json({
      success: false,
      error: '未找到会话'
    });
  }

  const options: ImageGenerationOptions = req.body;

  if (!options.prompt) {
    return res.status(400).json({
      success: false,
      error: '图像提示是必需的'
    });
  }

  const result = await imageGenerationTool(options);

  if (result.success) {
    // 通过SSE客户端发送事件
    emitEvent(sessionId, 'image-generation', {
      imageUrl: result.data.imageUrl,
      prompt: options.prompt,
      timestamp: new Date().toISOString()
    });
    
    res.status(200).json(result);
  } else {
    res.status(400).json(result);
  }
});

步骤5:更新API文档

/api/help端点的API文档中添加新的工具:

// 在helpDocs对象中找到endpoints数组
endpoints: [
  // 添加这些新条目
  {
    path: "/api/session/{sessionId}/image",
    method: "POST",
    description: "根据文本提示生成图像",
    parameters: [
      {
        name: "sessionId",
        in: "path",
        required: true,
        description: "会话标识符"
      }
    ],
    requestBodyExample: {
      prompt: "美丽的日落山景",
      width: 512,
      height: 512,
      style: "photorealistic",
      format: "png",
      negativePrompt: "模糊,低质量"
    },
    responseExample: {
      success: true,
      data: {
        prompt: "美丽的日落山景",
        imageUrl: "https://example.com/generated_images/1717451623456.png",
        width:  512,
        height: 512,
        style: "photorealistic",
        format: "png",
        generatedAt: "2025-06-03T12:00:00.000Z"
      }
    },
    curlExample: `curl -X POST ${baseUrl}/api/session/{sessionId}/image \\
  -H "Content-Type: application/json" \\
  -d '{"prompt": "美丽的日落山景", "style": "photorealistic"}'`
  },
  // 为image_generation工具添加Google ADK webhook文档
  {
    path: "/api/adk-webhook",
    method: "POST",
    description: "Google ADK图像生成的webhook",
    requestBodyExample: {
      session_id: "google-adk-session-123",
      tool_name: "image_generation",
      parameters: {
        prompt: "美丽的日落山景",
        width: 512,
        height: 512,
        style: "photorealistic"
      },
      request_id: "request-123"
    },
    responseExample: {
      success: true,
      data: {
        prompt: "美丽的日落山景",
        imageUrl: "https://example.com/generated_images/1717451623456.png",
        width: 512,
        height: 512,
        style: "photorealistic",
        format: "png",
        generatedAt: "2025-06-03T12:00:00.000Z"
      },
      mcp_session_id: "550e8400-e29b-41d4-a716-446655440000",
      request_id: "request-123"
    },
    notes: "此端点由Google ADK代理用于生成图像。"
  }
],

4. 向Google ADK代理添加工具支持

现在让我们在Google ADK代理中添加图像生成工具,它位于mcp_agent

步骤1:向MCPToolkit类添加方法

首先,在mcp_agent/mcp_toolkit.py文件中添加一个新方法以与图像生成工具交互:

# 在mcp_toolkit.py中的MCPToolkit类中添加此方法
def generate_image(self, prompt: str, width: int = 512, height: int = 512, 
                  style: str = "photorealistic", format: str = "png", 
                  negative_prompt: str = None) -> Dict:
    """使用MCP服务器从文本提示生成图像"""
    params = {
        "prompt": prompt,
        "width": width,
        "height": height,
        "style": style,
        "format": format
    }
    
    if negative_prompt:
        params["negativePrompt"] = negative_prompt
        
    return self.execute_tool("image_generation", params)

步骤2:在tools.py中添加工具函数

tools.py中创建一个新的工具函数,该函数将暴露给ADK代理:

# 将此添加到tools.py文件
def mcp_generate_image(prompt: str, style: str = "photorealistic", width: int = 512, height: int = 512) -> dict:
    """根据文本提示生成图像。
    
    参数:
        prompt: 要生成的图像的文字描述
        style: 图像的风格(例如,photorealistic,卡通,草图)
        width: 输出图像的宽度(像素)
        height: 输出图像的高度(像素)
        
    返回:
        dict: 包含状态('success' 或 'error')以及图像信息或错误消息的字典
    """
    try:
        result = mcp_toolkit.generate_image(
            prompt=prompt, 
            style=style,
            width=width, 
            height=height
        )
        
        if result.get("success"):
            image_data = result.get("data", {})
            return {
                "status": "success",
                "image_url": image_data.get("imageUrl"),
                "message": f"为提示:'{prompt}'生成了{style}风格的图像。"
            }
        else:
            return {
                "status": "error",
                "error_message": result.get("error", "生成图像时出现未知错误")
            }
    except Exception as e:
        logger.error(f"mcp_generate_image中的错误:{str(e)}")
        return {
            "status": "error",
            "error_message": f"异常:{str(e)}"
        }

步骤3:将工具注册到代理

更新agent.py文件以包含新工具:

# 在agent.py中添加导入
from .tools import (
    mcp_read_file, 
    mcp_write_file, 
    mcp_list_files, 
    mcp_delete_file,
    mcp_get_weather,
    mcp_call_api,
    mcp_store_data,
    mcp_store_number,
    mcp_store_boolean,
    mcp_retrieve_data,
    mcp_generate_image  # 添加此导入
)

# 更新代理定义
agent = Agent(
    name="mcp_agent",
    model="gemini-2.0-flash",
    description="能够处理天气、时间和与模型控制协议服务器交互的代理",
    instruction="""我可以通过与MCP服务器的集成帮助您完成各种任务。
我可以:
- 获取不同城市的当前时间
- 查看地点的天气状况
- 读取、写入、列出和删除文件
- 调用外部服务的API
- 在会话中存储