For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme
개요 ChatGPT 및 Codex 사용자 문서 활용 사례

MCP 서버 구축하기

플러그인에 실시간 데이터와 실행 범위를 제어할 수 있는 도구를 추가하세요.

플러그인 사용 사례에 실시간 데이터, 인증, 실행 범위를 제어해야 하는 작업 또는 직접 운영하는 인프라에서 실행할 코드가 필요하면 MCP 서버를 추가하세요. 서버는 ChatGPT와 Codex에서 사용할 수 있는 도구를 정의합니다. 커스텀 UI를 반환할 필요는 없습니다.

먼저 사용 사례 목록에서 플러그인이 지원할 사용자 목표를 확인하세요. 각 도구는 사용자가 달성하려는 구체적인 목표에 도움이 되어야 하며, 그 목표에 필요한 데이터와 작업만 제공해야 합니다.

도구부터 만드세요. 커스텀 UI 없이 서버가 정상적으로 작동하면 시각적 상호작용이 필요한 워크플로우를 위해 MCP 서버에 UI를 추가할 수 있습니다.

MCP 소프트웨어 개발 키트 선택하기

공식 소프트웨어 개발 키트는 스키마 헬퍼, 서버의 기본 구조, 스트리밍을 지원하는 HTTP 전송 방식을 제공합니다.

  • TypeScript SDK는 @modelcontextprotocol/sdk 패키지로 배포됩니다.
  • Python SDK는 mcp 패키지로 배포됩니다.

서버 기술 스택에 맞는 SDK를 설치하세요.

# TypeScript
npm install @modelcontextprotocol/sdk zod

# Python
pip install mcp

서버 만들기

고정된 이름과 버전을 지정해 MCP 서버를 만드세요.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

const server = new McpServer({
  name: "acme-projects",
  version: "1.0.0",
});

MCP 서버는 초기화할 때 instructions 필드도 반환할 수 있습니다. ChatGPT와 Codex는 이 지침을 도구 메타데이터와 함께 사용합니다.

필수 도구 호출 순서나 공유 요청 한도처럼 여러 도구에 공통으로 적용되는 내용은 서버 지침에 작성하세요. 가장 중요한 내용은 첫 512자 안에 담으세요. 모든 도구의 설명을 되풀이하거나 모델의 성격을 바꾸려 하지 마세요.

const server = new McpServer(
  { name: "acme-projects", version: "1.0.0" },
  {
    instructions:
      "Before updating a project, call get_project to confirm its ID and current status.",
  }
);

사용자 목표에 맞춰 도구 정의하기

플러그인이 지원해야 하는 작업마다 도구를 하나씩 만드세요. 서로 관련 없는 여러 모드를 한 도구에 넣기보다 list_projects, get_project, update_project처럼 각 도구가 한 가지 작업에 집중하도록 하세요.

각 도구에는 다음 요소가 필요합니다.

  • 수행할 작업이 드러나는 이름과 사람이 이해하기 쉬운 제목
  • 언제 도구를 사용해야 하는지 알려 주는 설명
  • 명시적인 입력 스키마
  • 도구가 구조화된 데이터를 반환하는 경우 출력 스키마
  • 실제 동작을 정확히 반영하는 안전 관련 어노테이션
  • 요청에 필요한 권한을 확인하고 작업을 수행하는 핸들러

모델은 이 메타데이터를 바탕으로 도구를 호출할지, 어떻게 호출할지 결정합니다. 이름, 설명, 스키마, 어노테이션을 사용자가 경험하는 플러그인 동작의 일부로 다루세요.

// Local example data; replace this with your application data.
const projects = [
  { id: "project-1", name: "Website", status: "active" },
  { id: "project-2", name: "Launch", status: "archived" },
];
async function listProjects({ status }: { status?: string }) {
  return projects.filter((project) => !status || project.status === status);
}

import { z } from "zod";

server.registerTool(
  "list_projects",
  {
    title: "List projects",
    description:
      "Use this when the user wants to find or review projects in their Acme workspace.",
    inputSchema: {
      status: z.enum(["active", "archived"]).optional(),
    },
    outputSchema: {
      projects: z.array(
        z.object({
          id: z.string(),
          name: z.string(),
          status: z.string(),
        })
      ),
    },
    annotations: {
      readOnlyHint: true,
      openWorldHint: false,
      destructiveHint: false,
    },
  },
  async ({ status }) => {
    const projects = await listProjects({ status });

    return {
      structuredContent: { projects },
      content: [
        {
          type: "text",
          text: `Found ${projects.length} projects.`,
        },
      ],
    };
  }
);

UI 없이 유용한 결과 반환하기

도구 결과에는 다음 항목을 포함할 수 있습니다.

  • structuredContent: 모델이 확인하고 이후 호출에서 활용할 수 있는 간결한 데이터
  • content: 모델이 사용자에게 답하는 데 도움이 되는 텍스트 또는 기타 MCP 콘텐츠
  • _meta: 모델에 표시되지 않는 클라이언트별 데이터

