MCP 오류 코드
MCP 호출이 실패하는 두 가지 방식과, 코드별 원인·해결 방법입니다.
실패는 두 자리 중 하나로 돌아옵니다. 요청 단계에서 막히면(형식·인증·권한·한도·없는 도구·요금제에 없는 도구·동시 실행) JSON-RPC error 로, 작업을 시작한 뒤 실패하면(작업 실패·시간 초과) result.isError 로 옵니다. 두 자리 모두 HTTP 200 으로 옵니다 — 예외는 인증 정보가 없거나 잘못된 경우로, 아래 HTTP 상태 표를 봅니다.
실패가 돌아오는 자리
요청이 막힘error 로 돌아옴
- 언제
- 형식 오류, 인증·권한·한도, 없는 도구, 요금제에 없는 도구, 기관 연동 꺼짐, 동시 실행
- 자리
- error.code · error.message
- 판단
- 코드로 분기합니다
작업 시작 뒤 실패result.isError 로 돌아옴
- 언제
- 작업 실패 · 대기 시간 초과
- 자리
- result.isError · result.content
- 판단
- 작업이면 두 번째 블록 JSON 의 safe_to_retry 로 다시 부를지 정합니다
JSON-RPC 표준 코드
| 코드 | 뜻 | 원인·해결 |
|---|---|---|
| -32700 | 본문을 읽지 못함 | JSON 형식이 깨졌습니다. |
| -32600 | 요청 형식 오류 | jsonrpc·method·id 형식을 확인합니다. |
| -32601 | 없는 메서드 | initialize · ping · tools/list · tools/call 중 하나를 씁니다. |
| -32602 | 파라미터 오류 | X-MCP-Env-Scope 에 sandbox 를 넣었거나, 인수 형식이 틀렸거나, 도구가 쓸 자격증명을 고르지 못했습니다. 자격증명 문제는 error.data.error_code 로 가르고 아래 표를 봅니다. |
| -32603 | 서버 내부 오류 | 잠시 뒤 다시 시도하고, 계속되면 서비스문의로 알려 주세요. |
-32602 — 자격증명을 고르지 못했을 때
| error.data.error_code | 뜻 | 할 일 |
|---|---|---|
| PRIMARY_ACCOUNT_LINK_NOT_FOUND | 등록한 자격증명이 없습니다. | 작업이 시작되지 않고 호출 수도 쓰지 않습니다. error.data.link_url 의 등록 화면을 사용자에게 알리고, 등록했다고 하면 같은 도구를 다시 부릅니다. |
| ACCOUNT_LINK_ID_REQUIRED | 이 상품은 자격증명을 자동으로 고르지 않습니다. | 등록이 없다는 뜻이 아닙니다. error.data.link_url 의 목록에서 쓸 자격증명의 id 를 복사해 도구 인수 account_link_id 로 넣고 다시 부릅니다. |
| MULTIPLE_ACTIVE_ACCOUNT_LINKS | 대표가 없고 쓸 수 있는 자격증명이 여러 개라 하나를 고를 수 없습니다. | 쓸 자격증명을 정해 그 id 를 account_link_id 로 넣습니다. |
| INVALID_ACCOUNT_LINK_ID | account_link_id 가 UUID 형식이 아닙니다. | 목록의 값을 그대로 복사해 넣습니다. |
| CREDENTIAL_OWNERSHIP_DENIED | 지정한 자격증명을 쓸 수 없습니다. | 없는 것, 다른 계정의 것, 다른 상품의 것, 사용을 중단한 것은 구별 없이 같은 응답입니다. 목록에서 다시 고릅니다. |
XBOSS 코드 — error 로 옴
| 코드 | 뜻 | 원인·해결 |
|---|---|---|
| -32000 | 해당 기관 연동이 꺼져 있음 | 운영에서 잠시 막아 둔 상태입니다. 서비스문의로 알려 주세요. |
| -32001 | 인증·권한·한도 | 키가 잘못됐거나, 정식 환경인데 유료 플랜이 아니거나, 하루 한도를 넘었거나, 짧은 시간에 너무 많이 불렀거나, 지금 요금제에 포함되지 않은 도구를 불렀습니다(그 도구가 이 환경에서 판매 중일 때 — error.data.error_code 는 POLICY_PROVIDER_FORBIDDEN, error.data.link_url 은 요금제 변경 화면 주소). 같은 코드 안의 상황은 error.data.reason 으로 가릅니다 — 오류 코드 의 reason 표. |
| -32002 | 없는 도구 | tools/list 에 있는 이름인지 확인합니다. 꺼져 있거나 이름이 틀렸을 때이고, 요금제에 없는 도구는 위 -32001 로 옵니다. 메시지는 '<이름>' 도구를 지금 쓸 수 없습니다. 로 시작합니다. |
| -32008 | 동시 실행 한도 | 같은 기관에 진행 중인 작업이 많습니다. 끝난 뒤 다시 부릅니다. |
| -32009 | 로그인 진행 중 | 같은 기관 로그인이 이미 진행 중입니다. 잠시 뒤 다시 부릅니다. |
result.isError 로 오는 실패
| 경우 | 문구의 시작 | 할 일 |
|---|---|---|
| 대기 시간 초과 | 요청이 60초 안에 끝나지 않았습니다(job …). | 작업은 서버에서 계속 돕니다. 두 번째 블록의 status_url 로 같은 키의 REST 조회를 하면 이미 끝난 결과를 다시 돌리지 않고 읽을 수 있습니다. safe_to_retry 가 false(되돌릴 수 없는 작업)면 다시 부르지 말고 그 조회로 처리 여부를 확인합니다. |
| 세션 만료 | 세션이 만료됐거나 없습니다(오류 <원인 코드>). | 두 번째 블록의 next_action 에 적힌 로그인 도구를 먼저 부릅니다. 되돌릴 수 없는 작업이면 다시 보내기 전에 기관 화면에서 처리 여부를 확인합니다. |
| 작업 실패 | 작업이 실패했습니다(오류 <원인 코드>). | 원인 코드는 두 번째 블록의 error_code 에도 있습니다 — 오류 코드 표에서 원인을 봅니다. |
HTTP 상태
| 상태 | 언제 |
|---|---|
| 200 | 정상 응답과 위 오류들 — 본문을 열어 확인합니다. 인증 정보 없이 tools/list 를 부르면 401 이 아니라 200 으로 공개 도구 목록이 옵니다. |
| 202 | 알림(id 없는 요청)을 받았습니다. 본문이 없습니다. |
| 400 | 지원하지 않는 MCP-Protocol-Version 헤더입니다. |
| 401 | 인증 정보 없이 도구를 부르거나(tools/call), 보낸 인증 정보가 잘못됐습니다. WWW-Authenticate 헤더가 함께 옵니다. ChatGPT 처럼 openai/* 메타를 보내는 앱은 인증 정보 없이 도구를 부르면 401 대신 200 과 isError 결과로 같은 안내를 받습니다. |
| 403 | 허용되지 않은 Origin 에서 브라우저로 호출했습니다. OAuth 토큰에 이 호출에 필요한 권한(scope)이 없을 때도 403 이고, WWW-Authenticate 에 insufficient_scope 가 실립니다. |
| 405 | GET /mcp 은 지원하지 않습니다. POST 로 보냅니다. |
응답 예시
json
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32001,
"message": "인증 정보가 없습니다. 아직 계정이 없다면 https://xdata.kr/auth/signup 에서 가입하세요. 스탠다드 요금제는 가입 즉시 적용되고 하루 100 사용 토큰까지 무료로 호출할 수 있습니다. 대부분의 조회는 한 번에 1 사용 토큰을 쓰고, 여러 곳을 한 번에 묻는 조회는 더 씁니다. 이미 가입했다면 https://console.xdata.kr/keys 에서 키를 발급해 'Basic base64(client_id:client_secret)' 형식으로 보내세요."
}
}json
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32001,
"message": "데모 환경은 사용 신청이 승인된 뒤 쓸 수 있습니다. 콘솔 프로필의 환경 메뉴에서 신청해 주세요.",
"data": {
"reason": "demo_access_not_approved"
}
}
}json
{
"jsonrpc": "2.0",
"id": 4,
"error": {
"code": -32001,
"message": "'hometax__etax__invoice__search_list' 은(는) 지금 요금제에 포함되지 않은 도구입니다. https://console.xdata.kr/billing 에서 이 도구가 포함된 요금제로 바꾸거나 추가 구매한 뒤 다시 호출하세요. API 키는 그대로 쓰면 됩니다. 지금 요금제로 쓸 수 있는 도구는 tools/list 로 확인할 수 있습니다.",
"data": {
"error_code": "POLICY_PROVIDER_FORBIDDEN",
"link_url": "https://console.xdata.kr/billing"
}
}
}json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "요청이 60초 안에 끝나지 않았습니다(job job_01JC8YH8R0E1ABCDEFGHJKMNPQ). 서버가 바쁠 수 있습니다. 같은 API 키로 연동한 서비스는 GET https://api.xdata.kr/v1/jobs/job_01JC8YH8R0E1ABCDEFGHJKMNPQ 로 결과를 읽을 수 있습니다. 잠시 뒤 다시 시도하거나, 요청 범위를 줄일 수 있으면 줄이세요."
},
{
"type": "text",
"text": "{\"job_id\": \"job_01JC8YH8R0E1ABCDEFGHJKMNPQ\", \"timeout_seconds\": 60, \"safe_to_retry\": true, \"status_url\": \"https://api.xdata.kr/v1/jobs/job_01JC8YH8R0E1ABCDEFGHJKMNPQ\"}"
}
],
"isError": true
}
}tools/list 가 도구 목록을 돌려주면 주소는 맞습니다. Authorization 헤더를 보냈다면 인증도 맞지만, 헤더 없이 부르면 공개 도구 목록이 오므로 _meta["xdata.kr/lane"].source 가 anonymous 인지 확인합니다. 환경 권한과 한도는 도구를 부를 때 다시 확인되므로, 그다음 오류는 환경 권한(-32001)이나 도구 이름·인수 문제일 수 있습니다.
되돌릴 수 없는 작업(발행·신고·신청)이 실패로 왔을 때는 메시지의 원인 코드를 먼저 봅니다. PROVIDER_OUTCOME_UNCONFIRMED 면 다시 부르지 말고 기관 화면에서 처리 여부를 확인합니다 — 오류 코드.