服務器開發
在本教程中,我們將構建一個簡單的MCP天氣服務器並將其連接到宿主應用程序Claude桌面版。我們將從基本設置開始,然後逐步進行到更復雜的用例。
我們將構建什麼
許多大語言模型(包括Claude)目前沒有獲取天氣預報和嚴重天氣警報的能力。讓我們使用MCP來解決這個問題!
我們將構建一個服務器,提供兩個工具:get-alerts和get-forecast。然後我們將服務器連接到MCP宿主應用程序(在本例中是Claude桌面版):
為什麼是Claude桌面版而不是Claude.ai?
因為服務器是本地運行的,MCP目前只支持桌面宿主。遠程宿主正在積極開發中。
為什麼是Claude桌面版而不是Claude.ai?
MCP核心概念
MCP服務器可以提供三種主要類型的功能:
- 資源:類似文件的數據,可以被客戶端讀取(如API響應或文件內容)
- 工具:可以被大語言模型調用的函數(需要用戶批准)
- 提示:預先編寫的模板,幫助用戶完成特定任務
本教程將主要關注工具。
讓我們開始構建我們的天氣服務器!您可以在這裡找到我們將要構建的完整代碼。
前提知識
本快速入門假設您熟悉:
- Python
- 像Claude這樣的大語言模型
系統要求
- 安裝Python 3.10或更高版本。
- 您必須使用Python MCP SDK 1.2.0或更高版本。
設置您的環境
首先,讓我們安裝uv並設置我們的Python項目和環境:
安裝 uv
curl -LsSf https://astral.sh/uv/install.sh | shpowershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"安裝後請確保重啟您的終端,以確保uv命令被正確識別。
現在,讓我們創建並設置我們的項目:
創建項目
# 為我們的項目創建一個新目錄
uv init weather
cd weather
# 創建虛擬環境並激活它
uv venv
source .venv/bin/activate
# 安裝依賴
uv add "mcp[cli]" httpx
# 創建我們的服務器文件
touch weather.py# 創建我們的服務器文件
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發出GET請求,處理錯誤並返回JSON響應"""
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"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""實現工具執行
工具執行處理程序負責實際執行每個工具的邏輯。讓我們添加它:
@mcp.tool()
async def get_alerts(state: str) -> str:
"""獲取指定州的天氣警報(使用兩字母州代碼如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: 位置的經度
"""
# 首先獲取預報網格端點
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']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)運行服務器
最後,讓我們初始化並運行服務器:
if __name__ == "__main__":
# 初始化並運行服務器
mcp.run(transport='stdio')您的服務器已完成!運行uv run weather.py以確認一切正常工作。
現在讓我們使用現有的MCP宿主應用程序Claude桌面版測試您的服務器。
使用Claude桌面版測試您的服務器
首先,確保您已安裝Claude桌面版。您可以在這裡安裝最新版本。 如果您已經安裝了Claude桌面版,請確保它已更新到最新版本。
我們需要為您想要使用的任何MCP服務器配置Claude桌面版。為此,請在文本編輯器中打開您的Claude桌面版應用程序配置文件,位於~/Library/Application Support/Claude/claude_desktop_config.json。如果該文件不存在,請創建它。
例如,如果您已安裝VS Code:
打開配置文件
code ~/Library/Application\ Support/Claude/claude_desktop_config.jsoncode %APPDATA%\Claude\claude_desktop_config.json然後您將在mcpServers鍵中添加您的服務器。只有在至少一個服務器正確配置的情況下,MCP UI元素才會在Claude桌面版中顯示。
在這種情況下,我們將添加我們的單個天氣服務器,如下所示:
配置Claude桌面版
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"ABSOLUTE_PATH_PLACEHOLDER",
"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桌面版:
- 有一個名為"weather"的MCP服務器
- 使用
uv命令運行該服務器 - 在指定目錄中運行服務器
- 使用
weather.py作為入口點
現在,重啟Claude桌面版。您應該會在工具欄中看到一個新的MCP圖標。點擊它,您將看到我們的天氣工具!
下一步
恭喜!您已經成功構建了您的第一個MCP服務器。這只是開始 - 您可以:
讓我們開始構建我們的天氣服務器!您可以在這裡找到我們將要構建的完整代碼。
前提知識
本快速入門假設您熟悉:
- Node.js
- 像Claude這樣的大語言模型
系統要求
- 安裝Node.js 18或更高版本
- 您必須使用Node.js MCP SDK 1.2.0或更高版本
設置您的環境
首先,讓我們創建一個新的Node.js項目:
創建項目
# 創建一個新目錄
mkdir weather
cd weather
# 初始化項目
npm init -y
# 安裝依賴
npm install @mcp/node node-fetch
# 創建我們的服務器文件
touch weather.js現在讓我們開始構建您的服務器。
構建您的服務器
導入包並設置實例
將這些添加到您的weather.js頂部:
const { MCPServer } = require('@mcp/node');
const fetch = require('node-fetch');
// 初始化MCP服務器
const mcp = new MCPServer('weather');
// 常量
const NWS_API_BASE = 'https://api.weather.gov';
const USER_AGENT = 'weather-app/1.0';輔助函數
接下來,讓我們添加我們的輔助函數,用於查詢和格式化來自國家氣象服務API的數據:
async function makeNWSRequest(url) {
const headers = {
'User-Agent': USER_AGENT,
'Accept': 'application/geo+json'
};
try {
const response = await fetch(url, { headers });
if (!response.ok) throw new Error('API request failed');
return await response.json();
} catch (error) {
return null;
}
}
function formatAlert(feature) {
const props = feature.properties;
return `
Event: ${props.event || 'Unknown'}
Area: ${props.areaDesc || 'Unknown'}
Severity: ${props.severity || 'Unknown'}
Description: ${props.description || 'No description available'}
Instructions: ${props.instruction || 'No specific instructions provided'}
`;
}實現工具執行
工具執行處理程序負責實際執行每個工具的邏輯。讓我們添加它:
// 獲取警報工具
mcp.tool({
name: 'get-alerts',
description: '獲取美國州的天氣警報',
parameters: {
state: {
type: 'string',
description: '兩字母美國州代碼(例如CA、NY)'
}
},
async execute({ state }) {
const url = `${NWS_API_BASE}/alerts/active/area/${state}`;
const data = await makeNWSRequest(url);
if (!data || !data.features) {
return '無法獲取警報或未找到警報。';
}
if (data.features.length === 0) {
return '該州沒有活動警報。';
}
const alerts = data.features.map(formatAlert);
return alerts.join('\n---\n');
}
});
// 獲取預報工具
mcp.tool({
name: 'get-forecast',
description: '獲取位置的天氣預報',
parameters: {
latitude: {
type: 'number',
description: '位置的緯度'
},
longitude: {
type: 'number',
description: '位置的經度'
}
},
async execute({ latitude, longitude }) {
// 首先獲取預報網格端點
const pointsUrl = `${NWS_API_BASE}/points/${latitude},${longitude}`;
const pointsData = await makeNWSRequest(pointsUrl);
if (!pointsData) {
return '無法為此位置獲取預報數據。';
}
// 從點響應中獲取預報URL
const forecastUrl = pointsData.properties.forecast;
const forecastData = await makeNWSRequest(forecastUrl);
if (!forecastData) {
return '無法獲取詳細預報。';
}
// 將時段格式化為可讀預報
const periods = forecastData.properties.periods;
const forecasts = periods.slice(0, 5).map(period => `
${period.name}:
Temperature: ${period.temperature}°${period.temperatureUnit}
Wind: ${period.windSpeed} ${period.windDirection}
Forecast: ${period.detailedForecast}
`);
return forecasts.join('\n---\n');
}
});運行服務器
最後,讓我們初始化並運行服務器:
// 初始化並運行服務器
mcp.start();您的服務器已完成!運行node weather.js以確認一切正常工作。
現在讓我們使用現有的MCP宿主應用程序Claude桌面版測試您的服務器。
使用Claude桌面版測試您的服務器
首先,確保您已安裝Claude桌面版。您可以在這裡安裝最新版本。 如果您已經安裝了Claude桌面版,請確保它已更新到最新版本。
我們需要為您想要使用的任何MCP服務器配置Claude桌面版。為此,請在文本編輯器中打開您的Claude桌面版應用程序配置文件,位於~/Library/Application Support/Claude/claude_desktop_config.json。如果該文件不存在,請創建它。
例如,如果您已安裝VS Code:
打開配置文件
code ~/Library/Application\ Support/Claude/claude_desktop_config.jsoncode $env:AppData\Claude\claude_desktop_config.json然後您將在mcpServers鍵中添加您的服務器。只有在至少一個服務器正確配置的情況下,MCP UI元素才會在Claude桌面版中顯示。
在這種情況下,我們將添加我們的單個天氣服務器,如下所示:
配置Claude桌面版
{
"mcpServers": {
"weather": {
"command": "node",
"args": [
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/weather.js"
]
}
}
}{
"mcpServers": {
"weather": {
"command": "node",
"args": [
"C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\weather.js"
]
}
}
}這告訴Claude桌面版:
- 有一個名為"weather"的MCP服務器
- 使用
node命令運行該服務器 - 使用
weather.js作為入口點
現在,重啟Claude桌面版。您應該會在工具欄中看到一個新的MCP圖標。點擊它,您將看到我們的天氣工具!
下一步
恭喜!您已經成功構建了您的第一個MCP服務器。這只是開始 - 您可以:
讓我們開始構建我們的天氣服務器!您可以在這裡找到我們將要構建的完整代碼。
前提知識
本快速入門假設您熟悉:
- Java
- 像Claude這樣的大語言模型
系統要求
- 安裝Java 17或更高版本
- 您必須使用Java MCP SDK 1.2.0或更高版本
設置您的環境
首先,讓我們創建一個新的Maven項目。在您喜歡的IDE中創建一個新的Maven項目,或者使用以下命令:
創建項目
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=weather \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false然後,將以下依賴項添加到您的pom.xml文件中:
<dependencies>
<dependency>
<groupId>dev.mcp</groupId>
<artifactId>mcp-java</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>現在讓我們開始構建您的服務器。
構建您的服務器
創建主類
在src/main/java/com/example目錄中創建一個新的Weather.java文件:
package com.example;
import dev.mcp.MCPServer;
import dev.mcp.Tool;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Weather {
private static final String NWS_API_BASE = "https://api.weather.gov";
private static final String USER_AGENT = "weather-app/1.0";
private static final HttpClient client = HttpClient.newHttpClient();
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) {
MCPServer mcp = new MCPServer("weather");
setupTools(mcp);
mcp.start();
}
private static void setupTools(MCPServer mcp) {
// 工具設置代碼將在這裡
}
}輔助方法
在Weather類中添加以下輔助方法:
private static Map<String, Object> makeNWSRequest(String url) {
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("User-Agent", USER_AGENT)
.header("Accept", "application/geo+json")
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
return null;
}
return mapper.readValue(response.body(), Map.class);
} catch (Exception e) {
return null;
}
}
private static String formatAlert(Map<String, Object> feature) {
Map<String, Object> props = (Map<String, Object>) feature.get("properties");
return String.format("""
Event: %s
Area: %s
Severity: %s
Description: %s
Instructions: %s
""",
props.getOrDefault("event", "Unknown"),
props.getOrDefault("areaDesc", "Unknown"),
props.getOrDefault("severity", "Unknown"),
props.getOrDefault("description", "No description available"),
props.getOrDefault("instruction", "No specific instructions provided"));
}實現工具執行
現在讓我們在setupTools方法中實現我們的工具:
private static void setupTools(MCPServer mcp) {
// 獲取警報工具
mcp.tool(new Tool.Builder()
.name("get-alerts")
.description("獲取美國州的天氣警報")
.parameter("state", "string", "兩字母美國州代碼(例如CA、NY)")
.execute(params -> {
String state = params.get("state").toString();
String url = String.format("%s/alerts/active/area/%s", NWS_API_BASE, state);
Map<String, Object> data = makeNWSRequest(url);
if (data == null || !data.containsKey("features")) {
return "無法獲取警報或未找到警報。";
}
List<Map<String, Object>> features = (List<Map<String, Object>>) data.get("features");
if (features.isEmpty()) {
return "該州沒有活動警報。";
}
return features.stream()
.map(Weather::formatAlert)
.collect(Collectors.joining("\n---\n"));
})
.build());
// 獲取預報工具
mcp.tool(new Tool.Builder()
.name("get-forecast")
.description("獲取位置的天氣預報")
.parameter("latitude", "number", "位置的緯度")
.parameter("longitude", "number", "位置的經度")
.execute(params -> {
double latitude = Double.parseDouble(params.get("latitude").toString());
double longitude = Double.parseDouble(params.get("longitude").toString());
// 首先獲取預報網格端點
String pointsUrl = String.format("%s/points/%f,%f", NWS_API_BASE, latitude, longitude);
Map<String, Object> pointsData = makeNWSRequest(pointsUrl);
if (pointsData == null) {
return "無法為此位置獲取預報數據。";
}
// 從點響應中獲取預報URL
Map<String, Object> properties = (Map<String, Object>) pointsData.get("properties");
String forecastUrl = properties.get("forecast").toString();
Map<String, Object> forecastData = makeNWSRequest(forecastUrl);
if (forecastData == null) {
return "無法獲取詳細預報。";
}
// 將時段格式化為可讀預報
Map<String, Object> forecastProps = (Map<String, Object>) forecastData.get("properties");
List<Map<String, Object>> periods = (List<Map<String, Object>>) forecastProps.get("periods");
return periods.stream()
.limit(5)
.map(period -> String.format("""
%s:
Temperature: %s°%s
Wind: %s %s
Forecast: %s
""",
period.get("name"),
period.get("temperature"),
period.get("temperatureUnit"),
period.get("windSpeed"),
period.get("windDirection"),
period.get("detailedForecast")))
.collect(Collectors.joining("\n---\n"));
})
.build());
}您的服務器已完成!運行mvn compile exec:java -Dexec.mainClass="com.example.Weather"以確認一切正常工作。
現在讓我們使用現有的MCP宿主應用程序Claude桌面版測試您的服務器。
使用Claude桌面版測試您的服務器
首先,確保您已安裝Claude桌面版。您可以在這裡安裝最新版本。 如果您已經安裝了Claude桌面版,請確保它已更新到最新版本。
我們需要為您想要使用的任何MCP服務器配置Claude桌面版。為此,請在文本編輯器中打開您的Claude桌面版應用程序配置文件,位於~/Library/Application Support/Claude/claude_desktop_config.json。如果該文件不存在,請創建它。
例如,如果您已安裝VS Code:
打開配置文件
code ~/Library/Application\ Support/Claude/claude_desktop_config.jsoncode $env:AppData\Claude\claude_desktop_config.json然後您將在mcpServers鍵中添加您的服務器。只有在至少一個服務器正確配置的情況下,MCP UI元素才會在Claude桌面版中顯示。
在這種情況下,我們將添加我們的單個天氣服務器,如下所示:
配置Claude桌面版
{
"mcpServers": {
"weather": {
"command": "mvn",
"args": [
"compile",
"exec:java",
"-Dexec.mainClass=com.example.Weather",
"-f",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/pom.xml"
]
}
}
}{
"mcpServers": {
"weather": {
"command": "mvn",
"args": [
"compile",
"exec:java",
"-Dexec.mainClass=com.example.Weather",
"-f",
"C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\pom.xml"
]
}
}
}這告訴Claude桌面版:
- 有一個名為"weather"的MCP服務器
- 使用
mvn命令運行該服務器 - 在指定目錄中運行服務器
- 使用
Weather類作為入口點
現在,重啟Claude桌面版。您應該會在工具欄中看到一個新的MCP圖標。點擊它,您將看到我們的天氣工具!
下一步
恭喜!您已經成功構建了您的第一個MCP服務器。這只是開始 - 您可以:
測試命令
讓我們確認Claude桌面端能正確識別天氣服務中的兩個工具。注意查看錘子圖標
點擊錘子圖標後應該看到兩個工具:
如果工具未顯示,請參考故障排除章節。
成功顯示工具後,可以在Claude桌面端測試以下命令:
- 薩克拉門託的天氣如何?
- 德克薩斯州有哪些活躍的天氣警報?
底層工作原理
問題處理流程:
- 客戶端將問題發送給Claude
- Claude分析可用工具並選擇使用
- 通過MCP服務器執行工具
- 返回結果給Claude
- Claude生成自然語言響應
- 向用戶展示最終結果
故障排除
Claude桌面端集成問題
獲取桌面端日誌
日誌文件位於~/Library/Logs/Claude:
mcp.log包含MCP連接日誌mcp-server-SERVERNAME.log包含指定服務器的錯誤日誌
實時查看日誌命令:
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log服務器未顯示
- 檢查claude_desktop_config.json文件語法
- 確認項目使用絕對路徑
- 完全重啟Claude桌面端
工具調用靜默失敗
- 檢查Claude日誌
- 驗證服務器能否正常啟動
- 嘗試重啟Claude桌面端
天氣API問題
錯誤:無法獲取網格點數據 可能原因:
- 座標不在美國境內
- NWS API服務異常
- 觸發速率限制
解決方案:
- 確認使用美國座標
- 增加請求間隔時間
- 查看NWS API狀態頁



