-
MCP가 JSON-RPC 봉투 안에 채운 것들: 세 기본 단위와 20가지 메서드 전체 지도IT 2026. 6. 12. 22:00
지난 글에서 JSON-RPC 2.0이 봉투 6단어(
jsonrpc·id·method·params·result·error)만 정의하고, 그 안의 내용물은 전부 상위 계층이 채운다는 걸 짚었다. 그 상위 계층이 바로 MCP(Model Context Protocol)다. 이번 글은 MCP가 봉투 안에 실제로 뭘 채웠는지를 다룬다 — 메서드 이름, params 구조, result 구조, 그리고 각 메서드가 왜 필요하고 언제 쓰이는지.MCP의 메서드는 현재 20여 개다. 흩어져 보이지만 세 기본 단위(Tools·Resources·Prompts)와 초기화·보조 카테고리로 묶으면 구조가 선명해진다. 가장 중요한 발견을 먼저 꺼내자면 — MCP는 단방향이 아니다. 서버가 클라이언트에게 LLM 호출을 위임(
sampling/createMessage)하거나, 클라이언트가 보유한 파일 시스템 루트 목록을 서버가 물어보는(roots/list) 역방향 흐름이 프로토콜 안에 설계되어 있다. 이 역방향을 이해해야 MCP 아키텍처 전체가 보인다.세 기본 단위 — Tools·Resources·Prompts
MCP 명세는 AI 모델이 외부 세계와 상호작용할 수 있는 경로를 세 개로 분류한다.
그림: MCP의 세 기본 단위 — 각각 두 개의 메서드 쌍(list/call)으로 노출된다 다이어그램 설명: 세 단위는 목적이 분명히 다르다. Tools는 모델이 실행하고 결과를 받는 "행동", Resources는 모델이 문맥으로 읽어들이는 "데이터", Prompts는 사람이 골라서 대화에 끼우는 "템플릿"이다. 이 구분이 명세 전반에 걸쳐 일관되게 유지된다 — 메서드 이름의 접두어(
tools/·resources/·prompts/)가 곧 이 분류를 따른다.왜 중요한가: 셋을 구분하는 게 API 설계의 의도를 읽는 열쇠다. "이 도구를 왜 Tool로 안 만들고 Resource로 만들었지?"라는 질문의 답이 이 분류에 있다 — 모델이 직접 실행해서 결과를 만들면 Tool, 읽어서 맥락으로 쓰면 Resource다.
초기화 핸드셰이크 — initialize와 notifications/initialized
클라이언트(LLM 에이전트)와 서버가 처음 만날 때 반드시 거쳐야 하는 단계가 있다. 서로 어떤 기능을 지원하는지 협상(capability negotiation)하는 핸드셰이크다. 이 없이는
tools/list를 보내도 서버가 거부할 수 있다 — 아직 준비 안 됐으니까.다이어그램 설명: 세 단계 핸드셰이크다. 1) 클라이언트가
initialize를 보내면서 자신의 버전과 capabilities(지원하는 기능 목록)를 알린다. 2) 서버가 자신의 capabilities로 응답한다. 3) 클라이언트가notifications/initialized를 보내면 세션이 활성화된다. 세 번째 단계가 "알림(notification)"인 게 중요 —id가 없으므로 서버는 응답을 돌려보내지 않는다. 클라이언트의 일방적인 "나 준비 끝" 신호다.// 1단계: 클라이언트 → 서버 (initialize 요청) { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", // MCP 명세 버전 "capabilities": { "roots": { "listChanged": true }, // 클라이언트가 roots/list_changed 알림을 보낼 수 있음 "sampling": {} // 클라이언트가 sampling/createMessage를 처리할 수 있음 }, "clientInfo": { "name": "claude-code", "version": "1.0.0" } } } // 2단계: 서버 → 클라이언트 (응답) { "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", // 합의된 버전 "capabilities": { "tools": { "listChanged": true }, // 도구 목록이 바뀌면 알림 보낼 수 있음 "resources": { "subscribe": true, // 리소스 변경 구독 지원 "listChanged": true }, "prompts": { "listChanged": true }, "logging": {} }, "serverInfo": { "name": "mcp-server", "version": "0.9.0" } } } // 3단계: 클라이언트 → 서버 (알림, id 없음 → 응답 없음) { "jsonrpc": "2.0", "method": "notifications/initialized" }코드 설명:
capabilities객체가 핵심이다. "나는 이런 기능을 지원한다"는 선언이지, "나는 이 기능을 사용하겠다"는 요청이 아니다. 클라이언트가sampling: {}을 넣으면 "서버야, 나한테 LLM 호출을 위임해도 돼"라는 뜻이다. 서버가tools.listChanged: true를 넣으면 "내 도구 목록이 바뀌면 알림 보낼게"라는 뜻이다. 이 협상이 끝난 후에야 해당 기능이 활성화된다.protocolVersion은 클라이언트가 먼저 제안하고 서버가 자신이 지원하는 버전으로 응답한다 — 버전이 안 맞으면 연결을 끊는다.왜 중요한가: 핸드셰이크를 건너뛰거나 순서를 바꾸면 서버 구현에 따라 이후 모든 요청이
-32603 Internal error로 거부된다. MCP 클라이언트를 직접 만들 때 가장 흔한 실수 1위가 이 순서를 빠뜨리는 것이다.Tools — 모델이 실행하는 함수
가장 많이 쓰이는 카테고리다. 이전 글에서
tools/list와tools/call의 JSON 모양을 다뤘으니 여기서는 설계 원칙과 심화 내용에 집중한다.다이어그램 설명: tools/list → tools/call 흐름이다. 모델 자체는 MCP를 직접 호출하지 않는다 — 항상 클라이언트(Claude Code, Cursor 등 에이전트 런타임)가 중간에서 중계한다. 모델이 "build-app 써줘"라고 말하면 클라이언트가
tools/call을 MCP 서버에 보내고, 결과를 받아 다시 모델에게 전달한다. 이 삼각 구도가 MCP 전체 흐름의 기본 패턴이다.tools/call 응답의
content배열은 여러 형식을 섞을 수 있다. 텍스트 결과만 돌려주는 게 아니라 이미지나 리소스 참조도 포함할 수 있다.// tools/call 응답 — content 배열의 세 가지 타입 { "jsonrpc": "2.0", "id": 7, "result": { "content": [ // 타입 1: 텍스트 { "type": "text", "text": "빌드 성공. 출력: app-release-arm64.pkg" }, // 타입 2: 이미지 (base64 인코딩) { "type": "image", "data": "iVBORw0KGgo...", "mimeType": "image/png" }, // 타입 3: 리소스 참조 (서버 리소스를 URI로 가리킴) { "type": "resource", "resource": { "uri": "file:///app/build/report.html", "mimeType": "text/html" } } ], "isError": false // true면 도구는 실행됐지만 오류 발생 (JSON-RPC 에러와 다름) } }코드 설명:
isError: true와 JSON-RPC의error필드는 의미가 다르다.isError: true는 "도구는 정상 실행됐는데 도구의 로직이 실패를 보고"하는 것이다 — 예를 들어 빌드 오류. JSON-RPC의error는 "도구를 실행하기 전에 프로토콜 수준에서 실패"한 것이다 — 예를 들어 인자 형식 오류. 클라이언트는 둘을 다르게 처리해야 한다:isError: true면 모델에게 실패 내용을 전달하고 재시도를 허용하고, JSON-RPCerror면 재시도 전에 인자 자체를 수정해야 한다.Resources — 모델이 읽는 데이터
Resources는 MCP 서버가 외부 데이터를 모델에게 공급하는 경로다. 파일, 데이터베이스 레코드, API 응답, 로그 같은 것들이 URI(Uniform Resource Identifier, URL처럼 리소스를 고유하게 가리키는 식별자)로 식별되어 노출된다. Tools와의 결정적 차이 — Resources는 모델이 직접 실행하지 않고, 클라이언트가 context에 삽입한다.
Resources에는 정적 리소스 외에 URI 템플릿도 있다. 고정 파일 경로가 아니라 파라미터로 동적으로 결정되는 리소스를 노출할 때 쓴다.
// resources/list 응답 { "jsonrpc": "2.0", "id": 2, "result": { "resources": [ { "uri": "file:///src/main.c", "name": "main.c", "description": "연결 모듈 진입점", "mimeType": "text/x-csrc" }, { "uri": "sqlite:///build.db?table=jobs", "name": "build_jobs", "description": "빌드 작업 이력", "mimeType": "application/json" } ] } } // resources/templates/list 응답 — URI 템플릿 (RFC 6570 형식) { "jsonrpc": "2.0", "id": 3, "result": { "resourceTemplates": [ { "uriTemplate": "log://build/{job_id}", // {job_id}가 파라미터 "name": "build_log", "description": "빌드 작업별 로그", "mimeType": "text/plain" } ] } } // resources/read — 실제 파일 내용 요청 { "jsonrpc": "2.0", "id": 4, "method": "resources/read", "params": { "uri": "file:///src/main.c" } } // resources/read 응답 { "jsonrpc": "2.0", "id": 4, "result": { "contents": [ { "uri": "file:///src/main.c", "mimeType": "text/x-csrc", "text": "#include \nint main() { ... }" // 텍스트면 text, 바이너리면 blob } ] } }코드 설명: URI 스키마는 MCP가 강제하지 않는다 —
file://·sqlite://·log://모두 서버가 자유롭게 정의한다. 클라이언트가 opaque string으로 취급하면 된다. URI 템플릿의{job_id}는 RFC 6570(URI Template) 표준으로, 클라이언트가 실제 값으로 채워서resources/read에 보낸다.contents배열의 각 항목은text(UTF-8 텍스트) 또는blob(base64 바이너리) 중 하나다 — 이미지·PDF 같은 바이너리 리소스도 이 경로로 노출된다.resources/subscribe — 변경 감지
MCP는 리소스 내용이 바뀌면 서버가 클라이언트에게 알릴 수 있는 구독 메커니즘도 갖고 있다. 파일을 편집 중인데 그 파일이 다른 프로세스에 의해 바뀌면 자동으로 알림이 온다.
다이어그램 설명: subscribe → (변경 알림) → read → unsubscribe의 전형적인 흐름이다.
notifications/resources/updated는 서버에서 클라이언트로 가는 알림 — 응답을 기대하지 않는다. 알림을 받은 클라이언트가 직접resources/read를 다시 보내서 새 내용을 가져온다. "push 알림 + pull 데이터"의 패턴이다.resources/subscribe가 지원되는지는 초기화 핸드셰이크의capabilities.resources.subscribe: true로 확인한다.Prompts — 재사용 프롬프트 템플릿
Prompts는 MCP의 세 기본 단위 중 가장 오해받는다. Tools도 Resources도 아닌 세 번째 — 서버가 "이런 방식으로 나를 사용하면 잘 돌아가"라는 사용 패턴을 미리 정의해두는 것이다. 사람이 명시적으로 선택해서 대화에 끼우는 템플릿이라는 점에서 Tools(모델이 자율 실행)·Resources(context 삽입)와 다르다.
다이어그램 설명: 모델이 아니라 사람이 프롬프트를 선택한다는 점이 Tools 흐름과 다르다. IDE 플러그인이 슬래시 명령어 드롭다운으로 prompts/list를 보여주고, 사람이 고르면 prompts/get으로 완성된 메시지 배열을 받아 대화에 끼워 넣는 식이다.
// prompts/list 응답 { "jsonrpc": "2.0", "id": 5, "result": { "prompts": [ { "name": "code-review", "description": "코드를 검토하고 개선점을 제안합니다", "arguments": [ { "name": "language", "description": "프로그래밍 언어", "required": true }, { "name": "focus", "description": "리뷰 초점 (성능/보안/가독성)", "required": false } ] } ] } } // prompts/get — 인자를 채워서 완성된 프롬프트 요청 { "jsonrpc": "2.0", "id": 6, "method": "prompts/get", "params": { "name": "code-review", "arguments": { "language": "rust", "focus": "보안" } } } // prompts/get 응답 — messages 배열로 돌아옴 { "jsonrpc": "2.0", "id": 6, "result": { "description": "Rust 보안 코드 리뷰", "messages": [ { "role": "user", "content": { "type": "text", "text": "다음 Rust 코드를 보안 관점에서 검토해주세요. unsafe 블록, 정수 오버플로, 메모리 안전성을 중점으로..." } } ] } }코드 설명:
messages배열은 LLM 대화의 history 형식과 같다 —role이user·assistant·system중 하나고,content에 메시지 내용이 담긴다. 클라이언트는 이 배열을 그대로 대화 context에 prepend하면 된다. 인자(arguments)를 받아 템플릿을 채우는 로직은 서버 안에 있다 — 클라이언트는 인자만 넘기고 완성된 메시지를 받는다. 이 덕분에 MCP 서버를 만드는 팀이 "최적 프롬프트"를 서버에 캡슐화하고, 클라이언트는 그냥 따른다.역방향의 충격 — sampling/createMessage
여기서 MCP의 가장 독특한 설계가 나온다. 지금까지는 클라이언트가 서버에게 요청을 보내는 흐름이었다.
sampling/createMessage는 반대다 — 서버가 클라이언트에게 "LLM 호출을 대신 해줘"라고 요청한다.다이어그램 설명: 서버가 클라이언트에게 JSON-RPC 요청을 보낸다. 방향이 완전히 뒤집혔다. 서버는 LLM API 키를 갖고 있지 않아도 된다 — LLM 접근 권한은 클라이언트가 갖고 있다. 클라이언트는 이 요청을 받았을 때 사람에게 확인을 구하거나 자동으로 처리하거나 거부할 수 있다. 이 승인 단계가 MCP에서 Human-in-the-Loop(사람의 중간 개입)를 구현하는 표준 방법이다.
// 서버 → 클라이언트: sampling/createMessage 요청 { "jsonrpc": "2.0", "id": 100, "method": "sampling/createMessage", "params": { "messages": [ { "role": "user", "content": { "type": "text", "text": "다음 C 코드에서 parse_request의 실제 의도를 한 문장으로 요약해줘:\n[코드 스니펫]" } } ], "modelPreferences": { "hints": [{ "name": "claude-3-5-haiku" }], // 선호 모델 힌트 (강제 아님) "speedPriority": 0.9, // 0=품질, 1=속도 "intelligencePriority": 0.3 }, "systemPrompt": "너는 연결 모듈 전문가다.", "maxTokens": 200 } } // 클라이언트 → 서버: 응답 (클라이언트가 LLM을 호출한 결과) { "jsonrpc": "2.0", "id": 100, "result": { "role": "assistant", "content": { "type": "text", "text": "parse_request는 HTTP 요청 버퍼를 파싱해 구조체로 변환하는 비동기 진입점이다." }, "model": "claude-3-5-haiku-20241022", // 실제 사용된 모델 "stopReason": "end_turn" } }코드 설명:
modelPreferences는 서버가 선호를 "힌트"로 제안하는 것이지 강제가 아니다 — 클라이언트가 실제로 어떤 모델을 쓸지는 클라이언트가 결정한다.speedPriority·intelligencePriority는 0~1 사이 값으로 트레이드오프를 표현한다. 응답에model필드가 있어서 서버는 실제로 어떤 모델이 답했는지 알 수 있다. 이 메커니즘이 가능하려면 초기화 핸드셰이크에서 클라이언트가capabilities.sampling: {}을 선언했어야 한다 — 선언하지 않은 클라이언트에게 서버가sampling/createMessage를 보내면-32601 Method not found가 온다.왜 중요한가: 이 설계의 핵심은 "LLM 접근을 클라이언트가 독점한다"는 것이다. 서버는 LLM에 직접 접근하지 않는다 — 클라이언트에게 위임한다. 그래서 API 키 관리·비용 제어·사용자 승인이 한 곳(클라이언트)에서 통제된다. 서버가 악의적이어도 클라이언트가 모든 LLM 호출을 검토할 수 있다는 보안 모델이기도 하다.
roots/list — 클라이언트의 파일시스템을 서버가 물어본다
sampling/createMessage처럼 역방향인 메서드가 하나 더 있다.roots/list는 서버가 클라이언트에게 "너는 어떤 파일시스템 루트에 접근 권한이 있니?"를 묻는다. IDE 플러그인이 MCP 클라이언트라면, 현재 열려 있는 프로젝트 디렉토리를 roots로 노출한다.// 서버 → 클라이언트: 내가 접근할 수 있는 디렉토리 목록 요청 { "jsonrpc": "2.0", "id": 101, "method": "roots/list" } // 클라이언트 → 서버: 현재 열린 작업 공간 { "jsonrpc": "2.0", "id": 101, "result": { "roots": [ { "uri": "file:///home/user/projects/my-app", "name": "my-app" }, { "uri": "file:///home/user/projects/shared-lib", "name": "shared-lib" } ] } }코드 설명: 서버는 이 응답으로 어떤 경로를
resources/read로 노출할지, 어떤 범위에서 파일을 검색할지를 결정한다. 클라이언트가 루트 목록을 바꾸면(새 프로젝트 열기, 기존 닫기)notifications/roots/list_changed알림을 서버에게 보내고, 서버는roots/list를 다시 요청한다. "클라이언트가 제공하는 컨텍스트 범위를 서버가 동적으로 따라간다"는 설계다.알림(Notifications) 시스템 — 일방향 신호들
MCP의 알림은
id없이 보내는 일방향 메시지다. 응답을 기대하지 않는다. 크게 세 카테고리로 묶인다 — 초기화 신호, 변경 감지, 진행 상황.다이어그램 설명: 알림도 방향이 있다. 클라이언트에서 서버로 가는 것(3개)과 서버에서 클라이언트로 가는 것(6개)이 따로 있다. 가장 자주 마주치는 것들:
notifications/progress는 긴 작업의 중간 진행률 업데이트(프론트엔드 프로그레스 바에 해당),notifications/tools/list_changed는 "내 도구 목록 바뀌었으니 다시 tools/list 해줘"라는 힌트,notifications/cancelled는 클라이언트가 이미 보낸 요청을 취소할 때 쓴다.// notifications/progress — 긴 작업의 진행률 알림 (서버 → 클라이언트) { "jsonrpc": "2.0", "method": "notifications/progress", "params": { "progressToken": "build-42", // 원래 요청에 붙인 progressToken과 같은 값 "progress": 73, // 현재 진행 (단위는 서버 자유) "total": 100 // 총량 (선택 — 없으면 클라이언트가 진행바를 indeterminate로 표시) } } // notifications/cancelled — 클라이언트가 요청 취소 (클라이언트 → 서버) { "jsonrpc": "2.0", "method": "notifications/cancelled", "params": { "requestId": 7, // 취소할 요청의 id "reason": "user requested" // 선택: 취소 이유 } } // notifications/message — 서버 로그 메시지 (서버 → 클라이언트) { "jsonrpc": "2.0", "method": "notifications/message", "params": { "level": "warning", // debug | info | warning | error "logger": "build-runner", "data": "빌드 디렉토리 쓰기 권한 없음, 임시 디렉토리로 대체" } }코드 설명:
notifications/progress를 사용하려면 원래 요청(tools/call등)의params에progressToken을 넣어야 한다. 서버는 이 토큰을 받으면 "이 클라이언트는 진행률 알림을 원한다"는 신호로 알고 중간중간 알림을 보낸다. 토큰이 없으면 서버는 알림을 보내지 않는다.notifications/message의level은 Python logging과 같은 레벨 체계다 — 클라이언트는 이를 받아 IDE 콘솔이나 로그 패널에 표시한다.logging/setLevel — 서버 로그 제어
서버가
notifications/message로 얼마나 상세한 로그를 보낼지를 클라이언트가 제어한다. 배포 환경에서는warning, 디버깅할 때는debug로 동적으로 바꿀 수 있다.// logging/setLevel — 클라이언트 → 서버 { "jsonrpc": "2.0", "id": 10, "method": "logging/setLevel", "params": { "level": "debug" // debug | info | notice | warning | error | critical | alert | emergency } } // 응답 { "jsonrpc": "2.0", "id": 10, "result": {} }코드 설명: 8단계 레벨은 syslog 표준을 따른다.
debug→info→notice→warning→error→critical→alert→emergency순서로 심각도가 높아진다. 서버는 설정된 레벨 이상의 메시지만notifications/message로 보낸다. 응답이 빈 객체({})라는 게 특징 — "성공했다"는 신호만 준다. 이 메서드가 지원되는지도 초기화 핸드셰이크의capabilities.logging: {}으로 확인한다.completion/complete — 인자 자동완성
IDE의 자동완성처럼, 클라이언트가 "이 Tool·Prompt의 이 인자에 어떤 값을 넣으면 되나요?"를 서버에게 실시간으로 물어보는 메서드다. 사람이 MCP 서버 UI에서 인자를 입력할 때 도움이 된다.
// completion/complete 요청 { "jsonrpc": "2.0", "id": 11, "method": "completion/complete", "params": { "ref": { "type": "ref/prompt", // ref/prompt 또는 ref/resource "name": "code-review" // 어떤 프롬프트/리소스의 인자인지 }, "argument": { "name": "language", // 어떤 인자를 자동완성하는지 "value": "ru" // 지금까지 입력한 값 } } } // 응답 { "jsonrpc": "2.0", "id": 11, "result": { "completion": { "values": ["rust", "ruby", "r"], // 후보 목록 (최대 100개) "total": 3, // 전체 후보 수 (선택) "hasMore": false // 더 있으면 true (페이징) } } }코드 설명:
ref.type이ref/prompt면 프롬프트 인자 자동완성,ref/resource면 리소스 URI 템플릿 파라미터 자동완성이다. 예를 들어uriTemplate: "log://build/{job_id}"에서job_id에 어떤 값이 들어가는지 서버에게 물어볼 수 있다. 후보 목록이 100개를 넘으면hasMore: true로 잘려서 오고, 사용자가 더 입력할 때 다시 물어봐야 한다.전체 메서드 지도
그림: MCP 전체 메서드 — 파란 화살표는 클라이언트→서버, 빨간 화살표는 서버→클라이언트(역방향) 다이어그램 설명: 메서드를 5개 그룹으로 묶었다. 초기화(파란 테두리)·Tools(남색)·Resources(초록)·Prompts(노랑)는 클라이언트가 시작하는 요청이다. 역방향(빨간 테두리)은 서버가 시작한다 —
sampling/createMessage·roots/list·서버발 notifications가 여기 속한다. 보조(보라)는logging/setLevel·completion/complete처럼 부가 기능이다. 방향 화살표를 다르게 그린 이유는 이 구분이 구현에서 가장 헷갈리는 부분이기 때문이다 — 서버 코드를 짜다 보면 클라이언트로 요청을 보낼 수 있다는 걸 나중에야 알게 되는 경우가 많다.메서드별 언제/왜 쓰나 — 한 눈에
그림: MCP 메서드 사용 시점과 방향 — 빨간 행이 역방향(서버발) 계층 책임 정리
두 편에 걸쳐 JSON-RPC 2.0과 MCP를 살폈다. 각 계층이 무엇을 책임지고 무엇을 위임하는지 정리하면 이렇다.
JSON-RPC 2.0이 정한 것: jsonrpc · id · method · params · result · error (봉투 6단어) 표준 에러 코드 -32700 ~ -32603 id 유무로 알림(notification) 구분 MCP가 정한 것: method 값: initialize, tools/list, tools/call, resources/list, resources/read, resources/templates/list, resources/subscribe, resources/unsubscribe, prompts/list, prompts/get, sampling/createMessage, roots/list, logging/setLevel, completion/complete, notifications/* (20여 개) params 구조: 메서드별 별도 명세 result 구조: 메서드별 별도 명세 capabilities 협상 모델 (핸드셰이크) 세 기본 단위 분류 (Tools·Resources·Prompts) MCP 서버 개발자가 정하는 것: 도구별 inputSchema (JSON Schema 형식) 도구별 반환 페이로드 (content 배열의 내용) 리소스 URI 스키마 및 실제 데이터 프롬프트 템플릿 내용 어떤 capabilities를 지원할지코드 설명: 세 계층은 책임이 분리되어 있고, 각 계층의 변경이 다른 계층에 영향을 주지 않는다. MCP가 새 메서드를 추가해도 JSON-RPC 봉투는 그대로다. 서버 개발자가 새 도구를 추가해도 MCP 명세는 그대로다. 이 분리가 MCP 생태계가 중앙 조율 없이 확장될 수 있는 이유다.
MCP 서버를 직접 만들어보면 이 계층 구분이 구체적으로 와닿는다 —
tools/call을 처리하는 핸들러를 짤 때, 내가 건드리는 건content배열의 내용물뿐이다. JSON-RPC 봉투를 싸는 건 MCP SDK가 하고, MCP의 result 구조도 SDK가 안다. 내가 새 도구를 만든다는 건 "이 이름·이 inputSchema·이 반환 페이로드"를 SDK에 등록하는 것뿐이다. 봉투 계층에서 손댈 게 없다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
MCP sampling/createMessage: AI 도구가 AI를 부르는 역방향 설계 (0) 2026.06.14 MCP Roots 완전 분해: 서버가 클라이언트에게 먼저 묻는 역방향 설계 (0) 2026.06.13 MCP Prompts의 멀티턴 messages — 서버가 모델의 첫 생각을 설계하는 방법 (0) 2026.06.13 MCP Prompts 완전 분해: 최적 프롬프트를 서버에 봉인하고 재사용하는 방법 (0) 2026.06.13 MCP Resources 완전 분해: URI로 AI에게 데이터를 공급하는 7가지 메서드 (0) 2026.06.12 JSON-RPC 2.0이 정의하는 건 봉투 6단어뿐: MCP 사례로 그 안과 밖을 가른다 (1) 2026.06.12 서브에이전트 패키지를 직접 뜯어보다 — debug-pack 플러그인 해부 (0) 2026.06.11 Claude에 브라우저 눈과 손을 달다 — Playwright MCP 플러그인 (0) 2026.06.10 Claude에 GitHub 전체를 연결하다 — GitHub MCP 플러그인 실전 가이드 (0) 2026.06.10 Claude Code에서 나만의 AI 전문가 만들기 — 서브에이전트 제작 가이드 (0) 2026.06.10