모델이 컴포넌트 없이 워크플로우를 완료할 수 있도록 충분한 정보를 반환하세요. 이후에 호출하는 도구가 같은 레코드를 참조할 수 있도록 구조화된 결과에 고정된 식별자를 사용하세요.

도구 결과에 시크릿, 액세스 토큰 또는 불필요한 개인 데이터를 넣지 마세요. _meta의 내용은 모델에 표시되지 않지만, 이 필드가 권한 검사나 안전한 저장소를 대신할 수는 없습니다.

요청 인증 및 권한 검사하기

도구가 비공개 데이터를 읽거나 사용자를 대신해 작업을 수행한다면 인증을 추가하세요. MCP 서버에서 모든 요청의 권한을 검사하세요. 사용자에게 접근 권한이 있는지 판단하는 일을 모델에 맡기지 마세요.

OAuth 검색, 보안 스킴, 인가 챌린지에 대해서는 사용자 인증하기를 참고하세요.

사용자가 여러 계정을 더 편리하게 사용할 수 있도록 인증이 필요한 읽기 전용 프로필 도구를 제공하고 _meta["openai/profile"]: true로 표시하세요. OpenAI는 프로필 정보를 사용해 연결된 계정을 일관된 방식으로 식별하고 사용자가 계정을 구분할 수 있도록 돕습니다. 요청의 검증된 자격 증명으로 프로필을 조회하고, 모든 도구 호출을 해당 자격 증명이 허용하는 범위로 제한하세요. 프로필 도구가 없어도 사용자는 여러 계정을 연결할 수 있습니다. 스키마와 구현 예시는 여러 계정 지원하기를 참고하세요.

도구 어노테이션과 입력 유도

도구의 실제 동작에 맞게 어노테이션을 설정하세요.

  • readOnlyHint: 도구가 상태를 변경할 수 없을 때만 true로 설정하세요.
  • destructiveHint: 도구가 되돌릴 수 없거나 되돌리기 어려운 결과를 초래할 수 있다면 true로 설정하세요.
  • openWorldHint: 도구가 공개 인터넷에 접근하거나 접근할 외부 대상의 범위가 정해져 있지 않다면 true로 설정하세요. 웹 검색 같은 읽기 전용 작업도 여기에 해당합니다. 접근 범위가 특정 비공개 계정이나 워크스페이스로 한정된 도구는 해당 서비스가 외부에서 호스팅되더라도 false로 설정할 수 있습니다.

ChatGPT와 Codex는 어노테이션을 참고해 적절한 확인 절차와 안전 조치를 선택합니다. 서버에서는 별도로 권한 검사, 유효성 검사, 확인 절차를 수행해야 합니다.

서버에 필요한 구조화된 정보가 원래 도구 호출에 포함되지 않았다면 MCP의 입력 유도 기능을 사용하세요. 사용자가 무리 없이 제공할 수 있는 정보만 요청하세요. 시크릿을 수집하거나 일반적인 인증 절차를 우회하는 데 이 기능을 사용하지 마세요.

회사 지식과의 호환성

회사 지식 기능은 MCP 서버의 읽기 전용 도구를 사용할 수 있습니다. 플러그인을 회사 지식의 정보 소스로 사용할 수 있도록 표준 search 및 fetch 도구의 입력 스키마를 구현하고, 다른 읽기 전용 도구에는 readOnlyHint: true를 설정하세요.

모델이 인용해야 하는 출처에는 사용자가 열 수 있는 절대 URL을 반환하세요. 내부 문서 식별자는 결과의 id 필드에 넣으세요. 필수 스키마와 결과 형식은 ChatGPT 및 API 연동용 MCP 서버 구축하기를 참고하세요.

로컬에서 실행하고 테스트하기

스트리밍을 지원하는 HTTP 엔드포인트를 제공하세요. 일반적으로 /mcp 경로를 사용합니다. 그런 다음 MCP Inspector로 엔드포인트를 점검하세요.

npx @modelcontextprotocol/inspector

Inspector UI에서 Streamable HTTP를 선택하고 http://localhost:3000/mcp를 입력하세요.

Inspector로 다음 사항을 점검하세요.

  1. 초기화가 성공하는지 확인하세요.
  2. 서버 지침과 서버가 제공하는 도구 목록을 검토하세요.
  3. 대표적인 입력값과 유효하지 않은 입력값으로 각 도구를 호출하세요.
  4. 스키마, 결과, 오류, 어노테이션을 확인하세요.
  5. 비공개 데이터에 접근하거나 쓰기 작업을 수행할 때 권한 검사가 적용되는지 확인하세요.

그런 다음 커스텀 MCP 서버를 ChatGPT에 연결하고 사용 사례 목록에 있는 직접 요청, 간접 요청, 경계 사례에 해당하는 요청, 지원 범위를 벗어나는 요청을 실행하세요.

엔드포인트 배포하기

