읽고 입력할 때마다 연결 프로세스를 다시 준비하면 작은 업무 코드에도 반복이 늘어난다. 나는 하나의 MCP 클라이언트에서 작업과 페이지 객체를 이어 쓰는 API를 만들었다. 호출 문장은 간결해져도 내부의 실행 조건까지 느슨해져서는 안 됐다.

연결 객체와 작업 객체의 책임을 나눈다

connectNorthstar는 기존 stdio 서버로 연결하고 초기화를 마친 뒤 브라우저 객체를 돌려준다. begin은 목표와 문맥으로 작업을 시작하고 그 ID를 BrowserTask에 보관한다. page는 같은 작업 안의 탭을 가리킨다. 객체를 만들었다고 새 탭을 여는 것은 아니다.

McpClient는 요청 번호와 대기 중 응답, 시간 제한을 같은 프로세스에서 관리한다. 연결을 재사용하는 기능과 업무 자체를 재사용하는 기능은 다르다. 이 API가 프로그램 원장을 대신하거나 이전 성공을 새 요청의 성공으로 넘겨주는 것은 아니다. 먼저 어떤 수명을 재사용하는지 구별했다.

page라는 이름 아래에 임의 평가를 숨기지 않았다

page는 관찰과 검색, 추출, 탐색과 고정 조작을 기존 typed MCP에 전달한다. 일반적인 자동화 라이브러리와 비슷한 사용 모양이 있어도 임의 evaluate를 제공하는 것은 아니다. 익숙한 문법을 만들면서 기존 Broker의 제한을 우회하지 않으려 했다.

snapshot은 텍스트와 대상 목록을 제한된 크기로 정리하고 잘림 여부를 표시한다. 이 값은 페이지 전체의 무손실 복사본이 아니다. 짧게 반환했다고 필요한 내용이 모두 있다는 뜻도 아니다. 더 구체적인 찾기나 추출을 선택할 수 있도록 생략 사실을 호출자에게 남긴다.

locator는 첫 번째 비슷한 대상을 고르지 않는다

getByRole은 정확한 role과 name을 요구하고 필요한 경우 href를 함께 사용한다. resolve는 새 find를 수행한 뒤 이름·역할·주소가 맞는 대상을 고른다. 여러 개면 TARGET_AMBIGUOUS, 결과가 잘렸으면 TARGET_QUERY_TRUNCATED로 멈춘다.

대상을 못 찾았다고 화면의 첫 입력창으로 대체하지 않는다. API의 사용 문장이 짧아도 그 안의 유일성 검사는 유지한다. 다만 같은 이름이 여러 프레임에 있는 모든 문제를 이 조건만으로 해결하는 것은 아니다. 더 구체적인 계약과 호스트의 프레임·참조 검사가 뒤에서 계속 필요하다.

입력 뒤에는 새 참조로 값을 확인한다

fill은 현재 대상을 찾고 입력한 뒤 조작 응답에 담긴 새 관찰을 받아들인다. 이전 참조를 고집하지 않고 새로 맞는 참조를 찾거나 다시 resolve해 verifyField로 실제 값을 대조한다. 값이 다르면 FIELD_MISMATCH로 끝내고 입력을 반복하지 않는다.

click과 Enter도 기대 결과를 요구한다. URL 기대값은 절대 URL인지 전달 전에 검사하며 문자열 일부를 주소 전체처럼 쓰지 않게 한다. 실제 기대의 정확성은 호출자가 정해야 한다. 잘못된 성공 문구를 기대하면 API가 업무의 의미까지 알아서 바로잡는 것은 아니다.

사용하기 쉬워도 불확실성은 남긴다

전달 뒤 결과가 불확실해지면 task는 blocked를 유지한다. 읽기는 허용하되 다음 변경과 finish는 막는다. OUTCOME_UNKNOWN 뒤에는 원래 결과를 한 번 읽어 늦게 온 성공을 확인할 수 있지만 원래 클릭을 다시 보내지 않는다.

실제 API 시험은 하나의 MCP 프로세스 유지, 새 참조의 값 검증, 중복 대상에서 입력 0회, 미확정 뒤 읽기 허용과 추가 입력 차단을 확인한다. 시험 서버 대역을 이용한 통합 시험의 범위다. 이 글을 위해 실제 계정의 생성이나 발행을 다시 수행한 것은 아니며 모든 사이트의 호환성으로 넓히지 않는다.

좋은 추상화는 실패의 위치도 보여 준다

나는 짧은 업무 코드를 위해 대상 선택과 결과 확인을 감추기보다 반복 문법만 줄이려 했다. caller가 어떤 목표와 탭을 썼고 어느 기대에서 멈췄는지 알 수 있어야 수정도 가능하다. 실패를 모두 재시도로 바꾸는 API는 사용하기 쉬워 보여도 책임을 흐릴 수 있다.

재사용할 때는 연결 종료와 작업 중지, 로컬 대기와 원격 결과를 구별해야 한다. metrics의 요청·응답 수치는 바이트이며 토큰을 측정한 값이 아니다. 익숙한 page API를 제공하면서도 원래 실행 계약과 관찰의 한계를 그대로 읽을 수 있게 하는 것이 이 계층의 역할이었다.