좋은 MCP 서버는 왜 설계에서 갈린다
MCP 서버를 처음 만들 때 많은 사람이 제일 먼저 하는 일은 코드를 여는 것입니다. TypeScript 프로젝트를 만들고, Python 가상환경을 켜고, tool() 함수를 하나 등록해 봅니다. 여기까지는 신나죠. 문제는 그다음입니다. 도구가 하나 둘 늘어나고, 외부 API가 붙고, 권한이 섞이고, 설명이 길어지고, 어느 순간 서버가 작은 괴물이 됩니다.
좋은 MCP 서버는 "코드를 빨리 짜는 서버"가 아니라 "오래 버티는 서버"입니다. 오래 버틴다는 말은 세 가지를 뜻합니다. 고치기 쉽고, 설명하기 쉽고, 실수했을 때 덜 위험해야 한다는 뜻입니다. 결국 핵심은 하나입니다. 코드보다 먼저 구조를 잡아야 한다는 것입니다.
MCP 서버를 식당 주방에 비유해 봅시다. 손님이 메뉴를 주문하는 건 쉽습니다. 하지만 주방이 엉망이면 주문이 밀리고, 재료가 섞이고, 알레르기 정보가 빠지고, 결국 사고가 납니다. MCP 서버도 똑같습니다. 툴 하나 띄우는 건 쉬워도, 설계가 없으면 곧바로 복잡성이 폭발합니다.
이 장에서는 좋은 MCP 서버를 설계할 때 꼭 붙잡아야 할 원칙을 다룹니다. 단일 책임 원칙, 도메인 분리, 입력 스키마 설계, 도구 설명 작성, 출력 형태, 에러 설계, 권한 분리까지 차근차근 살펴보겠습니다.
첫 번째 원칙: 서버는 똑똑한 분석가가 아니라 똑똑한 공급자다
MCP 서버를 만들 때 가장 흔한 오해는 서버가 스스로 "생각을 많이 해야 한다"는 믿음입니다. 예를 들어 어떤 문서를 읽고, 서버가 의미를 해석하고, 결론을 내리고, 최종 보고서까지 써 주게 만들고 싶어집니다. 얼핏 멋져 보이지만, 이 방향은 대체로 잘못 갑니다.
왜냐하면 분석과 종합은 원래 LLM이 잘하는 일이기 때문입니다. MCP 서버가 해야 할 일은 다른 데 있습니다. 서버의 역할은 풍부하고 구조화된 정보, 그리고 안전한 실행 기능을 제공하는 것입니다. 한마디로 말하면, 서버는 "똑똑한 분석가"보다 "잘 정리된 전문 자료실"에 가까워야 합니다.
예를 들어 고객 지원 서버를 만든다고 해 봅시다. 나쁜 설계는 이렇게 갑니다. 사용자가 "이 고객이 왜 이탈하려고 하지?"라고 묻자 서버가 제멋대로 로그를 읽고, 감정 분석을 하고, "가격 불만 때문입니다" 같은 결론을 반환합니다. 겉보기엔 편해 보이지만, 기준이 불명확하고 결과가 쉽게 부서집니다.
좋은 설계는 다르게 움직입니다. 고객의 최근 문의, 결제 이력, 환불 요청, 해지 사유, 최근 접점, 관련 정책 문서를 구조적으로 반환합니다. 그다음 이 정보를 바탕으로 해석하고 우선순위를 정하는 일은 LLM이 맡습니다. 이렇게 역할을 나누면 서버는 단단해지고, LLM은 더 잘 뛸 수 있습니다.
좋은 MCP 서버는 "답을 대신 생각하는 서버"가 아니라 "답을 잘 생각할 수 있게 돕는 서버"입니다.
두 번째 원칙: 한 서버는 한 가지 일을 잘해야 한다
단일 책임 원칙은 어렵게 들리지만 뜻은 단순합니다. 한 서버는 하나의 명확한 목적을 가져야 한다는 말입니다.
파일 읽기, 데이터베이스 조회, 이메일 발송, 사내 위키 검색, GitHub 이슈 생성, 캘린더 일정 변경을 전부 한 서버에 밀어 넣고 싶을 수 있습니다. 하지만 그렇게 만든 서버는 대개 다음과 같은 문제를 만듭니다.
권한이 한 덩어리로 섞입니다.
장애가 났을 때 원인을 찾기 어려워집니다.
설명이 길어져서 LLM이 어떤 도구를 써야 할지 헷갈립니다.
테스트 범위가 커져서 작은 수정도 무서워집니다.
좋은 예는 "GitHub 작업 서버", "사내 문서 검색 서버", "데이터베이스 읽기 서버"처럼 책임이 선명한 서버입니다. 이렇게 나누면 각 서버가 다루는 인증 방식, 실패 방식, 데이터 구조도 함께 정리됩니다.
여기서 중요한 건 "서버 수를 무조건 많이 쪼개라"는 뜻이 아니라는 점입니다. 기준은 기술 스택이 아니라 업무 경계와 위험 경계입니다. 같은 인증 체계와 같은 도메인, 같은 위험 수준을 공유한다면 하나의 서버 안에서도 잘 묶일 수 있습니다. 반대로 같은 회사 시스템이라도 읽기 전용 조회와 실제 결제 변경은 위험 수준이 다르므로 분리하는 편이 좋습니다.
설계를 시작할 때는 먼저 이 질문을 던져 보세요. "이 서버는 정확히 무엇을 위해 존재하는가?" 이 질문에 한 문장으로 답하기 어려우면, 이미 너무 많은 걸 넣고 있을 가능성이 큽니다.
세 번째 원칙: API 목록이 아니라 사용자 워크플로에서 출발하라
초보 설계자가 자주 빠지는 함정은 내부 API를 그대로 MCP 툴로 내보내는 것입니다. get_user, get_user_profile, get_user_settings, get_user_permissions, upload_attachment, create_issue 같은 식으로 잘게 쪼갠 도구를 잔뜩 만들면, 언뜻 보기에 체계적입니다. 하지만 LLM 입장에서는 오히려 불친절할 수 있습니다.
LLM은 스무 번의 연속 호출보다 몇 번의 의미 있는 호출을 훨씬 잘 다룹니다. 그래서 좋은 MCP 서버는 아래가 아니라 위에서 아래로 설계합니다.
먼저 "사용자가 어떤 일을 끝내고 싶어 하는가?"를 생각합니다. 그다음 "그 일을 가장 적은 단계로 끝낼 수 있는 도구 묶음은 무엇인가?"를 설계합니다.
예를 들어 버그 접수 워크플로를 생각해 봅시다. 내부 API 관점에서는 사용자 조회, 프로젝트 조회, 파일 업로드, 이슈 생성이 각각 따로 있을 수 있습니다. 하지만 MCP 도구는 create_bug_report 하나로 설계하는 편이 더 나을 수 있습니다. 이 도구는 필요한 내부 API를 서버 안에서 조용히 엮고, LLM에게는 "버그 신고를 만들기 위해 필요한 최소 입력"만 요구합니다.
이때 주의할 점도 있습니다. 모든 것을 거대한 만능 툴로 만들라는 뜻은 아닙니다. 핵심은 LLM이 다루기 좋은 작업 단위를 찾는 것입니다. 너무 잘게 쪼개도 안 좋고, 너무 크게 뭉쳐도 안 좋습니다. 사람이 서랍을 정리하듯, 자주 함께 쓰이는 동작끼리 묶어 주는 감각이 필요합니다.
네 번째 원칙: 도메인과 구현을 분리하라
MCP 서버가 오래 살려면 "툴 함수 안에 모든 걸 때려 넣는 방식"에서 빨리 벗어나야 합니다. 처음엔 편합니다. 하지만 곧 툴 함수 하나가 입력 검증, 권한 확인, 외부 API 호출, 비즈니스 규칙, 응답 포맷팅, 로그 기록까지 다 해 버립니다. 그러면 코드는 금방 질척해집니다.
좋은 구조는 보통 네 층으로 생각하면 편합니다.
프로토콜 계층은 MCP 요청과 응답을 다룹니다. 툴 등록, 리소스 노출, 요청 수신 같은 일이 여기에 있습니다.
애플리케이션 계층은 "무슨 작업을 수행할지"를 조정합니다. 예를 들어 고객 환불 요청을 처리할 때 어떤 서비스들을 어떤 순서로 호출할지 정합니다.
도메인 계층은 비즈니스 규칙이 사는 곳입니다. 환불 가능 조건, 승인 규칙, 상태 전이 같은 핵심 규칙이 여기에 들어갑니다.
인프라 계층은 데이터베이스, 외부 API, 파일 시스템, 메시지 큐와 통신합니다.
이렇게 나누면 좋은 점이 많습니다. 먼저 테스트가 쉬워집니다. 도메인 규칙은 MCP 없이도 검증할 수 있습니다. 둘째로 SDK나 전송 방식이 바뀌어도 핵심 비즈니스 로직은 흔들리지 않습니다. 셋째로 같은 도메인을 리소스, 프롬프트, 툴에서 재사용하기도 쉬워집니다.
쉽게 말해, MCP는 문이고 도메인은 집 안 살림입니다. 문을 새로 달 수는 있어도, 냉장고와 식탁까지 문짝에 붙여 두면 곤란합니다.
다섯 번째 원칙: 입력 스키마는 계약서다
MCP 툴의 입력 스키마는 단순한 형식 정의가 아닙니다. LLM에게 "이 도구는 이렇게 써야 해요"라고 가르치는 계약서이자 안내문입니다. 그래서 스키마 설계가 허술하면 도구 품질이 바로 떨어집니다.
좋은 입력 스키마는 세 가지를 분명하게 말해 줍니다. 어떤 값이 필요한지, 어떤 형태여야 하는지, 어떤 제약이 있는지입니다.
예를 들어 priority라는 필드가 있다고 합시다. 그냥 문자열로 열어 두면 LLM은 urgent, super high, ASAP 같은 값을 만들어 낼 수 있습니다. 하지만 low, medium, high라는 enum으로 제한하면 실수가 크게 줄어듭니다. 날짜라면 형식을 명확히 적어야 하고, 개수라면 최소값과 최대값을 정해야 하며, 경로라면 허용된 루트 범위를 밝혀야 합니다.
스키마를 설계할 때 특히 중요한 것은 각 필드의 설명입니다. 여기에는 단순히 "제목"이라고 쓰는 것보다, "버그를 한 문장으로 요약한 제목. 사용자에게 보일 수 있으므로 구체적이고 짧게 작성"처럼 맥락을 주는 것이 훨씬 좋습니다. LLM은 설명을 읽고 인자를 채우기 때문에, 설명은 문서가 아니라 사실상 프롬프트의 일부입니다.
좋은 스키마 설명은 이런 정보를 담고 있습니다.
값의 의미와 목적
허용 형식과 범위
기본값이 있을 경우 그 의미
다른 필드와의 관계
실수하기 쉬운 점
반대로 나쁜 스키마는 "query: string", "path: string", "id: string"처럼 너무 건조합니다. 이런 스키마는 사람 개발자도 잠깐 멈칫하게 만들고, LLM은 더 자주 틀립니다.
좋은 스키마는 엄격하되, 도구는 친절해야 한다
여기서 재미있는 균형이 하나 있습니다. 스키마는 엄격해야 하지만, 실제 실행은 가능하면 친절해야 합니다.
무슨 뜻일까요? 예를 들어 공식 필드 이름이 project_path인데 모델이 path를 넣어 왔다고 해 봅시다. 이런 경우 무조건 실패시키는 대신, 내부에서 안전하게 보정해 줄 수 있다면 사용자 경험이 좋아질 수 있습니다. 물론 이 친절함은 어디까지나 안전한 범위 안에서만 허용해야 합니다.
정리하면 이렇습니다. 바깥 계약은 엄격하게 유지하고, 안쪽 실행은 회복 가능성을 조금 열어 두는 것입니다. 단, 보정이 모호하거나 위험하면 즉시 거절해야 합니다. 파일 삭제 경로나 SQL 조각처럼 민감한 입력은 친절함보다 명확함이 우선입니다.
여섯 번째 원칙: 도구 설명은 짧게, 필드 설명은 자세하게
좋은 MCP 서버를 보면 도구 설명과 필드 설명이 서로 역할을 나눕니다. 이 구분이 흐려지면 LLM이 헷갈립니다.
도구 설명은 "이 도구가 무엇을 하는가"를 짧고 선명하게 말해야 합니다. 보통 한두 문장이면 충분합니다. 예를 들어 "특정 프로젝트에 버그 이슈를 생성합니다. 제목, 설명, 우선순위, 첨부 파일을 받아 이슈 ID를 반환합니다." 정도면 좋습니다.
반면 각 입력 필드의 설명은 훨씬 구체적이어야 합니다. 우선순위는 어떤 값만 가능한지, 첨부 파일은 어떤 형식인지, 설명은 얼마나 길어도 되는지, 프로젝트 키는 어디서 얻는지 같은 세부 사항은 스키마 필드에 써야 합니다.
이 역할 분담이 중요한 이유는 간단합니다. 도구 설명은 선택을 돕고, 필드 설명은 실행을 돕기 때문입니다. 전자는 "이 툴을 쓸까?"에 답하고, 후자는 "어떻게 호출하지?"에 답합니다.
도구 설명을 쓸 때 기억할 요령도 있습니다. 맨 앞에 가장 중요한 정보를 두고, 동사로 시작하면 좋습니다. "조회한다", "생성한다", "업데이트한다", "분석한다"처럼 말입니다. 그리고 가능한 한 리소스 이름을 함께 적으면 좋습니다. create_invoice는 "송장을 생성한다"라는 뜻이 바로 보이지만, process_item은 너무 추상적입니다.
일곱 번째 원칙: 한 도구에는 가능하면 한 가지 위험 수준만 담아라
MCP 서버는 기능만 잘하면 끝나는 소프트웨어가 아닙니다. 승인, 권한, 사용자 신뢰와 아주 가깝게 붙어 있습니다. 그래서 도구를 설계할 때는 "무엇을 할 수 있나?"만큼이나 "얼마나 위험한가?"를 생각해야 합니다.
좋은 설계는 읽기 전용 도구와 변경 도구를 섞지 않습니다. 예를 들어 get_and_update_customer 같은 이름은 좋지 않습니다. 조회와 수정이 한 함수에 들어 있으면, 사용자와 호스트 애플리케이션이 권한을 판단하기 어려워집니다.
가능하면 다음처럼 나누는 편이 좋습니다. 고객 조회는 읽기 전용 도구로, 고객 상태 변경은 쓰기 도구로 분리합니다. 삭제나 취소처럼 되돌리기 어려운 동작은 더 분명하게 분리해야 합니다.
이 원칙은 보안 때문이기도 하지만, LLM의 선택을 돕기 위해서도 중요합니다. 읽기 도구는 부담 없이 탐색에 쓸 수 있고, 쓰기 도구는 정말 필요할 때만 신중하게 호출하면 됩니다. 도구 하나의 성격이 선명할수록 승인 UX도 좋아집니다.
여덟 번째 원칙: 출력은 풍부해야 하지만, 덩어리째 쏟아내면 안 된다
서버를 만들다 보면 "그냥 원본 JSON을 통째로 반환하면 되지 않을까?"라는 유혹이 찾아옵니다. 가장 쉬운 길이죠. 하지만 쉬운 길이 꼭 좋은 길은 아닙니다.
LLM은 구조화된 정보는 잘 다루지만, 쓸모없는 큰 덩어리를 좋아하진 않습니다. 특히 긴 로그, 거대한 문서, 수백 개 레코드, 복잡한 API 원문은 토큰만 많이 먹고 판단력을 흐리게 만듭니다.
좋은 출력은 두 가지를 동시에 만족해야 합니다. 충분히 풍부해야 하고, 바로 쓸 수 있게 정리되어 있어야 한다는 점입니다.
예를 들어 검색 도구라면 결과 전체를 무작정 던지는 대신, 제목, 요약, 관련 점수, 원문 링크, 총 결과 수를 정리해서 반환하는 편이 좋습니다. 파일 읽기 도구라면 파일이 너무 클 때는 에러를 내거나 범위를 지정해 재시도하도록 유도해야 합니다. 데이터 조회 도구라면 핵심 필드 위주로 반환하고, 필요한 경우 다음 호출을 위한 식별자를 함께 주는 편이 좋습니다.
여기서 중요한 균형이 있습니다. 너무 적게 주면 분석이 불가능하고, 너무 많이 주면 맥락 창이 막힙니다. 좋은 MCP 서버는 "완전함"과 "집중도" 사이의 줄타기를 잘합니다.
아홉 번째 원칙: 에러도 설계해야 한다
좋은 서버는 성공할 때만 친절한 서버가 아닙니다. 실패할 때도 친절해야 합니다.
에러 메시지가 "Internal error" 하나로 끝나면, 사람도 답답하고 LLM은 더 답답합니다. 반면 "프로젝트 키가 유효하지 않습니다. list_projects로 사용 가능한 프로젝트 키를 먼저 확인하세요." 같은 메시지는 다음 행동을 바로 떠올리게 만듭니다.
에러를 설계할 때는 적어도 세 가지를 구분하는 것이 좋습니다. 입력이 잘못된 경우, 권한이 없는 경우, 외부 의존성이 고장 난 경우입니다. 이 셋은 복구 방식이 다르기 때문입니다.
입력 오류는 사용자가 값을 바꾸면 해결됩니다. 권한 오류는 승인이나 역할 변경이 필요합니다. 외부 시스템 오류는 잠시 기다리거나 다른 경로를 선택해야 할 수 있습니다. 이 차이를 서버가 명확히 표현해 주면, LLM도 더 똑똑하게 다음 수를 둡니다.
에러 메시지는 너무 숨겨도 안 되고, 내부 구현을 지나치게 노출해도 안 됩니다. 데이터베이스 커넥션 문자열이나 내부 스택 트레이스를 그대로 내보내는 것은 위험합니다. 대신 원인 범주와 회복 힌트를 주는 쪽이 좋습니다.
열 번째 원칙: 리소스, 툴, 프롬프트를 성격에 맞게 배치하라
MCP에는 세 가지 기본 재료가 있습니다. 툴, 리소스, 프롬프트입니다. 서버 설계가 어설퍼지는 이유 중 하나는 이 셋을 전부 툴로 처리하려고 하기 때문입니다.
읽기 전용으로 참고할 정보라면 리소스가 더 잘 어울립니다. 반복되는 작업 시작점이나 템플릿이라면 프롬프트가 편합니다. 실제로 무언가를 실행하거나 상태를 바꾸는 동작이라면 툴이 맞습니다.
예를 들어 데이터베이스 스키마는 리소스로 제공할 수 있습니다. "월간 매출 보고서를 작성해 달라" 같은 자주 쓰는 시작 문구는 프롬프트로 만들 수 있습니다. 그리고 실제 조회나 갱신은 툴로 수행하면 됩니다.
이 구분을 잘해 두면 도구 수가 불필요하게 늘지 않고, LLM도 상황에 맞는 수단을 고르기 쉬워집니다. 망치 하나로 나사까지 돌리려 하지 않는 것과 비슷합니다.
열한 번째 원칙: 설정과 비밀은 코드 밖으로 빼라
처음엔 서버 코드 안에 API URL, 타임아웃, 기본 페이지 크기, 토큰 제한 같은 값을 박아 넣기 쉽습니다. 하지만 이런 값은 환경에 따라 달라지고, 운영 중에 바뀌기도 합니다. 그러니 설정은 반드시 코드 밖으로 분리하는 습관을 들여야 합니다.
개발 환경, 테스트 환경, 운영 환경이 서로 다른 인증 정보와 제한값을 가져야 하는 경우가 많습니다. 이때 설정이 코드에 박혀 있으면 배포가 지저분해지고, 실수로 운영 키를 로컬에서 쓰는 사고도 생깁니다.
환경 변수나 설정 파일을 사용하고, 시작 시 검증하는 편이 좋습니다. 잘못된 설정 때문에 서버가 애매하게 동작하는 것보다, 시작할 때 분명하게 알려 주는 것이 훨씬 낫습니다.
비밀 값은 더 엄격해야 합니다. API 키, 토큰, 인증서 경로 같은 민감 정보는 절대 코드나 평문 파일에 박아 두면 안 됩니다. MCP 서버는 종종 강한 권한을 가지므로, 비밀 관리가 허술하면 곧바로 큰 문제로 이어집니다.
열두 번째 원칙: 관찰 가능성을 처음부터 넣어라
디버깅은 보통 문제가 생긴 뒤에 떠올리지만, 사실은 설계 단계에서 준비해야 합니다. 좋은 MCP 서버는 나중에 들여다보기 쉽게 만들어져 있습니다.
도구가 호출되었는지, 어떤 입력이 들어왔는지, 얼마나 오래 걸렸는지, 어떤 외부 시스템에서 실패했는지, 사용자가 어떤 권한으로 요청했는지 정도는 추적 가능해야 합니다. 물론 민감 정보는 적절히 가려야 합니다.
로그는 사람을 위한 기록이고, 메트릭은 시스템을 위한 체온계입니다. 두 가지가 모두 필요합니다. 평균 응답 시간, 실패율, 특정 툴의 호출 빈도, 외부 API 지연 같은 정보가 쌓이면, 나중에 "왜 이 서버는 오후만 되면 느려지지?" 같은 질문에도 답할 수 있습니다.
운영 중인 MCP 서버는 마술 상자가 아니라 관찰 가능한 기계여야 합니다.
설계 예시: 나쁜 서버와 좋은 서버의 차이
같은 기능을 가진 두 서버를 상상해 봅시다. 둘 다 사내 이슈 추적 시스템과 연결됩니다.
나쁜 서버는 get_user, get_project, get_statuses, create_issue, attach_file, assign_issue, update_issue_status, delete_issue, send_notification 같은 툴을 API 그대로 늘어놓습니다. 각 툴 설명은 짧고 모호하며, 입력 필드 설명도 거의 없습니다. 읽기와 쓰기가 섞여 있고, 에러는 대부분 "failed"입니다.
좋은 서버는 다릅니다. 먼저 사용 흐름을 보고 핵심 작업을 다시 묶습니다. 예를 들어 search_issues, get_issue_details, create_bug_report, update_issue_fields, add_issue_comment처럼 실제 작업 중심으로 정리합니다. 읽기 도구와 쓰기 도구를 구분하고, 각 도구는 필요한 최소 입력만 받습니다. 첨부 파일은 별도 도구로 분리할 수도 있고, 버그 생성 워크플로에 자연스럽게 포함할 수도 있습니다. 프로젝트 키, 우선순위, 재현 단계 같은 필드에는 구체적인 설명이 붙습니다. 에러는 다음 행동을 안내합니다.
둘 다 동작은 할 수 있습니다. 하지만 오래 쓸 수 있는 건 거의 항상 두 번째입니다.
설계할 때 바로 써먹는 체크리스트
새 MCP 서버를 설계할 때는 구현 전에 아래 질문에 답해 보면 좋습니다.
이 서버의 한 문장 목적은 무엇인가?
이 서버가 다루는 도메인과 권한 경계는 어디까지인가?
사용자가 끝내고 싶은 핵심 워크플로는 무엇인가?
그 워크플로를 가장 적은 단계로 돕는 도구는 무엇인가?
각 도구는 읽기 전용인지, 변경을 일으키는지 분명한가?
입력 스키마는 타입, 범위, 기본값, 예외 조건을 충분히 설명하는가?
도구 설명과 필드 설명의 역할이 분리되어 있는가?
출력은 풍부하지만 과도하게 크지 않은가?
실패 시 다음 행동을 유도하는 에러 메시지가 준비되어 있는가?
로깅, 설정, 권한, 테스트가 설계에 포함되어 있는가?
이 질문에 대답하지 못한 채 바로 코딩을 시작하면, 나중에 코드가 대신 비명을 질러 줍니다.
결국 좋은 서버는 "잘 만든 기능 모음"이 아니라 "좋은 경계의 집합"이다
MCP 서버를 잘 만든다는 것은 툴을 많이 등록하는 일이 아닙니다. 진짜 핵심은 경계를 잘 긋는 것입니다. 어디까지가 이 서버의 책임인지, 어디서 입력을 거절할지, 무엇을 LLM에게 맡기고 무엇을 서버가 책임질지, 어떤 도구가 읽기이고 어떤 도구가 쓰기인지, 어떤 정보는 리소스로 주고 어떤 동작은 툴로 줄지, 이런 경계가 선명해야 서버가 오래 살아남습니다.
설계가 좋은 서버는 겉으로 보기엔 오히려 덜 화려할 수 있습니다. 툴 수가 적고, 설명은 짧고, 응답은 정돈되어 있습니다. 하지만 실제로 써 보면 다릅니다. LLM이 덜 헷갈리고, 사용자가 덜 불안하고, 개발자가 덜 고생합니다.
좋은 MCP 서버는 한마디로 이런 서버입니다. 자기 역할을 알고, 말이 분명하고, 실수했을 때도 얌전한 서버. 그런 서버가 결국 오래 갑니다.
다음 장에서는 이 원칙들을 바탕으로, 실제로 나만의 첫 MCP 서버를 Python과 TypeScript로 하나씩 만들어 보겠습니다. 설계도는 이제 손에 들어왔으니, 다음엔 진짜 벽돌을 쌓을 차례입니다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.