1、百度翻译mcp服务端 pom文件
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
2、百度翻译mcp服务端yml配置文件
#
# Copyright 2025-2026 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# spring.main.web-application-type=none
# NOTE: You must disable the banner and the console logging
# to allow the STDIO transport to work !!!
spring:
main:
banner-mode: off
ai:
mcp:
server:
name: my-translate-server
version: 0.0.1
alibaba:
toolcalling:
baidutranslate:
enabled: true
app-id: xxxxxxxx
secret-key: oooooooo
server:
port: 38080
# logging.pattern.console=
3、百度翻译mcp服务端 百度appid合key配置文件类
package org.springframework.ai.mcp.sample.server.conf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "spring.ai.alibaba.toolcalling.baidutranslate")
@Configuration
public class BaidutranslateProperties {
private String appId;
private String secretKey;
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}
4、百度翻译 mcp 服务端 百度翻译service类
package org.springframework.ai.mcp.sample.server;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.mcp.sample.server.conf.BaidutranslateProperties;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* @author yingzi
* @date 2025/3/27:11:13
*/
@Service
public class BaidutranslateService {
private static final Logger logger = LoggerFactory.getLogger(BaidutranslateService.class);
private static final String TRANSLATE_HOST_URL = "https://fanyi-api.baidu.com/api/trans/vip/translate";
private static final Random random = new Random();
private final WebClient webClient;
private final String appId;
private final String secretKey;
public BaidutranslateService(BaidutranslateProperties properties) {
assert StringUtils.hasText(properties.getAppId());
this.appId = properties.getAppId();
assert StringUtils.hasText(properties.getSecretKey());
this.secretKey = properties.getSecretKey();
this.webClient = WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.build();
}
@Tool(description = "Baidu translation function for general text translation")
public Map<String, String> baiduTranslateMethod(@ToolParam(description = "Content that needs to be translated") String q,
@ToolParam(description = "Source language that needs to be translated") String from,
@ToolParam(description = "Target language to translate into") String to) {
if (!StringUtils.hasText(q) || !StringUtils.hasText(from)
|| !StringUtils.hasText(to)) {
return null;
}
String salt = String.valueOf(random.nextInt(100000));
String sign = DigestUtils.md5DigestAsHex((appId + q + salt + secretKey).getBytes());
String url = UriComponentsBuilder.fromHttpUrl(TRANSLATE_HOST_URL).toUriString();
try {
MultiValueMap<String, String> body = constructRequestBody(q, from, to, salt, sign);
Mono<String> responseMono = webClient.post().uri(url).bodyValue(body).retrieve().bodyToMono(String.class);
String responseData = responseMono.block();
assert responseData != null;
logger.info("Translation request: {}, response: {}", q, responseData);
return parseResponse(responseData);
}
catch (Exception e) {
logger.error("Failed to invoke translate API due to: {}", e.getMessage());
return null;
}
}
private MultiValueMap<String, String> constructRequestBody(String q, String from, String to, String salt, String sign) {
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("q", q);
body.add("from", from);
body.add("to", to);
body.add("appid", appId);
body.add("salt", salt);
body.add("sign", sign);
return body;
}
private Map<String, String> parseResponse(String responseData) {
ObjectMapper mapper = new ObjectMapper();
try {
Map<String, String> translations = new HashMap<>();
TranslationResponse responseList = mapper.readValue(responseData, TranslationResponse.class);
String to = responseList.to;
List<TranslationResult> translationsList = responseList.trans_result;
if (translationsList != null) {
for (TranslationResult translation : translationsList) {
String translatedText = translation.dst;
translations.put(to, translatedText);
logger.info("Translated text to {}: {}", to, translatedText);
}
}
return translations;
}
catch (Exception e) {
try {
Map<String, String> responseList = mapper.readValue(responseData,
mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class));
logger.info(
"Translation exception, please inquire Baidu translation api documentation to info error_code:{}",
responseList);
return responseList;
}
catch (Exception ex) {
logger.error("Failed to parse json due to: {}", ex.getMessage());
return null;
}
}
}
public record TranslationResult(String src, String dst) {
}
public record TranslationResponse(String from, String to, List<TranslationResult> trans_result) {
}
}
5、百度翻译 mcp服务端启动类
/*
* Copyright 2025-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author brianxiadong
*/
package org.springframework.ai.mcp.sample.server;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class McpBaiduServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpBaiduServerApplication.class, args);
}
@Bean
public ToolCallbackProvider baiduTranslateFunction(BaidutranslateService baidutranslateService) {
return MethodToolCallbackProvider.builder().toolObjects(baidutranslateService).build();
}
}
6、spring-ai 大模型应用程序 mcp客户端, 集成了mcp天气查询工具和 mcp百度翻译工具
pom文件
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>${spring-ai-alibaba.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
yml配置文件
server:
port: 58888
servlet:
encoding:
charset: UTF-8
enabled: true
force: true
spring:
application:
name: mcp
ai:
dashscope:
api-key: sk-xoxoxoxoxoxox
mcp:
client:
sse:
connections:
server1:
url: http://localhost:58080
server2:
url: http://localhost:38080
mandatory-file-encoding: UTF-8
# 调试日志
logging:
level:
io:
modelcontextprotocol:
client: DEBUG
spec: DEBUG
百度翻译controller
package org.springframework.ai.mcp.samples.client.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
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;
@RestController
@RequestMapping("/translate")
public class McpTranslateController {
private final ChatClient dashScopeChatClient;
private final ToolCallbackProvider tools;
public McpTranslateController(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) {
this.tools = tools;
this.dashScopeChatClient = chatClientBuilder
.build();
}
/**
* 无工具版
*/
@GetMapping("/chat")
public String simpleChat(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:寻寻觅觅") String query) {
return dashScopeChatClient.prompt(query).call().content();
}
/**
* 调用工具版 - function
*/
@GetMapping("/chat-mcp")
public String chatTranslateFunction(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:寻寻觅觅") String query) {
return dashScopeChatClient.prompt(query).tools(tools).call().content();
}
}
天气查询 controller
package org.springframework.ai.mcp.samples.client.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
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;
@RestController
@RequestMapping("/weather")
public class McpWeatherController {
private final ChatClient dashScopeChatClient;
private final ToolCallbackProvider tools;
public McpWeatherController(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools) {
// 使用方式只需注入ToolCallbackProvider和ChatClient.Builder
this.tools = tools;
this.dashScopeChatClient = chatClientBuilder
.build();
}
/**
* 调用工具版 - function
*/
@GetMapping("/chat-mcp")
public String chatMcp(@RequestParam(value = "query", defaultValue = "请告诉我北京1天以后的天气",required = false) String query) {
System.out.println("\n>>> QUESTION: " + query);
String msg = dashScopeChatClient.prompt(query).tools(tools).call().content();
System.out.println("\n>>> ASSISTANT: " + msg);
return msg;
}
@GetMapping("/chat")
public String chat(@RequestParam(value = "query", defaultValue = "请告诉我北京1天以后的天气",required = false) String query) {
System.out.println("\n>>> QUESTION: " + query);
String msg = dashScopeChatClient.prompt(query).call().content();
System.out.println("\n>>> ASSISTANT: " + msg);
return msg;
}
}
启动类
/*
* Copyright 2025-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author brianxiadong
*/
package org.springframework.ai.mcp.samples.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(exclude = {
org.springframework.ai.autoconfigure.mcp.client.SseHttpClientTransportAutoConfiguration.class
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}