High Altitude Oolong
2025/11/2
2025/10/23
MediaWiki 1.44 使用者帳號管理指令
注意:MediaWiki 1.40 之後,維護腳本需使用 maintenance/run.php 執行,不再直接執行腳本檔案。
以 https://github.com/checko/mediawiki144 啟動/restore 的 mediawiki container 為例:
方法一:建立新的管理員帳號
建立一個具有管理員和行政員權限的新帳號:
docker compose exec mediawiki php maintenance/run.php createAndPromote \
--bureaucrat --sysop --force \
使用者名稱 密碼範例:
docker compose exec mediawiki php maintenance/run.php createAndPromote \
--bureaucrat --sysop --force \
admin AdminPassword123!方法二:重設現有使用者密碼
變更現有使用者的密碼:
docker compose exec mediawiki php maintenance/run.php changePassword \
--user=使用者名稱 \
--password=新密碼範例:
docker compose exec mediawiki php maintenance/run.php changePassword \
--user=Ken.Lin \
--password=kenlinpassword123!方法三:提升現有使用者為管理員
將現有使用者提升為管理員和行政員:
docker compose exec mediawiki php maintenance/run.php createAndPromote \
--bureaucrat --sysop --force \
使用者名稱範例:
docker compose exec mediawiki php maintenance/run.php createAndPromote \
--bureaucrat --sysop --force \
ExistingUser方法四:使用 SQL 指令直接操作(不建議)
直接在資料庫中授予使用者管理員權限:
docker compose exec mysql mysql -u root -proot_password mediawiki -e "
INSERT INTO user_groups (ug_user, ug_group)
SELECT user_id, 'sysop' FROM user WHERE user_name = '使用者名稱'
ON DUPLICATE KEY UPDATE ug_group = ug_group;
INSERT INTO user_groups (ug_user, ug_group)
SELECT user_id, 'bureaucrat' FROM user WHERE user_name = '使用者名稱'
ON DUPLICATE KEY UPDATE ug_group = ug_group;
"權限說明
- sysop:管理員權限,可以刪除頁面、封鎖使用者、保護頁面等
- bureaucrat:行政員權限,可以授予其他使用者權限、重新命名使用者等
注意事項
- 使用 maintenance/run.php 是 MediaWiki 1.40 之後的標準做法
- 舊的直接執行方式(maintenance/scriptName.php)雖仍可用但已過時
- 建議使用維護腳本而非直接操作 SQL 資料庫
- 密碼中如有特殊字元,需注意 shell 跳脫字元處理
2025/10/22
ESP32-DevKitC V4 與 ESP32 系列產品的關係
產品分層架構
ESP32 的產品線可以分為三個層級:晶片(SoC)、模組(Module)、開發板(Development Board)。這三層形成了從矽晶片到最終使用者產品的完整架構。
第一層:晶片(SoC - System on Chip)
這是最底層的矽晶片元件,是所有後續產品的核心。常見的 ESP32 晶片包括:
ESP32-D0WD-V3:雙核處理器版本ESP32-S0WD:單核處理器版本ESP32-D0WDR2-V3:雙核版本,內建 PSRAM 快取記憶體
第二層:模組(Module)
模組是將晶片與必要的周邊元件(如 Flash 記憶體、晶振、天線等)整合在小型 PCB 上的產品。這些模組已通過必要的認證,可以直接用於產品設計。常見的 ESP32 模組包括:
ESP32-WROOM-32E:採用 ESP32-D0WD-V3 晶片的標準模組ESP32-WROVER-E:採用 ESP32-D0WD-V3 晶片,並增加 PSRAM 快取ESP32-SOLO-1:採用 ESP32-S0WD 單核晶片的版本ESP32-PICO-D4:系統級封裝(SiP)版本,體積更小
第三層:開發板(Development Board / EVB)
開發板是將模組焊接在一個完整的電路板上,並提供 USB 連接、電源管理、GPIO 引腳等便利開發的功能。開發板適合開發者和創客使用。常見的 ESP32 開發板包括:
ESP32-DevKitC V4:最受歡迎的通用開發板,可搭載 WROOM 或 WROVER 系列模組ESP32-DevKitM-1:搭載 ESP32-MINI-1 模組的小型開發板ESP32-PICO-KIT-1:搭載 ESP32-PICO-D4 模組的開發板
ESP32-DevKitC V4 在產品線中的位置
所屬系列
ESP32-DevKitC V4 屬於 ESP32 原始系列(第一代 ESP32,使用 Xtensa LX6 雙核或單核處理器)。它不是以下變體系列:
- ESP32-S2(單核 LX7 架構)
- ESP32-S3(雙核 LX7 架構)
- ESP32-C3 / C6(RISC-V 架構)
- ESP32-H2(RISC-V 架構,無 Wi-Fi 功能)
與 ESP32 系列的技術關係
ESP32-DevKitC V4 使用的是標準的 ESP32 晶片,因此它在技術規格上與原始的 ESP32 系列完全相同。具體來說:
硬體構成
- 預設搭載
ESP32-WROOM-32E模組 - 該模組內部採用
ESP32-D0WD-V3晶片
核心技術規格
- 處理器:Xtensa 雙核 32 位元 LX6,最高時脈 240 MHz
- 指令集架構:Xtensa ISA
- 記憶體:520 KB SRAM(快速記憶體),448 KB ROM(唯讀記憶體)
- GPIO 引腳:34 個
- 類比轉換器(ADC):2 個,各 12 位元
- 數位轉換器(DAC):2 個,各 8 位元
- SPI 介面:4 個
- I2C 介面:2 個
- UART 介面:3 個
差異
雖然核心規格相同,但使用方式有所不同:
- 晶片或模組:需要設計客製 PCB、處理電源管理、連接 USB 轉換晶片等,適合產品設計工程師
- 開發板:已整合所有必要電路,可直接透過 USB 連接電腦進行開發,適合開發者和創客使用
產品線對照
ESP32 原始系列的各層級產品及其適用對象:
| 產品層級 | 產品名稱 | 說明 | 適用對象 |
|---|---|---|---|
| 晶片(SoC) | ESP32-D0WD-V3 | 雙核 Xtensa LX6 裸晶片 | 晶片設計廠商 |
| 模組(Module) | ESP32-WROOM-32E | 晶片 + Flash + 天線整合模組 | 產品設計工程師 |
| 模組(Module) | ESP32-WROVER-E | 晶片 + Flash + PSRAM + 天線 | 產品設計工程師 |
| 模組(Module) | ESP32-SOLO-1 | 單核版本模組 | 產品設計工程師 |
| 開發板(EVB) | ESP32-DevKitC V4 | 模組 + USB + 電源 + GPIO 引腳 | 開發者、創客、學生 |
| 開發板(EVB) | ESP32-DevKitM-1 | 搭載 ESP32-MINI-1 小型模組 | 開發者 |
| 開發板(EVB) | ESP32-PICO-KIT-1 | 搭載 ESP32-PICO-D4 模組 | 開發者 |
實際應用情境
開發者和創客
選擇使用 ESP32-DevKitC V4 這類開發板的主要優點:
- 開箱即用,透過 USB 直接連接電腦
- 已整合電源管理和 USB 轉 UART 晶片
- 所有 GPIO 引腳引出到排針,方便連接其他元件
- 價格低廉,約 5 到 10 美元
產品設計工程師
選擇使用 ESP32-WROOM-32E 這類模組的主要優點:
大量生產廠商
直接使用 ESP32 晶片的主要優點:
- 成本最低
- 產品設計完全客製化
- 可將產品體積最小化
總結
ESP32-DevKitC V4 與最初列出的 ESP32 系列的關係可以總結如下:
- 核心架構相同:DevKitC V4 搭載的模組使用的正是最初列出的 ESP32 系列晶片(ESP32-D0WD-V3)
- 技術規格一致:處理器、指令集架構、時脈、記憶體、周邊介面等技術規格與最初列出的 ESP32 系列完全相同
- 產品形式不同:最初列出的是晶片和模組層級的技術規格,而 ESP32-DevKitC V4 是開發板層級的最終產品,但核心都是同一顆 ESP32 晶片
- 官方開發板:ESP32-DevKitC V4 就是 Espressif 公司推出的官方開發板,代表了最受歡迎的通用 ESP32 開發解決方案
因此,ESP32-DevKitC V4 是 ESP32 原始系列的官方開發板實現,讓開發者能夠方便地使用和學習 ESP32 晶片的所有功能特性。
參考資料
[1] https://www.espboards.dev/esp32/esp32-devkitc/
[2] https://akizukidenshi.com/goodsaffix/esp32-wroom-32e_esp32-wroom-32ue_datasheet_en.pdf
[4] https://innovationyourself.com/esp32-wroom-vs-esp32-wrover/
[5] https://www.tme.eu/Document/fdc60b33b2951b4708cdfeb0e74a6b52/esp32-solo-1_datasheet_en.pdf
[6] https://www.espressif.com/sites/default/files/documentation/esp32-solo-1_datasheet_en.pdf
[7] https://www.espboards.dev/esp32/pico32/
[8] https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-devkitc/user_guide.html
[10] https://www.espboards.dev/esp32/manufacturer/espressif/
[11] https://www.espboards.dev/esp32/esp32-pico-kit-1/
[13] https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf
[14] https://mischianti.org/esp32-devkitc-v4-high-resolution-pinout-and-specs/
[15] https://www.espressif.com/en/products/devkits/esp32-devkitc/overview
2025/10/14
GNOME Terminal 啟動延遲問題再次發生
問題描述
在執行 apt update 和 apt upgrade 之後,gnome-terminal 啟動延遲的問題再次出現。終端機在系統開機後需要 20-30 秒才能啟動,儘管先前的修正(停用 im-config 自動啟動 fcitx5 並建立 systemd 使用者服務)仍然有效。
症狀
- GNOME Terminal 在系統開機後首次啟動時會有明顯延遲(約 26 秒)
- 問題只發生在開機後的第一次啟動
- 後續的啟動正常,沒有延遲
- 先前的設定(im-config 設為 "none" 及自訂的 fcitx5.service)仍然完整
診斷過程
步驟 1:驗證先前的設定
確認先前的修正仍然有效:
$ im-config -l
ibus fcitx5 xim
$ cat ~/.xinputrc
# im-config(8) generated on Fri, 10 Oct 2025 13:01:31 +0800
run_im none
# im-config signature: 0a0fbfefedad5558a9e9e2919b262f89 -
$ systemctl --user status fcitx5.service
● fcitx5.service - Fcitx5 Input Method
Loaded: loaded (/home/charles-chang/.config/systemd/user/fcitx5.service; enabled; preset: enabled)
Active: inactive (dead) since Tue 2025-10-14 08:32:41 CST
設定完整保留
步驟 2:檢查開機日誌的時序問題
$ journalctl --user -b 0 --no-pager | grep -E "(fcitx5|gnome-terminal|graphical-session)"
從開機序列中發現的關鍵資訊:
08:31:46 - graphical-session.target 尚未就緒
08:31:49 - 達到目標 graphical-session.target
08:31:49 - fcitx5.service 啟動
08:31:55 - 請求啟動 gnome-terminal
08:31:59 - fcitx5: DBus call error: org.freedesktop.DBus.Error.NoReply Method call timed out
08:32:04 - fcitx5: DBus call error: org.freedesktop.DBus.Error.NoReply Method call timed out
08:32:09 - fcitx5: DBus call error: org.freedesktop.DBus.Error.NoReply Method call timed out
08:32:14 - fcitx5: DBus call error: org.freedesktop.DBus.Error.NoReply Method call timed out
08:32:14 - fcitx5: Query portal value reaches retry limit
08:32:21 - gnome-terminal-server.service 啟動(請求後 26 秒!)
步驟 3:找出 Portal 服務問題
fcitx5 的日誌顯示 portalsettingmonitor.cpp 重複嘗試查詢桌面 portal 設定時發生錯誤。進一步檢查 portal 服務:
$ journalctl --user -b 0 --no-pager | grep -E "portal"
關鍵發現:
08:31:46 - 啟動 xdg-desktop-portal.service
08:31:46 - 啟用 org.freedesktop.impl.portal.desktop.gnome
08:31:46 - xdg-desktop-portal-gnome.service: Job failed with result 'dependency'
08:31:49 - fcitx5 啟動(portal 尚未就緒!)
08:32:36 - xdg-desktop-portal-gtk.service 以備用方案啟動(延遲 50 秒!)
根本原因分析
這個問題是從先前問題演變而來的:
先前的問題(已解決):
- fcitx5 啟動太早(在 graphical-session.target 之前)
- 透過讓 fcitx5 等待 graphical-session.target 來修正
目前的問題(apt upgrade 之後):
xdg-desktop-portal-gnome.service在 08:31:46 嘗試啟動,早於graphical-session.target完全就緒的時間(08:31:49)- 由於
Requisite=graphical-session.target相依性,GNOME portal 啟動失敗 - fcitx5 在 08:31:49 正確啟動(在 graphical-session.target 之後),但立即嘗試查詢 portal 設定
- portal 尚未就緒,導致 fcitx5 被阻塞並重試 4 次(每次逾時 5 秒 = 總共 20 秒)
- gnome-terminal 的啟動被阻塞,等待 fcitx5 完成初始化
- 在 fcitx5 放棄後,
xdg-desktop-portal-gtk以備用方案啟動,gnome-terminal 終於能夠啟動
為什麼在 apt upgrade 後發生:
套件更新可能修改了 xdg-desktop-portal 服務的時序或相依性,導致 GNOME portal 在開機序列中更早失敗。這造成了 fcitx5 和 portal 服務之間的新競爭條件。
解決方案
更新 fcitx5 systemd 服務,明確等待桌面 portal 服務:
檔案: ~/.config/systemd/user/fcitx5.service
[Unit]
Description=Fcitx5 Input Method
Documentation=man:fcitx5(1)
PartOf=graphical-session.target
After=graphical-session.target xdg-desktop-portal.service
Wants=graphical-session.target xdg-desktop-portal.service
[Service]
Type=simple
ExecStart=/usr/bin/fcitx5
ExecStartPost=/usr/bin/dbus-update-activation-environment --systemd GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx
Restart=on-failure
RestartSec=3
[Install]
WantedBy=graphical-session.target
變更內容:
- 在
After=指令中加入xdg-desktop-portal.service:fcitx5 會等到 portal 就緒後才啟動 - 在
Wants=指令中加入xdg-desktop-portal.service:確保 portal 服務被請求/啟動
套用修正:
$ systemctl --user daemon-reload
$ systemctl --user show fcitx5.service | grep -E "^(After|Wants)="
Wants=graphical-session.target xdg-desktop-portal.service
After=graphical-session.target basic.target xdg-desktop-portal.service app.slice
驗證結果
重新開機系統後:
- gnome-terminal 立即啟動,沒有延遲
- fcitx5 日誌中沒有 DBus 逾時錯誤
- 正確的啟動序列:graphical-session.target → xdg-desktop-portal → fcitx5 → gnome-terminal
關鍵要點
- 服務相依性很重要:即使修正了最初的 im-config 競爭條件,其他相依性(如桌面 portal)仍可能引入新的時序問題
- 系統更新可能改變時序:套件更新可能改變服務啟動順序或相依性,暴露出先前隱藏的競爭條件
- 監控所有元件:問題不在於 fcitx5 相對於 graphical-session.target 的時序(這部分是正確的),而是它與 portal 服務的互動
- 適當的相依鏈:同時使用
After=和Wants=確保服務以正確順序啟動,並且所需的服務確實被啟動
參考資料
- 先前的修正:http://highaltitudeoolong.blogspot.com/2025/10/gnome-terminal_32.html
- systemd.unit(5):服務相依性和順序
- fcitx5 portalsettingmonitor.cpp:桌面 portal 整合
2025/10/11
MCP Weather Server:SSE Transport
SSE (Server-Sent Events) transport,這是一個基於 HTTP 的傳輸方式,讓 MCP server 可以作為獨立的網路服務運行。
SSE Transport
SSE transport 有以下特點:
- 透過 HTTP 通訊,而非標準輸入/輸出
- server 作為獨立的 HTTP 服務運行
- client 透過網路連線到 server
- 使用 Server-Sent Events 實作雙向通訊
- 可同時服務多個 client
架構
SSE server 的核心檔案位於 src/weather_server/sse_server.py,包含以下組件:
- MCP server 實例:處理工具註冊和調用
- SSE transport:管理 HTTP 連線
- Starlette application:提供 HTTP endpoints
- Uvicorn server:運行 ASGI 應用程式
實作
1. 建立 MCP Server
建立 MCP server 並註冊:
from mcp.server import Server
from mcp.server.sse import SseServerTransport
mcp_server = Server("weather-server-sse")
@mcp_server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="get_weather",
description="Get current weather information for a city.",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Name of the city to get weather for",
}
},
"required": ["city"],
},
)
]
2. 設定 SSE Transport
建立 SSE transport ,指定訊息處理的路徑:
sse = SseServerTransport("/messages")
3. 實作 HTTP Endpoints
SSE transport 需要兩個 HTTP endpoints:
GET /sse - 建立 SSE 連線
async def handle_sse(request: Request):
logger.info(f"New SSE connection from {request.client.host}")
async with sse.connect_sse(
request.scope,
request.receive,
request._send,
) as streams:
await mcp_server.run(
streams[0],
streams[1],
mcp_server.create_initialization_options(),
)
此 endpoint 接收來自 client 的連線請求,並建立持久的 SSE 連線。
POST /messages - 接收訊息
async def handle_messages(request: Request):
await sse.handle_post_message(request.scope, request.receive, request._send)
此 endpoint 處理 client 發送的 POST 請求,實作雙向通訊的「上行」部分。
4. 建立 Starlette Application
from starlette.applications import Starlette
from starlette.routing import Route
app = Starlette(
debug=True,
routes=[
Route("/sse", endpoint=handle_sse, methods=["GET"]),
Route("/messages", endpoint=handle_messages, methods=["POST"]),
],
)
5. 啟動 Server
if __name__ == "__main__":
import uvicorn
uvicorn.run(
app,
host="localhost",
port=3000,
log_level="info"
)
執行 SSE Server
1. 直接執行
python -m weather_server.sse_serverserver 將在 http://localhost:3000 啟動。
2. 使用 uv run(推薦)
uv run weather-server-ssepyproject.toml 中定義了 script entry point。配置 Claude Code
在 Claude Code 中使用 SSE server,需要在配置檔案中加入以下設定:
{
"mcpServers": {
"weather": {
"url": "http://localhost:3000/sse"
}
}
}
與 stdio transport 不同,這裡使用 url 而非 command。
SSE vs Stdio Transport 比較
| 特性 | Stdio Transport | SSE Transport |
|---|---|---|
| 通訊方式 | 標準輸入/輸出 | HTTP (SSE + POST) |
| 啟動方式 | 由 client 啟動 process | 獨立運行的 HTTP server |
| 生命週期 | 與 client 綁定 | 獨立於 client |
| 多 client 支援 | 否(一對一) | 是(一對多) |
| 適用場景 | 本地開發、簡單整合 | 生產環境、多用戶服務 |
除錯技巧
查看 Server 日誌
SSE server 的日誌會直接輸出到啟動 server 的終端機:
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:3000
測試連線
可以使用 curl 測試 SSE endpoint 是否正常運作:
curl -N http://localhost:3000/sse結語
相關檔案:src/weather_server/sse_server.py:1
MCP 伺服器:stdio 傳輸實作
MCP
Model Context Protocol (MCP) 是 Anthropic 推出的協定,讓 AI 助理可以呼叫外部工具。透過 MCP,我們可以擴展 Claude 的能力,讓它存取資料或執行特定功能。
MCP 支援兩種傳輸方式:
本文介紹 stdio 方式,它比較簡單適合入門。
專案
建立一個簡單的天氣查詢 MCP 伺服器:
- 提供 5 個城市的預設天氣資料
- 定義
get_weather工具讓 Claude 呼叫 - 當使用者詢問天氣時,Claude 自動使用這個工具
環境準備
# 建立專案 mkdir weather-mcp-server cd weather-mcp-server # 初始化並安裝套件 uv init --python 3.11 uv add mcp
結構
weather-mcp-server/ ├── .mcp.json # Claude Code 設定 ├── src/ │ └── weather_server/ │ ├── __init__.py │ ├── weather_data.py # 天氣資料 │ └── stdio_server.py # MCP 伺服器 └── pyproject.toml
步驟 1:定義天氣資料
檔案:src/weather_server/weather_data.py
from typing import TypedDict class WeatherData(TypedDict): temperature: float condition: str humidity: int WEATHER_DATA: dict[str, WeatherData] = { "New York": {"temperature": 22.0, "condition": "Sunny", "humidity": 60}, "London": {"temperature": 12.0, "condition": "Rainy", "humidity": 85}, "Tokyo": {"temperature": 24.0, "condition": "Sunny", "humidity": 65}, "Sydney": {"temperature": 18.0, "condition": "Cloudy", "humidity": 70}, "Paris": {"temperature": 15.0, "condition": "Foggy", "humidity": 80}, } def get_weather(city: str) -> WeatherData | None: for city_name, data in WEATHER_DATA.items(): if city_name.lower() == city.lower(): return data return None def get_supported_cities() -> list[str]: return list(WEATHER_DATA.keys())
步驟 2:實作 MCP 伺服器
檔案:src/weather_server/stdio_server.py
import asyncio
import logging
from typing import Any
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
from .weather_data import get_weather, get_supported_cities
# 設定日誌
logging.basicConfig(
level=logging.INFO,
handlers=[
logging.StreamHandler(), # stderr
logging.FileHandler('/tmp/weather-mcp-server.log')
]
)
logger = logging.getLogger("weather-server")
app = Server("weather-server")
@app.list_tools()
async def list_tools() -> list[Tool]:
"""定義可用的工具"""
return [
Tool(
name="get_weather",
description=f"查詢城市天氣。支援:{', '.join(get_supported_cities())}",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名稱"}
},
"required": ["city"],
},
)
]
@app.call_tool()
async def call_tool(name: str, arguments: Any) -> list[TextContent]:
"""處理工具呼叫"""
if name != "get_weather":
raise ValueError(f"未知的工具:{name}")
city = arguments.get("city")
if not city:
raise ValueError("缺少參數:city")
logger.info(f"查詢:{city}")
weather = get_weather(city)
if weather is None:
supported = get_supported_cities()
text = f"沒有 '{city}' 的資料。支援:{', '.join(supported)}"
else:
text = (
f"{city} 的天氣:\n"
f"溫度:{weather['temperature']}°C\n"
f"狀況:{weather['condition']}\n"
f"濕度:{weather['humidity']}%"
)
return [TextContent(type="text", text=text)]
async def main():
logger.info("啟動天氣 MCP 伺服器")
async with stdio_server() as (read_stream, write_stream):
await app.run(read_stream, write_stream, app.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
步驟 3:設定 Claude Code
檔案:.mcp.json
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["run", "python", "-m", "weather_server.stdio_server"],
"env": {"PYTHONPATH": "src"}
}
}
}
關鍵概念
為什麼要用 -m 參數?
因為程式碼使用相對引入(from .weather_data import ...),必須作為模組執行。
# 錯誤 python src/weather_server/stdio_server.py # 正確 PYTHONPATH=src python -m weather_server.stdio_server
stdio 傳輸運作原理
Claude Code 啟動時: 1. 讀取 .mcp.json 2. 執行指定指令(建立子程序) 3. 透過 stdin/stdout 溝通(JSON-RPC) 4. 日誌輸出到 stderr(被捕捉但不顯示)
為什麼需要檔案日誌?
因為 stderr 被 Claude Code 捕捉後不會顯示,所以同時寫到檔案。監看日誌:
tail -f /tmp/weather-mcp-server.log
測試
手動測試伺服器
PYTHONPATH=src uv run python -m weather_server.stdio_server
應該看到啟動訊息,按 Ctrl+C 停止。
在 Claude Code 中測試
- 重新啟動 Claude Code
- 執行
/mcp確認 weather 伺服器已連接 - 詢問 Claude:"東京現在的天氣如何?"
- 另開終端機監看日誌:
tail -f /tmp/weather-mcp-server.log
Tool 定義說明
Tool(
name="get_weather", # 工具名稱
description="...", # 告訴 Claude 這個工具的用途
inputSchema={ # JSON Schema 定義參數
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
)
Claude 會根據 description 和 inputSchema,在適當時機自動呼叫工具。
常見問題
伺服器連接失敗?
確認 .mcp.json 有設定:
- 使用
-m參數 - 設定
PYTHONPATH=src
如何看日誌?
tail -f /tmp/weather-mcp-server.log
修改程式碼後如何重新載入?
重新啟動 Claude Code 即可。