Skip to content

[설계] dev-server spawn — "MCP만 설정하면 알아서"의 천장 측정 + env-2 부트스트랩 경로 고정 #428

@DaveDev42

Description

@DaveDev42

배경 / 성격

설계 조사. 1.0.0 acceptance 필수는 아니다 — north star의 천장을 정확히 측정하고 그 안에서의 최선 경로를 고정하는 게 목적이다.

north star (사용자 결정): ".mcp.json(MCP 서버)만 설정하면 나머지는 알아서 진행된다" — 사용자가 config를 hand-wire하지 않고 도구가 흐름을 몬다.

직접 동기: Dep ②(#425, merged)·Dep ③(#424, merged)로 vite.config tunnel 옵션 indirection·env-var hand-off를 제거해 config 의존을 줄여왔다. 남은 질문은 "그 줄이기의 끝은 어디인가 — MCP 데몬이 dev 서버까지 띄울 수 있나?"다.

결론 먼저 (TL;DR)

env-2 live-dev에서 "MCP만 설정" north star는 구조적으로 도달 불가다. 세 후보 접근(A/B/C)을 코드 근거로 평가하고 adversarial 검증으로 천장을 확정했다. 진짜 레버는 "script/config 제거"가 아니라 앱 번들을 누가 서빙하느냐이고, 그건 제거할 수 없다 — 옮길 수 있을 뿐이다.

권고: 접근 B (agent-plugin skill 부트스트랩). devtools 변경 0, install-graph 불변식 보존, fix-env2-cdp-tunnel-seam changeset의 자연스러운 연속, 사용자 intent 충족. 별도로 접근 C2(relay-manager)는 #420 orphan 문제를 구조적으로 푸는 아키텍처 개선이라 독립 트래킹 후보로 남긴다.

확정된 천장 (adversarial 검증 완료)

env-2(실기기 PWA가 cloudflared 터널로 미니앱 로드)에는 독립된 두 터널이 있다:

  1. tunnel#1 → Vite dev serverhttpServer.address()로 잡은 Vite 바인드 포트(src/unplugin/index.ts:252-266)를 노출. 런처 PWA iframe이 앱 자산(HTML/JS) 을 로드하는 채널.
  2. tunnel#2 + Chii relaystartChiiRelay(port 0) → startQuickTunnel(relay.port)(src/unplugin/index.ts:304). CDP 디버깅 채널일 뿐.

src/mcp/chii-relay.ts:117-170 startChiiRelay는 순수 CDP 브리지(target WS + client WS)다 — 앱 HTML/JS를 서빙하지 않는다. 데몬·relay 어디에도 정적 파일 서빙 모드는 없다.

env-2 live-dev에는 무언가가 앱 번들을 서빙해야 하고, 그게 Vite dev server다. MCP relay는 이걸 대체 못 한다. 따라서 "MCP만 설정하면 앱이 뜬다"는 live-dev에서 불가능하다(static build를 서빙하면 가능하지만 HMR을 죽여 env-2의 존재 이유를 없앤다).

검증으로 무너진 전제: "install-graph 불변식이 데몬의 relay 기동을 막는다"는 틀렸다. scripts/check-mcp-react-free.sh:20-23의 grep PATTERN은 react/react-dom 전용이고 chii/cloudflared/ws는 스캔하지 않는다. 이들은 이미 package.json dependencies이자 tsdown.config.ts:121external이며, 데몬은 이미 env3/4에서 bootRelayFamily(debug-server.ts:1684+, startChiiRelay+startQuickTunnel 호출)로 직접 relay+tunnel을 띄운다. env-2만 bootExternalRelayFamily(debug-server.ts:1795, attach-only)로 unplugin에 위임한다. 즉 데몬의 relay 기동 능력은 이미 있고, 천장은 relay가 아니라 앱 서버다.

세 접근 평가

A. MCP 데몬이 Vite dev server를 child process로 spawn

FEASIBLE-WITH-CAVEATS. child_process.spawn은 이미 데몬 번들에서 쓰임(src/mcp/local-launcher.ts:29 정적 import) → install-graph 불변식(react 전용) 위반 아님. 새 tool start_dev_server({projectRoot, script?})pnpm dev:phone:cdp를 consumer cwd에서 spawn.

최대 리스크 둘:

남는 consumer-side irreducible: vite.config의 unplugin 등록(tunnel:{cdp:true} 또는 AIT_TUNNEL), 알려진 pnpm script 이름. .mcp.json만으론 불충분 — 데몬은 vite.config를 만들 수 없다.

B. agent-plugin skill이 dev+attach를 한 번에 부트스트랩 ★권고

FEASIBLE. agent-plugin이 100% 소유, devtools 변경 0. /ait debug skill(shared/skills/debug/SKILL.md)이 env-2를 소유하나 현재는 dev 서버가 떠 있다고 가정(SKILL.md:61). skill이 직접: (1) pnpm dev:phone:cdp를 background Bash로 기동, (2) <projectRoot>/.ait_urls 출현까지 poll, (3) start_debug({mode:'relay-sandbox', projectRoot}) 호출.

.ait_urls 발견 seam(#424/relay-url-store.ts)이 정확히 이 자동화를 위해 설계됨 — unplugin이 쓰고 데몬이 lazy fallback으로 읽음(debug-server.ts:1888). fix-env2-cdp-tunnel-seam changeset이 이미 setup-phone-preview → debug seam 절벽을 제거했고, B는 "사용자가 pnpm dev:phone:cdp를 직접 쳐라"를 "skill이 대신 친다"로 잇는 자연스러운 다음 걸음.

install-graph 불변식 보존(데몬에 vite/react를 안 끌어들임) + 사용자 intent("내가 hand-wire 안 함, 도구가 몬다") 충족. .mcp.json만이 유일 config는 아니지만(skill이 오케스트레이터), 런타임 호출 단계는 자동화됨.

활성 버그 발견 (B와 무관하게 선결): debug/SKILL.md:212-220mode:'mobile'/'relay-dev'를 호출하는데 실제 start_debug enum은 ['local-browser','relay-sandbox','relay-staging','relay-live'](tools.ts:423)다. 에이전트가 mode:'mobile'로 호출하면 실패한다 — 정합 결함, 먼저 고친다.

C. relay+tunnel을 Vite 밖 독립 프로세스로 분리

  • C1 (데몬이 dynamic import로 relay+tunnel 기동): FEASIBLE-WITH-CAVEATS이나 north star 근접도는 A보다 낮다. 데몬이 app tunnel을 띄우려면 앱 포트를 알아야 하는데(AIT_DEVTOOLS_URL 수동 설정), .ait_urls IPC 채널을 우회해 수동 env 설정을 재도입. 여전히 pnpm dev 필요.
  • C2 (standalone relay-manager CLI): FEASIBLE-WITH-CAVEATS. cli.ts flat dispatch에 4번째 target으로 자연스럽게 들어감. unplugin 터널 경로에 orphan parent-watcher 부재 — vite 고아화 시 cloudflared 좀비 잔존 (#347 사각) #420 SIGKILL/orphan 문제를 구조적으로 해결(relay+tunnel 수명이 Vite와 분리) — 이게 진짜 가치. .mcp.json에 relay-manager를 등록하면 Claude Code가 자동 기동, 사용자는 plain pnpm dev만. 단 앱 서버는 여전히 사용자 몫이라 north star 거리는 A/B와 동일.

비교 / 권고

devtools 변경 install-graph north star 거리 부수 효과
A 신규 tool + 수명주기 OK(react 전용) pnpm dev 제거 orphan/race 신규 복잡도
B 0 보존 런타임 호출 자동화 seam 연속, skill 버그 선결
C1 신규 경로 OK A보다 멀어짐 수동 env 재도입
C2 신규 CLI target OK A/B와 동일 #420 orphan 구조 해결

권고:

  1. 접근 B를 채택 — agent-plugin /ait debug에 env-2 부트스트랩(background dev 기동 + .ait_urls poll + attach) 추가. devtools 무변경, 최소 비용, intent 충족. (선결: skill의 mode:'mobile' enum 버그 정정.)
  2. 접근 C2를 별도 아키텍처 개선으로 트래킹 — relay-manager가 unplugin 터널 경로에 orphan parent-watcher 부재 — vite 고아화 시 cloudflared 좀비 잔존 (#347 사각) #420 orphan 문제를 근본 해결하므로 north star와 무관하게 가치. 단 우선순위 낮음(현 parentWatcher가 동작 중).
  3. 접근 A는 보류 — race/orphan 복잡도 대비 이득(pnpm dev 한 줄 제거)이 B 대비 낮다.

천장은 명확히 고정: env-2 live-dev에서 앱 서버(Vite)는 누군가 띄워야 하고, 그 "누군가"를 사람→skill로 옮기는 게(접근 B) 도달 가능한 최선이다. 완전 무인은 비목표.

연관

acceptance (이 issue의 종료 조건)

Metadata

Metadata

Assignees

No one assigned

    Labels

    roadmapharness roadmap 작업 항목 (Project #1)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions