Unreal Engine 5 Dev Log ― MCP 실험 랩 1
오늘 한 일
- Unreal Engine의 MCP 서버를 Claude Code에 붙이고 연결을 확인했다.
list_toolsets로 toolset 52개가 잡히는 것까지 봤다.- 붙이는 절차: Unreal Engine 5.8이 필요하다. 플러그인에서 MCP와 toolset을 켜고 에디터를 재시작한다. 편집 > Editor Preferences > General > Model Context Protocol에서 Auto Start Server를 켜면 에디터를 열 때마다 서버가 뜬다. 그다음 Claude Code에서
/mcp로 연결한다.
- 붙이는 절차: Unreal Engine 5.8이 필요하다. 플러그인에서 MCP와 toolset을 켜고 에디터를 재시작한다. 편집 > Editor Preferences > General > Model Context Protocol에서 Auto Start Server를 켜면 에디터를 열 때마다 서버가 뜬다. 그다음 Claude Code에서
- 노출 구조를 파악했다. 클라이언트가 보는 도구는 3개뿐이고(
list_toolsets→describe_toolset→call_tool), 실제 도구는call_tool이 이름으로 간접 호출한다. toolset 52개를 다 펼치면 도구가 수백 개라 접어둔 것으로 보인다. - “어디서 처음 깨지는지” 찾는 실험 사다리를 만들어 자연어로만 시켰다.
0 원점에 큐브 하나

1 큐브 10×10 격자, 간격 200

2 기둥 24개를 반지름 1000 원형으로, 전부 중심을 바라보게

3 큐브 100개를 나선으로, 위로 갈수록 작아지게

4 격자 중 짝수 번째만 빨간 머티리얼

5 전부 Z로 300 올려 → 절반 지워

6 11×11로 4와 같은 규칙 + 중심에서 멀어질수록 Z에 +50씩

