MCP 서버가 죽은 건 아니다. 하지만 모든 서버를 항상 활성화하면 컨텍스트가 부풀어 비용 증가와 성능 저하로 이어진다. agent-skills과 달리 MCP 서버는 기본적으로 점진적 공개(progressive disclosure)를 제공하지 않는다. 필요한 도구만 선택해서 주입하는 것은 개발자의 책임이다.
패턴 1: 명시적 MCP (인라인 툴 주입)
MCP 서버를 옵트인 방식으로 유지한다. 프롬프트에 @mention을 작성하면 에이전트가 해당 서버를 즉석에서 가져와 도구를 주입한다.
# 사용자 프롬프트 예시
@github의 최근 PR 목록을 가져와서 리뷰가 필요한 항목을 정리해줘에이전트가 @github를 감지하면:
- 등록된 MCP 서버 URL로 해석
- 서버에서 도구 스키마 fetch
- API 요청의
tools[]배열에 주입 - 모델이 필요한 도구를 호출
async function handlePrompt(prompt: string) {
const mentions = parseMentions(prompt); // ["@github", "@slack"]
const servers = mentions.map(m => mcpServers.resolve(m));
const mcpTools = await Promise.all(servers.map(s => s.listTools()));
const response = await llmCall({
prompt,
tools: [...nativeTools, ...mcpTools],
});
}언제 사용: MCP 사용이 간헐적이고 사용자 주도일 때. 요청마다 Slack이나 GitHub 데이터가 필요한 경우에만 가져오므로 불필요한 도구 노이즈가 없다.
패턴 2: 서브에이전트 MCP
MCP 서버를 서브에이전트 정의에 선언하면 런타임에 자동으로 사용 가능해진다. allowed_tools로 각 서브에이전트에 필요한 도구만 허용할 수 있다.
# code_reviewer.md
name: code-reviewer
model: gemini-3-flash
mcp_servers:
- url: https://github-mcp.example
allowed_tools:
- list_pulls
- list_reviews
- get_diff
당신은 코드 리뷰어입니다. 오픈 PR을 검토하세요...오케스트레이터가 서브에이전트를 툴로 등록한다.
const codeReviewer = createSubagent("./agents/code_reviewer.md");
const slackMonitor = createSubagent("./agents/slack_monitor.md");
const response = await llmCall({
prompt,
tools: [...nativeTools, codeReviewer, slackMonitor],
});allowed_tools는 MCP 서버를 포크하지 않고도 최소 권한 스코핑을 구현한다.
언제 사용: 사용 사례가 도구를 결정할 때. 코드 리뷰 에이전트는 항상 GitHub이 필요하고, 지원 에이전트는 항상 Zendesk가 필요하다. MCP 서버가 에이전트의 정체성(identity)의 일부인 경우다.
두 패턴 비교
| 패턴 1 (인라인 주입) | 패턴 2 (서브에이전트) | |
|---|---|---|
| 활성화 시점 | 사용자가 @mention 할 때 | 서브에이전트 호출 시 항상 |
| 적합한 경우 | 간헐적·사용자 주도 통합 | 에이전트 역할에 필수적인 통합 |
| 권한 제어 | 요청 단위 | allowed_tools로 서브에이전트 단위 |
| 컨텍스트 영향 | 해당 요청만 증가 | 서브에이전트 컨텍스트에만 존재 |
핵심 원칙
필요하지 않은 MCP 서버를 미리 로드하지 마라. 컨텍스트의 도구 밀도가 높아질수록 모델 성능이 저하된다.
MCP를 처음 연결할 때는 패턴 1로 시작해 사용 패턴을 파악한 뒤, 특정 에이전트에 항상 필요한 서버가 명확해지면 패턴 2로 전환하는 게 좋다.
참고 자료
- How to correctly use MCP servers with your AI Agents — Philipp Schmid (2026-04-27)