증상: 대화는 되는데 도구 인자가 검증에서 실패하고, 재시도가 주문을 두 번 만들고, MCP 서버는 켜져 있는데 도구가 안 보입니다.
가장 빠른 해법: JSON을 모델과 도구 사이의 유일한 계약으로 두십시오. 입력은 JSON Schema로 막고, 결과는 고정 필드로 돌려보내며, 그 계약을 프로세스 밖으로 발견 가능하게 만드는 층이 MCP입니다.
이 글은 언어 모델을 실제 시스템에 붙이는 개발자, 플랫폼 엔지니어, 아키텍트를 위한 것입니다. 새 용어보다, 같은 JSON이 Function Calling, Tool Calling, MCP를 어떻게 지나고 어느 홉에서 멈추는지를 봐야 합니다.
프레임워크 선정이 먼저라면 인공지능 에이전트 개발 프레임워크 선택법을 먼저 읽으십시오. 도구가 실제로 실행될 때의 격리는 AI Sandbox와 Docker, 가상 파일 시스템 비교를 참고하면 됩니다.
AI Agent가 JSON 없이는 못 사는 이유
모델은 자연어를 만듭니다. 운영 시스템은 구조화된 명령만 받습니다. 재고 조회, 티켓 수정, 테스트 실행, 브라우저 조작이 필요해지는 순간 의도는 검증·거부·감사할 수 있는 데이터가 되어야 합니다. JSON은 그 틈에 있습니다. 사람이 읽고, 기계가 파싱하며, HTTP·로그·큐·데이터베이스가 이미 다룹니다.
핵심은 검증 가능성입니다. 산문은 게이트웨이에 order_id는 문자열, amount는 양수, currency는 열거형이라고 알려 주지 못합니다. JSON Schema는 가능합니다. OpenAI Function Calling 문서는 함수 파라미터를 JSON Schema로 정의해, 샘플링 단계에서 합법 구조로 유도합니다. OpenAI Function Calling 가이드 보기
타입, 필수값, enum, additionalProperties는 논문 주제가 아닙니다. 모델이 필드를 지어 내고, 문자열을 숫자에 밀어 넣고, 멱등 키를 빠뜨리는 것을 막는 첫 문입니다. JSON Schema 설명 보기
- 대화 층: 사용자가 “상하이 창고 그 주문을 급송으로”라고 말합니다.
- 계약 층: 모델이
{"name":"update_order","arguments":{"order_id":"A938","priority":"expedited"}}를 냅니다. - 실행 층: 스키마 검증, 권한, 업무 API, 결과 JSON을 모델에 다시 넣습니다.
계약 층이 없으면 에이전트는 채팅창입니다. 있으면 통제 가능한 실행기가 될 수 있습니다.
⚠️ 현장 판단: 도구 인자를 아직 “자유 텍스트 + 정규식”으로 뽑고 있다면 프로토콜이 아니라 프롬프트 운입니다. 스키마를 고정한 뒤에 다중 도구 조율을 하십시오.
Function Calling: 모델이 양식을 채운다
Function Calling의 본질은 사용자에게 답하기 전에 선언된 함수를 호출할지 정하고, 스키마에 맞는 인자를 내는 것입니다. 흐름은 다섯 단계이고 각 단계에서 필드가 빠질 수 있습니다.
- 등록: 요청에 name, description, JSON Schema parameters.
- 결정: 함수 호출 또는 직접 답변.
- 작성: tool_calls. arguments는 JSON 문자열 또는 객체.
- 실행: 파싱, 검증, 인가, 실제 시스템 호출.
- 재주입: 도구 결과를 돌려 최종 답변을 쓰게 함.
description은 광고 문구가 아니라 라우팅 신호입니다. “날씨 조회”와 “배송 조회”가 서로 싸웁니다. “도시명이 있을 때만 현재 기온을 조회하고 과거 기후에는 쓰지 말 것”이 오호출을 줄입니다. 스키마 안 필드 설명도 프롬프트이므로 “order_id는 업무 주문 번호이지 결제 ID가 아님”은 시스템 프롬프트에만 두지 마십시오.
strict / Structured Outputs는 “JSON처럼 보임”을 “스키마 일치”로 올립니다. JSON mode는 중괄호가 파싱된다는 것만 보장합니다. 스키마 합법이 업무 합법은 아닙니다. 음수 금액, 없는 창고, 권한 없는 주문은 애플리케이션에서 막아야 합니다.
최소 실행 계약
아래 스키마는 열거형과 멱등 키를 고정합니다. 호출하지 않을 수는 있어도 창고 필드를 지어 내거나 idempotency_key를 빼먹을 수는 없습니다.
{
"type": "function",
"name": "update_shipment",
"description": "사용자가 배송 우선순위 변경을 분명히 요청할 때만 호출한다.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "업무 주문 번호"},
"priority": {"type": "string", "enum": ["standard", "expedited"]},
"idempotency_key": {"type": "string"}
},
"required": ["order_id", "priority", "idempotency_key"],
"additionalProperties": false
}
}
실행 순서는 JSON parse → 스키마 검증 → 권한 → 멱등 테이블 → 업무 API → {"ok":true,"shipment_id":"..."} 또는 {"ok":false,"error":"not_found"}입니다. 스택과 비밀을 tool result에 넣지 마십시오.
Tool Calling: 함수에서 도구 평면으로
팀이 필요한 것은 자체 함수만이 아닙니다. 검색, 코드 실행, 브라우저, 컴퓨터 조작, 파일 검색도 도구입니다. API는 초기 function_call에서 통합 tools / Tool Calling으로 옮겼습니다. 이름은 바뀌었고 JSON 계약(이름, 스키마, 호출 기록, 결과 회수)은 그대로입니다.
Anthropic은 Tool use라고 부르며 input_schema를 JSON Schema로 적습니다. 모델은 tool_use 블록으로 구조화 인자를 내고, 앱은 tool_result로 돌립니다. Anthropic Tool use 문서 보기
- 병렬 호출: 읽기는 병렬, 재고 잠금과 결제는 직렬.
- 승인: 고위험 도구는 실행 대신 pending JSON.
- 관측: trace에 도구 이름, 인자 요약, 지연, 오류 코드.
실패 형태도 바뀝니다. 올바른 도구를 골라도 문자열 필드에 위험한 페이로드를 숨길 수 있습니다. 타입은 스키마가 잡고, 의미 공격은 실행 층의 허용 목록·타임아웃·샌드박스가 잡습니다.
MCP: JSON 계약을 꽂을 수 있게
Function / Tool Calling은 한 API 요청 안의 대화입니다. MCP는 도구 발견, 여러 호스트 재사용, 별도 프로세스 실행입니다. 규격은 JSON-RPC 2.0으로 initialize, 목록, 호출, 알림을 나릅니다. MCP 규격 보기
- 호스트가 MCP Client로 기동합니다.
- stdio, SSE, Streamable HTTP로 연결합니다.
- initialize로 버전과 능력을 협상합니다.
- tools/list가 여전히 JSON Schema인 inputSchema를 돌려줍니다.
- 모델은 Tool Calling을 하고, MCP 도구면 Client가 JSON 인자로 tools/call을 보냅니다.
- Server content를 tool result로 바꿔 모델에 넣습니다.
MCP는 JSON을 대체하지 않습니다. 코드에 박힌 tools 배열을 런타임 카탈로그로 바꿉니다. 같은 Git, 브라우저 자동화, 티켓 API를 Cursor, Claude Desktop, 자체 에이전트가 공유할 수 있습니다.
“설치했는데 도구가 안 보인다”는 거의 계약 문제입니다. initialize 실패, 빈 list, strict 비호환, required 누락, JSON-RPC error 대신 자연어 오류입니다.
전체 흐름: 한 문장에서 MCP 실행까지
- 사용자가 자연어를 입력합니다.
- 런타임이 messages, 로컬 tools, MCP tools/list를 모읍니다.
- 모델이 Tool Calling으로 JSON 인자를 냅니다.
- 로컬 함수 또는 JSON-RPC tools/call로 분기합니다.
- 결과 JSON이 대화로 돌아옵니다.
- 재호출, 사용자 확인, 최종 답변 중 하나입니다.
놓치기 쉬운 경계: 모델은 데이터베이스 연결을 갖지 않습니다. JSON만 냅니다. 누가 파싱하고 어느 기계에서 실행하며 SSH/VNC와 외부 네트워크를 허용할지는 런타임 정책입니다. 클라우드 Mac의 에이전트도 프로토콜은 같고 권한 평면만 다릅니다.
| 층 | JSON의 역할 | 막아야 할 지점 |
|---|---|---|
| Function Calling | 한 요청의 함수 인자 | schema, strict, 업무 검증 |
| Tool Calling | 공통 평면의 호출 기록 | 병렬, 승인, trace |
| MCP | 프로세스 간 발견과 호출 | 전송, 인증, list/call 오류 |
제품 이름에 끌리지 마십시오. 한 앱 전용이면 Function/Tool Calling이면 됩니다. 여러 호스트가 재사용하면 MCP Server가 이득입니다. 스키마와 검증 없이 MCP만 올리면 혼란이 다른 프로세스로 이사할 뿐입니다.
JSON이 깨지면 에이전트 전체가 깨진다
- 유효 JSON이 아님: strict 꺼짐, 먼저 설명하라는 프롬프트, 마크다운 코드 블록. 구조화 도구 채널만 쓰고 산문에서 인자를 뽑지 마십시오.
- 파싱은 되나 스키마 실패: required 누락, 잘못된 enum, 추가 속성. 검증 오류를 tool result로 주고 재시도를 제한하십시오.
- 스키마는 통과, 업무 실패: 없는 주문, 재고 부족, 권한 거부. 안정된 error code를 반환하십시오.
- 재시도 이중 기록: 타임아웃 후 두 번째 호출. idempotency_key와 실행 측 중복 제거.
- list와 call 불일치: 핫 리로드 후 이름·스키마 변경. 이름과 스키마 해시를 버전하고 변경 시 initialize를 다시 하십시오.
- 비밀이 JSON 로그에: 공유 trace에 전체 인자. 필드명과 해시만 남기고 토큰·개인정보를 가리십시오.
타임아웃, 스키마 실패, 권한 거부를 하나의 인수 시나리오로 만드십시오. 무한 재시도나 인자 임의 변경이 남으면 결제·출고·운영 DB에 연결하지 마십시오.
출고 전 JSON 계약 점검표
- [ ] 모든 도구에 name, description, JSON Schema, additionalProperties: false.
- [ ] 고위험 필드는 enum / format / 최대 길이.
- [ ] 쓰기는 멱등 키. 타임아웃과 재시도는 런타임에.
- [ ] tool result는 ok / error / data. 스택 원문 금지.
- [ ] 부작용으로 병렬을 나눔. 결제·메일·삭제는 기본 직렬.
- [ ] MCP initialize / list / call에 타임아웃, 인증, 오류 코드.
- [ ] 카탈로그 변경 후 호스트가 스키마를 다시 가져옴.
- [ ] trace는 호출 사슬을 복원하고 비밀은 복원하지 않음.
- [ ] 고정 입력은 같은 도구 이름과 같은 필수 필드 집합에 도달.
통과한 뒤에 다중 에이전트나 무거운 워크플로를 검토하십시오. 불안정한 프로토콜은 깨진 JSON을 더 빨리 복제할 뿐입니다.
FAQ
왜 자연어를 프로그램이 바로 읽게 하지 않나요?
필수 필드와 타입이 없습니다. “급하게”를 열거형에 안정적으로 매핑할 수 없고 여분 필드도 거절하기 어렵습니다. JSON Schema는 파싱을 검증으로 바꿉니다.
Function Calling과 Tool Calling은 실질적으로 다른가요?
앱 개발자에게 핵심은 같습니다. 모델이 JSON 양식을 채우고 코드가 실행합니다. Tool Calling은 검색·코드 실행 같은 호스트 도구, 병렬 호출, 통합 결과 채널이 더 넓습니다. 이전할 때는 스키마와 메시지 역할을 먼저 맞추십시오.
언제 MCP가 필요하고 언제 배열 하드코딩이면 되나요?
같은 도구를 여러 호스트가 쓰고, 별도 프로세스로 격리하거나 다른 팀이 배포할 때 MCP가 이득입니다. 한 내부 서비스와 수명을 같이하면 Function/Tool Calling이 단순합니다.
가끔 잘못된 JSON이 나옵니다. 재시도할까요, 프로토콜을 바꿀까요?
엄격한 구조화 출력을 켜고 산문에서 인자 추출을 중지하십시오. 빈도가 높으면 스키마 깊이, 설명 충돌, 도구 개수를 점검하십시오. MCP로 바꿔도 인자는 여전히 JSON입니다.
공유 노트북에서 에이전트를 돌리면 환경이 바뀔 때마다 스키마 회귀가 깨지고 MCP 프로세스가 개발 포트와 싸웁니다. Kvmjet 베어메탈 Mac 클라우드 호스트는 macOS 이미지를 고정해 SSH 또는 VNC로 같은 Tool Calling / MCP 실패를 재현할 수 있습니다. 공개 안내에 일 단위부터 분기 단위 과금이 있어, JSON 계약을 안정시킨 뒤 장기 사용을 결정할 수 있습니다.
점검표를 들고 Kvmjet 도움말 센터에서 상시 실행, 권한 격리, 원격 접속을 확인한 다음 MCP 서버를 노트북, 랙, 클라우드 Mac 중 어디에 둘지 정하십시오.
고정된 Mac 런타임에서 Tool Calling과 MCP 검증
스키마, 멱등 키, MCP 서버는 재현 가능한 환경이 필요합니다. 공유 노트북은 디렉터리와 포트가 금방 흔들립니다.
Kvmjet 베어메탈 M4 Mac은 실제 macOS와 SSH/VNC로 같은 tools/call 실패를 반복 재현할 수 있습니다.