샌드박스에 MCP 게이트웨이 부여하기

샌드박스에 MCP 게이트웨이 부여하기

MCP(Model Context Protocol)를 통해 에이전트에 외부 도구 접근을 부여해 봐요. 게이트웨이는 여러 도구 서버를 하나의 엔드포인트로 제공해요.

출처: 문서

본문

인증된 클라이언트와 계정에서 사용 가능한 서버 ID가 필요해요. Docker MCP 카탈로그에서 서버를 선택하고, 애플리케이션이 만든 표시 이름이 아니라 그 카탈로그 ID를 사용하세요. 제공자 로그인과 각 도구 사용 권한이 필요할 수 있어요.

키트 실행 시 MCP 구성

샌드박스를 만들 때 키트의 MCP 옵션에 서버 ID를 제공하세요. 이렇게 하면 에이전트가 시작할 때 게이트웨이 구성이 준비돼요. 에이전트가 필요로 하는 모델 제공자 시크릿은 별도로 첨부하세요.

기존 샌드박스에 게이트웨이를 추가하려면 MCP가 구성된 상태로 샌드박스를 다시 만드세요. 별도의 게이트웨이 시작이나 중지 연산은 없어요.

핵심 코드:

const sandbox = await client.kits.launch(
  kitName,
  {
    resources: { cpus: 2, memoryMib: 4096 },
    mcp: { servers, static: true },
    storage: { secrets },
  },
  { timeoutMs: 300_000 },
);
return sandbox.waitUntilRunning();

완전한 TypeScript 예시: mcp/create.ts

import type { Sandboxes } from '@docker/sandboxes';

export async function launchMcpKit(
  client: Sandboxes,
  kitName: string,
  servers: string[],
  secrets: string[] = [],
) {
  const sandbox = await client.kits.launch(
    kitName,
    {
      resources: { cpus: 2, memoryMib: 4096 },
      mcp: { servers, static: true },
      storage: { secrets },
    },
    { timeoutMs: 300_000 },
  );
  return sandbox.waitUntilRunning();
}

게이트웨이 주소 읽기

sandboxes/{sandbox}/mcp-gateway 이름으로 게이트웨이를 읽어요. 예시는 SDK의 경계 있는 대기자(bounded waiter)로 프로비저닝을 통과하며 기다리고, 준비되었을 때만 URL을 반환해요. 실패한 게이트웨이나 만료된 대기는 오류를 반환해요. 애플리케이션에 적합한 타임아웃을 제공하세요.

게이트웨이 자격 증명을 비밀로 유지하세요. 게이트웨이의 주소와 샌드박스 안의 애플리케이션이 게시한 URL은 다른 엔드포인트예요.

핵심 코드:

const deadline = AbortSignal.timeout(options.timeoutMs);
const signal = options.signal
  ? AbortSignal.any([options.signal, deadline])
  : deadline;
options = { ...options, signal };
const observed = await client.getMcpGateway({ name }, options);
const gateway = await client
  .mcpGateway(observed)
  .waitFor(['ready', 'failed'], options);
if (gateway.state !== 'ready')
  throw new Error('MCP gateway is not ready');
if (!gateway.url) throw new Error('The ready MCP gateway has no URL');
return gateway.url;

완전한 TypeScript 예시: mcp/read.ts

import type { Sandboxes, WaitOptions } from '@docker/sandboxes';

export async function readGatewayUrl(
  client: Sandboxes,
  name: string,
  options: WaitOptions = { timeoutMs: 120_000 },
) {
  const deadline = AbortSignal.timeout(options.timeoutMs);
  const signal = options.signal
    ? AbortSignal.any([options.signal, deadline])
    : deadline;
  options = { ...options, signal };
  const observed = await client.getMcpGateway({ name }, options);
  const gateway = await client
    .mcpGateway(observed)
    .waitFor(['ready', 'failed'], options);
  if (gateway.state !== 'ready')
    throw new Error('MCP gateway is not ready');
  if (!gateway.url) throw new Error('The ready MCP gateway has no URL');
  return gateway.url;
}

카탈로그 서버 추가

준비되고 쓰기 가능한 게이트웨이에 서버를 추가해요. 이미 있는 서버를 추가해도 두 번째 복사본이 생기지 않아요. URL로 첨부된 공유 게이트웨이는 이 샌드박스를 통해 수정할 수 없어요.

핵심 코드:

await sandbox.mcp.servers.add({ server });

완전한 TypeScript 예시: mcp/add.ts

import type { Sandboxes } from '@docker/sandboxes';

export async function addMcpGatewayServer(
  client: Sandboxes,
  name: string,
  server: string,
) {
  const sandbox = await client.get(name.replace(/\/mcp-gateway$/, ''));
  await sandbox.mcp.servers.add({ server });
}

서버의 로그인 완료

사용자 로그인이 필요한 서버의 인증을 시작해요. 인증 URL을 사용자에게 보여주고, 인증 리소스를 읽어 진행 상황을 확인해요. 예시는 시작과 읽기 호출을 수행해요. 흐름을 어떻게 표시하고 폴링할지는 애플리케이션이 결정해요.

권한이 부여된 결과일 때만 자격 증명이 준비된 거예요. 나중의 시도가 이전 것의 완료로 오인되지 않도록 인증 정체성을 보관하세요. 새 로그인을 의도할 때만 재인증을 요청하세요.

더 이상 필요 없을 때 샌드박스를 삭제하세요. 그 관리되는 게이트웨이도 함께 정리돼요. URL로 첨부된 공유 게이트웨이는 다른 사용자에게 계속 사용 가능해요.

핵심 코드:

return client.mcp.authorizations.authorize({
  server: name,
  forceReauth,
});

완전한 TypeScript 예시: mcp/authorize.ts

import type { Sandboxes } from '@docker/sandboxes';

export async function authorizeMcpServer(
  client: Sandboxes,
  name: string,
  forceReauth: boolean,
) {
  return client.mcp.authorizations.authorize({
    server: name,
    forceReauth,
  });
}

export async function getMcpAuthorization(
  client: Sandboxes,
  name: string,
) {
  return client.mcp.authorizations.get(name);
}

더 알아보기 (Learn more)