MCP 게이트웨이
MCP 게이트웨이 (MCP gateway)
Docker Sandboxes의 MCP 게이트웨이로 에이전트를 Model Context Protocol 서버에 연결하는 방법을 자세히 알아볼게요.
출처: 문서
본문
이 페이지는 로컬 MCP 게이트웨이를 설명해요. 클라우드 샌드박스는 Docker Agentic Platform에서 구성한 MCP 서버를 사용해요: MCP 서버 로드를 참고하세요.
Docker Sandboxes에는 에이전트를 Model Context Protocol 서버에 연결하기 위한 MCP 게이트웨이가 포함돼 있어요. 게이트웨이는 샌드박스 안의 에이전트에 MCP 엔드포인트 하나를 제공하고, sbx가 호스트에서 등록된 서버, OAuth 자격 증명, 샌드박스 수명주기를 관리해요.
이는 Claude Code 같은 에이전트에 MCP 서버를 직접 구성하는 것과 달라요. 직접 MCP 설정은 그 에이전트 자신의 MCP 클라이언트를 구성해요. Docker Sandboxes에서는 호스트에 MCP 서버를 한 번 등록하면, 샌드박스 게이트웨이가 이를 격리된 샌드박스 안의 지원 에이전트에게 노출해요. 이 호스트가 관리하는 게이트웨이는 자격 증명, 명시적 서버 로딩, 실시간 업데이트, organization 거버넌스를 위한 단일 경로를 제공해요.
[!NOTE] Docker Sandboxes MCP 게이트웨이는 Docker Desktop MCP Toolkit과 별개예요.
sbx mcp를 사용하는 데 Docker Desktop MCP Toolkit이 필요하지 않고, MCP Toolkit 서버 설정은 Docker Sandboxes와 공유되지 않아요.
사전 요구 사항 (Prerequisites)
sbx login으로 로그인하세요.- 시작 시 MCP를 구성하는 에이전트 통합을 사용하세요: Claude Code, Codex, Devin, Gemini, Kiro, 또는 OpenCode.
- Dynamic Client Registration 없이 OAuth가 필요한 원격 서버는 서버 제공자에게 OAuth 클라이언트를 등록하세요.
- OCI 패키지로 해석되는
--local --url등록은 Docker가 설치되고 실행 중인 호스트를 사용하세요. 명시적--command docker ...등록에도 Docker가 필요해요.
빠른 시작 (Quick start)
호스트에 MCP 서버 하나를 등록하는 것부터 시작하세요:
$ sbx mcp add notion --url https://mcp.notion.com/mcp
서버가 OAuth를 요구하면 sbx가 등록을 저장하기 전에 인증 흐름을 열어요. 등록 후 서버가 등록되었는지 확인하세요:
$ sbx mcp ls
NAME TYPE URL/COMMAND
notion remote https://mcp.notion.com/mcp
그런 다음 샌드박스를 시작하고 등록된 서버를 노출하세요:
$ sbx run claude --name mcp-demo --static-mcp notion
샌드박스는 MCP 게이트웨이와 함께 시작되고 notion 서버를 미리 로드해요. 등록은 호스트에 남아 다른 샌드박스가 재사용할 수 있어요.
MCP 서버 등록 (Register an MCP server)
sbx mcp add는 MCP 서버를 이름으로 등록해요. 등록은 호스트에 서버 정의를 기록해요. 서버를 샌드박스에 자체적으로 붙이지는 않아요. 등록된 서버를 샌드박스에 노출하려면 샌드박스를 만들 때 --static-mcp로 전달하거나, 이미 실행 중인 샌드박스에는 sbx mcp load를 사용하세요.
서버 이름은 문자, 숫자, 점, 하이픈, 밑줄을 포함할 수 있어요.
--url 플래그는 다양한 종류의 입력을 가리킬 수 있어요. 실행 위치는 무엇을 등록하느냐에 따라 달라져요:
- 원격 엔드포인트 URL은 실행 중인 MCP 서버를 식별해요. 서버는 원격으로 실행되고 샌드박스 게이트웨이가 여기에 연결돼요.
--local이 붙은 메타데이터 URL은 OCI 패키징된 stdio 서버를 설명하는 레지스트리 항목,server.json, 또는server.yaml을 반환해요.sbx가 이미지를 해석해 호스트에서 Docker로 실행해요.- 명시적 명령은 호스트에서 stdio MCP 서버로 실행돼요.
로컬 stdio 서버는 샌드박스 안이 아니라 호스트에서 실행돼요. 샌드박스 안의 에이전트는 MCP 게이트웨이에만 연결돼요.
--url 호스트네임이 사설, 루프백, link-local, 또는 클라우드 메타데이터 주소로 해석되면 sbx가 서버를 등록하지만 해석된 주소에 대해 경고해요. 신뢰하는 URL만 등록하세요. 신뢰하지 않는 URL에서 매니페스트를 가져오면 내부 서비스나 클라우드 메타데이터가 노출될 수 있고, DNS 리바인딩이 확인된 후 호스트네임을 리다이렉트할 수 있어요.
OAuth 메타데이터 탐색도 리다이렉트 대상을 포함해 이런 주소를 만나면 경고하고 계속 진행해요. 신뢰하는 내부 서버에는 --skip-ssrf-check를 전달해 MCP URL 검사와 OAuth 메타데이터 탐색 검사 모두를 건너뛰고 그 경고를 억제할 수 있어요. MCP 호스트, OAuth 제공자, 모든 메타데이터 리다이렉트 대상을 신뢰할 때만 이 플래그를 사용하세요.
원격 엔드포인트 URL
원격 MCP 엔드포인트에는 서버 URL을 전달하세요:
$ sbx mcp add notion --url https://mcp.notion.com/mcp
$ sbx mcp add linear --url https://mcp.linear.app/mcp
원격 서버에 대한 요청이 멈추면 MCP 서버 스트림 정체를 참고하세요.
사용자 정의 요청 헤더
--header 'Name: value'로 원격 MCP 엔드포인트에 사용자 정의 HTTP 헤더를 보내 API 키로 인증할 수 있어요. 헤더마다 플래그를 반복하되 각 헤더 이름은 한 번만 사용하세요:
$ sbx mcp add acme --url https://mcp.acme.com/mcp \
--header 'Authorization: Bearer ***' \
--header 'Accept: application/json, text/event-stream'
$ sbx secret set mcp:acme:api-key
예시 URL을 여러분의 MCP 엔드포인트로 바꾸세요. sbx secret set 명령은 API 키를 묻고 이를 호스트 자격 증명 저장소에 저장해요. ${api-key} 플레이스홀더는 등록에 남아 있어요. 샌드박스가 연결하면 게이트웨이가 비밀을 읽고 헤더에 그 값을 대입해요. 셸이 플레이스홀더를 보존하도록 헤더 값 주위에 작은따옴표를 사용하세요. 플레이스홀더는 환경 변수가 아니라 저장된 비밀을 이름 짓는 것이에요: ${api-key}는 셸 환경과 무관하게 mcp:acme:api-key를 읽어요.
각 플레이스홀더를 sbx secret set mcp:<server>:<placeholder>로 저장하세요. Authorization 같은 자격 증명 헤더는 비밀 플레이스홀더를 사용해야 해요. 명시적 Authorization 헤더는 OAuth 액세스 토큰보다 우선해요.
비밀을 저장한 후 서버를 샌드박스에 노출하세요:
$ sbx run claude --name acme-demo --static-mcp acme
사용자 정의 헤더는 원격 HTTP 엔드포인트가 필요하고 --command나 --local과는 쓸 수 없어요. 또한 호스트가 서버에 연결해야 해요. 호스팅 게이트웨이는 호스트를 통해 연결을 라우팅하는 --oauth-authorization-server를 제공하지 않으면 이러한 등록을 거부해요.
헤더 비밀 관리
헤더 비밀은 호스트의 전역 스코프를 사용해요. --sandbox 없이 sbx secret set mcp:<server>:<placeholder>로 설정하세요. 헤더 비밀은 저장된 값이 필요하며 --ref나 --command 동적 소스를 지원하지 않아요. 헤더 템플릿과 비밀이 설정되었는지 확인하려면 sbx mcp inspect acme를 실행하세요. 이 명령은 해석된 비밀 값을 표시하지 않아요.
비밀 저장소에는 자동 관리되는 :endpoint 기록(예: mcp:acme:api-key:...)도 포함돼 있어요. 이 메타데이터는 비밀을 등록된 서버의 URL에 바인딩해 게이트웨이가 비밀을 보내기 전에 엔드포인트 변경을 감지할 수 있게 해줘요. 이 기록을 직접 설정할 필요는 없어요. 서버의 엔드포인트를 바꾸면 CLI 안내에 따라 해당 엔드포인트에 대한 비밀을 다시 설정하세요.
헤더 비밀을 회전하려면 같은 이름으로 sbx secret set을 실행하세요. 헤더 비밀을 설정, 변경, 제거한 후에는 샌드박스를 중지하고 다시 시작하거나 sandboxd를 다시 시작해야 기존 게이트웨이에 변경이 적용돼요. 기존 연결은 이전 값을 유지하고, 비밀 누락으로 건너뛴 서버는 자동으로 재시도되지 않아요.
sbx mcp rm으로 등록을 제거하면 헤더 비밀은 유지되고 제거 명령이 출력돼요. 예시 비밀을 제거하려면:
$ sbx secret rm mcp:acme:api-key
로컬 stdio 서버
일부 MCP 서버는 원격 HTTP 엔드포인트를 노출하는 대신 stdio로 통신해요. sbx가 호스트에서 MCP 서버를 시작해야 할 때 로컬 stdio 서버를 사용하세요. 메타데이터 URL이나 명시적 명령을 제공할 수 있어요.
레지스트리 또는 매니페스트 메타데이터에서
MCP 커뮤니티 레지스트리 URL이나 server.json 또는 server.yaml 문서를 반환하는 URL이 있을 때 --local --url을 사용하세요. 레지스트리 항목이나 매니페스트는 stdio 전송을 사용하는 OCI 패키지를 설명해야 해요. sbx는 npm 같은 비-OCI 패키지 타입을 메타데이터에서 시작하지 않아요. 그런 서버를 사용하려면 명시적 명령을 등록하세요.
이 경로는 메타데이터에서 이미지를 해석해 호스트에서 Docker로 시작하므로, 호스트에 Docker가 설치되고 실행 중이어야 해요.
$ sbx mcp add fetch --local \
--url https://registry.modelcontextprotocol.io/v0/servers/fetch-mcp/versions/latest
항목이 OCI stdio 패키지를 게시하지 않으면 sbx는 로컬로 시작하는 대신 등록을 거부해요.
서버 매니페스트는 MCP 서버 패키지와 시작 방법을 설명해요. GitHub raw URL, 내부 HTTP 서버, 또는 CDN에 호스팅될 수 있어요.
$ sbx mcp add opine --local --url https://example.com/mcp/opine/server.yaml
명시적 명령에서
실행 파일과 인자를 이미 알고 있거나 사용자 정의 Docker 플래그가 필요할 때 --command를 사용하세요. 명령은 npx 같은 패키지 러너나 Docker 컨테이너 명령일 수 있어요:
$ sbx mcp add playwright --command npx --args @playwright/mcp@latest
$ sbx mcp add local-image-server --command docker \
--args "run,-i,--rm,your/image"
호스트 프로세스의 작업 디렉터리를 설정하려면 --dir을 전달하세요. 이 플래그는 --command에서만 유효해요:
$ sbx mcp add local-fs --command node --args server.js --dir /srv/data
게시된 서버 정의가 있고 docker run을 사용자 정의할 필요가 없으면 레지스트리 또는 매니페스트 메타데이터를 사용하세요. 로컬 개발, 사설 서버, 또는 사용자 정의 컨테이너 플래그에는 --command를 사용하세요.
[!WARNING] 로컬 stdio 서버는 샌드박스 격리 밖인 호스트에서 실행돼요. 명령이 Docker 컨테이너를 시작하면 그 컨테이너는 샌드박스 격리가 아니라 호스트 Docker 격리를 사용해요. 그 프로세스나 컨테이너는 호스트 파일, 호스트 네트워크 리소스, 제공된 자격 증명에 접근할 수 있어요. 신뢰하는 명령과 이미지를 사용하고, 서버가 필요하지 않으면 호스트 경로 마운트나 자격 증명 전달을 피하세요.
OAuth 기반 서버 인증 (Authorize OAuth-backed servers)
등록된 원격 서버가 OAuth를 요구하면 sbx mcp add가 기본적으로 인증 흐름을 시작해요:
$ sbx mcp add notion --url https://mcp.notion.com/mcp
Resolving MCP server "notion"...
Open this URL to authorize MCP server "notion":
https://api.notion.com/v1/oauth/authorize?...
MCP server "notion" authorized
MCP server "notion" registered (type: remote)
OAuth 자격 증명은 호스트에 남아 있어요. 로컬 게이트웨이 모드에서는 sbx가 토큰을 호스트 OS의 자격 증명 저장소에 저장해요.
OAuth 기반 서버를 인증 없이 등록하려면 --skip-auth를 전달하세요:
$ sbx mcp add notion --url https://mcp.notion.com/mcp --skip-auth
사전 등록된 OAuth 클라이언트 사용
로컬 게이트웨이 모드에서 Dynamic Client Registration을 지원하지 않는 원격 OAuth 서버를 등록할 수 있어요. 서버가 OAuth 메타데이터를 게시하면 서버 제공자에게 등록한 클라이언트 ID를 전달하세요:
$ sbx mcp add slack --url https://slack.example.com/mcp \
--client-id <CLIENT_ID>
서버가 OAuth 메타데이터를 게시하지 않으면 --oauth-authorization-server와 함께 클라이언트 ID를 전달하세요. 이 플래그는 RFC 8414 인증 서버 메타데이터 문서에 대한 로컬 파일 경로 또는 HTTP/HTTPS URL을 받아요. 문서는 authorization_endpoint와 token_endpoint를 정의해야 해요:
$ sbx mcp add serverx --url https://mcp.serverx.example/mcp \
--oauth-authorization-server ./serverx-authorization-server.json \
--client-id <CLIENT_ID>
이 플래그들은 --url에서만 유효해요.
기밀(confidential) OAuth 클라이언트의 경우 서버를 등록하기 전에 클라이언트 비밀을 저장하세요. --client-secret 플래그는 없어요:
$ sbx secret set mcp:slack:client_secret
$ sbx mcp add slack --url https://slack.example.com/mcp \
--client-id <CLIENT_ID>
클라이언트 비밀은 호스트 자격 증명 저장소에 남고 MCP 등록에 기록되지 않아요. 서버가 기밀 클라이언트를 요구하고 비밀이 저장되지 않으면 등록은 성공하지만 인증은 건너뜁니다. 비밀을 저장한 다음 sbx mcp auth <server>를 실행하세요.
MCP OAuth 클라이언트 비밀은 mcp:<server>:client_secret 이름을 사용해요. 저장소는 비밀을 OAuth 클라이언트에 바인딩하는 mcp:<server>:client_secret:identity 기록도 유지해요. mcp:<server>.client_secret을 사용한 버전이 저장한 비밀은 콜론으로 구분된 이름으로 다시 설정하세요.
OAuth 스코프 설정
반복 가능한 --scope 플래그로 인증 중 요청되는 기본 스코프를 기록할 수 있어요:
$ sbx mcp add serverx --url https://mcp.serverx.example/mcp \
--scope read --scope write
sbx mcp auth 명령은 --scope를 받아 한 번의 인증에 대해 기록된 기본값을 덮어쓸 수 있어요:
$ sbx mcp auth serverx --scope read
--no-scope를 전달하지 않으면 sbx는 다음 순서로 첫 번째 사용 가능한 스코프 집합을 요청해요:
sbx mcp auth --scope에 전달된 스코프sbx mcp add --scope가 기록한 기본 스코프- 보호된 리소스가 요구한다고 말하는 스코프
- 인증 서버가 광고하는
openid,email,profile,offline_access중 하나
이 중 어느 것도 스코프 집합을 제공하지 않으면 sbx는 OAuth scope 파라미터를 생략해 인증 서버가 기본 허가를 적용하게 해요. 다른 광고된 스코프는 폴백에 포함되지 않아요.
--no-scope를 전달하면 한 번의 인증에 대해 기록된 기본값, 리소스 필수 스코프, 광고된 스코프 폴백을 막고 저장된 기본값은 변경하지 않아요:
$ sbx mcp auth serverx --no-scope
--no-scope는 --scope와 함께 쓸 수 없어요. 선택한 스코프는 인증 서버의 광고된 스코프와 리소스의 필수 스코프에 대해 검사돼요. 두 소스 중 하나라도 스코프를 게시하면, 어느 쪽에도 없는 스코프는 경고가 나오지만 여전히 요청돼요. 인증 서버는 특정 클라이언트에 대해 광고된 스코프를 여전히 거부할 수 있어요. 스코프를 요청한 로컬 인증 흐름의 경우 sbx는 요청된, 광고된, 거부된 스코프를 나열하고 재시도 명령을 제안해요. 서버가 거부된 스코프를 식별하면 명령이 그것들을 제거해요. 그렇지 않으면 --no-scope를 사용해요. sbx는 절대 자동으로 재시도하지 않아요.
샌드박스에 노출된 각 OAuth 기반 원격 서버에 대해 게이트웨이는 <server>-authorize(예: notion-authorize)라는 헬퍼 도구를 노출해요. 에이전트가 이 도구를 호출해 서버를 인증하거나 재인증할 수 있어요. 서버가 인증되지 않으면 그 서버에 대해 노출된 유일한 도구가 이 헬퍼예요.
호스트에서 OAuth 자격 증명을 관리할 수 있어요:
$ sbx mcp auth status notion
$ sbx mcp auth notion
$ sbx mcp auth rm notion
--all로 등록된 모든 OAuth 기반 서버에 auth, auth status, auth rm을 적용할 수 있어요. auth status 출력은 인증 서버가 부여한 스코프, sbx mcp add --scope로 기록된 기본값, 서버가 지원하는 스코프를 보고해요. 중복 스코프 이름을 합치고, 요청되지 않았거나 더 이상 지원 집합에 없는 부여된 스코프를 강조해요. 머신이 읽을 수 있는 출력은 --json을 사용하세요:
$ sbx mcp auth status notion --json
MCP 모드 선택 (Choose an MCP mode)
모든 샌드박스는 MCP 게이트웨이를 시작해요. 샌드박스가 시작되면 지원되는 에이전트 통합이 게이트웨이 URL을 읽고 에이전트에 등록해요.
샌드박스를 만들 때 --static-mcp를 전달하는지가 그 MCP 모드를 결정해요:
- 정적 모드는 지정된 서버를 미리 로드하고 에이전트에 동적 탐색 도구를 노출하지 않아요.
- 동적 모드는 서버를 미리 로드하지 않고 에이전트가 등록된 서버를 찾아 붙일 수 있게 해요.
이 선택은 샌드박스 재시작에도 유지돼요.
정적 모드 사용
--static-mcp를 전달해 등록된 MCP 서버를 미리 로드하세요:
$ sbx mcp add notion --url https://mcp.notion.com/mcp
$ sbx mcp add linear --url https://mcp.linear.app/mcp
$ sbx run claude --name my-session --static-mcp notion,linear
--static-mcp는 쉼표로 구분된 목록으로 전달하거나 플래그를 반복할 수 있어요:
$ sbx run claude --name my-session \
--static-mcp notion --static-mcp linear
정적 집합의 모든 이름은 sbx mcp add로 이미 등록되어야 해요. 게이트웨이는 에이전트에 mcp-find, mcp-add, mcp-config-set을 노출하지 않아요.
기존 샌드박스에 재연결할 때 --static-mcp를 전달해 초기 집합을 바꿀 수 없어요. 호스트에서 다른 서버를 붙이려면 sbx mcp load를 사용하세요.
동적 모드 사용
동적 모드를 사용하려면 --static-mcp를 생략하세요. 게이트웨이는 서버를 미리 로드하지 않고 에이전트에 mcp-find, mcp-add, mcp-config-set을 노출해요. 에이전트는 등록된 서버 카탈로그를 검색하고 세션 중 서버를 붙일 수 있어요.
동적 샌드박스가 시작된 후 sbx mcp add를 실행하면 게이트웨이가 검색 가능한 카탈로그를 갱신해요. 에이전트는 재시작 없이 새 등록을 찾아 붙일 수 있어요. sbx mcp add 명령은 서버를 자체적으로 붙이지 않아요.
실행 중인 샌드박스에 서버 추가 (Add a server to a running sandbox)
이미 등록된 서버를 실행 중인 샌드박스에 붙이려면 sbx mcp load를 사용하세요. 이는 정적 및 동적 모드 모두에서 동작해요:
$ sbx mcp add linear --url https://mcp.linear.app/mcp
$ sbx mcp load linear --sandbox my-session
MCP server "linear" loaded into sandbox "my-session" (live)
연결된 에이전트 세션은 도구 목록 업데이트를 받으므로, 추가된 도구가 재연결 없이 보여요. 로드된 서버는 샌드박스 재시작에도 붙어 있어요.
내장 게이트웨이 도구 (Built-in gateway tools)
로컬 MCP 게이트웨이는 소수의 내장 도구를 노출해요. 이 도구들은 등록된 MCP 서버가 아니라 게이트웨이 자체에 속해요. 에이전트가 서버 도구와 같은 MCP 연결에서 이들을 보고 호출할 수 있으므로, 에이전트 도구 목록, 로그, 정책 결정, 감사 로그, 승인 프롬프트에 나타날 수 있어요.
정상 설정에 이 도구들을 직접 호출할 필요는 없어요. 호스트에서 서버를 등록하고 자격 증명을 관리하려면 sbx mcp 명령을 사용하세요. 이 도구들이 중요한 이유는 에이전트가 세션 중 호출할 수 있고, 관리자가 등록된 MCP 서버가 제공하는 도구와 별도로 통제할 수 있기 때문이에요.
| 도구 | 설명 |
|---|---|
mcp-exec |
게이트웨이를 통해 이름으로 도구를 실행. |
code-mode |
게이트웨이를 통해 선택한 도구를 호출할 수 있는 일시적 JavaScript 도구를 생성. |
mcp-find |
샌드박스 상태를 바꾸지 않고 등록된 서버 카탈로그를 검색. 동적 모드 전용. |
mcp-add |
등록된 서버를 샌드박스에 붙임. 동적 모드 전용. |
mcp-config-set |
붙은 서버에 세션별 구성 오버라이드를 설정. 동적 모드 전용. |
<server>-authorize |
노출된 OAuth 기반 원격 서버에 대한 OAuth 인증을 시작하거나 재시작. |
mcp-add로 붙은 서버는 샌드박스 재시작에도 붙어 있어요. 게이트웨이는 이미 유효한 토큰이 있더라도 OAuth 기반 원격 서버에 <server>-authorize를 노출해요. 로컬 stdio 서버는 이 헬퍼를 노출하지 않아요. code-mode가 생성된 도구를 만들면 그 도구는 샌드박스의 게이트웨이에 연결된 클라이언트가 공유하고, 게이트웨이가 교체되거나 중지되면 사라져요.
MCP 접근 정책에서 내장 게이트웨이 도구는 MCP::Primordial 리소스이고 invokePrimordial 액션을 사용해요. 등록된 MCP 서버의 도구는 MCP::Tool 리소스이고 invokeTool 액션을 사용해요. 자세한 내용은 MCP 정책 참조를 참고하세요.
등록 관리 (Manage registrations)
등록된 서버 나열:
$ sbx mcp ls
등록된 서버 조사:
$ sbx mcp inspect notion
등록된 서버 제거:
$ sbx mcp rm notion
OAuth 기반 서버의 경우 sbx mcp rm은 서버 등록을 제거하기 전에 OAuth 액세스 토큰을 제거해요. 사전 등록된 OAuth 클라이언트의 클라이언트 비밀과 그 identity 바인딩은 호스트 자격 증명 저장소에 남아, 같은 클라이언트를 다시 추가할 때 재사용할 수 있어요. 명령은 이를 제거하는 sbx secret rm 명령을 출력해요. OAuth 액세스 토큰만 제거하려면 sbx mcp auth rm을 사용하세요.
거버넌스 (Governance)
AI Governance가 있는 조직은 MCP 접근 정책으로 MCP 서버 등록, 도구 호출, 게이트웨이 메타 도구, 리소스, 프롬프트, 승인 요구 사항을 제어할 수 있어요. MCP 접근 정책은 Cedar로 작성된 organization 정책이에요.