Skip to main content
Glama
andrew54068

line-cua-mcp

by andrew54068

line-cua-mcp

語言:繁體中文(台灣)|English README

macOS 專用的 LINE Desktop MCP server。讀取訊息時,直接讀 LINE 本機加密資料庫的唯讀快照;這條讀取路徑完全在背景執行,不碰 UI:不移動游標、不切換視窗焦點、不用 OCR、不捲動畫面,而且 LINE 關閉時也可以讀。送訊息時則必須透過 LINE UI,由 cua-driver 以不移動游標的方式操作;送出前會用 OCR 讀取聊天標題,並用本機資料庫交叉比對目標聊天。

實驗性警告

這是一個實驗性個人工具,不是成熟產品,也不是可以放心給一般使用者安裝的正式產品。它會讀取你本機 LINE Desktop 的加密資料庫,並且在你明確要求時透過 LINE 介面送出訊息。請把它當成研究用/自用的原型工具:

  • 只在你自己的 Mac、你自己的 LINE 帳號、你自己的資料上使用。

  • 首次設定需要擷取本機 LINE 資料庫金鑰;這通常會啟動一個重新簽章的 LINE 副本並要求你登入,可能會讓原本的 LINE Desktop 被登出。

  • 送訊息雖然有 OCR 和本機資料庫交叉比對來降低風險,但仍不應視為零風險;預設會先留下草稿(auto: false),建議確認後再送出。

  • LINE 更新、macOS 權限、OCR 結果、資料庫格式或 cua-driver 行為改變,都可能讓它失效。

  • 你必須自行確認使用方式符合 LINE 服務條款與所在地法律。本專案與 LINE/NAVER 無關,也不代表 LINE/NAVER 認可或支持。

Related MCP server: imessage-mcp

兩條資料路徑

  • 讀取是資料庫路徑。 macOS 版 LINE Desktop 是 Qt6/QML app,訊息文字由 GPU 繪製,accessibility tree 裡拿不到;但完整歷史訊息存在本機 wxSQLite3 / QtCipherSqlitePlugin AES-128-CBC 加密 SQLite DB(…/Data/db/qwb*.edb)。read_history / list_chats 會用 macOS keychain 裡的帳號金鑰解開唯讀快照,回傳完整歷史紀錄(sender、timestamp、direction)。這條路徑完全背景執行,不碰 UI。舊版曾用 OCR 讀螢幕,只能看到目前畫面;那條路徑已移除。

  • 送訊息是 UI 路徑,但不移動游標。 不能靠改 DB 送訊息,所以 send_message 會透過 cua-driver 操作 LINE UI:CGEvent 會送到指定座標/按鍵,但不 warp 可見游標;LINE 可能短暫跳到前景開啟目標聊天,完成後會把原本的前景 app 切回來。

MCP 工具

Tool

功能

line_status

回報 LINE UI 是否可用,以及本機 DB/金鑰/解密狀態。DB-backed 讀取(list_chats / read_history)不需要 LINE 正在執行;只有 UI 工具需要。

list_chats

從本機 DB 列出最近聊天(name、chatId、最後活動時間、是否群組)。完全背景執行。

read_history

依名稱或 chatId 從已解密的本機 DB 讀取聊天的完整歷史紀錄:文字、direction、絕對時間戳。不移動游標、不切前景、不用 OCR。

select_chat

透過 UI 開啟指定聊天(搜尋 → pixel-click 第一筆結果)。供 send_message 使用。不移動游標;會還原焦點。

send_message

透過 UI 對指定聊天送出或留下草稿。送出前有 anchored name、1:1-only、DB cross-check 等防護。

本機資料庫與金鑰

src/linedb.py(透過專案 venv 與 apsw-sqlite3mc 執行)負責解密。它會建立唯讀快照:把 qwb*.edb-wal-shm 複製到暫存資料夾,再開啟那份複本,所以不會鎖住或改動 LINE 正在寫入的檔案。cipher 參數是:

PRAGMA cipher='aes128cbc';
PRAGMA kdf_iter=1;
PRAGMA key='<32-hex>';

這是 wxSQLite3 AES-128,不是 SQLCipher;SQLCipher 的 PRAGMA/AES-256 開不起來。

金鑰

32-hex 金鑰不會由本專案寫進 repo 或明文檔案。linedb.py 會從 $LINE_DB_KEY 或 macOS login keychain service line-cua-mcp-dbkey 讀取:

security find-generic-password -s line-cua-mcp-dbkey -w   # 讀回金鑰

擷取金鑰(第一次設定)

在有 SIP 的 Mac 上,不能直接 attach 到 hardened、sandboxed 的 LINE app 讀記憶體。可行的一次性流程(不需要關 SIP):

  1. LINE.app 複製到暫存資料夾;對副本執行 xattr -cr

  2. 對副本做 ad-hoc re-sign,加入 com.apple.security.get-task-allow(同時會移除 hardened-runtime flag),例如:codesign -f -s - --deep --entitlements ent.plist LINEcopy.app

  3. 啟動這個副本並登入你的帳號。這通常會讓原本的 LINE Desktop 被登出;擷取完再登入回去即可。金鑰跟帳號穩定相關,所以副本中的金鑰可解開真實 DB。

  4. lldb attach 到副本(get-task-allow 讓它可被 debug);在 writable memory 裡找 encryption_key= / mse 附近的 32-hex token。

  5. 用真實 DB 驗證後存進 keychain:

    security add-generic-password -a "$USER" -s line-cua-mcp-dbkey -w <key> -U

    然後刪掉這個 LINE 副本。

