MCP를 활용한 코드 실행: 더 효율적인 AI 에이전트 구축
요약: Model Context Protocol(MCP)은 AI 에이전트를 외부 시스템에 연결하는 개방형 표준입니다. 하지만 연결된 도구가 많아지면 도구 정의와 중간 결과가 과도한 토큰을 소비하여 에이전트 효율성이 저하될 수 있습니다. 코드 실행 환경에서 MCP 서버를 코드 API로 제공하면 필요한 도구만 로드하고, 데이터를 모델로 전달하기 전에 처리하며, 복잡한 논리를 한 단계로 실행할 수 있습니다. 이 접근 방식은 토큰 사용량을 98.7%까지 감소시키고, 보안 및 상태 관리 이점도 제공합니다.
===BODY_KO##
MCP를 통한 코드 실행: 더 효율적인 AI 에이전트 구축Model Context Protocol(MCP)은 AI 에이전트를 외부 시스템에 연결하는 개방형 표준입니다. 전통적으로 에이전트를 도구와 데이터에 연결하려면 각 연결마다 사용자 정의 통합이 필요하며, 이는 단편화와 중복 작업을 초래하여 진정으로 연결된 시스템을 확장하기 어렵게 만듭니다. MCP는 보편적인 프로토콜을 제공합니다. 개발자는 에이전트에 MCP를 한 번만 구현하면 전체 통합 생태계가 잠금 해제됩니다. 2024년 11월 MCP 출시 이후 도입이 급격히 증가했습니다. 커뮤니티는 수천 개의 MCP 서버를 구축했고, 모든 주요 프로그래밍 언어에 대한 SDK를 사용할 수 있으며, 업계는 MCP를 도구와 데이터를 연결하는 사실상의 표준으로 채택했습니다. 오늘날 개발자는 수십 개의 MCP 서버에 걸쳐 수백 또는 수천 개의 도구에 액세스할 수 있는 에이전트를 정기적으로 구축합니다. 그러나 연결된 도구 수가 증가함에 따라 모든 도구 정의를 미리 로드하고 중간 결과를 컨텍스트 윈도우를 통해 전달하면 에이전트가 느려지고 비용이 증가합니다. 이 블로그에서는 코드 실행이 에이전트가 MCP 서버와 더 효율적으로 상호 작용하여 더 적은 토큰으로 더 많은 도구를 처리할 수 있도록 하는 방법을 살펴보겠습니다.
## 도구로 인한 과도한 토큰 소비는 에이전트 효율성을 저하시킵니다
MCP 사용이 확장됨에 따라 에이전트 비용과 대기 시간을 증가시킬 수 있는 두 가지 일반적인 패턴이 있습니다:
– 도구 정의가 컨텍스트 윈도우를 과부하시킵니다.
– 중간 도구 결과가 추가 토큰을 소비합니다.### 1. 도구 정의가 컨텍스트 윈도우를 과부하시킵니다
대부분의 MCP 클라이언트는 모든 도구 정의를 컨텍스트에 미리 로드하고, 직접 도구 호출 구문을 사용하여 모델에 노출합니다. 이러한 도구 정의는 다음과 같이 보일 수 있습니다:
“`
gdrive.getDocument
설명: Google Drive에서 문서를 검색합니다.
매개변수:
documentId (필수, 문자열): 검색할 문서의 ID
fields (선택사항, 문자열): 반환할 특정 필드
반환값: 제목, 본문 콘텐츠, 메타데이터, 권한 등이 포함된 문서 객체
“`“`
salesforce.updateRecord
설명: Salesforce에서 레코드를 업데이트합니다.
매개변수:
objectType (필수, 문자열): Salesforce 개체 유형(Lead, Contact, Account 등)
recordId (필수, 문자열): 업데이트할 레코드의 ID
data (필수, 객체): 새 값으로 업데이트할 필드
반환값: 확인 메시지와 함께 업데이트된 레코드 객체
“`도구 설명은 더 많은 컨텍스트 윈도우 공간을 차지하여 응답 시간과 비용을 증가시킵니다. 에이전트가 수천 개의 도구에 연결된 경우 요청을 읽기 전에 수십만 토큰을 처리해야 할 수 있습니다.
### 2. 중간 도구 결과가 추가 토큰을 소비합니다
대부분의 MCP 클라이언트는 모델이 MCP 도구를 직접 호출할 수 있도록 허용합니다. 예를 들어, 에이전트에게 다음과 같이 요청할 수 있습니다:
“Google Drive에서 내 회의 기록을 다운로드하여 Salesforce 리드에 첨부해주세요.”
모델은 다음과 같은 호출을 수행합니다:
“`
TOOL CALL: gdrive.getDocument(documentId: "abc123")
→ "4분기 목표에 대해 논의…\n[전체 기록 텍스트]" 반환 (모델 컨텍스트에 로드됨)TOOL CALL: salesforce.updateRecord(
objectType: "SalesMeeting",
recordId: "00Q5f000001abcXYZ",
data: {
"Notes": "4분기 목표에 대해 논의…\n[전체 기록 텍스트가 작성됨]"
}
)
(모델이 전체 기록을 다시 컨텍스트에 작성해야 함)
“`모든 중간 결과는 모델을 통과해야 합니다. 이 예에서 전체 통화 기록이 두 번 흐릅니다. 2시간 분량의 영업 회의의 경우 이는 추가로 50,000개의 토큰을 처리하는 것을 의미할 수 있습니다. 더 큰 문서는 컨텍스트 윈도우 제한을 초과하여 워크플로가 중단될 수 있습니다. 큰 문서나 복잡한 데이터 구조의 경우 모델이 도구 호출 간에 데이터를 복사할 때 실수를 할 가능성이 더 높을 수 있습니다.
MCP 클라이언트는 도구 정의를 모델의 컨텍스트 윈도우에 로드하고 각 도구 호출과 결과가 작업 간에 모델을 통과하는 메시지 루프를 조율합니다.
## MCP를 통한 코드 실행은 컨텍스트 효율성을 개선합니다
에이전트에 대한 코드 실행 환경이 더 보편화됨에 따라 한 가지 해결책은 MCP 서버를 직접 도구 호출이 아닌 코드 API로 제공하는 것입니다. 그러면 에이전트가 MCP 서버와 상호 작용하는 코드를 작성할 수 있습니다. 이 접근 방식은 두 가지 과제를 모두 해결합니다. 에이전트는 필요한 도구만 로드하고 결과를 모델로 다시 전달하기 전에 실행 환경에서 데이터를 처리할 수 있습니다.
이를 수행하는 방법은 여러 가지가 있습니다. 한 가지 접근 방식은 연결된 MCP 서버의 모든 사용 가능한 도구에 대한 파일 트리를 생성하는 것입니다. 다음은 TypeScript를 사용하는 구현 예입니다:
“`
servers
├── google-drive
│ ├── getDocument.ts
│ ├── … (기타 도구)
│ └── index.ts
├── salesforce
│ ├── updateRecord.ts
│ ├── … (기타 도구)
│ └── index.ts
└── … (기타 서버)
“`그런 다음 각 도구는 파일에 해당합니다. 예를 들어:
“`typescript
// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";interface GetDocumentInput {
documentId: string;
}interface GetDocumentResponse {
content: string;
}/* Google Drive에서 문서 읽기 */
export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
return callMCPTool<GetDocumentResponse>('google_drive__get_document', input);
}
“`위의 Google Drive에서 Salesforce로의 예는 다음과 같은 코드가 됩니다:
“`typescript
// Google 문서에서 기록을 읽고 Salesforce 잠재 고객에 추가
import * as gdrive from './servers/google-drive';
import * as salesforce from './servers/salesforce';const transcript = (await gdrive.getDocument({ documentId: 'abc123' })).content;
await salesforce.updateRecord({
objectType: 'SalesMeeting',
recordId: '00Q5f000001abcXYZ',
data: { Notes: transcript }
});
“`에이전트는 파일 시스템을 탐색하여 도구를 발견합니다. `./servers/` 디렉토리를 나열하여 사용 가능한 서버(google-drive 및 salesforce 등)를 찾은 다음 필요한 특정 도구 파일(getDocument.ts 및 updateRecord.ts 등)을 읽어 각 도구의 인터페이스를 이해합니다. 이렇게 하면 에이전트가 현재 작업에 필요한 정의만 로드할 수 있습니다.
이는 토큰 사용량을 150,000개에서 2,000개로 줄여 98.7%의 시간 및 비용 절감 효과를 가져옵니다. Cloudflare는 유사한 결과를 발표했으며, MCP를 통한 코드 실행을 “코드 모드”라고 언급했습니다. 핵심 통찰력은 동일합니다. LLM은 코드 작성에 능숙하며 개발자는 이 강점을 활용하여 MCP 서버와 더 효율적으로 상호 작용하는 에이전트를 구축해야 합니다.
## MCP를 통한 코드 실행의 이점
MCP를 통한 코드 실행은 도구를 요청 시 로드하고 데이터를 모델에 도달하기 전에 필터링하며 복잡한 논리를 한 단계로 실행하여 에이전트가 컨텍스트를 더 효율적으로 사용할 수 있도록 합니다. 이 접근 방식을 사용하면 보안 및 상태 관리 이점도 있습니다.
### 점진적 공개
모델은 파일 시스템 탐색에 능숙합니다. 파일 시스템의 코드로 도구를 제공하면 모델이 모든 정의를 미리 읽는 대신 요청 시 도구 정의를 읽을 수 있습니다. 또는 관련 정의를 찾기 위해 서버에 search_tools 도구를 추가할 수 있습니다. 예를 들어, 위에서 사용한 가상의 Salesforce 서버로 작업할 때 에이전트는 “salesforce”를 검색하고 현재 작업에 필요한 도구만 로드합니다. search_tools 도구에 세부 수준 매개변수를 포함하면 에이전트가 필요한 세부 수준(이름만, 이름 및 설명, 스키마가 포함된 전체 정의 등)을 선택할 수 있으므로 컨텍스트를 절약하고 도구를 효율적으로 찾을 수 있습니다.
### 컨텍스트 효율적인 도구 결과
큰 데이터 세트로 작업할 때 에이전트는 반환하기 전에 코드에서 결과를 필터링하고 변환할 수 있습니다. 10,000개 행의 스프레드시트를 가져오는 경우를 고려해 보세요:
“`typescript
// 코드 실행 없음 – 모든 행이 컨텍스트를 통과함
TOOL CALL: gdrive.getSheet(sheetId: ‘abc123’)
→ 수동으로 필터링하기 위해 컨텍스트에 10,000개 행 반환// 코드 실행 포함 – 실행 환경에서 필터링
const allRows = await gdrive.getSheet({ sheetId: ‘abc123’ });
const pendingOrders = allRows.filter(row => row[“Status”] === ‘pending’);
console.log(`${pendingOrders.length}개의 대기 중인 주문을 찾았습니다`);
console.log(pendingOrders.slice(0, 5)); // 검토를 위해 처음 5개만 기록
“`에이전트는 10,000개 대신 5개의 행을 봅니다. 유사한 패턴은 여러 데이터 소스 간의 집계, 조인 또는 특정 필드 추출에도 작동하며, 이 모든 작업은 컨텍스트 윈도우를 부풀리지 않고 수행할 수 있습니다.
### 더 강력하고 컨텍스트 효율적인 제어 흐름
루프, 조건문, 오류 처리는 개별 도구 호출을 연결하는 대신 익숙한 코드 패턴으로 수행할 수 있습니다. 예를 들어, Slack에 배포 알림이 필요한 경우 에이전트는 다음을 작성할 수 있습니다:
“`typescript
let found = false;
while (!found) {
const messages = await slack.getChannelHistory({ channel: ‘C123456’ });
found = messages.some(m => m.text.includes(‘deployment complete’));
if (!found) await new Promise(r => setTimeout(r, 5000));
}
console.log(‘배포 알림을 받았습니다’);
“`이 접근 방식은 MCP 도구 호출과 슬립 명령 사이를 에이전트 루프에서 번갈아가며 사용하는 것보다 더 효율적입니다. 또한 실행되는 조건 트리를 작성할 수 있으므로 "첫 번째 토큰까지의 시간" 대기 시간도 절약됩니다. 모델이 if 문을 평가할 때까지 기다리는 대신 코드 실행 환경이 이 작업을 수행할 수 있습니다.
### 프라이버시 보호 작업
에이전트가 MCP와 함께 코드 실행을 사용하면 중간 결과가 기본적으로 실행 환경에 유지됩니다. 이렇게 하면 에이전트가 명시적으로 기록하거나 반환하는 항목만 보게 되므로 모델과 공유하고 싶지 않은 데이터가 워크플로를 통해 흐르지만 모델의 컨텍스트에 들어가지 않을 수 있습니다.
더 민감한 워크로드의 경우 에이전트 하니스가 중요한 데이터를 자동으로 토큰화할 수 있습니다. 예를 들어, 스프레드시트에서 고객 연락처 세부 정보를 Salesforce로 가져와야 한다고 가정해 보겠습니다. 에이전트는 다음을 작성합니다:
“`typescript
const sheet = await gdrive.getSheet({ sheetId: ‘abc123’ });
for (const row of sheet.rows) {
await salesforce.updateRecord({
objectType: ‘Lead’,
recordId: row.salesforceId,
data: {
Email: row.email,
Phone: row.phone,
Name: row.name
}
});
}
console.log(`${sheet.rows.length}개의 리드를 업데이트했습니다`);
“`MCP 클라이언트는 모델에 도달하기 전에 데이터를 가로채 PII를 토큰화합니다:
“`typescript
// 에이전트가 sheet.rows를 기록하는 경우 보게 되는 항목:
[
{
salesforceId: ’00Q…’,
email: ‘[EMAIL_1]’,
phone: ‘[PHONE_1]’,
name: ‘[NAME_1]’
},
{
salesforceId: ’00Q…’,
email: ‘[EMAIL_2]’,
phone: ‘[PHONE_2]’,
name: ‘[NAME_2]’
},
…
]
“`그런 다음 데이터가 다른 MCP 도구 호출에서 공유될 때 MCP 클라이언트의 조회를 통해 토큰화가 해제됩니다. 실제 이메일 주소, 전화번호, 이름이 Google Sheets에서 Salesforce로 흐르지만 모델을 통과하지 않습니다. 이는 에이전트가 실수로 중요한 데이터를 기록하거나 처리하는 것을 방지합니다. 또한 이를 사용하여 데이터가 어디서 어디로 흐를 수 있는지 선택하여 결정론적 보안 규칙을 정의할 수 있습니다.
### 상태 지속성 및 스킬
파일 시스템 액세스를 통해 코드 실행은 에이전트가 작업 간에 상태를 유지할 수 있도록 합니다. 에이전트는 중간 결과를 파일에 작성하여 작업을 재개하고 진행 상황을 추적할 수 있습니다:
“`typescript
const leads = await salesforce.query({
query: ‘SELECT Id, Email FROM Lead LIMIT 1000’
});
const csvData = leads.map(l => `${l.Id},${l.Email}`).join(‘\n’);
await fs.writeFile(‘./workspace/leads.csv’, csvData);// 이후 실행은 중단한 곳에서 다시 시작
const saved = await fs.readFile(‘./workspace/leads.csv’, ‘utf-8’);
“`에이전트는 재사용 가능한 함수로 자체 코드를 유지할 수도 있습니다. 에이전트가 작업에 대한 작동하는 코드를 개발하면 향후 사용을 위해 해당 구현을 저장할 수 있습니다:
“`typescript
// ./skills/save-sheet-as-csv.ts에서
import * as gdrive from ‘./servers/google-drive’;export async function saveSheetAsCsv(sheetId: string) {
const data = await gdrive.getSheet({ sheetId });
const csv = data.map(row => row.join(‘,’)).join(‘\n’);
await fs.writeFile(`./workspace/sheet-${sheetId}.csv`, csv);
return `./workspace/sheet-${sheetId}.csv`;
}// 나중에 모든 에이전트 실행에서:
import { saveSheetAsCsv } from ‘./skills/save-sheet-as-csv’;const csvPath = await saveSheetAsCsv(‘abc123’);
“`이것은 스킬(Skills) 개념과 밀접하게 관련되어 있습니다. 스킬은 모델이 특화된 작업의 성능을 개선하기 위한 재사용 가능한 지침, 스크립트 및 리소스의 폴더입니다. 저장된 함수에 SKILL.md 파일을 추가하면 모델이 참조하고 사용할 수 있는 구조화된 스킬이 생성됩니다. 시간이 지남에 따라 이를 통해 에이전트가 더 높은 수준의 기능 도구 상자를 구축하고 가장 효과적으로 작동하는 데 필요한 스캐폴딩을 발전시킬 수 있습니다.
코드 실행은 자체적인 복잡성을 도입한다는 점에 유의하세요. 에이전트 생성 코드를 실행하려면 적절한 샌드박싱, 리소스 제한 및 모니터링이 있는 보안 실행 환경이 필요합니다. 이러한 인프라 요구 사항은 직접 도구 호출이 피할 수 있는 운영 오버헤드와 보안 고려 사항을 추가합니다. 코드 실행의 이점(감소된 토큰 비용, 더 낮은 대기 시간, 개선된 도구 구성)은 이러한 구현 비용과 비교하여 고려해야 합니다.
## 요약
MCP는 에이전트를 많은 도구와 시스템에 연결하기 위한 기본 프로토콜을 제공합니다. 그러나 너무 많은 서버가 연결되면 도구 정의와 결과가 과도한 토큰을 소비하여 에이전트 효율성이 저하될 수 있습니다. 여기서 많은 문제는 새로운 것처럼 보이지만(컨텍스트 관리, 도구 구성, 상태 지속성) 소프트웨어 엔지니어링에는 알려진 해결책이 있습니다. 코드 실행은 이러한 확립된 패턴을 에이전트에 적용하여 익숙한 프로그래밍 구문을 사용하여 MCP 서버와 더 효율적으로 상호 작용할 수 있습니다. 이 접근 방식을 구현하는 경우 MCP 커뮤니티와 귀하의 발견을 공유하시기를 권장합니다.
## 감사의 말
이 문서는 Adam Jones와 Conor Kelly가 작성했습니다. 초안에 대한 피드백을 제공한 Jeremy Fox, Jerome Swannack, Stuart Ritchie, Molly Vorwerck, Matt Samuels, Maggie Vo에게 감사드립니다.
MCP를 활용한 코드 실행: 더 효율적인 AI 에이전트 구축
Model Context Protocol(MCP)은 AI 에이전트를 외부 시스템에 연결하는 개방형 표준입니다. 하지만 연결된 도구가 많아지면 도구 정의와 중간 결과가 과도한 토큰을 소비하여 에이전트 효율성이 저하될 수 있습니다. 코드 실행 환경에서 MCP 서버를 코드 API로 제공하면 필요한 도구만 로드하고, 데이터를 모델로 전달하기 전에 처리하며, 복잡한 논리를 한 단계로 실행할 수 있습니다. 이 접근 방식은 토큰 사용량을 98.7%까지 감소시키고, 보안 및 상태 관리 이점도 제공합니다.
===BODY_KO##
MCP를 통한 코드 실행: 더 효율적인 AI 에이전트 구축
Model Context Protocol(MCP)은 AI 에이전트를 외부 시스템에 연결하는 개방형 표준입니다. 전통적으로 에이전트를 도구와 데이터에 연결하려면 각 연결마다 사용자 정의 통합이 필요하며, 이는 단편화와 중복 작업을 초래하여 진정으로 연결된 시스템을 확장하기 어렵게 만듭니다. MCP는 보편적인 프로토콜을 제공합니다. 개발자는 에이전트에 MCP를 한 번만 구현하면 전체 통합 생태계가 잠금 해제됩니다. 2024년 11월 MCP 출시 이후 도입이 급격히 증가했습니다. 커뮤니티는 수천 개의 MCP 서버를 구축했고, 모든 주요 프로그래밍 언어에 대한 SDK를 사용할 수 있으며, 업계는 MCP를 도구와 데이터를 연결하는 사실상의 표준으로 채택했습니다. 오늘날 개발자는 수십 개의 MCP 서버에 걸쳐 수백 또는 수천 개의 도구에 액세스할 수 있는 에이전트를 정기적으로 구축합니다. 그러나 연결된 도구 수가 증가함에 따라 모든 도구 정의를 미리 로드하고 중간 결과를 컨텍스트 윈도우를 통해 전달하면 에이전트가 느려지고 비용이 증가합니다. 이 블로그에서는 코드 실행이 에이전트가 MCP 서버와 더 효율적으로 상호 작용하여 더 적은 토큰으로 더 많은 도구를 처리할 수 있도록 하는 방법을 살펴보겠습니다.
도구로 인한 과도한 토큰 소비는 에이전트 효율성을 저하시킵니다
MCP 사용이 확장됨에 따라 에이전트 비용과 대기 시간을 증가시킬 수 있는 두 가지 일반적인 패턴이 있습니다:
- 도구 정의가 컨텍스트 윈도우를 과부하시킵니다.
- 중간 도구 결과가 추가 토큰을 소비합니다.
1. 도구 정의가 컨텍스트 윈도우를 과부하시킵니다
대부분의 MCP 클라이언트는 모든 도구 정의를 컨텍스트에 미리 로드하고, 직접 도구 호출 구문을 사용하여 모델에 노출합니다. 이러한 도구 정의는 다음과 같이 보일 수 있습니다:
“
gdrive.getDocument
설명: Google Drive에서 문서를 검색합니다.
매개변수:
documentId (필수, 문자열): 검색할 문서의 ID
fields (선택사항, 문자열): 반환할 특정 필드
반환값: 제목, 본문 콘텐츠, 메타데이터, 권한 등이 포함된 문서 객체
`
`
salesforce.updateRecord
설명: Salesforce에서 레코드를 업데이트합니다.
매개변수:
objectType (필수, 문자열): Salesforce 개체 유형(Lead, Contact, Account 등)
recordId (필수, 문자열): 업데이트할 레코드의 ID
data (필수, 객체): 새 값으로 업데이트할 필드
반환값: 확인 메시지와 함께 업데이트된 레코드 객체
`
도구 설명은 더 많은 컨텍스트 윈도우 공간을 차지하여 응답 시간과 비용을 증가시킵니다. 에이전트가 수천 개의 도구에 연결된 경우 요청을 읽기 전에 수십만 토큰을 처리해야 할 수 있습니다.
2. 중간 도구 결과가 추가 토큰을 소비합니다
대부분의 MCP 클라이언트는 모델이 MCP 도구를 직접 호출할 수 있도록 허용합니다. 예를 들어, 에이전트에게 다음과 같이 요청할 수 있습니다:
"Google Drive에서 내 회의 기록을 다운로드하여 Salesforce 리드에 첨부해주세요."
모델은 다음과 같은 호출을 수행합니다:
`
TOOL CALL: gdrive.getDocument(documentId: "abc123")
→ "4분기 목표에 대해 논의...\n[전체 기록 텍스트]" 반환 (모델 컨텍스트에 로드됨)
TOOL CALL: salesforce.updateRecord(
objectType: "SalesMeeting",
recordId: "00Q5f000001abcXYZ",
data: {
"Notes": "4분기 목표에 대해 논의...\n[전체 기록 텍스트가 작성됨]"
}
)
(모델이 전체 기록을 다시 컨텍스트에 작성해야 함)
`
모든 중간 결과는 모델을 통과해야 합니다. 이 예에서 전체 통화 기록이 두 번 흐릅니다. 2시간 분량의 영업 회의의 경우 이는 추가로 50,000개의 토큰을 처리하는 것을 의미할 수 있습니다. 더 큰 문서는 컨텍스트 윈도우 제한을 초과하여 워크플로가 중단될 수 있습니다. 큰 문서나 복잡한 데이터 구조의 경우 모델이 도구 호출 간에 데이터를 복사할 때 실수를 할 가능성이 더 높을 수 있습니다.
MCP 클라이언트는 도구 정의를 모델의 컨텍스트 윈도우에 로드하고 각 도구 호출과 결과가 작업 간에 모델을 통과하는 메시지 루프를 조율합니다.
MCP를 통한 코드 실행은 컨텍스트 효율성을 개선합니다
에이전트에 대한 코드 실행 환경이 더 보편화됨에 따라 한 가지 해결책은 MCP 서버를 직접 도구 호출이 아닌 코드 API로 제공하는 것입니다. 그러면 에이전트가 MCP 서버와 상호 작용하는 코드를 작성할 수 있습니다. 이 접근 방식은 두 가지 과제를 모두 해결합니다. 에이전트는 필요한 도구만 로드하고 결과를 모델로 다시 전달하기 전에 실행 환경에서 데이터를 처리할 수 있습니다.
이를 수행하는 방법은 여러 가지가 있습니다. 한 가지 접근 방식은 연결된 MCP 서버의 모든 사용 가능한 도구에 대한 파일 트리를 생성하는 것입니다. 다음은 TypeScript를 사용하는 구현 예입니다:
`
servers
├── google-drive
│ ├── getDocument.ts
│ ├── ... (기타 도구)
│ └── index.ts
├── salesforce
│ ├── updateRecord.ts
│ ├── ... (기타 도구)
│ └── index.ts
└── ... (기타 서버)
`
그런 다음 각 도구는 파일에 해당합니다. 예를 들어:
`typescript
// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";
interface GetDocumentInput {
documentId: string;
}
interface GetDocumentResponse {
content: string;
}
/ Google Drive에서 문서 읽기 /
export async function getDocument(input: GetDocumentInput): Promise
return callMCPTool
}
`
위의 Google Drive에서 Salesforce로의 예는 다음과 같은 코드가 됩니다:
`typescript
// Google 문서에서 기록을 읽고 Salesforce 잠재 고객에 추가
import * as gdrive from './servers/google-drive';
import * as salesforce from './servers/salesforce';
const transcript = (await gdrive.getDocument({ documentId: 'abc123' })).content;
await salesforce.updateRecord({
objectType: 'SalesMeeting',
recordId: '00Q5f000001abcXYZ',
data: { Notes: transcript }
});
`
에이전트는 파일 시스템을 탐색하여 도구를 발견합니다. ./servers/ 디렉토리를 나열하여 사용 가능한 서버(google-drive 및 salesforce 등)를 찾은 다음 필요한 특정 도구 파일(getDocument.ts 및 updateRecord.ts 등)을 읽어 각 도구의 인터페이스를 이해합니다. 이렇게 하면 에이전트가 현재 작업에 필요한 정의만 로드할 수 있습니다.
이는 토큰 사용량을 150,000개에서 2,000개로 줄여 98.7%의 시간 및 비용 절감 효과를 가져옵니다. Cloudflare는 유사한 결과를 발표했으며, MCP를 통한 코드 실행을 "코드 모드"라고 언급했습니다. 핵심 통찰력은 동일합니다. LLM은 코드 작성에 능숙하며 개발자는 이 강점을 활용하여 MCP 서버와 더 효율적으로 상호 작용하는 에이전트를 구축해야 합니다.
MCP를 통한 코드 실행의 이점
MCP를 통한 코드 실행은 도구를 요청 시 로드하고 데이터를 모델에 도달하기 전에 필터링하며 복잡한 논리를 한 단계로 실행하여 에이전트가 컨텍스트를 더 효율적으로 사용할 수 있도록 합니다. 이 접근 방식을 사용하면 보안 및 상태 관리 이점도 있습니다.
점진적 공개
모델은 파일 시스템 탐색에 능숙합니다. 파일 시스템의 코드로 도구를 제공하면 모델이 모든 정의를 미리 읽는 대신 요청 시 도구 정의를 읽을 수 있습니다. 또는 관련 정의를 찾기 위해 서버에 search_tools 도구를 추가할 수 있습니다. 예를 들어, 위에서 사용한 가상의 Salesforce 서버로 작업할 때 에이전트는 "salesforce"를 검색하고 현재 작업에 필요한 도구만 로드합니다. search_tools 도구에 세부 수준 매개변수를 포함하면 에이전트가 필요한 세부 수준(이름만, 이름 및 설명, 스키마가 포함된 전체 정의 등)을 선택할 수 있으므로 컨텍스트를 절약하고 도구를 효율적으로 찾을 수 있습니다.
컨텍스트 효율적인 도구 결과
큰 데이터 세트로 작업할 때 에이전트는 반환하기 전에 코드에서 결과를 필터링하고 변환할 수 있습니다. 10,000개 행의 스프레드시트를 가져오는 경우를 고려해 보세요:
`typescript
// 코드 실행 없음 - 모든 행이 컨텍스트를 통과함
TOOL CALL: gdrive.getSheet(sheetId: 'abc123')
→ 수동으로 필터링하기 위해 컨텍스트에 10,000개 행 반환
// 코드 실행 포함 - 실행 환경에서 필터링
const allRows = await gdrive.getSheet({ sheetId: 'abc123' });
const pendingOrders = allRows.filter(row => row["Status"] === 'pending');
console.log(${pendingOrders.length}개의 대기 중인 주문을 찾았습니다);
console.log(pendingOrders.slice(0, 5)); // 검토를 위해 처음 5개만 기록
`
에이전트는 10,000개 대신 5개의 행을 봅니다. 유사한 패턴은 여러 데이터 소스 간의 집계, 조인 또는 특정 필드 추출에도 작동하며, 이 모든 작업은 컨텍스트 윈도우를 부풀리지 않고 수행할 수 있습니다.
더 강력하고 컨텍스트 효율적인 제어 흐름
루프, 조건문, 오류 처리는 개별 도구 호출을 연결하는 대신 익숙한 코드 패턴으로 수행할 수 있습니다. 예를 들어, Slack에 배포 알림이 필요한 경우 에이전트는 다음을 작성할 수 있습니다:
`typescript
let found = false;
while (!found) {
const messages = await slack.getChannelHistory({ channel: 'C123456' });
found = messages.some(m => m.text.includes('deployment complete'));
if (!found) await new Promise(r => setTimeout(r, 5000));
}
console.log('배포 알림을 받았습니다');
`
이 접근 방식은 MCP 도구 호출과 슬립 명령 사이를 에이전트 루프에서 번갈아가며 사용하는 것보다 더 효율적입니다. 또한 실행되는 조건 트리를 작성할 수 있으므로 "첫 번째 토큰까지의 시간" 대기 시간도 절약됩니다. 모델이 if 문을 평가할 때까지 기다리는 대신 코드 실행 환경이 이 작업을 수행할 수 있습니다.
프라이버시 보호 작업
에이전트가 MCP와 함께 코드 실행을 사용하면 중간 결과가 기본적으로 실행 환경에 유지됩니다. 이렇게 하면 에이전트가 명시적으로 기록하거나 반환하는 항목만 보게 되므로 모델과 공유하고 싶지 않은 데이터가 워크플로를 통해 흐르지만 모델의 컨텍스트에 들어가지 않을 수 있습니다.
더 민감한 워크로드의 경우 에이전트 하니스가 중요한 데이터를 자동으로 토큰화할 수 있습니다. 예를 들어, 스프레드시트에서 고객 연락처 세부 정보를 Salesforce로 가져와야 한다고 가정해 보겠습니다. 에이전트는 다음을 작성합니다:
`typescript
const sheet = await gdrive.getSheet({ sheetId: 'abc123' });
for (const row of sheet.rows) {
await salesforce.updateRecord({
objectType: 'Lead',
recordId: row.salesforceId,
data: {
Email: row.email,
Phone: row.phone,
Name: row.name
}
});
}
console.log(${sheet.rows.length}개의 리드를 업데이트했습니다);
`
MCP 클라이언트는 모델에 도달하기 전에 데이터를 가로채 PII를 토큰화합니다:
`typescript
// 에이전트가 sheet.rows를 기록하는 경우 보게 되는 항목:
[
{
salesforceId: '00Q...',
email: '[EMAIL_1]',
phone: '[PHONE_1]',
name: '[NAME_1]'
},
{
salesforceId: '00Q...',
email: '[EMAIL_2]',
phone: '[PHONE_2]',
name: '[NAME_2]'
},
...
]
`
그런 다음 데이터가 다른 MCP 도구 호출에서 공유될 때 MCP 클라이언트의 조회를 통해 토큰화가 해제됩니다. 실제 이메일 주소, 전화번호, 이름이 Google Sheets에서 Salesforce로 흐르지만 모델을 통과하지 않습니다. 이는 에이전트가 실수로 중요한 데이터를 기록하거나 처리하는 것을 방지합니다. 또한 이를 사용하여 데이터가 어디서 어디로 흐를 수 있는지 선택하여 결정론적 보안 규칙을 정의할 수 있습니다.
상태 지속성 및 스킬
파일 시스템 액세스를 통해 코드 실행은 에이전트가 작업 간에 상태를 유지할 수 있도록 합니다. 에이전트는 중간 결과를 파일에 작성하여 작업을 재개하고 진행 상황을 추적할 수 있습니다:
`typescript
const leads = await salesforce.query({
query: 'SELECT Id, Email FROM Lead LIMIT 1000'
});
const csvData = leads.map(l => ${l.Id},${l.Email}).join('\n');
await fs.writeFile('./workspace/leads.csv', csvData);
// 이후 실행은 중단한 곳에서 다시 시작
const saved = await fs.readFile('./workspace/leads.csv', 'utf-8');
`
에이전트는 재사용 가능한 함수로 자체 코드를 유지할 수도 있습니다. 에이전트가 작업에 대한 작동하는 코드를 개발하면 향후 사용을 위해 해당 구현을 저장할 수 있습니다:
`typescript
// ./skills/save-sheet-as-csv.ts에서
import * as gdrive from './servers/google-drive';
export async function saveSheetAsCsv(sheetId: string) {
const data = await gdrive.getSheet({ sheetId });
const csv = data.map(row => row.join(',')).join('\n');
await fs.writeFile(./workspace/sheet-${sheetId}.csv, csv);
return ./workspace/sheet-${sheetId}.csv;
}
// 나중에 모든 에이전트 실행에서:
import { saveSheetAsCsv } from './skills/save-sheet-as-csv';
const csvPath = await saveSheetAsCsv('abc123');
“
이것은 스킬(Skills) 개념과 밀접하게 관련되어 있습니다. 스킬은 모델이 특화된 작업의 성능을 개선하기 위한 재사용 가능한 지침, 스크립트 및 리소스의 폴더입니다. 저장된 함수에 SKILL.md 파일을 추가하면 모델이 참조하고 사용할 수 있는 구조화된 스킬이 생성됩니다. 시간이 지남에 따라 이를 통해 에이전트가 더 높은 수준의 기능 도구 상자를 구축하고 가장 효과적으로 작동하는 데 필요한 스캐폴딩을 발전시킬 수 있습니다.
코드 실행은 자체적인 복잡성을 도입한다는 점에 유의하세요. 에이전트 생성 코드를 실행하려면 적절한 샌드박싱, 리소스 제한 및 모니터링이 있는 보안 실행 환경이 필요합니다. 이러한 인프라 요구 사항은 직접 도구 호출이 피할 수 있는 운영 오버헤드와 보안 고려 사항을 추가합니다. 코드 실행의 이점(감소된 토큰 비용, 더 낮은 대기 시간, 개선된 도구 구성)은 이러한 구현 비용과 비교하여 고려해야 합니다.
요약
MCP는 에이전트를 많은 도구와 시스템에 연결하기 위한 기본 프로토콜을 제공합니다. 그러나 너무 많은 서버가 연결되면 도구 정의와 결과가 과도한 토큰을 소비하여 에이전트 효율성이 저하될 수 있습니다. 여기서 많은 문제는 새로운 것처럼 보이지만(컨텍스트 관리, 도구 구성, 상태 지속성) 소프트웨어 엔지니어링에는 알려진 해결책이 있습니다. 코드 실행은 이러한 확립된 패턴을 에이전트에 적용하여 익숙한 프로그래밍 구문을 사용하여 MCP 서버와 더 효율적으로 상호 작용할 수 있습니다. 이 접근 방식을 구현하는 경우 MCP 커뮤니티와 귀하의 발견을 공유하시기를 권장합니다.
감사의 말
이 문서는 Adam Jones와 Conor Kelly가 작성했습니다. 초안에 대한 피드백을 제공한 Jeremy Fox, Jerome Swannack, Stuart Ritchie, Molly Vorwerck, Matt Samuels, Maggie Vo에게 감사드립니다.
- MCP를 사용하여 연결된 도구가 많아지면 도구 정의와 중간 결과가 컨텍스트 윈도우를 과부화시켜 비용과 대기 시간이 증가
- 코드 실행 환경에서 MCP 서버를 코드 API로 제공하면 필요한 도구만 로드하고 데이터를 처리하여 토큰 사용량을 98.7%까지 감소
- 점진적 공개, 컨텍스트 효율적 결과 처리, 강력한 제어 흐름, 프라이버시 보호, 상태 지속성 및 재사용 가능한 스킬 생성 가능
- 코드 실행은 보안 샌드박싱, 리소스 제한, 모니터링이 필요하며 이러한 인프라 비용을 고려해야 함
Model Context Protocol (MCP)|모델 컨텍스트 프로토콜|AI 에이전트를 외부 시스템에 연결하는 개방형 표준
context window|컨텍스트 윈도우|AI 모델이 한 번에 처리할 수 있는 토큰의 최대 수
sandboxing|샌드박싱|코드 실행을 안전하게 격리하여 시스템 보호하는 기술
Skills|스킬|모델이 특화된 작업의 성능을 개선하기 위한 재사용 가능한 지침, 스크립트 및 리소스
PII (Personally Identifiable Information)|개인 식별 정보|이름, 이메일, 전화번호 등 개인을 식별할 수 있는 정보
핵심 포인트
- MCP를 사용하여 연결된 도구가 많아지면 도구 정의와 중간 결과가 컨텍스트 윈도우를 과부화시켜 비용과 대기 시간이 증가
- 코드 실행 환경에서 MCP 서버를 코드 API로 제공하면 필요한 도구만 로드하고 데이터를 처리하여 토큰 사용량을 98.7%까지 감소
- 점진적 공개, 컨텍스트 효율적 결과 처리, 강력한 제어 흐름, 프라이버시 보호, 상태 지속성 및 재사용 가능한 스킬 생성 가능
- 코드 실행은 보안 샌드박싱, 리소스 제한, 모니터링이 필요하며 이러한 인프라 비용을 고려해야 함
출처: Code execution with MCP: building more efficient AI agents \ Anthropic