让我们开始构建我们的天气服务器!你可以在这里找到我们将构建的完整代码。
前提知识 本快速入门假设你熟悉:
系统要求
已安装 Python 3.10 或更高版本。
你必须使用 Python MCP SDK 1.2.0 或更高版本。
设置你的环境 首先,让我们安装 uv
并设置我们的 Python 项目和环境:
之后请务必重启你的终端,以确保 uv
命令被识别。
现在,让我们创建并设置我们的项目:
现在让我们深入构建你的服务器。
构建你的服务器 导入 packages 并设置 instance 将这些添加到你的 weather.py
文件的顶部:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化 FastMCP server
mcp = FastMCP( "weather" )
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP class 使用 Python type hints 和 docstrings 来自动生成 tool definitions,从而轻松创建和维护 MCP tools。
Helper functions 接下来,让我们添加 helper functions,用于查询和格式化来自 National Weather Service 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 :
"""将警报 feature 格式化为可读的字符串。"""
props = feature[ "properties" ]
return f """
事件: { props.get( 'event' , 'Unknown' ) }
区域: { props.get( 'areaDesc' , 'Unknown' ) }
严重性: { props.get( 'severity' , 'Unknown' ) }
描述: { props.get( 'description' , 'No description available' ) }
指示: { props.get( 'instruction' , 'No specific instructions provided' ) }
"""
Tool execution handler 负责实际执行每个 tool 的逻辑。让我们添加它:
@mcp.tool ()
async def get_alerts ( state : str ) -> str :
"""获取美国州的天气警报。
Args:
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 :
"""获取某个位置的天气预报。
Args:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 首先获取预报网格 endpoint
points_url = f " { NWS_API_BASE } /points/ { latitude } , { longitude } "
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取此位置的预报数据。"
# 从 points response 中获取预报 URL
forecast_url = points_data[ "properties" ][ "forecast" ]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将 periods 格式化为可读的预报
periods = forecast_data[ "properties" ][ "periods" ]
forecasts = []
for period in periods[: 5 ]: # 仅显示接下来的 5 个 periods
forecast = f """
{ period[ 'name' ] } :
温度: { period[ 'temperature' ] } ° { period[ 'temperatureUnit' ] }
风: { period[ 'windSpeed' ] } { period[ 'windDirection' ] }
预报: { period[ 'detailedForecast' ] }
"""
forecasts.append(forecast)
return " \n --- \n " .join(forecasts)
运行 server 最后,让我们初始化并运行 server:
if __name__ == "__main__" :
# 初始化并运行 server
mcp.run( transport = 'stdio' )
你的 server 已经完成!运行 uv run weather.py
以确认一切正常。
现在让我们从现有的 MCP host,Claude for Desktop 测试你的 server。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。Linux 用户可以继续阅读 构建 client 教程,以构建一个连接到我们刚刚构建的 server 的 MCP client。
首先,确保你已安装 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。如果该 file 不存在,请确保创建它。
例如,如果你安装了 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
key 中添加你的 servers。只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
{
"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
executable 的完整 path。你可以在 MacOS/Linux 上运行 which uv
或在 Windows 上运行 where uv
来获取它。
确保你传入的是你的 server 的绝对 path。
这告诉 Claude for Desktop:
有一个名为 “weather” 的 MCP server
通过运行 uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
来启动它
保存 file,并重新启动 Claude for Desktop 。
让我们开始构建我们的天气服务器!你可以在这里找到我们将构建的完整代码。
前提知识 本快速入门假设你熟悉:
系统要求
已安装 Python 3.10 或更高版本。
你必须使用 Python MCP SDK 1.2.0 或更高版本。
设置你的环境 首先,让我们安装 uv
并设置我们的 Python 项目和环境:
之后请务必重启你的终端,以确保 uv
命令被识别。
现在,让我们创建并设置我们的项目:
现在让我们深入构建你的服务器。
构建你的服务器 导入 packages 并设置 instance 将这些添加到你的 weather.py
文件的顶部:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化 FastMCP server
mcp = FastMCP( "weather" )
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP class 使用 Python type hints 和 docstrings 来自动生成 tool definitions,从而轻松创建和维护 MCP tools。
Helper functions 接下来,让我们添加 helper functions,用于查询和格式化来自 National Weather Service 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 :
"""将警报 feature 格式化为可读的字符串。"""
props = feature[ "properties" ]
return f """
事件: { props.get( 'event' , 'Unknown' ) }
区域: { props.get( 'areaDesc' , 'Unknown' ) }
严重性: { props.get( 'severity' , 'Unknown' ) }
描述: { props.get( 'description' , 'No description available' ) }
指示: { props.get( 'instruction' , 'No specific instructions provided' ) }
"""
Tool execution handler 负责实际执行每个 tool 的逻辑。让我们添加它:
@mcp.tool ()
async def get_alerts ( state : str ) -> str :
"""获取美国州的天气警报。
Args:
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 :
"""获取某个位置的天气预报。
Args:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 首先获取预报网格 endpoint
points_url = f " { NWS_API_BASE } /points/ { latitude } , { longitude } "
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取此位置的预报数据。"
# 从 points response 中获取预报 URL
forecast_url = points_data[ "properties" ][ "forecast" ]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将 periods 格式化为可读的预报
periods = forecast_data[ "properties" ][ "periods" ]
forecasts = []
for period in periods[: 5 ]: # 仅显示接下来的 5 个 periods
forecast = f """
{ period[ 'name' ] } :
温度: { period[ 'temperature' ] } ° { period[ 'temperatureUnit' ] }
风: { period[ 'windSpeed' ] } { period[ 'windDirection' ] }
预报: { period[ 'detailedForecast' ] }
"""
forecasts.append(forecast)
return " \n --- \n " .join(forecasts)
运行 server 最后,让我们初始化并运行 server:
if __name__ == "__main__" :
# 初始化并运行 server
mcp.run( transport = 'stdio' )
你的 server 已经完成!运行 uv run weather.py
以确认一切正常。
现在让我们从现有的 MCP host,Claude for Desktop 测试你的 server。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。Linux 用户可以继续阅读 构建 client 教程,以构建一个连接到我们刚刚构建的 server 的 MCP client。
首先,确保你已安装 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。如果该 file 不存在,请确保创建它。
例如,如果你安装了 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
key 中添加你的 servers。只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
{
"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
executable 的完整 path。你可以在 MacOS/Linux 上运行 which uv
或在 Windows 上运行 where uv
来获取它。
确保你传入的是你的 server 的绝对 path。
这告诉 Claude for Desktop:
有一个名为 “weather” 的 MCP server
通过运行 uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py
来启动它
保存 file,并重新启动 Claude for Desktop 。
让我们开始构建我们的天气服务器!你可以在这里找到我们将构建的完整代码。
前提知识 本快速入门假设你熟悉:
系统要求 对于 TypeScript,请确保你已安装最新版本的 Node。
设置你的环境 首先,如果你还没有安装 Node.js 和 npm,请安装它们。你可以从 nodejs.org 下载它们。
验证你的 Node.js 安装:
node --version
npm --version
在本教程中,你需要 Node.js 16 或更高版本。
现在,让我们创建并设置我们的项目:
更新你的 package.json 以添加 type: “module” 和一个 build script:
{
"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" ]
}
现在让我们深入构建你的服务器。
构建你的服务器 导入 packages 并设置 instance 将这些添加到你的 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" ;
// 创建 server instance
const server = new McpServer ({
name: "weather" ,
version: "1.0.0" ,
capabilities: {
resources: {},
tools: {},
},
});
Helper functions 接下来,让我们添加 helper functions,用于查询和格式化来自 National Weather Service API 的数据:
// Helper function 用于发送 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 [
`Event: ${ props . event || "Unknown" } ` ,
`Area: ${ props . areaDesc || "Unknown" } ` ,
`Severity: ${ props . severity || "Unknown" } ` ,
`Status: ${ props . status || "Unknown" } ` ,
`Headline: ${ props . headline || "No 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 [];
};
}
Tool execution handler 负责实际执行每个 tool 的逻辑。让我们添加它:
// 注册天气 tools
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: `No active alerts for ${ stateCode } ` ,
},
],
};
}
const formattedAlerts = features . map ( formatAlert );
const alertsText = `Active alerts for ${ 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: `Failed to retrieve grid point data for coordinates: ${ latitude } , ${ longitude } . This location may not be supported by the NWS API (only US locations are supported).` ,
},
],
};
}
const forecastUrl = pointsData . properties ?. forecast ;
if ( ! forecastUrl ) {
return {
content: [
{
type: "text" ,
text: "Failed to get forecast URL from grid point data" ,
},
],
};
}
// 获取预报数据
const forecastData = await makeNWSRequest < ForecastResponse >( forecastUrl );
if ( ! forecastData ) {
return {
content: [
{
type: "text" ,
text: "Failed to retrieve forecast data" ,
},
],
};
}
const periods = forecastData . properties ?. periods || [];
if ( periods . length === 0 ) {
return {
content: [
{
type: "text" ,
text: "No forecast periods available" ,
},
],
};
}
// 格式化预报 periods
const formattedForecast = periods . map (( period : ForecastPeriod ) =>
[
` ${ period . name || "Unknown" } :` ,
`Temperature: ${ period . temperature || "Unknown" } ° ${ period . temperatureUnit || "F" } ` ,
`Wind: ${ period . windSpeed || "Unknown" } ${ period . windDirection || "" } ` ,
` ${ period . shortForecast || "No forecast available" } ` ,
"---" ,
]. join ( " \n " ),
);
const forecastText = `Forecast for ${ latitude } , ${ longitude } : \n\n ${ formattedForecast . join ( " \n " ) } ` ;
return {
content: [
{
type: "text" ,
text: forecastText ,
},
],
};
},
);
运行 server 最后,实现 main function 以运行 server:
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
以 build 你的 server!这是让你的 server 连接起来非常重要的一步。
现在让我们从现有的 MCP host,Claude for Desktop 测试你的 server。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。Linux 用户可以继续阅读 构建 client 教程,以构建一个连接到我们刚刚构建的 server 的 MCP client。
首先,确保你已安装 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。如果该 file 不存在,请确保创建它。
例如,如果你安装了 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
key 中添加你的 servers。只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
这告诉 Claude for Desktop:
有一个名为 “weather” 的 MCP server
通过运行 node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js
来启动它
保存 file,并重新启动 Claude for Desktop 。
这是一个基于 Spring AI MCP auto-configuration 和 boot starters 的快速入门演示。
要学习如何手动创建 sync 和 async MCP Servers,请查阅 Java SDK Server 文档。
让我们开始构建我们的天气服务器!
你可以在这里找到我们将构建的完整代码。
有关更多信息,请参阅 MCP Server Boot Starter 参考文档。
有关手动 MCP Server 实现,请参阅 MCP Server Java SDK 文档 。
系统要求 设置你的环境 使用 Spring Initializer 来 bootstrap 项目。
你需要添加以下 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>
<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:
application.properties
application.yml
Server Configuration Properties 文档记录了所有可用的 properties。
现在让我们深入构建你的服务器。
构建你的服务器 Weather Service 让我们实现一个 WeatherService.java ,它使用 REST client 来查询来自 National Weather Service 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 = "Get weather forecast for a specific latitude/longitude" )
public String getWeatherForecastByLocation (
double latitude , // Latitude coordinate
double longitude // Longitude coordinate
) {
// Returns detailed forecast including:
// - Temperature and unit
// - Wind speed and direction
// - Detailed forecast description
}
@ Tool ( description = "Get weather alerts for a US state" )
public String getAlerts (
@ ToolParam ( description = "Two-letter US state code (e.g. CA, NY)" String state
) {
// Returns active alerts including:
// - Event type
// - Affected area
// - Severity
// - Description
// - Safety instructions
}
// ......
}
@Service
annotation 将在你的 application context 中自动注册该 service。
Spring AI @Tool
annotation,使其易于创建和维护 MCP tools。
auto-configuration 将自动向 MCP server 注册这些 tools。
创建你的 Boot Application @ 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
utils 将 @Tools
转换为 MCP server 使用的可操作 callbacks。
运行 server 最后,让我们 build server:
这将在 target
文件夹中生成一个 mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar
file。
现在让我们从现有的 MCP host,Claude for Desktop 测试你的 server。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。
首先,确保你已安装 Claude for Desktop。
你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。
为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。
如果该 file 不存在,请确保创建它。
例如,如果你安装了 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
key 中添加你的 servers。
只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
{
"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"
]
}
}
}
确保你传入的是你的 server 的绝对 path。
这告诉 Claude for Desktop:
有一个名为 “my-weather-server” 的 MCP server
通过运行 java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar
来启动它
保存 file,并重新启动 Claude for Desktop 。
使用 Java client 测试你的 server 手动创建 MCP Client 使用 McpClient
连接到 server:
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 Client Boot Starter 使用 spring-ai-starter-mcp-client
dependency 创建一个新的 boot starter application:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
并设置 spring.ai.mcp.client.stdio.servers-configuration
property 以指向你的 claude_desktop_config.json
。
你可以重用现有的 Anthropic Desktop configuration:
spring.ai.mcp.client.stdio.servers-configuration=file:PATH/TO/claude_desktop_config.json
当你启动你的 client application 时,auto-configuration 将从 claude_desktop_config.json 自动创建 MCP clients。
有关更多信息,请参阅 MCP Client Boot Starters 参考文档。
更多 Java MCP Server 示例 starter-webflux-server 演示了如何使用 SSE transport 创建 MCP server。
它展示了如何使用 Spring Boot 的 auto-configuration 功能来定义和注册 MCP Tools、Resources 和 Prompts。
让我们开始构建我们的天气服务器!你可以在这里找到我们将构建的完整代码。
前提知识 本快速入门假设你熟悉:
系统要求 设置你的环境 首先,如果你还没有安装 java
和 gradle
,请安装它们。
你可以从 官方 Oracle JDK 网站 下载 java
。
验证你的 java
安装:
现在,让我们创建并设置你的项目:
运行 gradle init
后,你将看到用于创建你的项目的选项。
选择 Application 作为项目类型,Kotlin 作为编程语言,Java 17 作为 Java 版本。
或者,你可以使用 IntelliJ IDEA 项目向导 创建一个 Kotlin application。
创建项目后,添加以下 dependencies:
build.gradle.kts
build.gradle
此外,将以下 plugins 添加到你的 build script:
build.gradle.kts
build.gradle
现在让我们深入构建你的服务器。
构建你的服务器 设置 instance 添加一个 server 初始化 function:
// Main function 以运行 MCP server
fun `run mcp server` () {
// 创建具有基本实现的 MCP Server instance
val server = Server (
Implementation (
name = "weather" , // Tool name 是 "weather"
version = "1.0.0" // Implementation 的 version
),
ServerOptions (
capabilities = ServerCapabilities (tools = ServerCapabilities. Tools (listChanged = true ))
)
)
// 创建一个使用 standard IO 的 transport,用于 server 通信
val transport = StdioServerTransport (
System.` in `. asInput (),
System.out. asSink (). buffered ()
)
runBlocking {
server. connect (transport)
val done = Job ()
server. onClose {
done. complete ()
}
done. join ()
}
}
Weather API helper functions 接下来,让我们添加 functions 和 data classes,用于查询和转换来自 National Weather Service API 的响应:
// Extension function 以获取给定纬度和经度的预报信息
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 ()
}
}
// Extension function 以获取给定州的 weather alerts
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 ?,
)
}
Tool execution handler 负责实际执行每个 tool 的逻辑。让我们添加它:
// 创建一个 HTTP client,它具有 default request configuration 和 JSON content negotiation
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)
}
// 安装 content negotiation plugin,用于 JSON serialization/deserialization
install (ContentNegotiation) { json ( Json { ignoreUnknownKeys = true }) }
}
// 注册一个 tool,以按州获取 weather alerts
server. addTool (
name = "get_alerts" ,
description = """
获取美国州的天气警报。输入是两个字母的美国州代码(例如 CA、NY)
""" . trimIndent (),
inputSchema = Tool. Input (
properties = buildJsonObject {
putJsonObject ( "state" ) {
put ( "type" , "string" )
put ( "description" , "两个字母的美国州代码(例如 CA、NY)" )
}
},
required = listOf ( "state" )
)
) { request ->
val state = request.arguments[ "state" ]?.jsonPrimitive?.content
if (state == null ) {
return @addTool CallToolResult (
content = listOf ( TextContent ( "The 'state' parameter is required." ))
)
}
val alerts = httpClient. getAlerts (state)
CallToolResult (content = alerts. map { TextContent (it) })
}
// 注册一个 tool,以按纬度和经度获取天气预报
server. addTool (
name = "get_forecast" ,
description = """
获取特定纬度/经度的天气预报
""" . trimIndent (),
inputSchema = Tool. Input (
properties = buildJsonObject {
putJsonObject ( "latitude" ) { put ( "type" , "number" ) }
putJsonObject ( "longitude" ) { put ( "type" , "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 ( "The 'latitude' and 'longitude' parameters are required." ))
)
}
val forecast = httpClient. getForecast (latitude, longitude)
CallToolResult (content = forecast. map { TextContent (it) })
}
运行 server 最后,实现 main function 以运行 server:
fun main () = `run mcp server` ()
确保运行 ./gradlew build
以 build 你的 server。这是让你的 server 连接起来非常重要的一步。
现在让我们从现有的 MCP host,Claude for Desktop 测试你的 server。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。Linux 用户可以继续阅读 构建 client 教程,以构建一个连接到我们刚刚构建的 server 的 MCP client。
首先,确保你已安装 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。
为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。
如果该 file 不存在,请确保创建它。
例如,如果你安装了 VS Code :
然后,你将在 mcpServers
key 中添加你的 servers。
只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
这告诉 Claude for Desktop:
有一个名为 “weather” 的 MCP server
通过运行 java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/libs/weather-0.1.0-all.jar
来启动它
保存 file,并重新启动 Claude for Desktop 。
让我们开始构建我们的天气服务器!你可以在这里找到我们将构建的完整代码。
前提知识 本快速入门假设你熟悉:
C#
LLMs,如 Claude
.NET 8 或更高版本
系统要求 设置你的环境 首先,如果你还没有安装 dotnet
,请安装它。你可以从 官方 Microsoft .NET 网站 下载 dotnet
。验证你的 dotnet
安装:
现在,让我们创建并设置你的项目:
运行 dotnet new console
后,你将看到一个新的 C# 项目。
你可以在你最喜欢的 IDE 中打开该项目,例如 Visual Studio 或 Rider 。
或者,你可以使用 Visual Studio 项目向导 创建一个 C# application。
创建项目后,为 Model Context Protocol SDK 和 hosting 添加 NuGet package:
# 添加 Model Context Protocol SDK NuGet package
dotnet add package ModelContextProtocol --prerelease
# 添加 .NET Hosting NuGet package
dotnet add package Microsoft.Extensions.Hosting
现在让我们深入构建你的服务器。
构建你的服务器 打开你项目中的 Program.cs
file,并将内容替换为以下代码:
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
。这确保了 server 不会向控制台写入任何其他消息。这仅对于使用 STDIO transport 的 servers 是必要的。
此代码设置了一个基本的控制台 application,它使用 Model Context Protocol SDK 创建一个具有 standard I/O transport 的 MCP server。
Weather API helper functions 接下来,定义一个 class,其中包含用于查询和转换来自 National Weather Service API 的响应的 tool execution handlers:
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 ( "Get weather alerts for a US state." )]
public static async Task < string > GetAlerts (
HttpClient client ,
[ Description ( "The US state to get alerts for." )] string state )
{
var jsonElement = await client . GetFromJsonAsync < JsonElement >( $"/alerts/active/area/{ state }" );
var alerts = jsonElement . GetProperty ( "features" ). EnumerateArray ();
if ( ! alerts . Any ())
{
return "No active alerts for this state." ;
}
return string . Join ( " \n -- \n " , alerts . Select ( alert =>
{
JsonElement properties = alert . GetProperty ( "properties" );
return $"""
Event: { properties . GetProperty ("event"). GetString ()}
Area: { properties . GetProperty ("areaDesc"). GetString ()}
Severity: { properties . GetProperty ("severity"). GetString ()}
Description: { properties . GetProperty ("description"). GetString ()}
Instruction: { properties . GetProperty ("instruction"). GetString ()}
""" ;
}));
}
[ McpServerTool , Description ( "Get weather forecast for a location." )]
public static async Task < string > GetForecast (
HttpClient client ,
[ Description ( "Latitude of the location." )] double latitude ,
[ Description ( "Longitude of the location." )] 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 ()}
Temperature: { period . GetProperty ("temperature"). GetInt32 ()}°F
Wind: { period . GetProperty ("windSpeed"). GetString ()} { period . GetProperty ("windDirection"). GetString ()}
Forecast: { period . GetProperty ("detailedForecast"). GetString ()}
""" ));
}
}
运行 server 最后,使用以下 command 运行 server:
这将启动 server 并侦听 standard input/output 上的传入请求。
使用 Claude for Desktop 测试你的 server Claude for Desktop 尚不适用于 Linux。Linux 用户可以继续阅读 构建 client 教程,以构建一个连接到我们刚刚构建的 server 的 MCP client。
首先,确保你已安装 Claude for Desktop。你可以在这里安装最新版本。 如果你已经安装了 Claude for Desktop,请确保它已更新到最新版本。
我们需要为你想要使用的任何 MCP servers 配置 Claude for Desktop。为此,请在文本编辑器中打开 ~/Library/Application Support/Claude/claude_desktop_config.json
中的 Claude for Desktop App configuration。如果该 file 不存在,请确保创建它。
例如,如果你安装了 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
key 中添加你的 servers。只有正确配置了至少一个 server,MCP UI 元素才会显示在 Claude for Desktop 中。
在本例中,我们将添加我们的单个天气服务器,如下所示:
{
"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 server
通过运行 dotnet run /ABSOLUTE/PATH/TO/PROJECT
来启动它
保存 file,并重新启动 Claude for Desktop 。