2026. 5. 25. 13:46ㆍ카테고리 없음
MCP(Model Context Protocol)는 AI 에이전트가 외부 도구와 데이터를 사용할 수 있게 해주는 표준 프로토콜입니다. GitHub 이슈를 조회하거나, 사내 API를 호출하거나, 로컬 문서를 검색하거나, 배포 상태를 확인하는 식의 작업을 AI에게 맡길 수 있습니다.
이전 글에서는 MCP가 무엇인지, 그리고 간단한 MCP 서버를 어떻게 만들 수 있는지 살펴봤습니다. 그런데 실제 프로젝트에 MCP를 붙이려고 하면 코드 작성보다 먼저 고민해야 할 문제가 생깁니다.
AI에게 어떤 도구를 열어줘야 할까?
어디까지 실행하게 해도 안전할까?
실패했을 때는 어떻게 처리해야 할까?
민감한 데이터는 어떻게 막아야 할까?
MCP 서버는 단순히 API를 감싸는 코드가 아닙니다. AI 에이전트에게 “무엇을 할 수 있는지”를 허용하는 경계면입니다. 그래서 처음 설계가 중요합니다.
이번 글에서는 MCP 서버를 만들기 전에 정해야 할 도구 설계, 권한, 입력 검증, 로그 기준을 실무 관점에서 정리해보겠습니다.
MCP 서버 설계에서 가장 위험한 착각
MCP를 처음 접하면 기존 API를 그대로 도구로 노출하면 된다고 생각하기 쉽습니다.
예를 들어 사내 관리자 API에 이런 엔드포인트가 있다고 해보겠습니다.
GET /orders
GET /orders/:id
POST /orders/:id/cancel
POST /users/:id/point
DELETE /products/:id
이 API들을 그대로 MCP 도구로 만들면 AI는 주문 조회, 주문 취소, 포인트 지급, 상품 삭제 같은 작업을 할 수 있게 됩니다. 기술적으로는 가능합니다. 하지만 실무에서는 매우 위험합니다.
AI는 사용자의 요청을 해석해서 도구를 호출합니다. 그 과정에서 문맥을 잘못 이해하거나, 애매한 요청을 과하게 해석하거나, 예상보다 넓은 범위의 작업을 시도할 수 있습니다.
따라서 MCP 서버는 “가능한 모든 API를 연결하는 곳”이 아니라 AI에게 안전하게 맡길 수 있는 작업만 선별해서 제공하는 곳이어야 합니다.
1. 도구 범위부터 작게 정하기
처음 MCP 서버를 만들 때는 도구를 작게 시작하는 것이 좋습니다. 특히 쓰기 작업보다 읽기 작업부터 시작하는 편이 안전합니다.
안전한 시작 예시
list_recent_orders
get_order_detail
search_customer_by_email
get_deployment_status
list_open_github_issues
이런 도구들은 데이터를 조회하는 역할을 합니다. 잘못 호출되더라도 시스템 상태를 바꾸지는 않습니다.
신중해야 하는 도구 예시
cancel_order
refund_payment
delete_user
update_product_price
run_production_deploy
이런 도구들은 실제 비즈니스 상태를 바꿉니다. MCP로 제공할 수는 있지만, 승인 절차나 권한 체크 없이 바로 실행되면 위험합니다.
처음에는 다음 원칙을 추천합니다.
- 1단계: 조회 도구만 제공한다.
- 2단계: 임시 데이터나 개발 환경에서만 쓰기 도구를 테스트한다.
- 3단계: 운영 쓰기 도구는 승인/확인 절차를 둔다.
- 4단계: 위험 작업은 사람이 최종 실행한다.
2. 도구 이름은 구체적으로 짓기
AI가 도구를 잘 사용하려면 도구 이름과 설명이 중요합니다. 이름이 애매하면 AI가 잘못 선택할 가능성이 높아집니다.
나쁜 예시는 다음과 같습니다.
handle_order
process_user
manage_product
run_task
이름만 봐서는 무엇을 하는 도구인지 알기 어렵습니다. 반면 다음처럼 구체적으로 짓는 것이 좋습니다.
list_recent_orders
get_order_detail_by_order_id
search_users_by_email
create_draft_refund_request
check_production_deployment_status
도구 이름에는 가능하면 다음 정보를 담습니다.
- 동작: list, get, search, create, update, delete, check
- 대상: order, user, issue, deployment
- 조건: by_email, by_order_id, recent, open
- 위험도: draft, preview, request 같은 단어로 즉시 실행이 아님을 표현
예를 들어 환불을 바로 실행하지 않고 요청 초안만 만드는 도구라면 refund_payment보다 create_draft_refund_request가 안전합니다. AI도 이 도구가 즉시 환불을 실행하는 것이 아니라 초안을 만드는 것임을 더 잘 이해할 수 있습니다.
3. 입력 스키마는 엄격하게 제한하기
MCP 도구의 입력값은 가능한 한 명확하고 제한적으로 정의해야 합니다. 자유 텍스트 하나로 모든 것을 처리하게 하면 AI가 예측하기 어려운 값을 넣을 수 있습니다.
예를 들어 다음 스키마는 위험합니다.
{
"query": "string",
"action": "string"
}
이런 형태는 유연하지만 너무 넓습니다. 대신 도구 목적에 맞게 입력을 나누는 것이 좋습니다.
{
"orderId": "string",
"includePayment": "boolean",
"includeCustomerMemo": "boolean"
}
또는 검색 도구라면 다음처럼 제한할 수 있습니다.
{
"keyword": "string",
"status": "open | closed | all",
"limit": "number"
}
여기서 중요한 것은 limit 같은 값에도 상한을 두는 것입니다.
- 한 번에 10개만 조회
- 최대 50개까지만 허용
- 날짜 범위는 최대 30일
- 민감 필드는 기본 제외
AI가 실수로 너무 넓은 조회를 하지 않도록 서버 쪽에서 방어해야 합니다.
4. 권한은 MCP 서버에서 다시 확인하기
기존 API에 권한 체크가 있더라도 MCP 서버에서도 최소한의 권한 정책을 가져가는 것이 좋습니다. MCP 서버는 AI가 사용하는 별도의 진입점이기 때문입니다.
확인해야 할 기준은 다음과 같습니다.
- 이 사용자가 이 도구를 호출할 수 있는가?
- 이 환경에서 이 도구를 실행해도 되는가?
- 이 리소스에 접근할 권한이 있는가?
- 쓰기 작업이라면 추가 승인이 필요한가?
- 호출 횟수나 조회 범위 제한이 필요한가?
예를 들어 배포 상태 조회는 누구나 가능하지만, 운영 배포 실행은 특정 역할만 가능하게 할 수 있습니다.
get_deployment_status: developer 이상 허용
create_deployment_plan: maintainer 이상 허용
run_production_deploy: MCP에서 직접 실행 금지, 승인 링크만 생성
중요한 것은 AI에게 권한 판단을 맡기지 않는 것입니다. AI가 “이 사용자는 아마 권한이 있을 것”이라고 판단하게 해서는 안 됩니다. 권한은 항상 서버에서 결정해야 합니다.
5. 쓰기 작업은 preview와 execute를 분리하기
운영 환경에서 쓰기 작업을 제공해야 한다면 preview와 execute를 분리하는 패턴이 유용합니다.
예를 들어 상품 가격 변경을 생각해보겠습니다.
preview_product_price_change
execute_product_price_change
첫 번째 도구는 변경될 내용을 계산해서 보여줍니다.
{
"productId": "P1004",
"currentPrice": 30000,
"newPrice": 27000,
"diff": -3000,
"affectedOptions": 3,
"requiresApproval": true
}
두 번째 도구는 실제 변경을 실행합니다. 이때는 다음 조건을 요구할 수 있습니다.
- preview 결과의 requestId가 있어야 한다.
- 사용자가 명시적으로 승인해야 한다.
- 일정 시간이 지나면 requestId가 만료된다.
- 운영 환경에서는 특정 역할만 실행할 수 있다.
이 구조를 사용하면 AI가 바로 위험한 작업을 실행하는 일을 줄일 수 있습니다.
6. 로그는 반드시 남기기
MCP 서버는 AI가 외부 시스템과 연결되는 지점이므로 로그가 중요합니다. 나중에 문제가 생겼을 때 “AI가 어떤 도구를 어떤 입력으로 호출했는지” 추적할 수 있어야 합니다.
기본적으로 남기면 좋은 정보는 다음과 같습니다.
- 호출 시간
- 사용자 또는 세션 ID
- 호출한 도구 이름
- 입력 파라미터
- 성공/실패 여부
- 응답 요약
- 실행 시간
- 쓰기 작업의 변경 대상
단, 로그에 민감한 값을 그대로 남기면 안 됩니다. 토큰, 비밀번호, 개인정보, 결제 정보는 마스킹해야 합니다.
email: mi***@example.com
accessToken: [REDACTED]
cardNumber: [REDACTED]
로그는 디버깅 목적뿐 아니라 보안 감사에도 필요합니다. 특히 AI가 운영 도구를 호출할 수 있다면 로그는 선택이 아니라 필수입니다.
7. 실패 메시지는 AI가 이해할 수 있게 작성하기
MCP 도구가 실패했을 때 단순히 500 error만 반환하면 AI는 다음 행동을 정하기 어렵습니다. 실패 원인을 구조화해서 알려주는 것이 좋습니다.
좋은 실패 응답은 다음 정보를 포함합니다.
- 실패 코드
- 사람이 읽을 수 있는 메시지
- 재시도 가능 여부
- 사용자가 해야 할 조치
- AI가 하면 안 되는 행동
예시는 다음과 같습니다.
{
"ok": false,
"errorCode": "PERMISSION_DENIED",
"message": "현재 사용자는 운영 배포를 실행할 권한이 없습니다.",
"retryable": false,
"nextAction": "배포 권한이 있는 관리자에게 승인을 요청하세요. 토큰 입력이나 우회 실행을 시도하지 마세요."
}
이런 응답은 AI가 불필요하게 재시도하거나 우회 방법을 찾는 일을 줄여줍니다.
MCP 서버 설계 체크리스트
마지막으로 MCP 서버를 만들기 전에 확인할 체크리스트를 정리해보겠습니다.
도구 설계
- 도구가 너무 넓은 역할을 하지 않는가?
- 읽기 도구와 쓰기 도구가 분리되어 있는가?
- 도구 이름만 봐도 동작을 이해할 수 있는가?
- 위험 작업은 preview/request/execute 단계로 나뉘어 있는가?
- AI에게 필요 없는 API까지 노출하지 않았는가?
입력 검증
- 입력 스키마가 구체적인가?
- enum, boolean, limit 같은 제한이 있는가?
- 날짜 범위나 조회 개수에 상한이 있는가?
- 자유 텍스트 입력을 최소화했는가?
- 서버에서 한 번 더 검증하는가?
권한과 보안
- 사용자 권한을 MCP 서버에서 확인하는가?
- 운영 환경 쓰기 작업은 추가 승인이 있는가?
- 민감 데이터는 기본 응답에서 제외되는가?
- 토큰과 비밀값이 로그에 남지 않는가?
- 실패 시 인증 우회를 유도하지 않는가?
운영과 관찰
- 도구 호출 로그가 남는가?
- 실패 원인이 구조화되어 있는가?
- 호출 횟수 제한이 있는가?
- 장애 시 안전하게 실패하는가?
- 문제가 생겼을 때 특정 호출을 추적할 수 있는가?
마무리
MCP는 AI 에이전트를 실제 업무 시스템과 연결해주는 강력한 방식입니다. 하지만 강력한 만큼 설계를 대충 하면 위험해질 수 있습니다.
좋은 MCP 서버는 많은 일을 할 수 있는 서버가 아닙니다. AI에게 맡겨도 되는 일을 명확하게 제한하고, 위험한 작업은 안전한 절차로 감싸는 서버입니다.
처음부터 완벽한 MCP 플랫폼을 만들 필요는 없습니다. 작은 조회 도구 하나부터 시작해도 충분합니다. 대신 다음 원칙은 지키는 것이 좋습니다.
- 도구 범위는 작게 시작한다.
- 입력 스키마는 엄격하게 정의한다.
- 권한 판단은 AI가 아니라 서버가 한다.
- 쓰기 작업은 preview와 execute를 분리한다.
- 로그와 실패 메시지를 운영 관점에서 설계한다.
AI 에이전트가 더 많은 일을 하게 될수록, 개발자는 “어떻게 연결할까?”뿐 아니라 “어디까지 허용할까?”를 함께 고민해야 합니다. MCP 서버 설계는 바로 그 경계를 정하는 작업입니다.
SEO 메타 설명 후보
MCP 서버를 실제 프로젝트에 적용하기 전에 도구 범위, 입력 스키마, 권한 체크, 로그, 실패 정책을 어떻게 설계해야 하는지 실무 체크리스트로 정리합니다.