如果 LINE 之後 rotate key,linedb.py status 會回報 decryptOk: false,需要重做一次擷取。

快速檢查

.venv/bin/python src/linedb.py status                 # db found, key, decryptOk, counts
.venv/bin/python src/linedb.py list-chats --limit 20
.venv/bin/python src/linedb.py read "<chat name>"     # 完整歷史(JSON)
.venv/bin/python src/linedb.py export-md --name "<chat>" --thread "<Name>" --out out.md

送訊息安全機制

send_message 是唯一會改變外部狀態的操作,所以加了多層防護:

  1. 重新選擇指定聊天,不會送到「目前剛好打開的聊天室」。

  2. Anchored name match(不是 substring):OCR 讀到的聊天標題正規化後必須等於目標名稱,只容許尾端多一個非英數字元(LINE header icon 造成的 OCR 雜訊)。例如短目標 不會通過 小明子 / 陳明婷Alice 不會通過 Alice2

  3. 預設只允許 1:1:如果開啟的聊天標題有 member-count badge (N),視為群組,拒絕送出。需要送群組時必須明確傳 allowGroup: true

  4. DB 交叉比對crossCheckSendTarget):本機 DB 是聊天 identity 與 group status 的權威來源,不只相信 OCR。目標會先用聊天列表解析;如果目標是群組、名稱有歧義,或 OCR 標題指向不同聊天,就拒絕。

  5. 真正按 Return 前會再驗一次

  6. auto: false 是預設值,只會把文字放進輸入框當草稿,不會送出。

ocr.ts(透過 src/ocr.swift 使用 macOS Vision)現在只用於送訊息前驗證聊天標題;讀訊息已不再用 OCR。

純 matcher / 交叉比對邏輯有 unit tests(yarn test)。DB 交叉比對補上 header OCR 可能 fail-open 的兩類問題:

  • 把群組誤當 1:1:即使 (N) badge 被裁掉或 OCR 錯讀,仍會用 DB 的 isGroup 拒絕。isGroup 是 fail-closed:只要不是 u 開頭的 1:1 聯絡人(例如群組、多人聊天室、LINE Square community、未知未來類型),都視為 group。

  • 錯人,包含兩個方向:extension — OCR 標題解析成另一個已知聊天(例如目標 小明,實際開到 小明華);truncation — 標題是另一個已知聊天名稱的嚴格前綴(可能是 OCR 把長名字裁短)。兩者都拒絕;目標名稱有歧義也拒絕。

殘餘限制與取捨: 交叉比對需要本機 DB(金鑰在 keychain);如果 DB 不可用,會降級成只靠 OCR 的保護機制並寫 log。若某個 1:1 名稱剛好是另一個聊天名稱的嚴格前綴,會被 truncation guard 拒絕;請改用完整名稱或精確 chatId。因為目前沒有獨立訊號能知道畫面上實際是哪個 chat,以下狀況無法只靠名稱完全解掉:兩個聊天顯示名稱完全相同(其中一個是群組);或某個新聊天還沒寫進本機 DB,而它的較長標題剛好被 OCR 裁短成目標名稱。預設仍是 auto: false,送出前請先檢查草稿。

需求

  • macOS,已安裝並登入 LINE desktop app。

  • Python venv,包含 apsw-sqlite3mc(DB 讀取路徑):

    python3 -m venv .venv && .venv/bin/pip install apsw-sqlite3mc
  • PATH 上的 python3 需要能 import Pillow (PIL);send-path header crop 會在 ocr.ts shell out 使用它(pip install Pillow)。讀取路徑不需要 Pillow。

  • DB 金鑰已放進 keychain service line-cua-mcp-dbkey(見上方)。

  • 安裝 cua-driver,並授權 Accessibility / Screen Recording(select_chat / send_message 需要):

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.sh)"
  • Node 18+。

建置與執行

yarn install
yarn build            # tsc + 複製 ocr.swift / linedb.py 到 dist/
node dist/server.js   # MCP stdio server

Register with Claude Code:

claude mcp add --transport stdio line-cua -- node /absolute/path/to/line-cua-mcp/dist/server.js

調整參數

DB 路徑與 cipher 參數在 src/linedb.py。送訊息用的 OCR crop 區域與 composer click point 是 window-fraction 常數:src/ocr.tsHEADER,以及 src/line.ts 的 composer 0.72, 0.89。如果 LINE 改 UI layout,要調這些值。

法律與免責

這是用來存取你自己的 LINE 帳號與資料、並且只在你自己的機器上使用的個人工具。使用前請理解:

  • 你必須自行遵守 LINE 服務條款與所在地法律。讀本機資料庫、操作 desktop client,可能違反 LINE 的 ToS;金鑰擷取流程修改的是 app 的副本,不是你安裝的 LINE.app。只在自己的帳號/資料上使用。

  • 本軟體以 AS IS 提供,沒有任何保證,作者不負任何責任;見 LICENSE

  • 這不是法律意見。如果你不確定某種使用方式是否合法,請尋求所在地法律意見。

商標:「LINE」是 LINE Corporation/NAVER 的商標。本專案是獨立專案,與 LINE/NAVER 無關,也不代表 LINE/NAVER 認可或支持。

隱私與金鑰處理說明請見 SECURITY.md

A
license - permissive license
-
quality - not tested
D
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/andrew54068/line-cua-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server