gitdaemon 不支援 lfs,如果要的話,要另外 install 一個 lfs server。
2025/11/1
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_server
server 將在 http://localhost:3000
啟動。
2. 使用 uv run(推薦)
uv run weather-server-sse
pyproject.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 即可。
結語
mcp servers for mediawiki
Feature/Project Name | ProfessionalWiki/MediaWiki-MCP-Server | shiquda/mediawiki-mcp-server | harugon/mediawiki-mcp-server | lucamauri/MediaWiki-MCP-adapter | Rowik (Roshan George) | wikipedia-mcp |
---|---|---|---|---|---|---|
Main Language | TypeScript | Python | JavaScript (Node.js) | Python/Node (custom) | JavaScript/TypeScript | Python |
OAuth 2.0 Support | Yes | No (read-only) | Optional (login/pass) | Customizable | Optional | No |
Read page content | Yes | Yes | Yes | Yes | Yes | Yes |
Edit/create pages | Yes | No | Yes | Yes | Yes | No |
Search functionality | Yes | Yes | Yes | Yes | Yes | Yes |
File/media retrieval | Yes | No | No | No | No | No |
Multi-wiki support | Yes | Yes (via endpoint) | Yes (via config) | Yes | Yes (configurable) | Yes |
Streaming/server-sent events | No | Yes | No | No | No | No |
HTTP transport mode | Yes | Yes | Yes | Yes | Yes | Yes |
Stdio transport mode | Yes | Yes | Yes | Yes | Yes | Yes |
Docker image available | Yes | No | Yes | Unknown | Unknown | No |
Major use case | Production, enterprise | Lightweight, quick read | General LLM agent use | Custom/enterprise | Personal wiki | Search-focused |
License | GPL v2 | MIT | MIT | GPL/MIT (varies) | MIT | MIT |
Community activity | High (active, multiple releases) | Low (archived, read-only) | Moderate (npm, Playbooks) | Moderate | Low | Moderate |
2025/10/10
GNOME Terminal 逾時問題 (解決)
14檢查 fcitx5 的啟動機制
我們發現 fcitx5 在 10:33:17 過早啟動,但需要確認:是什麼機制啟動了 fcitx5?
default fcitx5 ibus ibus
# im-config(8) generated on Mon, 22 Sep 2025 10:25:39 +0800 run_im fcitx5 # im-config signature: d0dc02817325a9a408600bd547799708 -
~/.xinputrc
設定為 run_im fcitx5
,這表示 im-config 框架會在 X session 初始化時自動啟動 fcitx5!
這解釋了為什麼 fcitx5 會在 graphical-session.target 就緒前就啟動。
15檢查是否有 systemd 服務也在管理 fcitx5
[Unit] Description=Fcitx5 Input Method PartOf=graphical-session.target After=graphical-session.target Wants=graphical-session.target [Service] ExecStart=/usr/bin/fcitx5 ...
系統中存在兩種啟動 fcitx5 的機制:
- im-config(傳統方式):透過
~/.xinputrc
在 X session 早期啟動 - systemd 服務(現代方式):透過
fcitx5.service
在 graphical-session.target 後啟動
問題:im-config 的啟動時機太早(10:33:17),在 graphical-session.target 就緒前(10:33:19),導致 fcitx5 請求 portal 時觸發競態條件!
16驗證修復方案
# im-config(8) generated on Fri, 10 Oct 2025 13:01:31 +0800 run_im none # im-config signature: 0a0fbfefedad5558a9e9e2919b262f89 -
禁用 im-config 自動啟動後,fcitx5 只會透過 systemd 服務在正確時機(graphical-session.target 之後)啟動,避免競態條件。
17系統重啟後驗證
Oct 10 13:03:34 systemd: Reached target graphical-session.target ⬅️ 先就緒 Oct 10 13:03:34 systemd: Starting fcitx5.service ⬅️ 後啟動 Oct 10 13:03:34 systemd: Started fcitx5.service Oct 10 13:03:34 dbus-daemon: Activating via systemd: xdg-desktop-portal Oct 10 13:03:34 systemd: Starting xdg-desktop-portal-gnome.service Oct 10 13:03:34 systemd: Started xdg-desktop-portal-gnome.service ⬅️ 成功! Oct 10 13:03:34 systemd: Started xdg-desktop-portal.service
Oct 10 13:03:39 dbus-daemon: Activating via systemd: org.gnome.Terminal Oct 10 13:03:39 systemd: Starting gnome-terminal-server.service Oct 10 13:03:39 systemd: Started gnome-terminal-server.service ⬅️ 立即啟動,無逾時!
正確的啟動順序:
- 13:03:34 - graphical-session.target 就緒
- 13:03:34 - fcitx5.service 啟動(在 target 之後)
- 13:03:34 - xdg-desktop-portal-gnome 成功啟動
- 13:03:39 - gnome-terminal 立即啟動(無逾時)
問題完全解決!
完整的解決方案
永久修復步驟
步驟 1:禁用 im-config 自動啟動
步驟 2:建立/更新 systemd 使用者服務
mkdir -p ~/.config/systemd/user cat > ~/.config/systemd/user/fcitx5.service << 'EOF' [Unit] Description=Fcitx5 Input Method Documentation=man:fcitx5(1) PartOf=graphical-session.target After=graphical-session.target Wants=graphical-session.target [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 EOF systemctl --user daemon-reload systemctl --user enable fcitx5.service
步驟 3:重新啟動系統
關鍵說明:
After=graphical-session.target
確保在圖形工作階段就緒後才啟動ExecStartPost
設定環境變數,讓應用程式能使用 fcitx5- 移除
-d --replace
參數,因為 systemd 會管理程序
GNOME Terminal 逾時問題追查過程
結果沒有解決問題...
第一階段:理解問題現象
1觀察錯誤訊息
Error constructing proxy for org.gnome.Terminal:/org/gnome/Terminal/Factory0: Error calling StartServiceByName for org.gnome.Terminal: Timeout was reached
- 錯誤提到
org.gnome.Terminal
- 這是 D-Bus 服務名稱 StartServiceByName
- D-Bus 正在嘗試啟動服務Timeout was reached
- 服務啟動時間過長,超過逾時限制- 但 terminal 最終有啟動 - 表示服務最終成功了,只是太慢
不是完全失敗,而是啟動太慢。需要找出是什麼在拖慢啟動速度。
2檢查當前系統狀態
- D-Bus 正常運作 - 排除 D-Bus 本身的問題
- gnome-terminal 已安裝且可執行 - 排除安裝問題
- 問題應該在啟動機制或相依服務
第二階段:追查服務啟動時間
3檢查 systemd 服務狀態
● gnome-terminal-server.service - GNOME Terminal Server Active: active (running) since Fri 2025-10-10 10:34:43 Main PID: 4791
- Terminal 是透過 systemd 的 D-Bus 啟動機制運作
- 服務目前正在運行 - 所以之前的啟動最終成功了
- 需要查看啟動歷史,找出為何第一次啟動很慢
4分析 systemd 服務啟動時間
1min 30.058s xdg-desktop-portal.service 25.121s gnome-terminal-server.service ⬅️ 發現問題! 2.264s snap.snapd-desktop-integration.service 2.139s org.gnome.Shell@x11.service
gnome-terminal-server.service
啟動花了 25.121 秒!
另外 xdg-desktop-portal.service
更慢,花了 90 秒。這兩者可能有關聯。
5檢查服務啟動日誌
Oct 10 10:34:43 systemd[3444]: Starting gnome-terminal-server.service Oct 10 10:35:08 systemd[3444]: Started gnome-terminal-server.service ⬅️ 25秒後!
- 10:34:43 開始啟動
- 10:35:08 完成啟動(25 秒間隔)
- 這 25 秒發生了什麼?需要更深入的追蹤
第三階段:分析相依性與等待原因
6檢查服務相依性鏈
gnome-terminal-server.service +25.121s └─basic.target @146ms └─sockets.target @146ms └─gpg-agent-ssh.socket @129ms +17ms
- 所有相依服務在 146ms 就準備好了
- 但 terminal-server 本身花了 25 秒
- 結論:延遲不是因為等待相依性,而是服務本身初始化慢
7查看完整的系統日誌(關鍵步驟)
Oct 10 10:34:43 dbus-daemon: Activating via systemd: org.gnome.Terminal Oct 10 10:34:43 systemd: Starting gnome-terminal-server.service Oct 10 10:34:45 systemd: xdg-desktop-portal.service: start operation timed out ⬅️ 重要! Oct 10 10:34:45 systemd: Failed to start xdg-desktop-portal.service Oct 10 10:35:08 dbus-daemon: Successfully activated service org.gnome.Terminal
在 terminal 啟動期間,xdg-desktop-portal.service
發生逾時失敗!
時間點很可疑:portal 在 10:34:45 失敗,terminal 在 10:35:08 完成(23 秒差異)。
第四階段:追查 Portal 與 Terminal 的關聯
8檢查更早的日誌,了解 Portal 為何失敗
Oct 10 10:34:07 xdg-desktop-por: Failed to create settings proxy: Error calling StartServiceByName for org.freedesktop.impl.portal.desktop.gnome: Timeout was reached ⬅️ GNOME portal backend 逾時! Oct 10 10:34:30 xdg-desktop-por: Failed to create file chooser proxy: Timeout was reached Oct 10 10:34:45 systemd: xdg-desktop-portal.service: start operation timed out
- 10:34:07 - portal 嘗試啟動 GNOME 後端,逾時
- 10:34:30 - portal 嘗試建立 file chooser,又逾時
- 10:34:45 - portal 服務整個逾時失敗
GTK 應用程式(如 gnome-terminal)會嘗試連接 portal,這導致等待。
9檢查 GNOME Portal 服務狀態與相依性
[Unit] Description=Portal service (GNOME implementation) After=graphical-session.target Requisite=graphical-session.target ⬅️ 關鍵!必須在圖形工作階段之後 PartOf=graphical-session.target
Requisite=graphical-session.target
是嚴格要求- 如果 graphical-session.target 未就緒,服務會立即失敗
- 需要確認 graphical-session.target 何時就緒
第五階段:追查工作階段初始化時序
10檢查 graphical-session.target 啟動時間
graphical-session.target @4.160s ⬅️ 工作階段開始後 4.16 秒才就緒 └─basic.target @146ms
Oct 10 10:33:17 systemd: graphical-session.target is inactive ⬅️ 還未就緒 Oct 10 10:33:19 systemd: Reached target graphical-session.target ⬅️ 2秒後就緒
- 10:33:15 - 使用者工作階段啟動
- 10:33:17 - graphical-session.target 還未就緒
- 10:33:19 - graphical-session.target 就緒
11檢查 Portal 何時嘗試啟動(關鍵發現)
Oct 10 10:33:17 dbus-daemon: Activating: org.freedesktop.impl.portal.desktop.gnome requested by fcitx5 ⬅️ fcitx5 觸發 portal 啟動! Oct 10 10:33:17 systemd: graphical-session.target is inactive ⬅️ 同時間 target 未就緒 Oct 10 10:33:17 systemd: Dependency failed for xdg-desktop-portal-gnome.service ⬅️ 失敗! Oct 10 10:33:19 systemd: Reached target graphical-session.target ⬅️ 2秒後才就緒
競態條件(Race Condition):
- 10:33:17 - fcitx5(輸入法)啟動並請求 portal
- 10:33:17 - portal 嘗試啟動但 graphical-session.target 未就緒
- 10:33:17 - portal 啟動失敗(相依性未滿足)
- 10:33:19 - graphical-session.target 就緒(但 portal 已失敗,不會重試)
- 10:34:43 - 使用者啟動 terminal,嘗試連接已失敗的 portal
- 10:35:08 - 25 秒逾時後放棄,terminal 繼續啟動
第六階段:驗證根本原因
12確認是誰觸發了過早的 Portal 啟動
Oct 10 10:33:17 dbus-update-activation-environment: setting GTK_IM_MODULE=fcitx Oct 10 10:33:17 dbus-daemon: requested by ':1.18' (uid=1000 pid=3699 comm="/usr/bin/fcitx5 -d")
fcitx5 在工作階段早期(10:33:17)就啟動了,比 graphical-session.target(10:33:19)早 2 秒。
當 fcitx5 啟動時,它作為 GTK 應用程式會嘗試連接 xdg-desktop-portal,觸發了過早的啟動嘗試。
13測試修復後的行為
real 0m0.045s ⬅️ 現在很快!(之前是 25 秒)
如果手動重啟服務,它啟動很快。這證實問題只發生在工作階段早期的特定時間窗口。