MCP 명령어
GeoOmni는 LLM 에이전트(Claude Code, Codex CLI 등)가 앱을 제어할 수 있는 MCP(Model Context Protocol) 서버를 제공합니다.
연결 정보
| 항목 | 값 |
|---|---|
| 프로토콜 | TCP 소켓 + JSON-RPC 2.0 |
| 포트 | 9234 (기본값, 설정 > MCP에서 변경 가능) |
| 엔드포인트 | localhost:9234 |
| 메시지 구분 | 줄바꿈 (\n) |
| 최대 메시지 크기 | 64KB |
| 최대 클라이언트 | 5 (설정 변경 가능) |
연결 예시 (Python)
import socket, json
def mcp_call(command, arguments=None):
sock = socket.create_connection(("localhost", 9234))
req = {
"jsonrpc": "2.0", "id": 1,
"method": "tools/call",
"params": {"name": command, "arguments": arguments or {}}
}
sock.sendall((json.dumps(req) + "\n").encode())
resp = json.loads(sock.recv(65536).decode())
sock.close()
return resp
# 예: 대시보드 페이지로 전환
result = mcp_call("nav.selectPage", {"page": "dashboard"})
print(result)
MCP 표준 메서드
| 메서드 | 설명 |
|---|---|
initialize |
세션 초기화 |
ping |
연결 확인 (pong 응답) |
tools/list |
등록된 명령 목록 반환 |
tools/call |
명령 실행 |
시스템 명령 (3개)
ping
연결 상태를 확인합니다.
| 항목 | 값 |
|---|---|
| 메서드 | ping (tools/call이 아닌 직접 호출) |
| 파라미터 | 없음 |
| 응답 | {"status": "pong"} |
system.getVersion
앱 버전 정보를 반환합니다.
| 항목 | 값 |
|---|---|
| 파라미터 | 없음 |
| 응답 | {"appVersion": "...", "qtVersion": "6.x.x"} |
system.listCommands
등록된 모든 MCP 명령 목록을 반환합니다.
| 항목 | 값 |
|---|---|
| 파라미터 | 없음 |
| 응답 | {"commands": [{"name": "...", "description": "..."}]} |
UI 위젯 명령 (6개)
위젯 명령은 Qt 위젯 트리를 직접 조회·조작합니다. 대화상자 자동화, UI 테스트에 활용됩니다.
ui.getWidgetTree
활성 윈도우의 Qt 위젯 트리를 반환합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
parent |
string | 아니요 | 특정 위젯 하위만 조회 |
응답: 재귀적 위젯 트리 (depth 최대 10)
ui.findWidget
name/class/text로 위젯을 검색합니다. 응답에 screenRect(전역 화면 좌표) 포함.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
name |
string | 하나 이상 | objectName 부분 매칭 |
class |
string | 하나 이상 | 클래스명 정확 매칭 |
text |
string | 하나 이상 | 표시 텍스트 매칭 |
// 좌표계 스핀박스 찾기
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"ui.findWidget", "arguments":{"name":"coordSpin"}}}
// 응답:
{"name": "coordSpin", "class": "QSpinBox", "visible": true,
"screenRect": {"x":400, "y":300, "w":120, "h":30}}
ui.getWidgetValue
위젯의 현재 값을 반환합니다. QLineEdit, QCheckBox, QComboBox, QSpinBox, QTabWidget 지원.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
name |
string | 예 | 위젯 objectName |
ui.setWidgetValue
위젯에 값을 설정합니다. QLineEdit, QCheckBox, QComboBox, QSpinBox, QTabWidget 지원.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
name |
string | 예 | 위젯 objectName |
value |
any | 예 | 설정할 값 |
// 좌표계 스핀박스에 EPSG 5186 설정
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"ui.setWidgetValue", "arguments":{"name":"coordSpin", "value":"5186"}}}
ui.clickWidget
지정한 objectName의 위젯을 클릭합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
name |
string | 예 | 위젯 objectName |
button |
string | 아니요 | left/right/middle (기본: left) |
QAbstractButton은 click() 직접 호출, 그 외는 QMouseEvent 시뮬레이션.
ui.captureWindow
메인 창을 캡처하여 이미지로 저장합니다.
| 파라미터 | 없음 |
|---|---|
| 응답 | {"path": "D:/Devs/Dev/sandbox/capture_YYYYMMDD_HHMMSS.jpg"} |
- JPG 우선, 실패 시 PNG 폴백
- 최대 50장 누적, 초과 시 오래된 파일 자동 삭제
- 저장 경로:
sandbox/capture_*.jpg
마우스 명령 (3개) — Windows 전용
Win32 SendInput API 기반 마우스 자동화 명령입니다.
mouse.getPosition
현재 마우스 커서의 화면 좌표를 반환합니다.
| 파라미터 | 없음 |
|---|---|
| 응답 | {"x": 500, "y": 300} |
mouse.move
마우스 커서를 지정한 화면 좌표로 이동합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
x |
int | 예 | 화면 X 좌표 |
y |
int | 예 | 화면 Y 좌표 |
mouse.click
지정한 좌표에서 마우스 클릭을 수행합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
x |
int | 예 | 화면 X 좌표 |
y |
int | 예 | 화면 Y 좌표 |
button |
string | 아니요 | left/right/middle (기본: left) |
키보드 입력 명령 (2개) — Windows 전용
Win32 SendInput 기반 키보드 자동화 명령입니다.
keyboard.type
유니코드 텍스트를 키보드 입력으로 주입합니다. KEYEVENTF_UNICODE로 IME를 우회하므로 한글도 지원됩니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
text |
string | 예 | 입력할 텍스트 |
delay |
int | 아니요 | 키 간 지연 ms (기본: 10) |
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"keyboard.type", "arguments":{"text":"테스트 프로젝트"}}}
keyboard.sendKey
특수 키를 전송합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
key |
string | 예 | 키 이름 |
지원 키 목록:
| 키 이름 | 설명 |
|---|---|
enter |
Enter 키 |
tab |
Tab 키 |
escape / esc |
Escape 키 |
backspace |
Backspace 키 |
delete |
Delete 키 |
up / down / left / right |
방향키 |
home / end |
Home / End |
space |
스페이스 |
pageup / pagedown |
Page Up / Down |
insert |
Insert 키 |
f1 ~ f12 |
기능키 |
ctrl+a ~ ctrl+z |
Ctrl 조합키 |
네비게이션 명령 (2개)
앱의 메인 페이지를 전환합니다.
nav.selectPage
NavigationView에서 페이지를 선택합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
page |
string | 예 | 페이지 태그 |
페이지 태그 목록:
| 태그 | 인덱스 | 페이지 |
|---|---|---|
dashboard |
0 | 대시보드 |
documents / mdi |
1 | MDI 문서 편집기 |
coordinate |
2 | 좌표계 설정 |
settings |
3 | 전역 설정 |
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"nav.selectPage", "arguments":{"page":"coordinate"}}}
nav.getCurrentPage
현재 활성 페이지를 반환합니다.
| 파라미터 | 없음 |
|---|---|
| 응답 | {"page": "dashboard", "index": 0} |
앱 설정 명령 (4개)
app.getTheme
현재 테마 상태를 반환합니다.
| 파라미터 | 없음 |
|---|---|
| 응답 | {"dark": true, "themeProgress": 1.0} |
themeProgress는 테마 전환 애니메이션 진행도(0.0~1.0)입니다.
app.setTheme
다크/라이트 테마를 전환합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
dark |
bool | 예 | true=다크, false=라이트 |
// 다크 모드로 전환
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"app.setTheme", "arguments":{"dark": true}}}
app.getEpsgCode
현재 설정된 EPSG 코드를 반환합니다.
| 파라미터 | 없음 |
|---|---|
| 응답 | {"code": 5186} |
app.setEpsgCode
좌표계 EPSG 코드를 설정합니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
code |
int | 예 | EPSG 코드 (양수) |
{"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":"app.setEpsgCode", "arguments":{"code": 5186}}}
위젯 자동화 워크플로우
MCP 명령을 조합하여 UI 자동화 시나리오를 구현할 수 있습니다.
예시: 좌표계 설정 자동화
import socket, json, time
def call(name, args=None):
sock = socket.create_connection(("localhost", 9234))
req = {"jsonrpc":"2.0", "id":1, "method":"tools/call",
"params":{"name":name, "arguments":args or {}}}
sock.sendall((json.dumps(req) + "\n").encode())
resp = json.loads(sock.recv(65536).decode())
sock.close()
return resp
# 1. 좌표계 페이지로 이동
call("nav.selectPage", {"page": "coordinate"})
time.sleep(0.5)
# 2. EPSG 코드 설정
call("app.setEpsgCode", {"code": 5186})
time.sleep(0.5)
# 3. 화면 캡처
result = call("ui.captureWindow")
print("캡처:", result)
예시: 대화상자 자동화 (findWidget + click + type)
# 1. 위젯 찾기
result = call("ui.findWidget", {"name": "projectNameEdit"})
rect = result["result"]["content"][0]["text"] # screenRect 포함
# 2. 위젯 클릭
call("ui.clickWidget", {"name": "projectNameEdit"})
# 3. 텍스트 입력
call("keyboard.type", {"text": "새 프로젝트"})
# 4. 확인 버튼 클릭
call("ui.clickWidget", {"name": "btnOk"})
명령 요약 표
| # | 명령 ID | 카테고리 | 설명 |
|---|---|---|---|
| 1 | ping |
시스템 | 연결 확인 |
| 2 | system.getVersion |
시스템 | 버전 조회 |
| 3 | system.listCommands |
시스템 | 명령 목록 |
| 4 | ui.getWidgetTree |
UI 위젯 | 위젯 트리 조회 |
| 5 | ui.findWidget |
UI 위젯 | 위젯 검색 |
| 6 | ui.getWidgetValue |
UI 위젯 | 위젯 값 조회 |
| 7 | ui.setWidgetValue |
UI 위젯 | 위젯 값 설정 |
| 8 | ui.clickWidget |
UI 위젯 | 위젯 클릭 |
| 9 | ui.captureWindow |
UI 위젯 | 화면 캡처 |
| 10 | mouse.getPosition |
마우스 | 커서 위치 조회 |
| 11 | mouse.move |
마우스 | 커서 이동 |
| 12 | mouse.click |
마우스 | 클릭 |
| 13 | keyboard.type |
키보드 | 텍스트 입력 |
| 14 | keyboard.sendKey |
키보드 | 특수 키 전송 |
| 15 | nav.selectPage |
네비게이션 | 페이지 전환 |
| 16 | nav.getCurrentPage |
네비게이션 | 현재 페이지 조회 |
| 17 | app.getTheme |
앱 설정 | 테마 조회 |
| 18 | app.setTheme |
앱 설정 | 테마 변경 |
| 19 | app.getEpsgCode |
앱 설정 | EPSG 코드 조회 |
| 20 | app.setEpsgCode |
앱 설정 | EPSG 코드 설정 |