AI项目博客
记录 AI 工程实践与大模型应用

Spring AI Alibaba 85|Graph Core · 分配 MCP 工具给指定节点 · tool

McpClientToolCallbackProvider

根据节点名称,匹配对应的 MCP 提供的 ToolCallback

package com.spring.ai.tutorial.graph.mcp.tool;

import com.spring.ai.tutorial.graph.mcp.config.McpNodeProperties;
import org.apache.commons.compress.utils.Lists;
import org.glassfish.jersey.internal.guava.Sets;
import org.springframework.ai.mcp.McpToolUtils;
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;

@Service
public class McpClientToolCallbackProvider {

  private final ToolCallbackProvider toolCallbackProvider;

  private final McpClientCommonProperties commonProperties;

  private final McpNodeProperties mcpNodeProperties;

  public McpClientToolCallbackProvider(ToolCallbackProvider toolCallbackProvider,
                                       McpClientCommonProperties commonProperties, McpNodeProperties mcpNodeProperties) {
      this.toolCallbackProvider = toolCallbackProvider;
      this.commonProperties = commonProperties;
      this.mcpNodeProperties = mcpNodeProperties;
  }

  public Set<ToolCallback> findToolCallbacks(String nodeName) {
      Set<ToolCallback> defineCallback = Sets.newHashSet();
      Set<String> mcpClients = mcpNodeProperties.getNode2servers().get(nodeName);
      if (mcpClients == null || mcpClients.isEmpty()) {
          return defineCallback;
      }

      List<String> exceptMcpClientNames = Lists.newArrayList();
      for (String mcpClient : mcpClients) {
          // my-mcp-client
          String name = commonProperties.getName();
          // mymcpclientserver1
          String prefixedMcpClientName = McpToolUtils.prefixedToolName(name, mcpClient);
          exceptMcpClientNames.add(prefixedMcpClientName);
      }

      ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();
      for (ToolCallback toolCallback : toolCallbacks) {
          ToolDefinition toolDefinition = toolCallback.getToolDefinition();
          // mymcpclientserver1getCityTimeMethod
          String name = toolDefinition.name();
          for (String exceptMcpClientName : exceptMcpClientNames) {
              if (name.startsWith(exceptMcpClientName)) {
                  defineCallback.add(toolCallback);
              }
          }
      }
      return defineCallback;
  }
}

McpNode

通过 ToolCallbacks 为节点配置 MCP 工具

import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.action.NodeAction;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallback;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import reactor.core.publisher.Flux;

/**
* MCP 节点实现
*/
public static class McpNode implements NodeAction {

  private static final String NODENAME = "mcp-node";

  private final ChatClient chatClient;

  public McpNode(ChatClient.Builder chatClientBuilder, Set<ToolCallback> toolCallbacks) {
      // 为节点配置 MCP 工具
      this.chatClient = chatClientBuilder
              .defaultToolCallbacks(toolCallbacks.toArray(ToolCallback[]::new))
              .build();
  }

  @Override
  public Map<String, Object> apply(OverAllState state) {
      String query = state.value("query", "");
      Flux<String> streamResult = chatClient.prompt(query).stream().content();
      String result = streamResult.reduce("", (acc, item) -> acc + item).block();

      HashMap<String, Object> resultMap = new HashMap<>();
      resultMap.put("mcpcontent", result);

      return resultMap;
  }
}

配置 MCP 节点

import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.action.NodeAction;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallback;

import java.util.Set;

/**
* 配置 MCP 节点
*/
public static void configureMcpNode(ChatClient.Builder chatClientBuilder, Set<ToolCallback> toolCallbacks) {
  McpNode mcpNode = new McpNode(chatClientBuilder, toolCallbacks);
  System.out.println("MCP node configured successfully");
}

McpController

package com.spring.ai.tutorial.graph.mcp.controller;

import com.alibaba.cloud.ai.graph.CompiledGraph;
import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.RunnableConfig;
import com.alibaba.cloud.ai.graph.StateGraph;
import com.alibaba.cloud.ai.graph.exception.GraphStateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/graph/mcp")
public class McpController {

  private static final Logger logger = LoggerFactory.getLogger(McpController.class);

  private final CompiledGraph compiledGraph;

  public McpController(@Qualifier("mcpGraph") StateGraph stateGraph) throws GraphStateException {
      this.compiledGraph = stateGraph.compile();
  }

  @GetMapping("/call")
  public Map<String, Object> call(@RequestParam(value = "query", defaultValue = "北京时间现在几点钟", required = false) String query,
                                    @RequestParam(value = "threadid", defaultValue = "yingzi", required = false) String threadId){
      RunnableConfig runnableConfig = RunnableConfig.builder().threadId(threadId).build();
      Map<String, Object> objectMap = new HashMap<>();
      objectMap.put("query", query);
      Optional<OverAllState> invoke = this.compiledGraph.invoke(objectMap, runnableConfig);
      return invoke.map(OverAllState::data).orElse(new HashMap<>());
  }

}

提供一个 MCP Server 服务,远端 or 本地都可以

这里本地启动一个MCP Server,提供一个时间服务

启动本地 MCP Server,提供时间服务

调用接口,触发本地端 MCP Server 提供的时间服务

本文整理自 Spring AI Alibaba 官方文档《分配 MCP 工具给指定节点》:https://java2ai.com/docs/frameworks/graph-core/examples/mcp-node

赞(0)
未经允许不得转载:AI项目博客 » Spring AI Alibaba 85|Graph Core · 分配 MCP 工具给指定节点 · tool

评论 抢沙发

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册