언젠가는 누군가 어시스턴트와의 채팅에 여권 사진을 올리고 "그냥 양식 좀 채워 줘"라고 부탁하게 됩니다. 범용 비전 모델은 시도는 할 것입니다. 이름을 맞힐 수도 있습니다. 하지만 기계 판독 영역(MRZ)의 체크 디지트가 통과했는지 알려 주거나, 날짜를 매번 같은 형식으로 돌려주거나, 추측하는 대신 "이건 읽을 수 없습니다"라고 말하지는 않습니다.
이 빈틈은 도구로 메우기에 알맞습니다. Model Context Protocol을 쓰면 에이전트가 도구를 호출할 수 있습니다. 이 글에서는 Claude Desktop, Claude Code, Cursor 등의 클라이언트에 문서 인식 도구를 추가하는 방법, 에이전트가 돌려받는 내용, 비용을 일정 범위 안에 묶어 두는 방법, 그리고 애초에 에이전트에게 신분증을 맡기기 전에 생각해 볼 점을 다룹니다.
이곳은 여기서 사용하는 MCP 서버의 바탕이 되는 API, doc.cheap의 블로그입니다. 서버는 MIT 라이선스이며, 설정에 관한 고려 사항은 이런 종류의 도구라면 어디에나 해당합니다.
에이전트가 얻는 것
서버는 npm의 @doc-cheap/mcp(MIT, Node 20 이상)이며 세 가지 도구를 제공합니다.
| 도구 | 하는 일 | 크레딧 사용 |
|---|---|---|
scan_document |
사진이나 스캔에서 여권, 국가 신분증, 운전면허증을 인식해 구조화된 결과를 반환 | 예. 문서가 인식된 경우에만 |
check_balance |
남은 크레딧과 이번 달 카운터를 조회 | 아니요 (읽기 전용) |
search_docs |
서버에 번들된 API 문서를 오프라인으로 검색 | 아니요 (읽기 전용) |
각 도구에는 제목, 설명(계정 상태에 관여하는 두 도구는 설명에 가격이 적혀 있음), 그리고 클라이언트가 먼저 사용자에게 확인을 받을지 결정할 때 읽는 MCP 동작 힌트가 붙어 있습니다. scan_document는 읽기 전용이 아닌 것으로, 나머지 둘은 읽기 전용으로 표시됩니다. 서버는 또한 모델이 호출 전에 읽는 지침을 보내며, 여기에는 무엇을 인식하는지와 호출 비용이 적혀 있습니다. 도구 외에 프롬프트 네 개(scan_document_to_json, check_document_expiry, batch_scan, explain_error)가 있고, 모든 문서 페이지는 doccheap://docs/reference/fields 같은 읽기 전용 리소스로 제공됩니다.
scan_document는 전체 결과를 구조화된 JSON으로, 그리고 한 줄 요약과 함께 돌려줍니다. 예를 들면 다음과 같습니다.
Scan 01a0af18-cd8d-7a61-9f2d-4c7b8e105da3: recognized · passport (GRC) · PARADEIGMA ELENI SOFIA · billed · 684 ms
(문서에 나오는 가상의 견본 소지자입니다.) 그 뒤의 JSON에는 소지자, 문서 번호와 ISO 8601 형식의 날짜, 신뢰도 등급이 붙은 모든 필드, passed / failed / absent 판정이 붙은 MRZ 줄, 그리고 billed 플래그가 들어 있습니다. 핵심은 이 구조입니다. 에이전트는 픽셀을 해석할 필요 없이 필드를 읽으면 됩니다.
설치: 로컬 서버
아래의 모든 클라이언트는 npx로 서버를 실행합니다. 키를 설정하지 않으면 공개 샌드박스 키를 사용하며, IP 주소당 총 10건의 인식 문서가 무료이고 시간당 최대 10건의 요청을 보낼 수 있습니다. 시험해 보기에는 충분합니다. 가입하면 무료 크레딧 20개를 받고, 그 후에는 인식된 문서 한 건에 $0.01입니다.
Claude Desktop, Cursor, Windsurf는 같은 블록을 읽으며, 각각 claude_desktop_config.json, ~/.cursor/mcp.json, ~/.codeium/windsurf/mcp_config.json에 넣습니다.
{
"mcpServers": {
"doc-cheap": {
"command": "npx",
"args": ["-y", "@doc-cheap/mcp"],
"env": { "DOC_CHEAP_API_KEY": "sk_live_your_key" }
}
}
}
샌드박스 키로 실행하려면 env 줄을 빼십시오.
Claude Code:
claude mcp add-json doc-cheap '{"command":"npx","args":["-y","@doc-cheap/mcp"],"env":{"DOC_CHEAP_API_KEY":"sk_live_your_key"}}'
VS Code:
code --add-mcp '{"name":"doc-cheap","command":"npx","args":["-y","@doc-cheap/mcp"]}'
Gemini CLI와 Kiro는 각자의 설정 파일에서 같은 mcpServers 블록을 사용합니다. 각 경로는 MCP 가이드에 있습니다. 편집한 뒤에는 클라이언트를 다시 시작하십시오. 서버는 새로 실행될 때만 바뀐 환경 변수를 반영합니다.
설치: 호스팅 서버
클라이언트가 명령을 실행하는 대신 URL에 연결하는 방식이라면, 같은 세 가지 도구가 https://mcp.doc.cheap/mcp에서 Streamable HTTP로 로그인 없이 제공됩니다. 키는 헤더 X-Doc-Cheap-Api-Key 또는 Authorization: Bearer로 보냅니다(둘 다 보내면 이름 붙은 헤더가 우선합니다). 키가 없으면 샌드박스 키가 사용됩니다.
Claude Code:
claude mcp add --transport http doc-cheap https://mcp.doc.cheap/mcp --header "Authorization: Bearer sk_live_your_key"
Cursor:
{
"mcpServers": {
"doc-cheap": {
"url": "https://mcp.doc.cheap/mcp",
"headers": { "Authorization": "Bearer sk_live_your_key" }
}
}
}
Claude Desktop과 claude.ai에서는 Settings → Connectors에서 이 URL로 사용자 지정 커넥터를 추가하십시오.
호스팅 서버는 여러분 컴퓨터의 파일을 볼 수 없으므로, 여기서 scan_document는 이미지를 image_base64 또는 공개 image_url로 받습니다.
로컬 파일과 URL은 의도적으로 제한됩니다
도구 인수는 모델이 고르고, 모델은 설득당할 수 있습니다. 그래서 로컬 서버는 임의의 경로를 읽지 않습니다.
image_path는DOC_CHEAP_IMAGE_ROOT에 디렉터리 하나를 지정하기 전까지 꺼져 있습니다. 경로는 먼저 심볼릭 링크를 따라 해석되며,..이나 디렉터리 밖을 가리키는 링크는 거부됩니다. 없는 파일과 범위 밖의 파일은 같은 메시지를 받으므로, 이 도구로 파일 존재 여부를 탐색할 수 없습니다.image_url은https:여야 하고, 공개 주소로만 해석되어야 하며(루프백, 사설, 링크 로컬 등의 대역은 거부), 리디렉션은 최대 세 번까지 따르되 매번 다시 검사하고, 크기 상한은 25 MB입니다.
전에 에이전트용 파일 읽기 도구를 연결해 본 적이 있다면 이 목록과 비교해 보십시오. "모델은 합리적인 경로만 넘길 것"은 보안 경계가 아닙니다.
비용을 일정 범위 안에 묶어 두기
두 가지 특성이 에이전트 사용을 예측 가능하게 만듭니다.
- 인식된 문서만 과금됩니다. 문서 유형이 판별되고 데이터가 실제로 추출된 경우, 즉 체크 디지트를 통과한 MRZ, 인쇄된 필드 5개 이상, 또는 올바르게 디코딩된 바코드가 있을 때 과금됩니다. 문서 없음, 읽을 수 없는 이미지, 지원하지 않는 유형, 내부 오류, 타임아웃은 비용이 들지 않습니다. 결과의
billed플래그가 매번 어느 쪽인지 알려 줍니다. 샌드박스 키에서는 아무것도 과금되지 않으며, 이때 플래그는 같은 스캔이 라이브 키였다면 과금되었을지를 알려 줍니다. - 재시도를 무료로 만들 수 있습니다.
scan_document는idempotency_key를 받습니다. 라이브 키에서 같은 키로 반복하면 다시 과금하는 대신 저장된 첫 결과를 돌려줍니다. 키 없는 재시도는 두 번째 스캔입니다. 반복 호출은 저장된 결과를 돌려주므로,retain_hours: 0과 재생 가능한 재시도는 둘 중 하나만 쓸 수 있습니다.
실제로는 다음과 같이 합니다.
- 배치 작업 전에 에이전트가
check_balance를 호출하게 하십시오. 서버 자체 지침이 모델에게 그렇게 하라고 알려 주고,batch_scan프롬프트도 이것부터 실행합니다. 샌드박스 키에서는 잔액이null이며, 도구는 0을 보여 주는 대신 잔액이 없다고 알려 줍니다. - 읽기 전용 도구만 자동 승인하십시오. 예를 들어 Kiro 설정은
"autoApprove": ["check_balance", "search_docs"]를 지원합니다. 비용을 쓰는 것은scan_document뿐이므로 이 도구는 확인 절차 뒤에 두십시오. - 에이전트가 직접 찾아보게 하십시오.
search_docs는 번들된 문서를 대상으로 오프라인에서 동작하므로, "unsupported_document가 무슨 뜻이지?" 같은 질문은 비용이 들지 않고 모델의 기억에 의존하지도 않습니다.
개인정보 보호: 시작하기 전에 따져 볼 질문
신분증은 가장 민감한 데이터에 속하며, 에이전트는 이 흐름에 참여하는 주체를 늘립니다. API 측에서 사실인 것과 여러분의 설정에 달린 것을 나눠 보겠습니다.
API 측 (문서에 명시된 대로):
- 업로드한 이미지는 요청 동안 메모리에만 있고 영구 저장소에는 절대 기록되지 않습니다.
- 인식 결과는 나중에 다시 읽을 수 있도록 계정에서 정한 기간(24시간, 7일, 30일, 1년) 동안 보관됩니다. 새 계정의 기본값은 1년입니다. 호출별로
retain_hours: 0을 지정하면 행을 전혀 쓰지 않으며,scan_document도retain_hours를 받습니다. 에이전트가 답을 한 번만 필요로 한다면 이 값을 설정하십시오. - 처리는 유럽연합에서 이루어집니다. 데이터는 모델 학습에 사용되지 않습니다.
return_portrait: false는 소지자 사진의 크롭인images.main_photo를 빼 줍니다. 페이지 전체의 크롭은 여전히 돌아오며, 일부 문서가 페이지에 흐리게 한 번 더 인쇄하는 얼굴 사본도 마찬가지입니다.
여러분 측:
- 결과는 모델의 컨텍스트에 들어갑니다.
scan_document가 돌려주는 모든 것(이름, 번호, 날짜)은 이제 대화 안에 있으며, 여러분의 클라이언트를 구동하는 LLM 제공업체가 그 업체의 약관에 따라 처리합니다. 이는 모든 MCP 도구에 본질적인 것이지, 이 도구만의 문제가 아닙니다. - 이미지가 전달되는 방식이 중요합니다. 로컬 서버에서
image_path를 쓰면 서버가 파일을 읽어 API로 바로 보냅니다.image_base64를 쓰면 이미지 바이트가 모델의 도구 호출 인수에 들어갑니다. 픽셀을 모델의 컨텍스트 밖에 두고 싶다면 제한된 로컬 디렉터리를 사용하십시오. - 이것은 인식이지 검증이 아닙니다. 결과의
authenticity그룹은not_checked입니다. MRZ 통과는 영역이 읽혔고 내부적으로 일관된다는 뜻일 뿐, 문서가 진짜라는 뜻이 아닙니다. 라이브니스 확인이나 얼굴 대조 단계는 없습니다. KYC 용도라면 이것은 판단 근거 중 하나일 뿐, 결정 자체가 아닙니다. - 개발하는 동안에는 합성 문서를 사용하십시오. 견본과 생성한 MRZ만으로도 모든 연결을 마칠 수 있습니다.
짧은 세션 예시
서버를 설치했다면 합성 견본을 첨부하고 "이 여권 스캔을 읽고 앞으로 6개월 안에 만료되는지 알려 줘" 같은 프롬프트 하나면 충분합니다. 제대로 동작하는 에이전트는 scan_document를 호출하고, 결과에서 document.expiry_date와 document.days_remaining을 읽어, 이미지에 대한 인상이 아니라 그 필드를 근거로 답합니다. 스캔 결과가 unreadable이면 그렇다고 말하고 더 나은 사진을 요청해야 하며, 여러분에게는 비용이 청구되지 않습니다.
이 마지막 동작이야말로 여기서 도구를 쓰는 진짜 이유입니다. 에이전트는 빈칸을 채우고 싶은 유혹 대신 명시적인 "읽을 수 없음"을 받습니다.
링크
- 모든 클라이언트 설정 예시가 있는 MCP 페이지: https://doc.cheap/mcp
- 전체 가이드: https://doc.cheap/docs/guides/use-the-mcp-server
- 소스 코드 (MIT): https://gitlab.com/doccheap/ocr-mcp
- npm: https://www.npmjs.com/package/@doc-cheap/mcp
이 서버로 무언가를 만드셨거나 위 설정이 동작하지 않는 클라이언트를 발견하셨다면 admin@doc.cheap으로 알려 주십시오.
doc.cheap과 그 MCP 서버에 관한 모든 설명은 해당 코드와 대조해 확인했습니다.