WebMCP — 웹사이트가 AI에게 사용법을 알려 주는 방법
- WebMCP는 웹 페이지의 기능과 입력 규칙을 AI가 발견하고 호출할 수 있는 도구로 공개하는 방법이다.
- Playwright MCP를 쓰는 Codex는 지원되는 같은 브라우저·탭에서
browser_evaluate로getTools()·executeTool()을 실행해 도구를 사용한다. - 도구는 사이트가 직접 제공하거나 우리가 확장으로 덧붙일 수 있다. 도구 등록과 AI의 브라우저 연결은 별도로 준비해야 한다.
- AI가 도구를 고르면 페이지가 준비된 코드를 실행한다. 업무 API를 호출할 때도 서버의 로그인·사용자 권한 검사는 계속 필요하다.
- WebMCP 도구는 실행 중인 브라우저 페이지에 있다. 브라우저 없이 업무 API를 쓰는 서버 Agent에는 MCP 서버 같은 별도 연동이 필요하다.
로컬에서 쓰는 Codex에 **“회의실 사이트에서 4명이 쓸 수 있는 방을 찾아줘”**라고 부탁했다고 하자.
Codex가 Playwright MCP로 브라우저에 연결되어 있다면 입력칸을 채우고 검색 버튼을 누를 수 있다.
사이트가 WebMCP 도구도 제공하면, Codex는 search_rooms라는 기능과 capacity라는 입력 규칙을
읽고 그 도구를 호출하는 경로를 사용할 수 있다.
Codex가 판단하고, Playwright MCP가 브라우저로 전달하고, 페이지가 검색 코드를 실행한다. 이 페이지는 이미 Codex로 브라우저 작업을 맡기는 사용자를 위해 WebMCP 도구를 쓰려면 무엇을 연결하고 어떤 코드를 실행해야 하는지 설명한다. 읽고 나면 브라우저 연결, 도구 발견, 실제 업무 실행을 구분하고 연결이 끊긴 지점을 찾을 수 있다.
먼저 Codex에서 호출하는 쪽을 보고, 뒤에서 사이트가 도구를 등록하는 쪽을 설명한다. 사이트를 고칠 수 없다면 브라우저 확장으로 도구 덧붙이기를 함께 본다.
이 장에서 처음 나오는 말4개
WebMCPWeb Model Context Protocol- 웹 페이지의 기능을 AI가 발견하고 호출할 수 있는 도구로 공개하는 브라우저 API 제안이다.
도구Tool- AI가 이름과 입력값으로 호출할 수 있게 공개한 기능이다. 이 예에서는 회의실 검색이다.
브라우저 AIBrowser Agent- 브라우저의 페이지와 연결되어 사용자 요청을 수행하는 AI다. 여기서는 Playwright MCP를 쓰는 Codex가 이 역할을 맡는다. 모델 자체는 외부 서버에서 실행될 수도 있다.
Playwright MCPPlaywright MCP- Codex 같은 MCP client에 브라우저 조작과 페이지 JavaScript 실행 도구를 제공하는 서버다.
여기서 브라우저 AI는 누구인가
섹션 제목: “여기서 브라우저 AI는 누구인가”브라우저 AI는 특정 제품명이나 모델의 실행 위치가 아니라 페이지를 사용하는 에이전트의 역할이다. Playwright를 통해 탭을 조작하는 로컬 Codex도 포함된다. 사이트에 채팅창을 넣어야만 사용할 수 있는 것은 아니다.
| AI가 제공되는 형태 | 페이지와 만나는 방식 |
|---|---|
| 로컬 Codex + Playwright MCP | 브라우저 조작 도구로 대상 탭에 연결하고 페이지 JavaScript 실행 기능으로 WebMCP 호출 |
| 브라우저 내장 AI·AI 확장 | 해당 구현이 제공하는 WebMCP 도구 발견·호출 기능 사용 |
| 사이트 운영자가 넣은 AI 채팅 패널 | 페이지 또는 iframe의 에이전트가 허용된 WebMCP 도구를 사용하도록 구현 |
공식 제안은 브라우저 내장 AI와 페이지·iframe에 넣은 에이전트를 모두 다룬다. 아래 Codex 예는 Playwright의 페이지 실행 기능과 WebMCP API를 조합하는 방식이며, Codex 자체의 WebMCP 자동 발견 기능을 전제하지 않는다.
브라우저 agent는 화면을 보고 추측한다
섹션 제목: “브라우저 agent는 화면을 보고 추측한다”웹사이트가 도구를 제공하지 않으면 AI는 화면 이미지나 DOM(페이지 요소의 구조), 접근성 정보를 읽고 입력칸과 버튼을 찾아 조작할 수 있다. 이 방식도 가능하지만 화면 구성이 바뀌면 다시 해석해야 한다.
WebMCP 제안은 사이트가 가능한 동작과 입력 규칙을 직접 알려 주는 방법을 추가한다. Google·Microsoft가 제안했으며 W3C Web Machine Learning Community Group에서 논의 중이다.
| 같은 요청 | 화면을 읽고 조작할 때 | WebMCP 도구를 쓸 때 |
|---|---|---|
| 기능 찾기 | “이 칸이 인원수이고, 저 버튼이 검색이겠구나” | “search_rooms는 회의실 검색이라고 적혀 있구나” |
| 값 전달 | 입력칸을 찾아 4를 채우고 버튼 클릭 | capacity: 4로 도구 호출 |
| 실제 검색 | 버튼에 연결된 사이트 코드가 실행 | 도구에 연결된 사이트 코드가 실행 |
| 결과 확인 | 화면을 다시 읽어 결과 파악 | 사이트 코드가 반환한 결과를 받음 |
사이트가 제공하는 기능은 같고, AI가 그 기능을 찾아 호출하는 길이 추가된다. 도구가 없는 동작은 여전히 화면 조작이 필요할 수 있다. WebMCP가 모든 버튼을 자동으로 도구로 바꾸거나 AI 모델을 사이트에 설치해 주는 것은 아니다.
Codex와 Playwright MCP를 연결한다
섹션 제목: “Codex와 Playwright MCP를 연결한다”이 경로에서 MCP와 WebMCP는 서로 다른 구간에 있다. Codex는 MCP로 Playwright의 도구를 호출하고, Playwright는 브라우저 안에서 WebMCP API를 실행한다.
| 구간 | 전달하는 것 | 실행하는 쪽 |
|---|---|---|
| Codex → Playwright MCP | browser_evaluate에 전달할 JavaScript | Playwright가 선택된 탭으로 전달 |
| 선택된 탭 → WebMCP | getTools()로 목록 조회, executeTool()로 호출 | 브라우저가 페이지에 등록된 도구 실행 |
| 페이지 → 업무 서버 | 기존 회의실 검색 HTTP 요청 | 서버가 로그인·권한 검사 후 데이터 반환 |
Playwright MCP의 browser_evaluate는 페이지에서
JavaScript를 실행하는 도구다. 이 기능이 이미 연결되어 있으면 별도의 WebMCP 중계 서버를 새로 만들 필요는 없다.
페이지의 search_rooms가 Codex의 MCP 도구 목록에 자동 등록되는 것은 아니며, 여기서는
browser_evaluate로 목록을 읽고 호출한다.
같은 브라우저와 탭을 준비한다
섹션 제목: “같은 브라우저와 탭을 준비한다”-
Codex에 Playwright MCP를 등록한다. 설치는 Playwright 공식 설정 안내와 Codex MCP 문서를 따른다. 아래는 로컬 Codex의
~/.codex/config.toml에 둘 연결 설정 예다. 이미 등록했다면 중복 추가하지 않는다.[mcp_servers.playwright]command = "npx"args = ["-y", "@playwright/mcp@latest", "--browser", "chrome"]codex mcp list로 등록을 확인한다. 이 확인은 서버 설정 확인이며 브라우저 연결·WebMCP 지원까지 증명하지 않는다. 예제는 공식 안내의@latest를 쓰므로, 반복 검증할 때는 실제 사용한 패키지·브라우저 버전을 기록한다. -
Playwright가 사용할 Chrome에서 WebMCP를 활성화한다. 로컬 실험은 Chrome 안내의
chrome://flags/#enable-webmcp-testing을 켜고 해당 브라우저를 재시작한다. 평소 쓰는 Chrome에만 켜고 Playwright의 다른 프로필도 준비됐다고 생각하면 안 된다. 아래 예는document.modelContext.getTools()와 객체 인자를 받는executeTool()을 지원하는 버전을 전제로 한다. -
도구가 등록된 페이지를 열고 그 탭을 선택한다. Playwright의
browser_navigate·browser_tabs로 회의실 페이지를 열거나 선택하고, 그 브라우저 세션에서 필요한 로그인을 마친다. 이미 로그인한 기존 Chrome 탭에 연결하려면 Playwright 확장 연결을 따른다. 이 경우 Playwright 확장을 설치하고 실행 인자에--extension을 사용한다. 이 확장은 Codex와 브라우저를 연결하며, 사이트에 회의실 도구를 주입하는 확장과는 역할이 다르다.
설정을 되돌리려면 추가한 mcp_servers.playwright 항목을 제거하고 Codex 세션을 다시 시작한다.
실험용 Chrome 플래그도 원래 값으로 복원한 뒤 재시작한다.
도구 설명을 읽고 검색을 호출한다
섹션 제목: “도구 설명을 읽고 검색을 호출한다”아래 두 코드는 Codex가 Playwright MCP의 browser_evaluate 도구에 function 값으로 전달할 JavaScript다.
사이트 소스에 붙이는 코드가 아니다. 뒤의 명령형 예제처럼
search_rooms를 등록한 페이지를 가정한 설명용 발췌이며, 실제 Codex·브라우저 통합 실행을 검증한 예제는 아니다.
먼저 지원 여부와 도구 목록을 읽는다.
async () => { const context = document.modelContext; if (typeof context?.getTools !== 'function' || typeof context?.executeTool !== 'function') { throw new Error('이 탭에서 필요한 WebMCP API를 사용할 수 없습니다.'); } const tools = await context.getTools(); return { url: location.href, tools: tools.map(({ name, description, inputSchema, origin }) => ({ name, description, inputSchema, origin, })), };}예상 결과에는 현재 탭 URL과 search_rooms의 설명, capacity가 1 이상의 정수라는 입력 규칙이 있다.
getTools() 결과의 window 같은 브라우저 객체는 밖으로 전달하지 않고 필요한 필드만 반환한다.
이 시점에는 검색이 실행되지 않는다. Codex는 반환된 설명을 읽고 사용자 요청에 맞는 도구와 인자를 고른다.
다음은 같은 탭에서 capacity: 4로 검색하는 호출이다. 도구 객체는 호출 시 페이지 안에서 다시 찾는다.
async () => { const context = document.modelContext; const tools = await context.getTools(); const tool = tools.find(t => t.name === 'search_rooms' && t.origin === location.origin ); if (!tool) throw new Error('현재 사이트의 회의실 검색 도구가 없습니다.'); return await context.executeTool(tool, { capacity: 4 });}조회·호출 형식은 Chrome의 발견·실행 API를 따른다.
서버가 한라실·정원 6명을 반환하는 예라면, 페이지는 결과를 표시하고 browser_evaluate도
[{"name":"한라실","capacity":6}]라는 JSON 문자열을 Codex에 돌려준다. 검색 결과가 없으면 빈 목록이고,
권한·네트워크 오류는 호출 실패다. 예약 완료로 해석하지 않는다.
Codex에 줄 요청은 다음처럼 구체화할 수 있다.
Playwright MCP로 회의실 탭을 선택하고 URL을 확인해. browser_evaluate로 WebMCP 도구 목록과 입력 규칙을 읽은 뒤, 현재 사이트의 search_rooms에 capacity 4를 전달해 검색 결과를 알려줘.
연결이 안 될 때 어디를 보는가
섹션 제목: “연결이 안 될 때 어디를 보는가”| 관찰한 결과 | 먼저 확인할 곳 |
|---|---|
browser_evaluate를 쓸 수 없음 | Codex의 Playwright MCP 연결과 도구 허용 설정 |
getTools·executeTool이 없음 | 실제 연결된 브라우저의 버전·플래그·페이지 기능 허용 조건 |
도구 목록이 비었거나 search_rooms가 없음 | 현재 URL·탭, 페이지의 등록 완료 여부, iframe의 origin과 공개 범위 |
| 검색 호출에서 로그인·권한 오류 | 그 브라우저 세션의 로그인과 업무 서버의 권한 검사 |
| 페이지 이동 뒤 기존 도구를 찾지 못함 | 새 문서에서 목록을 다시 조회. 이전 페이지의 도구가 남아 있다고 가정하지 않음 |
playwright-cli와 스킬로도 같은 경로를 쓴다
섹션 제목: “playwright-cli와 스킬로도 같은 경로를 쓴다”playwright-cli의 eval도 페이지 JavaScript를 실행한다.
따라서 Codex가 CLI를 실행할 수 있으면 위 함수들을 eval로 전달하는 방식으로 연결할 수 있다.
이 경우 Codex → CLI → 탭의 WebMCP API 경로이며 Playwright MCP 서버는 필수가 아니다.
스킬은 “탭 확인 → API 확인 → 도구 설명 읽기 → 입력 구성 → 호출 → 결과 확인” 절차를 Codex에 알려 주는 문서다. 일반 Playwright 사용법만 담은 스킬이 WebMCP 호출 절차까지 자동으로 제공하지는 않는다. WebMCP를 활성화하거나 사이트에 도구를 등록하는 작업도 별도로 필요하다.
회의실 검색을 한 단계씩 따라가기
섹션 제목: “회의실 검색을 한 단계씩 따라가기”아래에서 다음을 누르며 화살표와 각 구성 요소의 상태를 보자. 특히 도구 호출, 서버 요청, 권한 검사는 서로 다른 단계다.
아래의 AI는 앞에서 연결한 Codex다. Codex와 페이지 사이의 화살표에는 Playwright MCP를 통한 전달이 포함된다. 사이트 개발자가 도구를 제공하고, 로그인한 사용자가 같은 사이트의 회의실 API를 쓰는 설명용 예다. 실제 AI나 WebMCP를 실행하지 않으므로 실험 기능을 켤 필요가 없다. 처음으로 돌아가거나 전체 흐름을 펼쳐 비교할 수 있다.
회의실 검색: Codex가 고르고, 페이지가 실행하고, 서버가 권한을 확인한다
각 단계가 끝난 시점의 보관 상태입니다. 강조된 객체 사이의 화살표를 따라 전달 값을 읽으세요. 내부 처리는 같은 객체로 돌아옵니다.
구성 요소의 역할
- 웹 페이지
- Playwright MCP로 연결한 탭의 회의실 앱. 검색 도구의 실행 코드가 여기에 있다. 그림에서는 Playwright MCP와 브라우저의 전달 경로를 화살표에 포함한다.
- Codex
- 사용자 요청을 받아 도구와 입력값을 고른다. Playwright MCP의 browser_evaluate로 페이지의 WebMCP API를 실행한다. 모델 자체는 외부 서버에서 실행될 수도 있다.
- 업무 서버
- 로그인과 조회 권한을 검사하고 회의실 데이터를 돌려준다. 기존 웹 앱의 서버다.
사용자가 회의실 앱에 로그인해 페이지를 열었다. 페이지 코드가 search_rooms의 이름·설명·입력 규칙·실행 함수를 브라우저에 등록한다. 등록만으로 검색이 실행되지는 않는다.
- 웹 페이지
- 검색 실행 코드와 등록한 도구 정의. 조회 결과는 아직 없다.
- Codex
- 사용자의 요청: “4명이 쓸 수 있는 회의실을 찾아줘.” 아직 도구 목록을 읽지 않았다.
- 업무 서버
- 기존 사용자 세션과 회의실 데이터. 새 검색 요청은 없다.
Codex가 browser_evaluate로 페이지의 getTools()를 실행해 받은 결과다. 도구의 이름·설명·입력 규칙을 보고 search_rooms의 capacity에 인원수를 넣는다는 것을 안다. 실행 함수 자체를 받거나 Codex의 MCP 도구 목록에 search_rooms를 자동 등록하는 과정은 아니다.
- 웹 페이지
- 등록된 도구와 실행 코드. 조회 결과는 아직 없다.
- Codex
- 사용자 요청과 도구 설명. capacity에 4를 넣어 호출할 수 있다.
- 업무 서버
- 기존 사용자 세션과 회의실 데이터. 아직 검색 요청은 없다.
Codex가 browser_evaluate에 executeTool 호출 코드를 전달한다. 페이지 안에서 search_rooms 도구를 찾아 capacity: 4를 넘기면 브라우저가 등록된 execute를 실행한다. 조회·호출 코드는 Codex가 전달하지만 실제 검색 로직은 사이트가 준비한 코드다.
- 웹 페이지
- 실행 중인 검색 함수와 입력값 capacity: 4.
- Codex
- 보낸 도구 호출. 결과를 기다린다.
- 업무 서버
- 기존 사용자 세션과 회의실 데이터. 아직 검색 요청은 없다.
execute 안에서 같은 사이트의 /api/rooms?capacity=4로 fetch 요청을 보낸다. 이 예는 cookie로 로그인하는 앱이며, 브라우저가 기존 세션 cookie를 붙인다. 세션 cookie를 AI에게 넘기는 단계는 없다.
- 웹 페이지
- capacity: 4로 조회 중. 서버 응답을 기다린다.
- Codex
- 도구 결과를 기다린다. 이 예에서 로그인 cookie를 전달받지 않는다.
- 업무 서버
- 도착한 조회 요청과 cookie. 세션 유효성과 권한은 아직 검사 전이다.
서버가 페이지에 한라실 정보를 반환한다. 페이지 코드는 이 결과로 화면을 갱신하고 도구 반환값을 준비한다. 화면 갱신도 앱 개발자가 구현하는 동작이며 WebMCP가 자동으로 만들어 주지 않는다.
- 웹 페이지
- 검색 결과와 갱신된 화면: 한라실, 정원 6명.
- Codex
- 아직 도구 결과를 기다린다.
- 업무 서버
- 원래 회의실 데이터와 사용자 세션. 검색만 했으므로 예약 상태는 바뀌지 않았다.
execute의 반환값이 executeTool과 browser_evaluate의 결과로 Codex에 전달된다. Codex는 “4명이 쓸 수 있는 한라실이 있어요. 정원은 6명이에요”라고 답할 수 있다. 회의실 검색 완료는 예약 확정이 아니다. 날짜별 빈 시간 조회나 실제 예약에는 별도 기능이 필요하다.
- 웹 페이지
- 한라실을 보여 주는 검색 화면. 사용자가 이어서 조작할 수 있다.
- Codex
- 검색 결과: 한라실, 정원 6명. 예약은 수행하지 않았다.
- 업무 서버
- 원래 회의실 데이터와 사용자 세션. 예약 변경 없음.
공식 흐름 설명에서도 페이지 코드가 필요에 따라 서버 API를 부르고 화면을 갱신한 뒤 결과를 돌려준다. 여기서 기억할 것은 AI는 무엇을 호출할지 고르고, 페이지는 준비된 코드를 실행하며, 업무 서버는 권한과 데이터를 관리한다는 역할 분담이다. 도구가 화면의 색상만 바꾸는 기능이라면 서버 요청 없이 페이지 안에서 끝날 수도 있다.
사이트가 제공하지 않으면 확장으로 덧붙인다
섹션 제목: “사이트가 제공하지 않으면 확장으로 덧붙인다”회의실 사이트를 고칠 수 없어도 우리 브라우저에서 그 페이지에 추가 코드를 실행할 수 있다.
확장이 URL에 맞는 코드를 넣고, 그 코드가 search_rooms 같은 도구를 등록하는 방식이다.
Brave의 WebMCP 구현에도 URL별 스크립트를 주입해 도구를 등록하는 사례가 있다.
| 사이트가 직접 제공 | 우리가 확장으로 제공 | |
|---|---|---|
| 도구 코드는 어디서 오는가? | 사이트가 배포하는 페이지 코드 | 우리 확장이 페이지에 넣는 코드 |
| 실제 기능과 어떻게 연결하는가? | 사이트의 기존 내부 함수 등을 재사용 | 화면의 입력칸·버튼·결과나 접근 가능한 API를 이용 |
| 사이트가 바뀌면 누가 고치는가? | 사이트 개발자 | 연결 코드를 만든 우리 |
AI에게는 하나의 검색 도구로 보이지만, 그 안에서는 우리가 작성한 “입력칸 채우기 → 버튼 누르기 → 새 결과 기다리기 → 결과 읽기”가 실행될 수 있다. 원래 사이트의 배포 파일은 바뀌지 않고, 확장을 설치한 브라우저에만 도구가 추가된다.
도구 등록만으로 로컬 AI와 연결되는 것은 아니다. AI가 해당 브라우저·탭의 도구를 발견하고 호출하는 연결도 필요하다.
두 가지 작성 방식
섹션 제목: “두 가지 작성 방식”사이트 개발자는 JavaScript 함수로 도구를 등록하거나 기존 HTML form에 도구 설명을 붙인다. 둘 다 “AI가 이 기능의 이름과 입력을 알게 한다”는 목적은 같다.
명령형 — script가 도구를 등록한다
섹션 제목: “명령형 — script가 도구를 등록한다”registerTool은 기능 안내와 실행 코드를 묶어 등록하는 함수다.
공식 JavaScript API의 구조를 회의실 예로 바꾸면 다음과 같다.
아래는 회의실 앱의 페이지 script에 들어갈 설명용 발췌다. WebMCP를 지원하고 기능이 활성화된 브라우저,
기존 /api/rooms API, 화면 갱신 함수 renderRooms가 있다고 가정한다. 이 문서에서 그대로 실행하는 코드는 아니다.
await document.modelContext.registerTool({ name: 'search_rooms', description: '주어진 인원수 이상을 수용하는 회의실을 검색한다. 예약하지 않는다.', inputSchema: { type: 'object', properties: { capacity: { type: 'integer', minimum: 1, description: '사용 인원수' }, }, required: ['capacity'], }, execute: async ({ capacity }) => { const response = await fetch(`/api/rooms?capacity=${encodeURIComponent(capacity)}`); if (!response.ok) throw new Error('회의실 조회에 실패했습니다.'); const rooms = await response.json(); renderRooms(rooms); // 기존 앱이 제공하는 화면 갱신 함수 return JSON.stringify(rooms); // AI에게 돌려줄 검색 결과 },});| 코드 | 쉬운 뜻 |
|---|---|
name | 호출할 기능의 이름: search_rooms |
description | AI가 기능을 고를 때 읽는 설명 |
inputSchema | 입력 규칙: capacity에 1 이상의 정수가 필요하다 |
execute | 호출받았을 때 페이지가 실제로 실행할 코드 |
입력이 {"capacity": 4}이고 서버 응답이 [{"name":"한라실","capacity":6}]이면,
화면에는 한라실이 나타나고 AI도 그 검색 결과를 받는다. 도구를 등록할 때는 검색하지 않고, 호출될 때 execute가 실행된다.
이 예의 fetch는 같은 사이트로 요청하므로 기존 로그인 cookie를 사용할 수 있다.
다른 사이트의 API까지 인증이 자동으로 해결되는 것은 아니며, 요청 대상과 앱의 인증 방식에 따라 처리가 달라진다.
선언형 — 기존 form에 attribute를 붙인다
섹션 제목: “선언형 — 기존 form에 attribute를 붙인다”이미 인원수 입력칸과 검색 버튼이 있다면 선언형 API로 form에 도구 이름과 설명을 붙일 수 있다. 브라우저는 form 필드를 바탕으로 AI에게 보여 줄 입력 규칙을 만든다.
아래도 기존 회의실 앱의 form을 가정한 설명용 발췌다. /rooms 검색 결과 페이지가 있다는 전제다.
<form action="/rooms" method="get" toolname="search_rooms" tooldescription="인원수에 맞는 회의실을 검색한다. 예약하지 않는다."> <label> 사용 인원수 <input type="number" name="capacity" min="1" required toolparamdescription="사용 인원수"> </label> <button type="submit">회의실 검색</button></form>toolname은 기능 이름, tooldescription은 기능 설명, toolparamdescription은 입력값 설명이다.
제안 문서의 제출 규칙에 따르면
위 form은 AI가 값을 채운 뒤 사용자가 제출 버튼을 눌러야 검색된다. form에 toolautosubmit을 추가하면
사용자의 버튼 클릭을 기다리지 않고 제출할 수 있다.
이 차이는 선언형 form의 제출 규칙이다. JavaScript 도구까지 모두 자동으로 사람의 확인을 받는다는 뜻은 아니다.
MCP와 어디가 다른가
섹션 제목: “MCP와 어디가 다른가”둘 다 “이름과 입력 규칙을 가진 도구”를 AI에게 제공하지만 실행 코드가 있는 곳이 다르다. MCP 프로토콜의 서버 연결을 떠올리고 비교하면 된다.
| 질문 | 서버 MCP | WebMCP |
|---|---|---|
| 검색 코드의 진입점은 어디에 있는가? | MCP 서버 프로세스 또는 HTTP endpoint | 열려 있는 웹 페이지의 코드 |
| 어떻게 호출하는가? | MCP client가 stdio·Streamable HTTP 등으로 서버에 요청 | 브라우저가 페이지에 등록된 함수를 실행하거나 form을 처리 |
| 웹 페이지가 꼭 필요한가? | 필요 없다 | 페이지를 실행하는 브라우저 환경이 필요하다 |
| 누구의 권한으로 업무 API를 쓰는가? | 연동 설계에 따라 사용자 위임 또는 서비스 신원 | 이 예에서는 웹 앱의 기존 사용자 로그인 |
| 회의실 앱에 붙이면 무엇이 생기는가? | 서버 Agent가 연결할 수 있는 도구 경로 | 해당 페이지와 연결된 AI가 사용할 도구 경로 |
회의실 앱이 WebMCP를 붙였다고 사내 서버 Agent에 도구가 자동 등록되지는 않는다. 서버 Agent가 브라우저 없이 업무 API를 사용해야 한다면 MCP 서버 같은 별도 연동이 필요하다.
“서버 측 Agent는 절대 WebMCP를 사용할 수 없다”로 외울 필요는 없다. 브라우저를 제어하는 연결 계층을 추가할 수는 있지만, 이때도 페이지를 실행하는 브라우저가 필요하다. 제안의 범위도 기존 서버 연동과의 보완 관계를 설명한다. 반대로 브라우저 AI가 MCP client 기능을 별도로 갖고 있다면 서버 MCP도 사용할 수 있다.
보안 모델은 origin 경계 위에 있다
섹션 제목: “보안 모델은 origin 경계 위에 있다”회의실 검색 도구를 호출할 수 있다고 해서 모든 회의실을 예약할 권한까지 생기지는 않는다. 서로 다른 두 검사를 나누면 이해하기 쉽다.
| 검사 | 이 예에서 묻는 것 | 담당 |
|---|---|---|
| 도구 접근 | 이 페이지의 도구를 발견하고 호출해도 되는가? | 브라우저의 사이트 경계와 기능 허용 설정 |
| 업무 권한 | 로그인한 사용자가 이 회의실을 조회·예약해도 되는가? | 기존 업무 서버 |
origin은 프로토콜·호스트·포트로 구분하는 웹의 사이트 경계다.
Chrome의 접근 규칙은
다른 origin에 도구를 공개할 때 exposedTo, 상대 도구를 조회할 때 fromOrigins를 명시하도록 한다.
iframe의 기능 사용은 tools Permissions Policy로 통제한다. 즉 브라우저 기능을 어느 페이지에 허용할지도 정해야 한다.
업무 서버의 로그인·권한 검사는 계속 필요하다. UI에서 버튼을 숨기거나 도구 설명에 “관리자 전용”이라고 적는 것만으로 권한이 생기거나 제한되지 않는다. 이 덱의 도구 실행 권한과 같은 구분이다.
구현할 때 확인할 세부 API와 힌트
getTools()는 접근 가능한 도구 목록을 조회하고,executeTool()은 선택한 도구를 호출한다.toolchange는 목록이 바뀌었음을 알리는 이벤트다.annotations의readOnlyHint는 읽기 전용,consequentialHint는 중요한 결과를 만드는 동작,untrustedContentHint는 신뢰할 수 없는 내용이 결과에 포함됨을 알리는 힌트다. 힌트가 서버의 권한 검사나 악성 지시 방어를 대신하지 않는다.toolsPermissions Policy의 기본값은self다. 다른 origin의 iframe에서 등록하려면 부모의allow="tools"같은 명시적 허용이 필요하다.document.domain으로 origin 경계를 느슨하게 한 문서에서는 WebMCP API가 비활성화된다.
상세 조건은 JavaScript API와 보안·권한 조건을 확인한다.
이 덱과의 관계
섹션 제목: “이 덱과의 관계”이 덱은 서버에서 실행되는 사내 Agent 플랫폼을 설계한다. WebMCP가 들어왔을 때도 다음처럼 역할을 나누면 된다. 아래는 WebMCP의 필수 구조가 아니라 이 덱의 설계 적용안이다.
| 하고 싶은 일 | 연결할 곳 | 권한 검사 |
|---|---|---|
| 직원의 브라우저 AI가 회의실 웹 앱을 사용 | 웹 페이지에 WebMCP 도구 추가 | 회의실 앱 서버가 기존 사용자 권한 검사 |
| 사내 서버 Agent도 회의실 검색을 사용 | 같은 업무 API 앞에 MCP 서버 제공 | 플랫폼의 도구 사용 정책과 업무 API의 권한 검사 |
| 브라우저 AI가 사내 포털의 Agent를 호출 | 포털 페이지에 Agent 호출 도구 추가 | 포털 서버가 기존 Grant(호출 허용 규칙) 검사 |
같은 검색 기능을 양쪽에서 제공한다면 업무 규칙은 서버에 한 번 두고, 웹 페이지의 도구와 MCP 서버가 그 API를 각각 부르게 할 수 있다. 서버 도구의 등록·검증·공개는 사용자 MCP 관리를 따른다. WebMCP라는 이유로 이 덱에 새 도메인 객체를 추가하지는 않는다.
지금 어디까지 왔는가
섹션 제목: “지금 어디까지 왔는가”2026년 9월 29일 제안 저장소의 구현 현황을 확인했다. 아직 변할 수 있는 API이며 완성된 공통 웹 표준으로 가정하지 않는다.
| 구현 | 공식 현황에 적힌 상태 |
|---|---|
| Chrome | 149부터 origin trial. 로컬 실험은 chrome://flags/#enable-webmcp-testing |
| Edge | 150부터 origin trial |
| Brave | Leo 채팅에서 실험적 지원 |
| ChatGPT Desktop | 지원으로 기재 |
| Firefox · Safari | 표준 입장 논의 링크가 있으며 구현 지원은 기재되지 않음 |
origin trial은 정식 출시 전 기능을 참여 사이트에서 시험하는 제도다.
현재 API 예제는 document.modelContext를 사용한다.
초기 자료에서 보던 navigator.modelContext와 혼동하지 않는다.
선언형 제안에는
form 제약을 입력 규칙으로 바꾸는 세부 알고리즘도 아직 미정으로 남아 있다.
언제 검토를 여는가
섹션 제목: “언제 검토를 여는가”회사가 브라우저 AI 사용을 허용하고, 사내 웹 앱에 **“AI가 이 화면을 제대로 사용하게 해 달라”**는 요구가 생기면 검토할 만하다. 서버 Agent만 업무 API를 호출하면 되는 상황에서는 우선 서버 연동을 보면 된다.
실제 도입 전에는 대상 브라우저의 지원 상태, 웹 앱 서버의 기존 권한 검사, 서버 MCP와의 업무 로직 공유를 확인한다. 이 페이지의 설명용 흐름은 사내 도입 결정이나 실제 제품 동작 검증을 뜻하지 않는다.
이해 확인
섹션 제목: “이해 확인”Codex에서 Playwright로 버튼을 누를 수 있다. search_rooms도 자동으로 Codex의 도구 목록에 생길까?
답과 이유
아니다. 이 예에서 Codex가 직접 호출하는 MCP 도구는 browser_evaluate다.
그 도구로 페이지의 getTools()를 실행해 설명을 읽고, executeTool()로 search_rooms를 호출한다.
사이트 도구를 Codex의 MCP 도구 목록에 직접 노출하려면 그런 기능을 제공하는 별도 중계 구현이 필요하다.
회의실 사이트가 search_rooms를 등록했다. 사내 서버 Agent도 바로 호출할 수 있을까?
답과 이유
자동으로 연결되지는 않는다. 이 도구는 브라우저에서 실행 중인 페이지에 있다. 브라우저 없이 사용하는 서버 Agent에는 MCP 서버 같은 별도 연동이 필요하다.
AI가 검색 결과로 한라실을 받았다. 회의실 예약까지 완료된 것일까?
답과 이유
아니다. search_rooms는 정원에 맞는 회의실을 조회했을 뿐이다. 실제 예약에는 날짜·시간 등의 입력과
예약 기능이 필요하고, 업무 서버가 예약 권한도 검사해야 한다.
참고 자료
섹션 제목: “참고 자료”- WebMCP 제안 저장소 — 배경·설계 목표·페이지와 서버의 역할.
- Chrome WebMCP 문서 — 실험 환경과 공식 데모·검사 도구.