플러그인을 공개 제출하려면 외부에서 접근할 수 있는 고정 HTTPS 엔드포인트에 MCP 서버를 배포하세요. Secure MCP Tunnel을 사용하면 ChatGPT에서 비공개 MCP 서버에 연결할 수 있지만, 이 방식은 공개 제출 요건을 충족하지 않습니다.

프로덕션 엔드포인트는 다음 요건을 충족해야 합니다.

  • 스트리밍을 지원하는 MCP의 HTTP 전송 방식을 사용할 수 있어야 합니다.
  • 고정 URL에서 요청에 응답해야 합니다. 일반적으로 URL은 /mcp로 끝납니다.
  • 플러그인 워크플로우에 필요한 지연 시간과 가용성 요건을 충족해야 합니다.
  • 필요한 서비스와 데이터 저장소에 접근할 수 있어야 합니다.
  • 인증 및 권한 경계를 유지해야 합니다.
  • 초기화나 도구 호출이 실패하면 로그와 메트릭을 생성해야 합니다.

MCP 서버를 비공개로 유지해야 한다면 MCP 요청을 비공개 서버로 전달하는 공개 HTTPS 프록시를 배포하세요. OpenAI 관리형 mTLS로 ChatGPT를 MCP 클라이언트로 인증하고, 플러그인에 사용자 인증이 필요하면 OAuth 2.1을 사용하세요. 네트워크에서 IP 허용 목록을 요구한다면 공개된 ChatGPT 커넥터 IP 범위를 사용하고 허용 목록을 자동으로 업데이트하세요. IP 허용 목록은 인증이나 권한 검사를 대신할 수 없습니다.

플러그인 심사와 도메인 확인을 위해 공개 엔드포인트에 계속 접근할 수 있어야 합니다. 공개 제출 시에는 Secure MCP Tunnel을 단독으로 사용하거나 임시 터널 또는 로컬 엔드포인트를 사용하지 마세요.

인프라 선택하기

MCP 서버는 서버리스, 컨테이너, 엣지 또는 기존 애플리케이션 인프라에 배포할 수 있습니다. 다음 사항을 고려해 플랫폼을 선택하세요.

  • 런타임 및 종속성 지원 여부
  • 스트리밍 응답 처리 방식
  • 콜드 스타트 및 요청 지연 시간
  • 필요한 서비스에 대한 네트워크 접근 가능 여부
  • 데이터 레지던시 및 규정 준수 요건
  • 시크릿 관리
  • 로깅, 추적, 알림
  • 롤백 및 버전 관리 지원 여부

서버에서 선택적 UI 자산도 호스팅한다면 컴포넌트의 콘텐츠 보안 정책이 허용하는 고정 오리진에 해당 자산을 배포하세요.

프로덕션 엔드포인트 설정하기

배포 전에 다음 작업을 수행하세요.

  1. 호스트의 시크릿 관리 시스템에서 프로덕션 자격 증명을 설정하세요.
  2. 인가 서버를 설정하고 허용할 리디렉션 동작을 구성하세요.
  3. 실행 비용이 높거나 실행 결과가 외부에 드러나는 도구에 시간 제한과 요청 한도를 적용하세요.
  4. 디버그용 응답과 불필요한 개인 데이터를 제거하세요.
  5. 로그에 액세스 토큰이나 민감한 도구 결과가 포함되지 않는지 확인하세요.

배포 후에는 MCP Inspector로 프로덕션 엔드포인트를 호출하세요. 초기화, 서버 지침, 도구, 스키마, 어노테이션, 인증, 결과, 오류를 확인하세요.

업데이트 계획하기

이미 공개한 도구의 이름과 스키마는 하위 호환성을 유지하세요. 필드나 도구를 추가할 때는 기존 인터페이스 규약을 지키세요. 메타데이터가 변경되면 제출하기 전에 커스텀 MCP 서버 연결을 새로 고치고 평가 세트를 다시 실행하세요.

선택적 UI를 제공하는 경우 HTML, JavaScript 또는 CSS 변경으로 캐시된 컴포넌트가 제대로 작동하지 않을 수 있다면 리소스 식별자에 버전을 부여하세요.

MCP 확장 프로그램 추가하기

OpenAI MCP 확장 프로그램을 사용하면 플러그인을 ChatGPT의 사이드바, 메시지 입력창, 파일 뷰어와 연결할 수 있습니다. 예시와 설정 방법은 플러그인 확장 프로그램을 참고하세요.

보안 유의 사항

  • 모든 도구 입력은 신뢰할 수 없는 값으로 취급하세요.
  • 서버에서 매개변수의 유효성을 검사하고 권한 검사를 적용하세요.
  • 중요한 영향을 미치는 쓰기 작업에는 사용자 확인을 요구하세요.
  • 도구 메타데이터와 결과에 시크릿이나 민감한 데이터를 포함하지 마세요.
  • 실패 원인을 조사하는 데 필요한 컨텍스트를 로그에 남기되, 자격 증명이나 불필요한 개인 데이터는 기록하지 마세요.
  • 실행 비용이 높거나 실행 결과가 외부에 드러나는 작업에는 요청 한도를 적용하세요.