uia-mcp
Allows UI Automation-based control of AutoCAD, enabling an agent to inspect and interact with the application's interface; canvas drawing surfaces are handled via screenshot as a fallback.
Provides UI Automation-based integration with SAP applications such as SAP Business ByDesign, including reading virtualized tables/grids and using landmark-based targeting for fast interaction.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@uia-mcpIn Notepad, type 'Hello' and then press Ctrl+S."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
uia-mcp
MCP server điều khiển Windows qua cây trợ năng UI Automation — cùng API mà NVDA và Narrator dùng để đọc màn hình cho người khiếm thị.
Model không nhìn pixel và không đoán toạ độ: nó đọc một bảng ID, rồi tác động lên ID bằng control pattern của chính ứng dụng.
Thứ tự ưu tiên — không được đảo
1. MCP riêng của ứng dụng (API) revit-mcp · Excel-MCP · Navisworks · Outlook · ACC · SAP2000
nhanh nhất, tin cậy nhất, không cần ứng dụng mở cửa sổ
2. UIA — server này cho mọi ứng dụng còn lại
3. screenshot() CHỈ khi bậc 1 và 2 đều bó tayBậc 3 là lối thoát cuối, không phải công cụ mặc định. Bậc 1 và 2 cho biết trạng thái thật — enabled, on/off, giá trị ô nhập — mà ảnh không có, và rẻ hơn hàng nghìn token mỗi lần nhìn. Ảnh chỉ đáng dùng với bề mặt vẽ trên canvas: viewport 3D của Revit, canvas AutoCAD, lưới Excel Online, game.
Kỷ luật đó được mã hoá vào chính tool, không chỉ nằm trong tài liệu: screenshot() có
tham số tried bắt buộc, khai qua loa thì bị từ chối kèm lời nhắc thử hai bậc trên trước.
Mọi con số đo đạc trong tài liệu này đều lấy từ máy thật, không phải ước lượng.
Related MCP server: uiautomation-mcp
Cài đặt
git clone https://github.com/nhantruong96/uia-mcp
cd uia-mcp
uv venv
uv pip install -e .Yêu cầu: Windows 10/11, Python ≥ 3.11.
Kiểm tra bằng bộ test tự mở và tự đóng Notepad của riêng nó:
.venv\Scripts\python.exe smoke_test.pyĐăng ký với Claude Code
claude mcp add uia --scope user -- <đường-dẫn-repo>\.venv\Scripts\uia-mcp.exeBộ tool
Tool | Công dụng |
| Mọi cửa sổ top-level: hwnd, class, pid, tiêu đề, cái nào đang focus |
| Bảng |
| Tìm phần tử ở bất kỳ độ sâu nào, không bị |
| Quét một lần, ghi toạ độ mọi phần tử có tên của app đó |
| Trỏ bằng điểm neo — mili giây thay vì giây |
| Đã có bao nhiêu điểm neo, chụp lúc nào, cửa sổ có dịch chuyển không |
| Phần tử dưới một điểm màn hình (~2 ms) |
| Nội dung văn bản qua |
| Bảng/lưới qua |
| Tác động qua control pattern, có thang fallback |
| Phím tắt toàn cục, ví dụ |
| Thông báo Windows, đọc thẳng kho SQLite — không mở panel |
| Lối thoát cuối — chụp PNG, bắt khai đã thử gì trước đó |
observe trả về gì
window: 'Untitled - Notepad' hwnd=919222 class=Notepad pid=27820
# id|type|name|state|patterns
0|Document|Text editor|focused|value,scroll,text
3|TabItem|Untitled. Unmodified.|selected|select
5|Button|Add New Tab||invoke
6|MenuItem|File|collapsed|invoke,expand
11|Button|Bold (Ctrl+B)|off|togglefilter: interactive (mặc định) · text (nội dung đọc được) · table (lưới/bảng — dùng
trước read_table) · all (mọi thứ đang hiển thị).
Cột state chứa đúng những thứ ảnh chụp màn hình không nói chắc được: focused,
disabled, on/off, selected, expanded/collapsed, giá trị thật của ô nhập,
phần trăm cuộn. Cột patterns cho biết phần tử chấp nhận hành động nào.
find — khi observe không với tới
observe cắt theo thứ tự duyệt cây, nên thứ nằm sâu không bao giờ tới lượt. Đo trên máy
này: bảng thư Outlook là phần tử 196/325, tab thật của Edge nằm dưới EdgeTabStrip.
Tăng max_elements chỉ tổ đổ cả cây vào context. find không bị giới hạn đó.
by:
| khớp name, AutomationId hoặc ClassName |
| chỉ trường đó |
| control type chính xác: |
| phần tử có pattern đó: |
find("EdgeTab", window=<edge>, by="class")
→ find('EdgeTab', by=class): 7 kết quả, 1 khớp chính xác (xếp đầu)
0|TabItem|Product Development - Materials - SAP Business ByDesign…|selected|select
5|Button|Close tab [Ctrl+W]||invoke ← EdgeTabCloseButton, khớp tiền tố
find("grid", window=<outlook>, by="pattern")
→ 7|Table|Table View|scroll-v=1%|scroll,grid ← rồi read_table(7)Khớp chính xác luôn xếp trước khớp một phần, và header nói rõ có bao nhiêu cái chính xác —
tìm class EdgeTab cũng trúng EdgeTabCloseButton, EdgeTabStrip, nên cần biết tin dòng nào.
within=<id> thu phạm vi về một nhánh con. Với trình duyệt thì gần như bắt buộc: tìm
trong cả cửa sổ sẽ lẫn toàn bộ chrome của Edge vào kết quả của trang web. Đo trên SAP
Business ByDesign: find("Button", by="type") cho 38 kết quả trên cả cửa sổ, còn
within=<id Document> chỉ còn 19 — đúng các nút của trang.
read_table — phân trang và lưới ảo hoá
start_row để đọc tiếp bảng dài; khi start_row > 0, hàng 0 vẫn được kèm theo vì ở nhiều
lưới đó là hàng tiêu đề cột.
RowCount là số logic, không phải số hàng có dữ liệu. Lưới của SAP khai báo 10000×6
nhưng chỉ ~11 hàng đang render là có nội dung — phần còn lại rỗng hoàn toàn. Tool không im
lặng bỏ qua chúng, mà nói thẳng:
(3/3 hàng đọc được là rỗng — lưới ảo hoá, chỉ vùng đang render mới có dữ liệu.
RowCount=10000 là số logic, không phải số hàng thật đang có.)Muốn đọc sâu hơn thì phải act(<id lưới>, "scroll", "down") trước rồi đọc lại.
Điểm neo — cho app nặng dùng thường xuyên
Thứ đắt là duyệt cây, không phải bộ lọc. Đo trên Revit 2027 có model mở:
Quét toàn cây (701 phần tử) | 16 325 ms |
| 6 245 ms |
| 11 477 ms |
| 36 ms |
| 6 ms |
Trả một lần quét ~9–16 s, đổi lấy mọi lần trỏ sau đó nhanh gấp ~300 lần.
landmark_capture(window="<hwnd Revit>") → đã ghi 210 điểm neo (quét mất 9 280 ms)
landmark_find("Annotate", activate=True) → giải bằng điểm neo tại (686, 57) 36 msKho lưu ở %LOCALAPPDATA%\uia-mcp\landmarks.json, khoá theo tên tiến trình (revit.exe)
chứ không theo tiêu đề — tiêu đề Revit đổi theo model đang mở.
Hai điều bắt buộc phải hiểu:
Điểm neo là toạ độ màn hình. ElementFromPoint luôn trả về thứ nằm trên cùng tại điểm
đó, bất kể ta định nói tới cửa sổ nào. Nếu Revit bị Edge che, điểm neo của Revit sẽ trỏ vào
Edge. Vì vậy mặc định tool từ chối khi cửa sổ đích không ở trên cùng; truyền activate=True
để đưa nó lên trước.
Mỗi lần dùng đều kiểm chứng lại danh tính. Giải xong vẫn phải xác nhận phần tử dưới toạ độ đó đúng là mục tiêu (hoặc con cháu của nó) rồi mới trả về. Điểm neo cũ bị từ chối kèm mô tả thứ đang nằm ở đó, chứ không bao giờ trả về nhầm phần tử — click nhầm sang ứng dụng khác là tai nạn đã xảy ra thật trong quá trình phát triển.
Chụp lại khi giao diện đổi đáng kể: đổi tab ribbon, bật/tắt panel, đổi kích thước cửa sổ.
notifications — đọc mà không đụng màn hình
Đọc thẳng wpndatabase.db của Notification Center thay vì mở panel bằng Win+N. Chỉ đọc,
không can thiệp màn hình, và có cả lịch sử chứ không riêng thứ đang hiện. Không cần thư
viện ngoài — sqlite3 nằm sẵn trong Python.
# thời gian|app|loại|nội dung
2026-09-09 15:56|Microsoft.Todos|tile|Hi there, · what do you want to focus on today?Toast biến mất rất nhanh. Đo ngay trong lúc viết module: kho tụt từ 19 xuống 13 bản
ghi, toast từ 4 về 0, chỉ trong vài phút — Windows xoá khi người dùng gạt đi hoặc khi hết
hạn. tile và badge trụ lâu hơn. Nên "không có gì" thường nghĩa là chưa có gì gần đây,
không phải tool hỏng; thử kind="all".
Kho được chép ra thư mục tạm trước khi đọc, kèm cả -wal và -shm — SQLite chạy chế
độ WAL, chép mỗi .db sẽ thiếu đúng những thông báo mới nhất.
Riêng tư: thông báo chứa tin nhắn và email thật. Chỉ dùng khi người dùng yêu cầu.
act — các action
click · double_click · right_click · set_value · type · toggle · select ·
expand · collapse · scroll · scroll_into_view · set_number · focus ·
click_physical · drag · add_to_selection · close · restore · minimize · maximize
click_physical bỏ qua mọi pattern và click chuột thật ngay — dùng khi provider nhận
pattern rồi báo thành công nhưng ứng dụng không phản ứng (đặc trưng của web view React).
drag nhận value là "x,y" hoặc "id:N". UIA không có pattern nào cho kéo–thả nên
đây luôn là chuột thật, nhưng cả hai đầu đều được kẹp biên và kiểm chứng danh tính
trước khi bơm sự kiện. Đường đi qua nhiều bước trung gian vì nhiều ứng dụng chỉ nhận ra
thao tác kéo sau vài sự kiện di chuyển.
add_to_selection là multi-select: SelectionItemPattern.AddToSelection, tụt xuống
Ctrl+click khi provider không hỗ trợ. Phím Ctrl được nhả trong finally — Ctrl kẹt ở
trạng thái nhấn sẽ làm hỏng mọi thao tác sau đó của người dùng.
Ưu tiên set_value hơn type: nó ghi thẳng qua ValuePattern, tức thì, và không cần
cửa sổ ở foreground.
Thang fallback
Mỗi lời gọi act đi từ trên xuống và báo lại nó dừng ở bậc nào:
1. Control Pattern ← không cần foreground, không cướp chuột
2. LegacyIAccessible.DoDefaultAction()
3. SetFocus() + phím ← vẫn không cần toạ độ
4. Chuột thật tại BoundingRectangle ← toạ độ từ UIA, không phải từ ảnhOK: click qua InvokePattern.Invoke
OK: set_value qua ValuePattern.SetValue (không có synthetic input)
OK: click qua chuột tại BoundingRectangle (toạ độ 812,447 lấy từ BoundingRectangle)
— đã bỏ qua: InvokePattern.Invoke: không áp dụng được; …Dòng "đã bỏ qua" là dữ liệu đo được về chất lượng trợ năng của từng ứng dụng. Càng nhiều lần phải tụt xuống bậc 4, ứng dụng đó càng khai báo UIA kém.
Ba quyết định thiết kế đáng chú ý
Một thread STA duy nhất. UIA là COM và đòi hỏi STA. Nhiều thread cùng CoInitialize
rồi cùng chạm vào một cây UIA sẽ deadlock khi COM marshal qua lại giữa các apartment.
Mọi lời gọi ở đây đều đi qua sta.STA. Muốn song song thật thì phải nhiều tiến trình,
không phải nhiều thread.
CacheRequest.TreeScope = Element. FindAllBuildCache(Subtree, …) trả về N phần tử;
nếu cache request cũng chứa Children/Subtree thì provider dựng cache cho subtree của
từng phần tử — công việc bùng nổ bậc hai. Đo được: đặt đúng thì nhanh gấp ~2× so với đọc
live, đặt sai thì chậm hơn 2–6×.
Không tin lời pattern — kiểm chứng hậu điều kiện. Đo được hai lần, trên hai pattern khác nhau:
Notepad Win11 nhận
WindowPattern.SetWindowVisualState(Minimized), báo lạiCurrentWindowVisualState = 1, trong khiIsIconic()vẫnFalsevà cửa sổ vẫn hiện.Excel Online trong Edge nhận
ScrollPattern.Scroll(down)và trả về thành công, trong khiVerticalScrollPercentkhông nhúc nhích.
Provider nói dối, và không có quy luật nào đoán trước được app nào nói dối ở pattern
nào. Với action có hậu điều kiện rẻ và đáng tin, mỗi bậc phải tự chứng minh — Win32
IsIconic/IsZoomed cho cửa sổ, phần trăm trước/sau cho cuộn — không chứng minh được thì
coi như bậc đó hỏng và tụt tiếp (ShowWindow, lăn chuột). Báo "OK" khi không có gì xảy ra
là thứ tệ nhất một tool có thể làm với agent.
Hai chi tiết khiến việc kiểm chứng dễ tự lừa mình:
chỉ so trục được yêu cầu (dao động ngang từng làm một lệnh cuộn dọc bất động trông như
thành công), và đừng làm tròn về số nguyên (0.0 → 0.4% in ra "0% → 0%" thì báo cáo
tự mâu thuẫn với chữ OK của chính nó).
Toạ độ cho chuột phải là toạ độ sống. Các bậc bơm chuột đọc BoundingRectangle bằng
live=True, không dùng rect trong cache. Rect cache là ảnh chụp lúc observe, có thể đã
cũ hàng giây và phần tử đã dịch đi vì cuộn hay đổi layout — click theo nó chính là lỗi
"click trượt" mà cả thiết kế này sinh ra để loại bỏ.
Cửa sổ minimize phải được nói ra. Windows không render cửa sổ đã minimize, nên cây UI
của nó co lại chỉ còn khung — không có Document, không có nội dung. Trả về cây rỗng mà
không giải thích sẽ khiến agent kết luận nhầm "ứng dụng này không có UI" và đi sai hướng.
observe phát hiện IsIconic và cảnh báo; act(id, "focus") tự bung cửa sổ ra trước khi
focus, vì SetFocus trên cửa sổ minimize trả về thành công mà không khôi phục gì.
Trạng thái chỉ đọc khi pattern tồn tại. UIA trả về giá trị mặc định
(ToggleState=indeterminate, RangeValue=0, IsReadOnly=True) cho mọi phần tử kể cả
khi provider không hỗ trợ pattern đó. Báo cáo nguyên xi sẽ dán nhãn sai lên gần như toàn
bộ cây — mà trạng thái sai còn tệ hơn không có trạng thái.
Giới hạn đã biết
Vấn đề | Xử lý |
Chrome/Edge/Electron/VS Code có thể chỉ lộ title bar, nội dung web vô hình | Đo trên máy này: Edge có lộ đầy đủ cây web (đọc được toàn bộ text trang GitHub). Chromium bật provider khi có công cụ trợ năng yêu cầu, nên kết quả phụ thuộc từng máy — thử |
Cửa sổ minimize trả về cây gần rỗng |
|
Java (Swing/AWT) không có UIA | Cần Java Access Bridge — chưa làm, giai đoạn 3 |
Canvas / viewport 3D / game chỉ là một | UIA không cứu được. Dùng API riêng của app, hoặc vision |
Office web apps: lưới Excel Online vẽ trên canvas — không | Cây trợ năng vẫn đầy đủ (thanh công thức, Name Box, ribbon đều đọc được), nhưng bản thân lưới thì không. Muốn ô nào thì qua Name Box + formula bar, hoặc dùng Excel MCP trên file gốc |
Ribbon Revit — tab không có tên | 22 phần tử |
Ribbon Revit — panel không có phần tử con | Panel ribbon là leaf tuyệt đối: 0 con ở cả Raw/Control/Content view, không pattern nào, |
↳ đã loại trừ bằng thực nghiệm | Ngoại lệ Architecture không đến từ: pyRevit (ẩn Architecture → 0 ở mọi tab, không liên quan pyRevit) · thứ tự quét (đảo chiều vẫn 0/47/0/47) · tab nào mở đầu tiên (đặt Structure làm tab đầu → vẫn 0) · loại view (Sheet và Floor Plan đều như nhau) · model đang mở (tái hiện trên hai project khác nhau). Cơ chế thật vẫn chưa rõ. Kết luận thực dụng: coi như lệnh ribbon không truy cập được, vì ngoại lệ này phụ thuộc một tab mà người dùng tắt được bất cứ lúc nào |
App chạy admin | Server phải cùng mức toàn vẹn, hoặc ký với |
Cửa sổ treo |
|
Chưa có event-driven refresh | Mỗi |
Nhắc lại thứ tự ưu tiên
UIA là bậc 2, không phải bậc 1. Trước khi dùng server này, hãy hỏi ứng dụng đó có API không — Revit, AutoCAD, Navisworks, SAP2000, Excel, Graph, ACC đều đã có MCP riêng và luôn nhanh hơn, tin cậy hơn việc đi qua GUI.
Bố cục mã nguồn
File | Vai trò |
| Apartment STA dùng chung + timeout |
| Bọc COM client: hằng số, điều kiện lọc, cache request, đọc property an toàn |
| Bảng ID ổn định ( |
|
|
| Thang fallback hành động |
|
|
|
|
| Định nghĩa tool MCP |
This server cannot be deployed
Maintenance
Related MCP Connectors
Eyes and hands on real Windows PCs — observe, click, type via Glasswarp API.
AI-powered browser automation — navigate, click, fill forms, and extract data from any website.
Automate cloud Chrome—navigate, click, type, screenshot, run code, record screen video
Automate cloud browsers to navigate websites, interact with elements, and extract structured data.…
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn enterprise-grade automation server that enables AI assistants to control Windows PCs through intelligent UI element detection, window management, and system-level commands. It leverages the Windows UI Automation tree for reliable interaction, providing tools for mouse/keyboard control, application management, and high-performance screen state analysis.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to inspect and automate Windows desktop UI elements by exploring UI trees, checking properties, performing actions like clicking and typing, and generating Python automation scripts.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI coding agents to automate Windows desktop applications through semantic UI Automation instead of brittle coordinate clicks, with tools for discovering windows, finding controls by stable identifiers, and verifying actions.1MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to control Windows GUI by listing and focusing windows, capturing element snapshots via UIA/OCR/CDP, performing clicks/inputs/scrolls, verifying changes, waiting for screen updates, taking screenshots, and obtaining visual descriptions.2-