본문 바로가기

AI/MCP

[MCP] MCP를 이해하기 위한 JSON과 JSON-RPC 2.0 차이

제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁

 

서론

다른 프로젝트에서나 회사에서 MCP 서버를 개발해왔다. MCP의 통신 규약인 JSON-RPC 2.0이라는 것과, 이것의 개략적인 특징정도 뿐만 알고 있을 뿐이였다.(원격실행.. 메소드 이름 필요.. 등)

 

하지만 왜 이 통신규약이 필요하며 어떻게 발전하게 되었는지, 기존 JSON과의 차이점과 특징을 바탕으로 MCP의 통신 규약에 대해서 더욱 자세하게 공부하기 위해 해당 포스팅을 진행한다.

 

MCP 동작 원리

MCP(Model Context Protocol)을 공부하다보면 JSON-RPC 2.0이라는 용어를 자주 만나게 된다.

이는 MCP Client와 MCP Server가 서로 메시지를 주고 받을 때 사용하는 통신 규약이 JSON-RPC 2.0이기 때문이다.

 

MCP의 동작방식을 제대로 이해하기 위해서 관계를 설명하기 쉽게 표현하자면

  JSON
   ↓
JSON-RPC 2.0
   ↓
MCP Message

라고 표현할 수 있다.

  • JSON: 데이터를 표현하는 형식
  • JSON-RPC 2.0: JSON을 이용하여 함수 호출과 응답을 표현하는 RPC 프로토콜
  • MCP: JSON-RPC 2.0 메시지를 기반으로 Client와 Server가 통신하는 프로토콜

JSON 이란

JSON은 JavaScript Object Notation의 약자로, 데이터를 문자열 형태로 표현하기 위한 경량 데이터 형식이다.

해당 데이터 포맷은 현재 Server-Client API 통신에서 가장 널리 사용되는 데이터 형식 중 하나이다.

 

예를 들어 사용자 정보를 JSON으로 표현하면 다음과 같다.

{
  "name": "Kim",
  "age": 30,
  "developer": true
}

이렇게 JSON에서 사용할 수 있는 주요 데이터 타입은 다음과 같다.

  • String
  • Number
  • Boolean
  • Object
  • Array
  • Null

조금 더 복잡한 데이터로는 배열이나 dictionary 형태도 가능하다.

{
  "name": "Kim",
  "skills": [
    "Java",
    "Python",
    "MCP"
  ],
  "profile": {
    "career": 3,
    "backend": true
  }
}

이처럼 JSON은 Key-Value 형태의 데이터 구조를 표현하는 방법이다.

 

만약 서버에서 Client가 보낸 값에 따라서 실제로 어떤 동작을 해야하는지가 규정되어야 한다면 별도의 규칙이 필요할 것이다.

이때 등장한 것이 JSON-RPC이다.

 

RPC란

먼저 RPC란 Remote Procedure Call, 원격 프로시저 호출을 의미한다. 다음 코드를 살펴보자.

int result = add(10, 20);

우리는 일반적으로 코드 내에서 함수 호출을 다음과 같이 작성한다.

 

하지만 이는 Client가 지정한 동작이 아닌, 서버 내에서 지정한 동작이며, 호출하려고 하는 함수가 다른 프로세스나 다른 서버에 있다면 직접 호출 할 수 없다.

 

예를 들어 다음과 같이 코드를 작성하고 싶을 때는 이러한 과정이 필요하다.

// Client가 원하는 동작
result = Server.add(10, 20)

// 실제 네트워크 상에서 필요한 과정
Client
   │
   │ "add 함수를 10, 20으로 실행해줘"
   ▼
Server
   │
   │ add(10, 20)
   ▼
Result = 30
   │
   ▼
Client

RPC는 이러한 과정을 추상화하여 다른 곳에 존재하는 함수를 마치 로컬 함수처럼 호출할 수 있도록 하는 통신 방식이다.

 

JSON-RPC란

JSON-RPC는 RPC 메시지를 JSON 형식으로 표현하기 위한 프로토콜이다.

즉, RPC + JSON = JSON-RPC라고 이해하면 쉽다. 현재는 일반적으로 사용하는 버전은 JSON-RPC 2.0이다.

 

JSON-RPC 2.0에서는 Client가 Server의 메서드를 호출하기 위해 정해진 형태의 JSON 메시지를 보낸다.

