MCP Sampling은 왜 서버용 API 키가 아니라 역방향 권한 요청일까
MCP 서버가 모델을 한 번 더 불러 달라 요청할 때, 그 호출의 비용·권한·도구 실행 책임은 어디에 있어야 할까?
MCP Sampling은 왜 서버용 API 키가 아니라 역방향 권한 요청일까
- 카테고리: ai_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: MCP 서버가 “모델을 한 번 더 불러 달라”고 요청할 때, 그 호출의 비용·권한·도구 실행 책임은 어디에 있어야 할까?
- 핵심 출처:
- Sampling - Model Context Protocol - 게시일 2025-11-25, 확인일 2026-07-22
- SEP-1577: Sampling With Tools - Model Context Protocol - 게시일 2025-09-30, 확인일 2026-07-22
- MCP and Connectors | OpenAI API - 게시일 미표기, 확인일 2026-07-22
- Realtime with tools | OpenAI API - 게시일 미표기, 확인일 2026-07-22
- Model Context Protocol (MCP) | OpenAI Agents SDK - 게시일 미표기, 확인일 2026-07-22
1. 왜 지금 봐야 하나
에이전트 앱을 만들다 보면 “도구 서버도 가끔 LLM을 호출하고 싶다”는 요구가 나온다. 예를 들어 문서 검색 MCP 서버가 검색어를 정규화하거나, 캘린더 서버가 사용자의 자연어 요청을 내부 필터 조건으로 바꾸거나, 코드 분석 서버가 파일 목록을 보고 다음 탐색 단계를 정하고 싶을 수 있다. 가장 쉬운 구현은 MCP 서버에 LLM API 키를 넣고 서버가 직접 모델을 호출하게 하는 것이다.
하지만 그 순간 중요한 경계가 흐려진다. 누가 어떤 모델을 썼는가? 사용자는 서버가 보낸 프롬프트를 볼 수 있는가? 비용은 누구 계정에서 나가는가? 서버가 가진 도구 결과와 사용자의 대화 맥락이 어디까지 섞였는가? MCP의 sampling은 이 문제를 “서버도 모델 호출을 할 수 있다”가 아니라 서버가 클라이언트에게 모델 호출을 요청하고, 클라이언트가 모델·비용·승인·컨텍스트 공개 범위를 통제하는 역방향 권한 요청으로 정의한다.
특히 2025-11-25 MCP Sampling 사양과 SEP-1577은 sampling/createMessage에 tools와 toolChoice를 추가하면서, 서버가 클라이언트의 모델을 빌려 에이전트 루프를 만들 수 있는 길을 열었다. 동시에 sampling.tools capability, 도구 결과 균형 규칙, includeContext soft-deprecation 같은 제약도 넣었다. 개발자에게 중요한 포인트는 기능보다 경계다. Sampling을 잘못 이해하면 “도구 서버 안의 숨은 에이전트”가 되어 관측성, 승인, 비용 제한이 모두 빠질 수 있다.
2. 핵심 개념
MCP Sampling의 기본 흐름은 거꾸로 되어 있다.
일반적인 tool calling에서는 모델이 “이 도구를 호출해 달라”고 애플리케이션에 요청한다. 애플리케이션은 도구를 실행하고 결과를 모델에게 돌려준다. 반대로 Sampling에서는 MCP 서버가 클라이언트에게 sampling/createMessage 요청을 보낸다. 즉 “내가 이런 메시지와 선호 조건을 줄 테니, 네가 접근 가능한 LLM으로 한 번 생성해 달라”는 요청이다.
이 구조가 중요한 이유는 세 가지다.
첫째, API 키의 위치가 달라진다. MCP Sampling 문서는 서버가 자체 API 키 없이도 AI 기능을 활용할 수 있고, 클라이언트가 모델 접근과 선택을 통제한다고 설명한다. 서버가 직접 OpenAI, Claude, Gemini 키를 들고 있지 않아도 되므로 배포·과금·폐기 범위가 단순해진다. 대신 클라이언트는 “이 서버가 지금 어떤 생성을 요청하는지”를 검토할 책임이 생긴다.
둘째, 모델 선택은 이름 지정이 아니라 선호 계약이 된다. Sampling의 modelPreferences는 특정 모델명을 강제하기보다 costPriority, speedPriority, intelligencePriority, 그리고 advisory hints를 사용한다. 서버는 “sonnet 계열이면 좋겠다” 정도를 힌트로 줄 수 있지만, 최종 모델 선택은 클라이언트가 한다. 여러 공급자와 조직 정책이 섞이는 환경에서는 이 추상화가 중요하다.
셋째, 컨텍스트 공개는 기본값이 아니라 capability 문제다. 2025-11-25 사양은 includeContext의 thisServer, allServers 값을 soft-deprecated로 두고, sampling.context capability 없이는 쓰지 말라고 한다. 서버가 “전체 대화 맥락을 좀 넣어줘”라고 쉽게 요구하지 못하게 만드는 방향이다. 외부 서버에게 전체 컨텍스트를 넘기는 일은 편리하지만, 프롬프트 인젝션·민감정보 유출·비용 폭증의 출발점이 되기 쉽다.
3. 최신 이슈와 연결
새로운 변화는 Sampling에 도구 사용이 들어왔다는 점이다. SEP-1577은 sampling/createMessage에 tools와 toolChoice를 추가하고, 서버가 자체 agentic loop를 돌릴 수 있게 한다. 예를 들면 다음 순서다.
- MCP 서버가 클라이언트에게
sampling/createMessage를 보낸다. - 클라이언트의 모델이
tool_use를 포함한 응답과stopReason: "toolUse"를 돌려준다. - MCP 서버가 해당 도구를 실행한다.
- 서버가
tool_result를 포함해 다시 Sampling을 요청한다. - 모델이 다음 도구 호출을 하거나 최종 답을 만든다.
여기서 놓치기 쉬운 점은 도구 루프의 실행 책임이 서버에 있다는 것이다. OpenAI의 hosted MCP나 Realtime MCP 문서에서는 원격 MCP 도구를 Responses API 또는 Realtime API가 실행하는 패턴도 설명한다. 반면 MCP Sampling with Tools에서는 서버가 모델에게 도구 사용을 요청하고, 서버가 도구 결과를 맞춰 다시 넣는 구조다. 비슷해 보이지만 운영 책임이 다르다.
OpenAI 문서가 강조하는 allowed_tools, require_approval, mcp_list_tools, mcp_call, mcp_approval_request도 같은 문제를 다른 방향에서 보여준다. 원격 MCP 서버를 모델에게 붙이는 순간 도구 목록이 컨텍스트에 들어가고, 민감한 액션은 승인이 필요하며, 많은 도구를 노출하면 비용과 지연이 늘어난다. Realtime 문서는 MCP 도구가 로딩 중이면 해당 턴에서 사용할 수 없고, approval 응답이 없으면 호출이 진행되지 않는 실패 모드까지 따로 적는다.
결국 최신 MCP 흐름의 핵심은 “에이전트가 도구를 더 많이 쓸 수 있다”가 아니다. 누가 도구를 실행하는지, 누가 LLM 호출을 승인하는지, 어떤 도구 정의와 결과가 모델 컨텍스트에 들어가는지를 프로토콜 수준에서 분리하는 것이다.
4. 개발자 관점 해석
MCP Sampling을 도입할 때 가장 위험한 설계는 “서버 내부에서 알아서 모델을 불러 똑똑하게 처리한다”는 블랙박스다. 작은 데모에서는 편하다. 하지만 운영 환경에서는 아래 문제가 바로 생긴다.
첫째, 승인 UI가 사라진다. MCP Sampling 사양은 Sampling 요청에 대해 사람이 거부할 수 있는 human-in-the-loop를 권장하고, 사용자가 프롬프트와 결과를 검토할 수 있어야 한다고 말한다. 서버가 직접 API 키로 모델을 호출하면 이 검토 지점이 애플리케이션 밖으로 사라진다.
둘째, 비용 예산이 서버별로 샌다. 서버가 어느 모델을 얼마나 호출했는지 클라이언트의 정책과 별개로 흩어진다. 반대로 Sampling을 쓰면 클라이언트가 cost/speed/intelligence 우선순위를 해석하고 rate limit을 적용할 수 있다.
셋째, 도구 루프가 불균형해진다. 2025-11-25 Sampling 사양은 tool-enabled sampling에서 assistant의 tool_use마다 대응되는 user의 tool_result가 있어야 하고, tool result 메시지는 다른 콘텐츠 타입과 섞지 말아야 한다고 요구한다. 병렬 tool use가 가능해질수록 이 균형 규칙은 중요해진다. 하나라도 빠지면 공급자별 API 호환성, 재시도, trace 재구성이 깨진다.
넷째, 컨텍스트 주입 범위가 과해진다. includeContext: "allServers" 같은 사고방식은 편하지만, “서버가 정말 전체 대화와 다른 서버의 결과까지 볼 필요가 있는가?”라는 질문을 흐린다. 최근 사양이 이 값을 capability-gated soft-deprecated로 둔 이유는 맥락 공유를 기본값이 아니라 명시적 위험으로 보라는 신호다.
좋은 설계는 Sampling을 숨은 모델 호출이 아니라 다음 네 가지 로그 가능한 이벤트로 보는 것이다.
sampling_request_created: 어느 MCP 서버가 어떤 목적과 maxTokens로 요청했는가sampling_request_approved_or_denied: 누가 어떤 프롬프트를 보고 승인했는가sampling_model_selected: 실제 모델, 비용·속도·지능 우선순위 해석 결과는 무엇인가sampling_tool_loop_step: tool_use와 tool_result가 균형 있게 연결되었는가
이렇게 보면 Sampling은 기능 확장이 아니라 agent architecture의 권한·비용·관측성 인터페이스가 된다.
5. 내 프로젝트에 적용할 체크포인트
- MCP 서버가 LLM을 호출해야 한다면, 서버 내부 API 키 호출과 MCP Sampling 중 어느 쪽이 권한 경계를 덜 흐리는지 먼저 비교한다.
- Sampling을 지원하는 클라이언트라면
sampling,sampling.tools,sampling.contextcapability를 기능 플래그처럼 분리한다. includeContext를 기본으로 켜지 않는다. 필요한 경우 “어떤 서버의 어떤 데이터가 왜 필요한가”를 요청 단위로 기록한다.modelPreferences를 실제 모델명으로 오해하지 않는다. 서버는 힌트를 주고, 클라이언트가 조직 정책·비용·latency에 맞게 매핑한다.- tool-enabled sampling에서는 모든
tool_use.id와tool_result.toolUseId를 trace에 남긴다. toolChoice: "required"를 structured output 꼼수로 쓸 때는 “정말 도구 실행이 필요한가, 아니면 스키마 검증만 필요한가”를 분리한다.- 원격 MCP 도구를 붙일 때는 OpenAI 문서처럼
allowed_tools로 표면을 줄이고, 쓰기·결제·삭제·외부 전송 액션에는require_approval을 둔다. - Realtime 세션에서는 도구 로딩 완료 전 턴 시작, approval 응답 누락, 잘못된
server_label같은 상태 실패를 UI에 노출한다.
6. 오늘 10분 액션
오늘은 코드를 크게 바꾸지 말고, 내 에이전트 앱의 “숨은 모델 호출”을 찾는 표를 만든다.
위치 | 누가 호출하나 | API 키 위치 | 사용 모델 | 사용 컨텍스트 | 사용자 승인 | 로그 여부 | 대체 가능성
문서검색 MCP 서버 | 서버 | 서버 env | 고정 모델 | 검색 결과+질문 | 없음 | 일부 | Sampling 요청으로 전환 검토
캘린더 요약 도구 | 앱 서버 | 앱 env | 정책 모델 | 사용자 일정 | 승인 있음 | 있음 | function tool 유지
원격 MCP connector | Responses API | 사용자 OAuth | 클라이언트 선택 | tool call 인자 | 도구별 approval | output item | allowed_tools 축소
10분 동안 한 줄만 제대로 채워도 충분하다. 특히 “API 키 위치”와 “사용자 승인” 칸이 비어 있으면 위험 신호다. 그 호출은 기능적으로 성공하더라도, 나중에 비용·감사·보안 사고가 났을 때 설명하기 어렵다.
7. 더 볼 자료
- Sampling - Model Context Protocol:
sampling/createMessage, capability, tool result balancing의 기준 문서다. - SEP-1577: Sampling With Tools: 왜
tools,toolChoice,sampling.toolscapability가 들어왔는지 설계 배경을 볼 수 있다. - MCP and Connectors | OpenAI API: hosted MCP, connectors, approval,
allowed_tools, remote MCP 위험을 제품 API 관점에서 설명한다. - Realtime with tools | OpenAI API: 실시간 세션에서 MCP 도구 로딩·승인·실패 이벤트를 어떻게 다뤄야 하는지 확인할 수 있다.
- Model Context Protocol (MCP) | OpenAI Agents SDK: hosted MCP, Streamable HTTP, stdio 서버 선택 기준과 approval flow 예시가 있다.
중복 회피 메모
로컬 content/generated와 Supabase 최근 ai_dev 글을 확인했다. 최근 글은 임베딩 차원과 pgvector 스키마, 멀티모달 컨텍스트 예산, LLM 서비스 티어, 프롬프트 인젝션 신뢰 경계, Programmatic Tool Calling, RAG citation/grounding, 에이전트 trace, tool calling 왕복 프로토콜을 다뤘다. 이번 글은 도구 호출 자체나 원격 MCP 권한 승인 반복이 아니라, MCP 서버가 클라이언트에게 LLM 생성을 요청하는 sampling/createMessage를 비용·모델 선택·컨텍스트 공개·도구 루프 책임의 역방향 권한 요청으로 해석하는 데 집중한다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)