- 0~6단계를 전부 통과했다. 개수가 1개에서 100개로 늘자 전략이 갈렸다. 단건은 배치 전용 도구(
add_to_scene_from_asset), 대량은 스크립트 실행(ProgrammaticToolset.execute_tool_script)이다. 100번 왕복 대신 스크립트 한 번으로 돈다. - 매 단계마다 배치 스크립트의 반환값을 믿지 않고 씬을 되읽어 검증했다. 반지름·각도 간격·총 회전수·링별 Z·색 패턴을 다시 계산해 기대값과 대조하는 방식이다.
- 빨강·흰색 머티리얼을 만들어 체커보드를 칠했다.
Constant3Vector를MP_BaseColor에 연결하고 recompile하는 경로이고, 에셋은/Game/MCPLab/아래로 모았다. - 6단계 결과를 사발에서 계단 피라미드로 뒤집고, 마지막에 121개를 통째로 300 띄운 뒤 흰색 60개를 지워 공중에 성긴 체커보드를 남겼다.
막힌 부분
- 도구 이름을 짐작해서 부르면
Unknown tool로 튕긴다. 액터 라벨을 읽으려get_actor_label을 불렀는데 실제 이름은ActorTools.get_label이었다.- 해결:
describe_toolset으로 목록을 확인한 뒤 부른다. 3단 구조라 도구 이름이 컨텍스트에 미리 안 들어와 있어서 짐작이 특히 위험하다.
- 해결:
- 스폰 도중 되돌리기를 눌렀더니 검증에서 100개가 아니라 89개로 읽혔다.
- 원인: 되돌리기가 액터 단위다. 스크립트로 100개를 만들면 트랜잭션도 100개로 쌓여서 Ctrl+Z 한 번에 큐브 하나씩 사라진다.
- 해결: 대량 배치를 취소할 때는 되돌리기 대신 폴더째 지우는 스크립트를 쓴다.
- 덤: 검증 스크립트가 그 시점의 실제 씬 상태(89개)를 정확히 읽었다. 반환값을 믿지 않고 되읽는 방식이 실제로 어긋남을 잡아낸다는 확인이 됐다.
스크립트 샌드박스의 dict는 기본값 있는 get을 막는다
도구가 돌려주는 dict는 _StrictDict라 파이썬 표준 dict처럼 굴지 않는다. 기본값을 넘기는 순간 예외가 난다.
yaw = rot.get("yaw", 0.0)
# TypeError: _StrictDict.get() does not support a default value.
# Use direct key access [] instead.
대괄호 접근으로 바꿔야 한다. 모르고 기본값을 넘기면 검증 스크립트가 거기서 죽는다. 허용 모듈도 json·math·datetime·copy·re·time뿐이라, 스크립트는 도구 호출을 엮는 용도로만 쓰는 게 맞다.
- 해결: 반환값을 다룰 때는 대괄호 접근을 쓰고, 없을 수 있는 키는 미리 존재 여부로 갈랐다.
없는 폴더를 물으면 예외가 나고, 죽어도 앞부분은 반영돼 있다
정리 스크립트가 폴더 세 개를 도는 중에 끊겼다.
RuntimeError: Script error in ...SceneTools.get_actors_in_folder:
Folder does not exist: 'CubeGrid'
get_actors_in_folder는 없는 폴더에 빈 리스트가 아니라 예외를 던진다. 게다가 폴더는 안의 액터를 다 지우면 자동으로 사라지기 때문에, 삭제 후 delete_folder를 부르는 것도 같은 예외가 된다.
더 중요한 건 끊긴 뒤의 상태였다. 예외가 난 시점에 앞의 두 폴더는 이미 지워져 있었다. 스크립트가 중간에 죽어도 그때까지의 씬 변경은 롤백되지 않는다.
- 해결: 폴더를 돌기 전에
get_folders()로 존재하는 것만 거른다. 그리고 스크립트를 트랜잭션처럼 생각하지 않는다.
“짝수 번째만 빨강”이 체커보드가 아니라 줄무늬가 됐다
Cube_i_j를 행 우선 순번 i*10 + j로 세고 짝수만 칠했다. 열이 10개, 즉 짝수라서 i*10이 항상 짝수다. 순번의 홀짝이 j의 홀짝과 같아져 모든 행이 같은 무늬가 된다.
R.R.R.R.R. ← 10행 모두 동일
R.R.R.R.R.
- 해결: 체커보드는
(i + j) % 2 == 0으로 판정한다. - 남은 것: “짝수 번째”라는 말 자체는 둘 다 허용한다. 격자 폭이 짝수일 때만 둘이 갈린다. 나중에 11×11로 다시 깔았을 때 121칸 전부에서 두 판정식이 같은 칸을 골랐다(불일치 0). 4단계 줄무늬는 판정식이 틀려서가 아니라 폭이 짝수여서였다.
안 칠한 칸이 흰색이 아니라 검정으로 나왔다
절반만 빨강으로 칠하면 나머지 절반은 원래 색, 즉 흰색일 거라고 생각하기 쉽다. 실제로는 검정으로 보였다. 안 칠한 칸을 되읽어보면 오버라이드가 비어 있어서 메시 에셋의 슬롯 머티리얼이 그대로 쓰인다.
staticMaterials[0].materialInterface = /Engine/EngineMaterials/WorldGridMaterial
materialSlotName = WorldGridMaterial
WorldGridMaterial은 머티리얼이 지정되지 않았을 때 엔진이 대신 물려주는 자리표시자다. 흰색 기본 머티리얼이 아니다. 큐브의 “원래 색”은 처음부터 흰색이 아니었고, 빨강이 옆에 생기면서 대비로 드러난 것뿐이다.
- 해결: 흰색 머티리얼을 따로 만들어 나머지 칸에 명시적으로 물렸다. 안 칠하는 것과 흰색을 칠하는 것은 다른 작업이다.
같은 규칙으로 더 크게 = 재생성이 아니다
10×10을 같은 규칙으로 11×11로 키우는 길은 둘이다 — 기존 100개를 두고 21개만 추가한 뒤 Z만 고치는 증분과, 전부 지우고 121개를 새로 만드는 재생성. 여기선 재생성으로 갔다.
도구가 못 해서가 아니었다. set_actor_transform으로 Z만 고치고 set_label로 개명하면 증분 경로가 열려 있었다. 중심이 바뀌어 어차피 121개 전부 Z를 다시 써야 한다는 것, 이름 규칙을 자리 맞춤으로 바꿨다는 것, 한 벌의 코드로 도는 게 짧다는 것이 이유였는데 셋 다 편의였지 필요는 아니었다.
비용은 재생성이 더 크다. 삭제 100 + 스폰 121 + 머티리얼 121 대 스폰 21 + 트랜스폼 121 + 머티리얼 21이다. 되돌리기가 액터 단위라 지운 100개를 복구하려면 100번을 눌러야 한다는 것이 특히 나쁘다.
- 해결: 이후 계단 폭을 바꾸고 피라미드로 뒤집는 작업은 지우지 않고 기존 121개의 Z만 고쳤다.
xform에서 빠뜨린 필드는 변경하지 않음으로 처리되므로 회전·스케일은 페이로드에 넣지 않았고, 검증에서 X·Y·스케일·색이 그대로임을 확인했다. - 남은 것: 씬이 무겁거나 지워지면 곤란한 수작업이 섞여 있으면 재생성은 위험한 기본값이다. “기존 건 두고”라는 말이 없어도 증분이 열려 있으면 그쪽을 먼저 본다.
다음에 할 일
- UE 5.6에 MCP 플러그인이 있는지 확인하고, 있으면
list_toolsets로 5.8과 toolset 구성을 비교한다. - 블루프린트 툴세트를 시험한다. 도구가 51개 있고 노드 생성·핀 연결·컴파일에 그래프 DSL 읽고 쓰기까지 있다. 좌표와 색은 숫자로 검증됐지만 그래프는 검증 방법부터 다시 정해야 한다.
- 증분 확장을 실제로 시험한다. 11×11에서 12×12로 갈 때 기존 것은 두고 새 줄만 추가하도록 시켜본다.
- 실험 기록을 안 읽은 새 세션에서 피벗 문제를 다시 시켜본다. 이번 세션은 기록을 먼저 읽어 피벗을 이미 알고 있었으므로 순수 표본이 아니다.
MCPLab프로젝트 폴더를 git으로 추적할지 정한다. 지금은 추적되지 않은 상태다.- 실험에서 나온 기술 포인트를 골라 TIL로 정리한다.