모델 컨텍스트 프로토콜 (MCP)
The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide tools and context to LLMs. From the MCP docs:
MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.
이 SDK 가 지원하는 MCP 서버 유형은 세 가지입니다:
- 호스티드 MCP 서버 도구 – OpenAI Responses API가 도구로 사용하는 원격 MCP 서버
- Streamable HTTP MCP 서버 – Streamable HTTP transport를 구현한 로컬 또는 원격 서버
- Stdio MCP 서버 – 표준 입력/출력을 통해 접근하는 서버(가장 간단한 옵션)
참고: SDK 에는 레거시 Server‑Sent Events 전송을 위한
MCPServerSSE도 포함되어 있지만, SSE 는 MCP 프로젝트에서 더 이상 권장되지 않습니다. 새로운 통합에는 Streamable HTTP 또는 stdio 를 사용하세요.
사용 사례에 따라 서버 유형을 선택하세요:
| 필요한 것 | 권장 옵션 |
|---|---|
| 기본 OpenAI Responses 모델로 공개 원격 서버 호출 | 1. 호스티드 MCP 도구 |
| 공개 원격 서버 사용 + 로컬에서 도구 호출 트리거 | 2. Streamable HTTP |
| 로컬에서 실행 중인 Streamable HTTP 서버 사용 | 2. Streamable HTTP |
| OpenAI Responses 가 아닌 모델에서 Streamable HTTP 서버 사용 | 2. Streamable HTTP |
| 표준 I/O 프로토콜만 지원하는 로컬 MCP 서버 사용 | 3. Stdio |
1. 호스티드 MCP 서버 도구
섹션 제목: “1. 호스티드 MCP 서버 도구”호스티드 툴은 전체 라운드트립을 모델 내부에서 처리합니다. 애플리케이션 코드가 MCP 서버를 호출하는 대신 OpenAI Responses API 가 원격 도구 엔드포인트를 호출하고 결과를 모델로 스트리밍합니다.
다음은 호스티드 MCP 도구를 사용하는 가장 간단한 예시입니다. 원격 MCP 서버의 레이블과 URL 을 hostedMcpTool 유틸리티 함수에 전달하여 호스티드 MCP 서버 도구를 쉽게 생성할 수 있습니다.
import { Agent, hostedMcpTool } from '@openai/agents';
export const agent = new Agent({ name: 'MCP Assistant', instructions: 'You must always use the MCP tools to answer questions.', tools: [ hostedMcpTool({ serverLabel: 'gitmcp', serverUrl: 'https://gitmcp.io/openai/codex', }), ],});그런 다음 run 함수(또는 커스터마이즈한 Runner 인스턴스의 run 메서드)로 에이전트를 실행할 수 있습니다:
import { run } from '@openai/agents';import { agent } from './hostedAgent';
async function main() { const result = await run( agent, 'Which language is the repo I pointed in the MCP tool settings written in?', ); console.log(result.finalOutput);}
main().catch(console.error);증분 MCP 결과를 스트리밍하려면 Agent 를 실행할 때 stream: true 를 전달하세요:
import { run } from '@openai/agents';import { agent } from './hostedAgent';
async function main() { const result = await run( agent, 'Which language is the repo I pointed in the MCP tool settings written in?', { stream: true }, );
for await (const event of result) { if ( event.type === 'raw_model_stream_event' && event.data.type === 'model' && event.data.event.type !== 'response.mcp_call_arguments.delta' && event.data.event.type !== 'response.output_text.delta' ) { console.log(`Got event of type ${JSON.stringify(event.data)}`); } } console.log(`Done streaming; final result: ${result.finalOutput}`);}
main().catch(console.error);선택적 승인 플로우
섹션 제목: “선택적 승인 플로우”민감한 작업의 경우 개별 도구 호출에 대해 사람의 승인을 요구할 수 있습니다. requireApproval: 'always' 또는 도구 이름을 'never'/'always' 로 매핑하는 세분화된 객체를 전달하세요.
도구 호출의 안전성을 프로그램적으로 판단할 수 있다면 onApproval 콜백을 사용해 승인 또는 거부할 수 있습니다. 사람의 승인이 필요하다면 로컬 함수 도구에서와 동일하게 interruptions 를 사용하는 human-in-the-loop (HITL) approach를 적용할 수 있습니다.
import { Agent, run, hostedMcpTool, RunToolApprovalItem } from '@openai/agents';
async function main(): Promise<void> { const agent = new Agent({ name: 'MCP Assistant', instructions: 'You must always use the MCP tools to answer questions.', tools: [ hostedMcpTool({ serverLabel: 'gitmcp', serverUrl: 'https://gitmcp.io/openai/codex', // 'always' | 'never' | { never, always } requireApproval: { never: { toolNames: ['search_codex_code', 'fetch_codex_documentation'], }, always: { toolNames: ['fetch_generic_url_content'], }, }, }), ], });
let result = await run(agent, 'Which language is this repo written in?'); while (result.interruptions && result.interruptions.length) { for (const interruption of result.interruptions) { // Human in the loop here const approval = await confirm(interruption); if (approval) { result.state.approve(interruption); } else { result.state.reject(interruption); } } result = await run(agent, result.state); } console.log(result.finalOutput);}
import { stdin, stdout } from 'node:process';import * as readline from 'node:readline/promises';
async function confirm(item: RunToolApprovalItem): Promise<boolean> { const rl = readline.createInterface({ input: stdin, output: stdout }); const name = item.name; const params = item.arguments; const answer = await rl.question( `Approve running tool (mcp: ${name}, params: ${params})? (y/n) `, ); rl.close(); return answer.toLowerCase().trim() === 'y';}
main().catch(console.error);커넥터 기반 호스티드 서버
섹션 제목: “커넥터 기반 호스티드 서버”호스티드 MCP 는 OpenAI 커넥터도 지원합니다. serverUrl 을 제공하는 대신 커넥터의 connectorId 와 authorization 토큰을 전달하세요. 그러면 Responses API 가 인증을 처리하고 호스티드 MCP 인터페이스를 통해 커넥터의 도구를 노출합니다.
import { Agent, hostedMcpTool } from '@openai/agents';
const authorization = process.env.GOOGLE_CALENDAR_AUTHORIZATION!;
export const connectorAgent = new Agent({ name: 'Calendar Assistant', instructions: "You are a helpful assistant that can answer questions about the user's calendar.", tools: [ hostedMcpTool({ serverLabel: 'google_calendar', connectorId: 'connector_googlecalendar', authorization, requireApproval: 'never', }), ],});이 예시에서 GOOGLE_CALENDAR_AUTHORIZATION 환경 변수는 Google OAuth Playground 에서 얻은 OAuth 토큰을 포함하며, 커넥터 기반 서버가 Calendar API 를 호출하도록 승인합니다. 스트리밍도 함께 시연하는 실행 가능한 샘플은 examples/connectors를 참고하세요.
완전한 동작 샘플(호스티드 도구/Streamable HTTP/stdio + 스트리밍, HITL, onApproval)은 GitHub 저장소의 examples/mcp 에 있습니다.
2. Streamable HTTP MCP 서버
섹션 제목: “2. Streamable HTTP MCP 서버”에이전트가 로컬 또는 원격의 Streamable HTTP MCP 서버와 직접 통신할 때는 서버의 url, name 및 선택적 설정으로 MCPServerStreamableHttp 를 인스턴스화하세요:
import { Agent, run, MCPServerStreamableHttp } from '@openai/agents';
async function main() { const mcpServer = new MCPServerStreamableHttp({ url: 'https://gitmcp.io/openai/codex', name: 'GitMCP Documentation Server', }); const agent = new Agent({ name: 'GitMCP Assistant', instructions: 'Use the tools to respond to user requests.', mcpServers: [mcpServer], });
try { await mcpServer.connect(); const result = await run(agent, 'Which language is this repo written in?'); console.log(result.finalOutput); } finally { await mcpServer.close(); }}
main().catch(console.error);생성자는 authProvider, requestInit, fetch, reconnectionOptions, sessionId 와 같은 추가 MCP TypeScript‑SDK 옵션도 허용합니다. 자세한 내용은 MCP TypeScript SDK 저장소와 해당 문서를 참고하세요.
3. Stdio MCP 서버
섹션 제목: “3. Stdio MCP 서버”표준 I/O 만 노출하는 서버의 경우 fullCommand 로 MCPServerStdio 를 인스턴스화하세요:
import { Agent, run, MCPServerStdio } from '@openai/agents';import * as path from 'node:path';
async function main() { const samplesDir = path.join(__dirname, 'sample_files'); const mcpServer = new MCPServerStdio({ name: 'Filesystem MCP Server, via npx', fullCommand: `npx -y @modelcontextprotocol/server-filesystem ${samplesDir}`, }); await mcpServer.connect(); try { const agent = new Agent({ name: 'FS MCP Assistant', instructions: 'Use the tools to read the filesystem and answer questions based on those files. If you are unable to find any files, you can say so instead of assuming they exist.', mcpServers: [mcpServer], }); const result = await run(agent, 'Read the files and list them.'); console.log(result.finalOutput); } finally { await mcpServer.close(); }}
main().catch(console.error);알아두면 좋은 사항
섹션 제목: “알아두면 좋은 사항”Streamable HTTP 및 Stdio 서버의 경우, Agent 가 실행될 때마다 사용 가능한 도구를 확인하기 위해 list_tools() 를 호출할 수 있습니다. 이 라운드트립은 지연을 유발할 수 있으므로(특히 원격 서버), MCPServerStdio 또는 MCPServerStreamableHttp 에 cacheToolsList: true 를 전달하여 메모리에서 결과를 캐시할 수 있습니다.
도구 목록이 변경되지 않는다고 확신할 때만 활성화하세요. 나중에 캐시를 무효화하려면 서버 인스턴스에서 invalidateToolsCache() 를 호출하세요.
도구 필터링
섹션 제목: “도구 필터링”createMCPToolStaticFilter 를 통한 정적 필터 또는 사용자 정의 함수를 전달하여 각 서버에서 노출되는 도구를 제한할 수 있습니다. 다음은 두 접근 방식을 함께 보여 주는 예시입니다:
import { MCPServerStdio, MCPServerStreamableHttp, createMCPToolStaticFilter, MCPToolFilterContext,} from '@openai/agents';
interface ToolFilterContext { allowAll: boolean;}
const server = new MCPServerStdio({ fullCommand: 'my-server', toolFilter: createMCPToolStaticFilter({ allowed: ['safe_tool'], blocked: ['danger_tool'], }),});
const dynamicServer = new MCPServerStreamableHttp({ url: 'http://localhost:3000', toolFilter: async ({ runContext }: MCPToolFilterContext, tool) => (runContext.context as ToolFilterContext).allowAll || tool.name !== 'admin',});추가 자료
섹션 제목: “추가 자료”- Model Context Protocol – 공식 명세
- examples/mcp – 위에서 참조한 실행 가능한 데모