예를 들어 add(10, 20)을 호출한다고 생각해보자.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "add",
  "params": {
    "a": 10,
    "b": 20
  }
}

각 필드는 다음과 같은 의미를 가진다.

필드 의미
jsonrpc JSON-RPC 버전
id 요청과 응답을 연결하기 위한 식별자
method 호출하려는 메소드
params 메소드에 전달할 파라미터

 

Server는 message를 식별해 해당하는 메소드를 실행한다.(ex> add(10, 20))

그 이후 다음과 같이 응답할 수 있다.

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": 30
}

여기서 중요한 것이 id다.

Client가 여러 요청을 동시에 보낼 수 있기 때문에 Server의 응답이 어떤 요청에 대한 결과인지 구분할 방법이 필요하다.
이때
같은 id를 사용함으로써 요청과 응답을 연결할 수 있다.

 

JSON-RPC 2.0의 세가지 메시지

JSON-RPC를 이해할 때 세가지의 메시지가 중요하다.(Request, Response, Notification)

Request

Client가 Server에 어떤 작업을 요청하는 메시지이다.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "add",
  "params": {
    "a": 10,
    "b": 20
  }
}

Request에는 일반적으로 id가 존재하며, Server는 이 id를 통해 응답한다.

Respone

Request를 처리한 결과이다. 성공했다면 result를 반환한다.

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": 30
}

반대로 처리 과정에서 문제가 발생하면 error를 반환한다.

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "Method not found"
  }
}

에러의 필드 명은 다음과 같다.

  • code: 정해진 오류 코드 (예: -32601은 메서드 없음)
  • message: 사람이 읽을 수 있는 설명
  • data: 선택적으로 제공되는 추가 디버깅 정보

Notification

Notification은 Request와 비슷하지만 중요한 차이가 있다.

id가 없다.

{
  "jsonrpc": "2.0",
  "method": "log",
  "params": {
    "message": "Server started"
  }
}

id가 없다는 것은 응답을 기대하지 않는다는 의미다.

따라서 구조적으로 보면 다음과 같다.

// Request
Client ─────────▶ Server
       ◀─────────
         Response


// Notification
Client ─────────▶ Server
       응답 없음

이 Request / Response / Notification 구조는 MCP를 공부할 때도 매우 중요하다.

 

MCP와 JSON-RPC 2.0

MCP는 JSON-RPC 2.0을 기반으로 메시지를 주고받는다.

 

MCP는 어떤 메소드와 기능을 제공하고, Client와 Server가 어떻게 상호작용할 것인지에 대한 동작 방식이고,
JSON-RPC 2.0은 MCP Server와 MCP Client가 서로 통신을 하기 위한 데이터 규약이라고 볼 수 있다.

 

실제 예시를 살펴보면, MCP Client가 MCP Server가 제공하는 Tool 목록을 알고 싶을 때 자체적으로 MCP에서는 tools/list라는 메소드를 사용할 수 있다. 이때의 Request와 Response는 다음과 같다.

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

// Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_weather",
        "description": "현재 날씨를 조회합니다."
      }
    ]
  }
}

 

만약 조회한 tool을 통해서 실제 메소드 호출을 한다고 가정해보면 개념적으로 다음과 같은 흐름이다.

1. 사용자 -> AI
서울 날씨 알려줘.

2. LLM 또는 MCP Host/Client 측에서 필요한 Tool을 판단. MCP Server에 Tool 실행 요청

3. MCP Server 응답 후 응답 값 반환

4. LLM 노출

사용자
  │
  ▼
LLM / AI Application
  │
  ▼
MCP Client
  │
  │
  │ MCP Protocol
  │
  │ JSON-RPC 2.0 Message
  │
  ▼
Transport
(stdio / Streamable HTTP)
  │
  ▼
MCP Server
  │
  ▼
Tool / Resource / Prompt
  │
  ▼
DB / API / File / External System

 

이를 통해서 MCP는 언어에 구애받지 않고, 프로토콜에 의지하지 않는 처리가 가능하다.

'AI > MCP' 카테고리의 다른 글

[MCP] MCP Transport - SSE와 Streamable HTTP  (0) 2026.10.08
[MCP] MCP에서 JSON-RPC를 채택한 이유  (0) 2026.10.06