让我们开始构建我们的天气服务器吧!您可以在这里找到我们将要构建的完整代码。
前置知识 本快速入门假设您熟悉:
系统要求
安装Python 3.10或更高版本。
您必须使用Python MCP SDK 1.2.0或更高版本。
设置您的环境 首先,让我们安装uv
并设置我们的Python项目和环境:
curl -LsSf https://astral.sh/uv/install.sh | sh
确保之后重启您的终端,以确保uv
命令被识别。
现在,让我们创建并设置我们的项目:
# 为我们的项目创建一个新目录
uv init weather
cd weather
# 创建虚拟环境并激活它
uv venv
source .venv/bin/activate
# 安装依赖
uv add "mcp[cli]" httpx
# 创建我们的服务器文件
touch weather.py
现在让我们深入构建您的服务器。
构建您的服务器 导入包并设置实例 将这些添加到您的weather.py
顶部:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化FastMCP服务器
mcp = FastMCP( "weather" )
# 常量
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP类使用Python类型提示和文档字符串自动生成工具定义,使创建和维护MCP工具变得简单。
辅助函数 接下来,让我们添加辅助函数,用于查询和格式化来自国家气象局API的数据:
async def make_nws_request ( url : str ) -> dict[ str , Any] | None :
"""使用适当的错误处理向NWS API发出请求。"""
headers = {
"User-Agent" : USER_AGENT ,
"Accept" : "application/geo+json"
}
async with httpx.AsyncClient() as client:
try :
response = await client.get(url, headers = headers, timeout = 30.0 )
response.raise_for_status()
return response.json()
except Exception :
return None
def format_alert ( feature : dict ) -> str :
"""将警报特征格式化为可读字符串。"""
props = feature[ "properties" ]
return f """
事件: { props.get( 'event' , '未知' ) }
区域: { props.get( 'areaDesc' , '未知' ) }
严重性: { props.get( 'severity' , '未知' ) }
描述: { props.get( 'description' , '无可用描述' ) }
说明: { props.get( 'instruction' , '无具体说明' ) }
"""
实现工具执行 工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
@mcp.tool ()
async def get_alerts ( state : str ) -> str :
"""获取美国州的天气警报。
参数:
state: 两个字母的美国州代码(例如CA, NY)
"""
url = f " { NWS_API_BASE } /alerts/active/area/ { state } "
data = await make_nws_request(url)
if not data or "features" not in data:
return "无法获取警报或未找到警报。"
if not data[ "features" ]:
return "该州没有活跃的警报。"
alerts = [format_alert(feature) for feature in data[ "features" ]]
return " \n --- \n " .join(alerts)
@mcp.tool ()
async def get_forecast ( latitude : float , longitude : float ) -> str :
"""获取某地的天气预报。
参数:
latitude: 地点的纬度
longitude: 地点的经度
"""
# 首先获取预报网格端点
points_url = f " { NWS_API_BASE } /points/ { latitude } , { longitude } "
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取该位置的预报数据。"
# 从点响应中获取预报URL
forecast_url = points_data[ "properties" ][ "forecast" ]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将周期格式化为可读的预报
periods = forecast_data[ "properties" ][ "periods" ]
forecasts = []
for period in periods[: 5 ]: # 仅显示接下来的5个周期
forecast = f """
{ period[ 'name' ] } :
温度: { period[ 'temperature' ] } ° { period[ 'temperatureUnit' ] }
风: { period[ 'windSpeed' ] } { period[ 'windDirection' ] }
预报: { period[ 'detailedForecast' ] }
"""
forecasts.append(forecast)
return " \n --- \n " .join(forecasts)
运行服务器 最后,让我们初始化并运行服务器:
if __name__ == "__main__" :
# 初始化并运行服务器
mcp.run( transport = 'stdio' )
您的服务器已完成!运行uv run weather.py
以确认一切正常。
现在让我们从现有的MCP主机Claude for Desktop测试您的服务器。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。Linux用户可以继续构建客户端 教程,以构建一个连接到我们刚刚构建的服务器的MCP客户端。
首先,确保您已安装Claude for Desktop。您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather" ,
"run" ,
"weather.py"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather" ,
"run" ,
"weather.py"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"C: \\ ABSOLUTE \\ PATH \\ TO \\ PARENT \\ FOLDER \\ weather" ,
"run" ,
"weather.py"
]
}
}
}
您可能需要在command
字段中放入uv
可执行文件的完整路径。您可以通过在MacOS/Linux上运行which uv
或在Windows上运行where uv
来获取此路径。
这告诉Claude for Desktop:
有一个名为”weather”的MCP服务器
通过运行uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
来启动它
保存文件,并重启Claude for Desktop 。
让我们开始构建我们的天气服务器吧!您可以在这里找到我们将要构建的完整代码。
前置知识 本快速入门假设您熟悉:
系统要求
安装Python 3.10或更高版本。
您必须使用Python MCP SDK 1.2.0或更高版本。
设置您的环境 首先,让我们安装uv
并设置我们的Python项目和环境:
curl -LsSf https://astral.sh/uv/install.sh | sh
确保之后重启您的终端,以确保uv
命令被识别。
现在,让我们创建并设置我们的项目:
# 为我们的项目创建一个新目录
uv init weather
cd weather
# 创建虚拟环境并激活它
uv venv
source .venv/bin/activate
# 安装依赖
uv add "mcp[cli]" httpx
# 创建我们的服务器文件
touch weather.py
现在让我们深入构建您的服务器。
构建您的服务器 导入包并设置实例 将这些添加到您的weather.py
顶部:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化FastMCP服务器
mcp = FastMCP( "weather" )
# 常量
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP类使用Python类型提示和文档字符串自动生成工具定义,使创建和维护MCP工具变得简单。
辅助函数 接下来,让我们添加辅助函数,用于查询和格式化来自国家气象局API的数据:
async def make_nws_request ( url : str ) -> dict[ str , Any] | None :
"""使用适当的错误处理向NWS API发出请求。"""
headers = {
"User-Agent" : USER_AGENT ,
"Accept" : "application/geo+json"
}
async with httpx.AsyncClient() as client:
try :
response = await client.get(url, headers = headers, timeout = 30.0 )
response.raise_for_status()
return response.json()
except Exception :
return None
def format_alert ( feature : dict ) -> str :
"""将警报特征格式化为可读字符串。"""
props = feature[ "properties" ]
return f """
事件: { props.get( 'event' , '未知' ) }
区域: { props.get( 'areaDesc' , '未知' ) }
严重性: { props.get( 'severity' , '未知' ) }
描述: { props.get( 'description' , '无可用描述' ) }
说明: { props.get( 'instruction' , '无具体说明' ) }
"""
实现工具执行 工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
@mcp.tool ()
async def get_alerts ( state : str ) -> str :
"""获取美国州的天气警报。
参数:
state: 两个字母的美国州代码(例如CA, NY)
"""
url = f " { NWS_API_BASE } /alerts/active/area/ { state } "
data = await make_nws_request(url)
if not data or "features" not in data:
return "无法获取警报或未找到警报。"
if not data[ "features" ]:
return "该州没有活跃的警报。"
alerts = [format_alert(feature) for feature in data[ "features" ]]
return " \n --- \n " .join(alerts)
@mcp.tool ()
async def get_forecast ( latitude : float , longitude : float ) -> str :
"""获取某地的天气预报。
参数:
latitude: 地点的纬度
longitude: 地点的经度
"""
# 首先获取预报网格端点
points_url = f " { NWS_API_BASE } /points/ { latitude } , { longitude } "
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取该位置的预报数据。"
# 从点响应中获取预报URL
forecast_url = points_data[ "properties" ][ "forecast" ]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将周期格式化为可读的预报
periods = forecast_data[ "properties" ][ "periods" ]
forecasts = []
for period in periods[: 5 ]: # 仅显示接下来的5个周期
forecast = f """
{ period[ 'name' ] } :
温度: { period[ 'temperature' ] } ° { period[ 'temperatureUnit' ] }
风: { period[ 'windSpeed' ] } { period[ 'windDirection' ] }
预报: { period[ 'detailedForecast' ] }
"""
forecasts.append(forecast)
return " \n --- \n " .join(forecasts)
运行服务器 最后,让我们初始化并运行服务器:
if __name__ == "__main__" :
# 初始化并运行服务器
mcp.run( transport = 'stdio' )
您的服务器已完成!运行uv run weather.py
以确认一切正常。
现在让我们从现有的MCP主机Claude for Desktop测试您的服务器。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。Linux用户可以继续构建客户端 教程,以构建一个连接到我们刚刚构建的服务器的MCP客户端。
首先,确保您已安装Claude for Desktop。您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather" ,
"run" ,
"weather.py"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather" ,
"run" ,
"weather.py"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "uv" ,
"args" : [
"--directory" ,
"C: \\ ABSOLUTE \\ PATH \\ TO \\ PARENT \\ FOLDER \\ weather" ,
"run" ,
"weather.py"
]
}
}
}
您可能需要在command
字段中放入uv
可执行文件的完整路径。您可以通过在MacOS/Linux上运行which uv
或在Windows上运行where uv
来获取此路径。
这告诉Claude for Desktop:
有一个名为”weather”的MCP服务器
通过运行uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
来启动它
保存文件,并重启Claude for Desktop 。
让我们开始构建我们的天气服务器吧!您可以在这里找到我们将要构建的完整代码。
前置知识 本快速入门假设您熟悉:
系统要求 对于TypeScript,请确保您安装了最新版本的Node。
设置您的环境 首先,如果您还没有安装Node.js和npm,请安装它们。您可以从nodejs.org 下载。
验证您的Node.js安装:
node --version
npm --version
对于本教程,您需要Node.js版本16或更高。
现在,让我们创建并设置我们的项目:
# 为我们的项目创建一个新目录
mkdir weather
cd weather
# 初始化一个新的npm项目
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
# 创建我们的文件
mkdir src
touch src/index.ts
更新您的package.json以添加type: “module”和一个构建脚本:
{
"type" : "module" ,
"bin" : {
"weather" : "./build/index.js"
},
"scripts" : {
"build" : "tsc && chmod 755 build/index.js"
},
"files" : [
"build"
],
}
在项目的根目录创建一个tsconfig.json
:
{
"compilerOptions" : {
"target" : "ES2022" ,
"module" : "Node16" ,
"moduleResolution" : "Node16" ,
"outDir" : "./build" ,
"rootDir" : "./src" ,
"strict" : true ,
"esModuleInterop" : true ,
"skipLibCheck" : true ,
"forceConsistentCasingInFileNames" : true
},
"include" : [ "src/**/*" ],
"exclude" : [ "node_modules" ]
}
现在让我们深入构建您的服务器。
构建您的服务器 导入包并设置实例 将这些添加到您的src/index.ts
顶部:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { z } from "zod" ;
const NWS_API_BASE = "https://api.weather.gov" ;
const USER_AGENT = "weather-app/1.0" ;
// 创建服务器实例
const server = new McpServer ({
name: "weather" ,
version: "1.0.0" ,
capabilities: {
resources: {},
tools: {},
},
});
辅助函数 接下来,让我们添加辅助函数,用于查询和格式化来自国家气象局API的数据:
// 用于发出NWS API请求的辅助函数
async function makeNWSRequest < T >( url : string ) : Promise < T | null > {
const headers = {
"User-Agent" : USER_AGENT ,
Accept: "application/geo+json" ,
};
try {
const response = await fetch ( url , { headers });
if ( ! response . ok ) {
throw new Error ( `HTTP error! status: ${ response . status } ` );
}
return ( await response . json ()) as T ;
} catch ( error ) {
console . error ( "Error making NWS request:" , error );
return null ;
}
}
interface AlertFeature {
properties : {
event ?: string ;
areaDesc ?: string ;
severity ?: string ;
status ?: string ;
headline ?: string ;
};
}
// 格式化警报数据
function formatAlert ( feature : AlertFeature ) : string {
const props = feature . properties ;
return [
`事件: ${ props . event || "未知" } ` ,
`区域: ${ props . areaDesc || "未知" } ` ,
`严重性: ${ props . severity || "未知" } ` ,
`状态: ${ props . status || "未知" } ` ,
`标题: ${ props . headline || "无标题" } ` ,
"---" ,
]. join ( " \n " );
}
interface ForecastPeriod {
name ?: string ;
temperature ?: number ;
temperatureUnit ?: string ;
windSpeed ?: string ;
windDirection ?: string ;
shortForecast ?: string ;
}
interface AlertsResponse {
features : AlertFeature [];
}
interface PointsResponse {
properties : {
forecast ?: string ;
};
}
interface ForecastResponse {
properties : {
periods : ForecastPeriod [];
};
}
实现工具执行 工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
// 注册天气工具
server . tool (
"get-alerts" ,
"获取一个州的天气警报" ,
{
state: z . string (). length ( 2 ). describe ( "两个字母的州代码(例如CA, NY)" ),
},
async ({ state }) => {
const stateCode = state . toUpperCase ();
const alertsUrl = ` ${ NWS_API_BASE } /alerts?area= ${ stateCode } ` ;
const alertsData = await makeNWSRequest < AlertsResponse >( alertsUrl );
if ( ! alertsData ) {
return {
content: [
{
type: "text" ,
text: "无法检索警报数据" ,
},
],
};
}
const features = alertsData . features || [];
if ( features . length === 0 ) {
return {
content: [
{
type: "text" ,
text: `没有 ${ stateCode } 的活跃警报` ,
},
],
};
}
const formattedAlerts = features . map ( formatAlert );
const alertsText = `活跃警报 ${ stateCode } : \n\n ${ formattedAlerts . join ( " \n " ) } ` ;
return {
content: [
{
type: "text" ,
text: alertsText ,
},
],
};
},
);
server . tool (
"get-forecast" ,
"获取某地的天气预报" ,
{
latitude: z . number (). min ( - 90 ). max ( 90 ). describe ( "地点的纬度" ),
longitude: z . number (). min ( - 180 ). max ( 180 ). describe ( "地点的经度" ),
},
async ({ latitude , longitude }) => {
// 获取网格点数据
const pointsUrl = ` ${ NWS_API_BASE } /points/ ${ latitude . toFixed ( 4 ) } , ${ longitude . toFixed ( 4 ) } ` ;
const pointsData = await makeNWSRequest < PointsResponse >( pointsUrl );
if ( ! pointsData ) {
return {
content: [
{
type: "text" ,
text: `无法检索坐标的网格点数据: ${ latitude } , ${ longitude } 。此位置可能不受NWS API支持(仅支持美国位置)。` ,
},
],
};
}
const forecastUrl = pointsData . properties ?. forecast ;
if ( ! forecastUrl ) {
return {
content: [
{
type: "text" ,
text: "无法从网格点数据中获取预报URL" ,
},
],
};
}
// 获取预报数据
const forecastData = await makeNWSRequest < ForecastResponse >( forecastUrl );
if ( ! forecastData ) {
return {
content: [
{
type: "text" ,
text: "无法检索预报数据" ,
},
],
};
}
const periods = forecastData . properties ?. periods || [];
if ( periods . length === 0 ) {
return {
content: [
{
type: "text" ,
text: "没有可用的预报周期" ,
},
],
};
}
// 格式化预报周期
const formattedForecast = periods . map (( period : ForecastPeriod ) =>
[
` ${ period . name || "未知" } :` ,
`温度: ${ period . temperature || "未知" } ° ${ period . temperatureUnit || "F" } ` ,
`风: ${ period . windSpeed || "未知" } ${ period . windDirection || "" } ` ,
` ${ period . shortForecast || "无可用预报" } ` ,
"---" ,
]. join ( " \n " ),
);
const forecastText = `预报 ${ latitude } , ${ longitude } : \n\n ${ formattedForecast . join ( " \n " ) } ` ;
return {
content: [
{
type: "text" ,
text: forecastText ,
},
],
};
},
);
运行服务器 最后,实现主函数以运行服务器:
async function main () {
const transport = new StdioServerTransport ();
await server . connect ( transport );
console . error ( "Weather MCP Server running on stdio" );
}
main (). catch (( error ) => {
console . error ( "Fatal error in main():" , error );
process . exit ( 1 );
});
确保运行npm run build
以构建您的服务器!这是让您的服务器连接的一个非常重要的步骤。
现在让我们从现有的MCP主机Claude for Desktop测试您的服务器。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。Linux用户可以继续构建客户端 教程,以构建一个连接到我们刚刚构建的服务器的MCP客户端。
首先,确保您已安装Claude for Desktop。您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"weather" : {
"command" : "node" ,
"args" : [
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "node" ,
"args" : [
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "node" ,
"args" : [
"C: \\ PATH \\ TO \\ PARENT \\ FOLDER \\ weather \\ build \\ index.js"
]
}
}
}
这告诉Claude for Desktop:
有一个名为”weather”的MCP服务器
通过运行node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js
来启动它
保存文件,并重启Claude for Desktop 。
这是基于Spring AI MCP自动配置和启动启动器的快速入门演示。
要了解如何手动创建同步和异步MCP服务器,请查阅Java SDK服务器 文档。
让我们开始构建我们的天气服务器吧!
您可以在这里找到我们将要构建的完整代码。
有关更多信息,请参阅MCP服务器启动启动器 参考文档。
有关手动MCP服务器实现,请参阅MCP服务器Java SDK文档 。
系统要求 设置您的环境 使用Spring Initializer 引导项目。
您需要添加以下依赖项:
< dependencies >
< dependency >
< groupId > org.springframework.ai </ groupId >
< artifactId > spring-ai-starter-mcp-server </ artifactId >
</ dependency >
< dependency >
< groupId > org.springframework </ groupId >
< artifactId > spring-web </ artifactId >
</ dependency >
</ dependencies >
< dependencies >
< dependency >
< groupId > org.springframework.ai </ groupId >
< artifactId > spring-ai-starter-mcp-server </ artifactId >
</ dependency >
< dependency >
< groupId > org.springframework </ groupId >
< artifactId > spring-web </ artifactId >
</ dependency >
</ dependencies >
dependencies {
implementation platform( "org.springframework.ai:spring-ai-starter-mcp-server" )
implementation platform( "org.springframework:spring-web" )
}
然后通过设置应用程序属性来配置您的应用程序:
application.properties
application.yml
spring.main.bannerMode =off
logging.pattern.console =
服务器配置属性 文档记录了所有可用的属性。
现在让我们深入构建您的服务器。
构建您的服务器 天气服务 让我们实现一个WeatherService.java ,它使用REST客户端查询来自国家气象局API的数据:
@ Service
public class WeatherService {
private final RestClient restClient ;
public WeatherService () {
this . restClient = RestClient . builder ()
. baseUrl ( "https://api.weather.gov" )
. defaultHeader ( "Accept" , "application/geo+json" )
. defaultHeader ( "User-Agent" , "WeatherApiClient/1.0 (your@email.com)" )
. build ();
}
@ Tool ( description = "获取特定纬度/经度的天气预报" )
public String getWeatherForecastByLocation (
double latitude , // 纬度坐标
double longitude // 经度坐标
) {
// 返回详细预报,包括:
// - 温度和单位
// - 风速和方向
// - 详细预报描述
}
@ Tool ( description = "获取美国州的天气警报" )
public String getAlerts (
@ ToolParam ( description = "两个字母的美国州代码(例如CA, NY" ) String state )
) {
// 返回活跃警报,包括:
// - 事件类型
// - 受影响区域
// - 严重性
// - 描述
// - 安全说明
}
// ......
}
@Service
注解会自动将服务注册到您的应用程序上下文中。
Spring AI的@Tool
注解使创建和维护MCP工具变得简单。
自动配置将自动将这些工具注册到MCP服务器。
创建您的启动应用程序 @ SpringBootApplication
public class McpServerApplication {
public static void main ( String [] args ) {
SpringApplication . run ( McpServerApplication . class , args);
}
@ Bean
public ToolCallbackProvider weatherTools ( WeatherService weatherService ) {
return MethodToolCallbackProvider . builder (). toolObjects (weatherService). build ();
}
}
使用MethodToolCallbackProvider
工具将@Tools
转换为MCP服务器使用的可操作回调。
运行服务器 最后,让我们构建服务器:
这将在target
文件夹中生成一个mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar
文件。
现在让我们从现有的MCP主机Claude for Desktop测试您的服务器。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。
首先,确保您已安装Claude for Desktop。
您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。
为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。
确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。
只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"spring-ai-mcp-weather" : {
"command" : "java" ,
"args" : [
"-Dspring.ai.mcp.server.stdio=true" ,
"-jar" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
{
"mcpServers" : {
"spring-ai-mcp-weather" : {
"command" : "java" ,
"args" : [
"-Dspring.ai.mcp.server.stdio=true" ,
"-jar" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
{
"mcpServers" : {
"spring-ai-mcp-weather" : {
"command" : "java" ,
"args" : [
"-Dspring.ai.mcp.server.transport=STDIO" ,
"-jar" ,
"C: \\ ABSOLUTE \\ PATH \\ TO \\ PARENT \\ FOLDER \\ weather \\ mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
这告诉Claude for Desktop:
有一个名为”my-weather-server”的MCP服务器
通过运行java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar
来启动它
保存文件,并重启Claude for Desktop 。
使用Java客户端测试您的服务器 手动创建MCP客户端 使用McpClient
连接到服务器:
var stdioParams = ServerParameters . builder ( "java" )
. args ( "-jar" , "/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar" )
. build ();
var stdioTransport = new StdioClientTransport (stdioParams);
var mcpClient = McpClient . sync (stdioTransport). build ();
mcpClient . initialize ();
ListToolsResult toolsList = mcpClient . listTools ();
CallToolResult weather = mcpClient . callTool (
new CallToolRequest ( "getWeatherForecastByLocation" ,
Map . of ( "latitude" , "47.6062" , "longitude" , "-122.3321" )));
CallToolResult alert = mcpClient . callTool (
new CallToolRequest ( "getAlerts" , Map . of ( "state" , "NY" )));
mcpClient . closeGracefully ();
使用MCP客户端启动启动器 使用spring-ai-starter-mcp-client
依赖项创建一个新的启动启动器应用程序:
< dependency >
< groupId > org.springframework.ai </ groupId >
< artifactId > spring-ai-starter-mcp-client </ artifactId >
</ dependency >
并设置spring.ai.mcp.client.stdio.servers-configuration
属性以指向您的claude_desktop_config.json
。
您可以重用现有的Anthropic Desktop配置:
spring.ai.mcp.client.stdio.servers-configuration =file:PATH/TO/claude_desktop_config.json
当您启动客户端应用程序时,自动配置将从claude_desktop_config.json中自动创建MCP客户端。
有关更多信息,请参阅MCP客户端启动启动器 参考文档。
更多Java MCP服务器示例 starter-webflux-server 演示了如何使用SSE传输创建MCP服务器。
它展示了如何使用Spring Boot的自动配置功能定义和注册MCP工具、资源和提示。
让我们开始构建我们的天气服务器吧!您可以在这里找到我们将要构建的完整代码。
前置知识 本快速入门假设您熟悉:
系统要求 设置您的环境 首先,如果您还没有安装java
和gradle
,请安装它们。
您可以从官方Oracle JDK网站 下载java
。
验证您的java
安装:
现在,让我们创建并设置您的项目:
# 为我们的项目创建一个新目录
mkdir weather
cd weather
# 初始化一个新的kotlin项目
gradle init
运行gradle init
后,您将看到用于创建项目的选项。
选择Application 作为项目类型,Kotlin 作为编程语言,Java 17 作为Java版本。
或者,您可以使用IntelliJ IDEA项目向导 创建Kotlin应用程序。
创建项目后,添加以下依赖项:
build.gradle.kts
build.gradle
val mcpVersion = "0.4.0"
val slf4jVersion = "2.0.9"
val ktorVersion = "3.1.1"
dependencies {
implementation ( "io.modelcontextprotocol:kotlin-sdk: $mcpVersion " )
implementation ( "org.slf4j:slf4j-nop: $slf4jVersion " )
implementation ( "io.ktor:ktor-client-content-negotiation: $ktorVersion " )
implementation ( "io.ktor:ktor-serialization-kotlinx-json: $ktorVersion " )
}
还要将以下插件添加到您的构建脚本:
build.gradle.kts
build.gradle
plugins {
kotlin ( "plugin.serialization" ) version "your_version_of_kotlin"
id ( "com.github.johnrengelman.shadow" ) version "8.1.1"
}
现在让我们深入构建您的服务器。
构建您的服务器 设置实例 添加一个服务器初始化函数:
// 运行MCP服务器的主函数
fun `run mcp server` () {
// 使用基本实现创建MCP服务器实例
val server = Server (
Implementation (
name = "weather" , // 工具名称为"weather"
version = "1.0.0" // 实现的版本
),
ServerOptions (
capabilities = ServerCapabilities (tools = ServerCapabilities. Tools (listChanged = true ))
)
)
// 创建一个使用标准IO进行服务器通信的传输
val transport = StdioServerTransport (
System.` in `. asInput (),
System.out. asSink (). buffered ()
)
runBlocking {
server. connect (transport)
val done = Job ()
server. onClose {
done. complete ()
}
done. join ()
}
}
天气API辅助函数 接下来,让我们添加函数和数据类,用于查询和转换来自国家气象局API的响应:
// 扩展函数,用于获取给定纬度和经度的预报信息
suspend fun HttpClient . getForecast (latitude: Double , longitude: Double ): List < String > {
val points = this . get ( "/points/ $latitude , $longitude " ). body < Points >()
val forecast = this . get (points.properties.forecast). body < Forecast >()
return forecast.properties.periods. map { period ->
"""
${ period.name } :
温度: ${ period.temperature } ${ period.temperatureUnit }
风: ${ period.windSpeed } ${ period.windDirection }
预报: ${ period.detailedForecast }
""" . trimIndent ()
}
}
// 扩展函数,用于获取给定州的天气警报
suspend fun HttpClient . getAlerts (state: String ): List < String > {
val alerts = this . get ( "/alerts/active/area/ $state " ). body < Alert >()
return alerts.features. map { feature ->
"""
事件: ${ feature.properties.event }
区域: ${ feature.properties.areaDesc }
严重性: ${ feature.properties.severity }
描述: ${ feature.properties.description }
说明: ${ feature.properties.instruction }
""" . trimIndent ()
}
}
@Serializable
data class Points (
val properties: Properties
) {
@Serializable
data class Properties ( val forecast: String )
}
@Serializable
data class Forecast (
val properties: Properties
) {
@Serializable
data class Properties ( val periods: List < Period >)
@Serializable
data class Period (
val number: Int , val name: String , val startTime: String , val endTime: String ,
val isDaytime: Boolean , val temperature: Int , val temperatureUnit: String ,
val temperatureTrend: String , val probabilityOfPrecipitation: JsonObject ,
val windSpeed: String , val windDirection: String ,
val shortForecast: String , val detailedForecast: String ,
)
}
@Serializable
data class Alert (
val features: List < Feature >
) {
@Serializable
data class Feature (
val properties: Properties
)
@Serializable
data class Properties (
val event: String , val areaDesc: String , val severity: String ,
val description: String , val instruction: String ?,
)
}
实现工具执行 工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
// 创建一个具有默认请求配置和JSON内容协商的HTTP客户端
val httpClient = HttpClient {
defaultRequest {
url ( "https://api.weather.gov" )
headers {
append ( "Accept" , "application/geo+json" )
append ( "User-Agent" , "WeatherApiClient/1.0" )
}
contentType (ContentType.Application.Json)
}
// 安装用于JSON序列化/反序列化的内容协商插件
install (ContentNegotiation) { json ( Json { ignoreUnknownKeys = true }) }
}
// 注册一个工具以按州获取天气警报
server. addTool (
name = "get_alerts" ,
description = """
获取美国州的天气警报。输入为两个字母的美国州代码(例如CA, NY)
""" . trimIndent (),
inputSchema = Tool. Input (
properties = JsonObject (
mapOf (
"state" to JsonObject (
mapOf (
"type" to JsonPrimitive ( "string" ),
"description" to JsonPrimitive ( "两个字母的美国州代码(例如CA, NY)" )
)
),
)
),
required = listOf ( "state" )
)
) { request ->
val state = request.arguments[ "state" ]?.jsonPrimitive?.content
if (state == null ) {
return @addTool CallToolResult (
content = listOf ( TextContent ( "需要'state'参数。" ))
)
}
val alerts = httpClient. getAlerts (state)
CallToolResult (content = alerts. map { TextContent (it) })
}
// 注册一个工具以按纬度和经度获取天气预报
server. addTool (
name = "get_forecast" ,
description = """
获取特定纬度/经度的天气预报
""" . trimIndent (),
inputSchema = Tool. Input (
properties = JsonObject (
mapOf (
"latitude" to JsonObject ( mapOf ( "type" to JsonPrimitive ( "number" ))),
"longitude" to JsonObject ( mapOf ( "type" to JsonPrimitive ( "number" ))),
)
),
required = listOf ( "latitude" , "longitude" )
)
) { request ->
val latitude = request.arguments[ "latitude" ]?.jsonPrimitive?.doubleOrNull
val longitude = request.arguments[ "longitude" ]?.jsonPrimitive?.doubleOrNull
if (latitude == null || longitude == null ) {
return @addTool CallToolResult (
content = listOf ( TextContent ( "需要'latitude'和'longitude'参数。" ))
)
}
val forecast = httpClient. getForecast (latitude, longitude)
CallToolResult (content = forecast. map { TextContent (it) })
}
运行服务器 最后,实现主函数以运行服务器:
fun main () = `run mcp server` ()
确保运行./gradlew build
以构建您的服务器。这是让您的服务器连接的一个非常重要的步骤。
现在让我们从现有的MCP主机Claude for Desktop测试您的服务器。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。Linux用户可以继续构建客户端 教程,以构建一个连接到我们刚刚构建的服务器的MCP客户端。
首先,确保您已安装Claude for Desktop。您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"weather" : {
"command" : "java" ,
"args" : [
"-jar" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/libs/weather-0.1.0-all.jar"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "java" ,
"args" : [
"-jar" ,
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/libs/weather-0.1.0-all.jar"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "java" ,
"args" : [
"-jar" ,
"C: \\ PATH \\ TO \\ PARENT \\ FOLDER \\ weather \\ build \\ libs \\ weather-0.1.0-all.jar"
]
}
}
}
这告诉Claude for Desktop:
有一个名为”weather”的MCP服务器
通过运行java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/libs/weather-0.1.0-all.jar
来启动它
保存文件,并重启Claude for Desktop 。
让我们开始构建我们的天气服务器吧!您可以在这里找到我们将要构建的完整代码。
前置知识 本快速入门假设您熟悉:
C#
像Claude这样的LLM
.NET 8或更高版本
系统要求 设置您的环境 首先,如果您还没有安装dotnet
,请安装它。您可以从官方Microsoft .NET网站 下载。验证您的dotnet
安装:
现在,让我们创建并设置您的项目:
# 为我们的项目创建一个新目录
mkdir weather
cd weather
# 初始化一个新的C#项目
dotnet new console
运行dotnet new console
后,您将看到一个新的C#项目。
您可以在您喜欢的IDE中打开该项目,例如Visual Studio 或Rider 。
或者,您可以使用Visual Studio项目向导 创建C#应用程序。
创建项目后,添加NuGet包以用于Model Context Protocol SDK和托管:
# 添加Model Context Protocol SDK NuGet包
dotnet add package ModelContextProtocol --prerelease
# 添加.NET托管NuGet包
dotnet add package Microsoft.Extensions.Hosting
现在让我们深入构建您的服务器。
构建您的服务器 打开项目中的Program.cs
文件,并将其内容替换为以下代码:
using Microsoft . Extensions . DependencyInjection ;
using Microsoft . Extensions . Hosting ;
using ModelContextProtocol ;
using System . Net . Http . Headers ;
var builder = Host . CreateEmptyApplicationBuilder ( settings : null );
builder . Services . AddMcpServer ()
. WithStdioServerTransport ()
. WithToolsFromAssembly ();
builder . Services . AddSingleton ( _ =>
{
var client = new HttpClient () { BaseAddress = new Uri ( "https://api.weather.gov" ) };
client . DefaultRequestHeaders . UserAgent . Add ( new ProductInfoHeaderValue ( "weather-tool" , "1.0" ));
return client ;
});
var app = builder . Build ();
await app . RunAsync ();
创建ApplicationHostBuilder
时,请确保使用CreateEmptyApplicationBuilder
而不是CreateDefaultBuilder
。这确保服务器不会向控制台写入任何其他消息。这仅适用于使用STDIO传输的服务器。
此代码设置了一个使用Model Context Protocol SDK创建MCP服务器的基本控制台应用程序,使用标准I/O传输。
天气API辅助函数 接下来,定义一个类,其中包含用于查询和转换来自国家气象局API的响应的工具执行处理程序:
using ModelContextProtocol . Server ;
using System . ComponentModel ;
using System . Net . Http . Json ;
using System . Text . Json ;
namespace QuickstartWeatherServer . Tools ;
[ McpServerToolType ]
public static class WeatherTools
{
[ McpServerTool , Description ( "获取美国州的天气警报。" )]
public static async Task < string > GetAlerts (
HttpClient client ,
[ Description ( "要获取警报的美国州。" )] string state )
{
var jsonElement = await client . GetFromJsonAsync < JsonElement >( $"/alerts/active/area/{ state }" );
var alerts = jsonElement . GetProperty ( "features" ). EnumerateArray ();
if ( ! alerts . Any ())
{
return "该州没有活跃的警报。" ;
}
return string . Join ( " \n -- \n " , alerts . Select ( alert =>
{
JsonElement properties = alert . GetProperty ( "properties" );
return $"""
事件: { properties . GetProperty ("event"). GetString ()}
区域: { properties . GetProperty ("areaDesc"). GetString ()}
严重性: { properties . GetProperty ("severity"). GetString ()}
描述: { properties . GetProperty ("description"). GetString ()}
说明: { properties . GetProperty ("instruction"). GetString ()}
""" ;
}));
}
[ McpServerTool , Description ( "获取某地的天气预报。" )]
public static async Task < string > GetForecast (
HttpClient client ,
[ Description ( "地点的纬度。" )] double latitude ,
[ Description ( "地点的经度。" )] double longitude )
{
var jsonElement = await client . GetFromJsonAsync < JsonElement >( $"/points/{ latitude },{ longitude }" );
var periods = jsonElement . GetProperty ( "properties" ). GetProperty ( "periods" ). EnumerateArray ();
return string . Join ( " \n --- \n " , periods . Select ( period => $"""
{ period . GetProperty ("name"). GetString ()}
温度: { period . GetProperty ("temperature"). GetInt32 ()}°F
风: { period . GetProperty ("windSpeed"). GetString ()} { period . GetProperty ("windDirection"). GetString ()}
预报: { period . GetProperty ("detailedForecast"). GetString ()}
""" ));
}
}
运行服务器 最后,使用以下命令运行服务器:
这将启动服务器并监听标准输入/输出上的传入请求。
使用Claude for Desktop测试您的服务器 Claude for Desktop尚未在Linux上可用。
首先,确保您已安装Claude for Desktop。
您可以在这里安装最新版本。 如果您已经有Claude for Desktop,请确保它已更新到最新版本。
我们需要为您想要使用的MCP服务器配置Claude for Desktop。
为此,请在文本编辑器中打开您的Claude for Desktop应用配置~/Library/Application Support/Claude/claude_desktop_config.json
。
确保在文件不存在时创建该文件。
例如,如果您安装了VS Code :
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code ~/Library/Application \ Support/Claude/claude_desktop_config.json
code $ env: AppData \Claude\claude_desktop_config.json
然后,您将在mcpServers
键中添加您的服务器。
只有至少一个服务器正确配置时,Claude for Desktop中的MCP UI元素才会显示。
在这种情况下,我们将像这样添加我们的单个天气服务器:
{
"mcpServers" : {
"weather" : {
"command" : "dotnet" ,
"args" : [
"run" ,
"--project" ,
"/ABSOLUTE/PATH/TO/PROJECT" ,
"--no-build"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "dotnet" ,
"args" : [
"run" ,
"--project" ,
"/ABSOLUTE/PATH/TO/PROJECT" ,
"--no-build"
]
}
}
}
{
"mcpServers" : {
"weather" : {
"command" : "dotnet" ,
"args" : [
"run" ,
"--project" ,
"C: \\ ABSOLUTE \\ PATH \\ TO \\ PROJECT" ,
"--no-build"
]
}
}
}
这告诉Claude for Desktop:
有一个名为”weather”的MCP服务器
通过运行dotnet run /ABSOLUTE/PATH/TO/PROJECT
来启动它
保存文件,并重启Claude for Desktop 。