MCP 서버를 3개월 동안 방치했다가 GitHub Copilot으로 48시간 만에 완성한 이야기
요약
방치되었던 MCP(Model Context Protocol) 서버 프로젝트를 GitHub Copilot을 활용해 48시간 만에 완성한 개발 경험담입니다. Dev.to API를 AI 에이전트가 표준화된 방식으로 사용할 수 있도록 돕는 devto-mcp 서버 구축 과정을 다룹니다.
핵심 포인트
- MCP를 통해 AI 에이전트와 외부 API 간의 표준화된 상호작용 구현
- GitHub Copilot을 활용한 방치된 프로젝트의 빠른 복구 및 완성
- Dev.to API를 위한 12개의 전문화된 도구(tools) 세트 구축
- 구조화된 JSON 응답과 에러 핸들링을 통한 에이전트 신뢰성 확보
이 글은 GitHub Finish-Up-A-Thon Challenge를 위한 제출물입니다.
놓쳐버린 프로젝트
3개월 전, 저는 진심으로 기대하며 무언가를 만들기 시작했습니다. 바로 devto-mcp입니다. 이는 AI 에이전트가 Dev.to의 API와 네이티브하게 상호작용할 수 있게 해주는 Model Context Protocol (MCP) 서버입니다. 더 이상 curl 명령어를 짜깁기할 필요도, 모든 AI 도구에 맞춰 커스텀 래퍼(wrapper) 스크립트를 작성할 필요도 없습니다. 그저 어떤 AI 에이전트라도 바로 연결할 수 있는 깔끔하고 표준을 준수하는 MCP 서버를 만드는 것이 목표였습니다.
저에게는 비전이 있었습니다. 트렌딩 주제를 자율적으로 조사하고, 기사를 초안하고, 게시하고, 참여도를 추적하며, 반복 개선까지 — 이 모든 것을 단 하나의 프로토콜을 통해 수행하는 AI 에이전트 말이죠. 실제로 구축을 시작하기 전까지는 단순하게 들리는 그런 종류의 일입니다.
약 40% 정도 진행했을 때, 삶의 여러 상황이 닥쳤습니다. 클라이언트 프로젝트 마감일, 타 지역으로의 이사, 그리고 최악의 타이밍에 SSD가 손상되어 버린 노트북까지 말이죠. 레포지토리(repo)는 GitHub에 그대로 방치되어 디지털 먼지만 쌓여갔고, 기능 구현이 절반만 된 도구 함수들과 코드보다 훨씬 많은 것을 약속하는 README 파일만이 남아 있었습니다.
익숙한 상황인가요? 개발자로 1년 이상 일했다면, 여러분에게도 이런 '유령 레포지토리'가 적어도 하나쯤은 있을 것입니다. "다음 주말"에는 반드시 끝낼 수 있을 거라고 확신했던 야심 찬 사이드 프로젝트 말이죠. 이름은 기발하고 상세한 아키텍처 문서도 있지만, 코드는 거의 작동하지 않는 그런 프로젝트 말입니다.
2주 전, 저는 GitHub Finish-Up-A-Thon 공고를 보았습니다. 방치된 레포지토리 목록을 훑어보며 생각했습니다. '이제 때가 됐다.'
내가 만든 것: devto-mcp
devto-mcp는 Dev.to의 전체 API를 MCP 호환 도구로 노출하는 Model Context Protocol 서버입니다. MCP가 생소하시다면, 이는 Claude, Cursor 및 기타 코딩 에이전트와 같은 AI 어시스턴트가 외부 도구와 표준화된 방식으로 상호작용할 수 있게 해주는 프로토콜입니다. AI 모델과 개발자들이 실제로 사용하는 서비스 사이의 범용 어댑터라고 생각하시면 됩니다.
이것이 해결하고자 하는 문제는 다음과 같습니다: AI 에이전트가 Dev.to와 상호작용하기를 원할 때마다 — 기사를 검색하거나, 게시물을 발행하거나, 분석 데이터를 확인하거나, 댓글을 관리하는 등 어떤 작업이든 — 매번 맞춤형 통합 코드 (custom integration code)를 작성해야 합니다. 서로 다른 AI 도구들은 각기 다른 플러그인 시스템을 가지고 있습니다. 동일한 API가 수십 가지의 서로 다른 방식으로 재구현됩니다.
MCP는 이 문제를 해결합니다. 하나의 서버, 하나의 프로토콜로 어디에서나 작동합니다.
도구 모음 (The Tool Suite)
완성된 서버는 Dev.to API 표면에 걸쳐 **12개의 도구 (tools)**를 노출합니다:
Article Management
search_articles - 태그, 키워드, 상태, 페이지네이션을 통한 검색
get_article - ID 또는 슬러그(slug)를 통한 전체 기사 가져오기
...
각 도구에는 적절한 입력 유효성 검사 (input validation), 에러 핸들링 (error handling), 속도 제한 (rate-limit) 인지, 그리고 AI 에이전트가 실제로 신뢰성 있게 파싱할 수 있는 구조화된 JSON 응답이 포함되어 있습니다.
재기 스토리 (The Comeback Story)
이전의 코드 상태
3개월간의 방치 끝에 저장소 (repo)를 열었을 때, 제가 발견한 것은 다음과 같았습니다:
# server.py - 이전에 작성했던 것 (임포트가 깨진 스켈레톤 코드)
from mcp import Server # 이 임포트는 잘못되었습니다
import requests # 세션 관리(session management) 없음
...
그게 전부였습니다. 그것이 코드베이스의 전부였습니다. TODO 주석들이 마치 도움을 요청하는 비명처럼 느껴지는, 망가진 스켈레톤 코드일 뿐이었습니다. README에는 아름다운 ASCII 아트 로고와 90%가 희망 사항뿐인 기능 목록이 적혀 있었습니다. requirements.txt에는 패키지로 존재하지도 않는 의존성 (dependencies)들이 나열되어 있었습니다.
다시 말해, 아주 전형적인 방치된 사이드 프로젝트였습니다.
GitHub Copilot으로 바뀐 점
여기서 제가 Copilot을 어떻게 사용했는지 솔직하게 말씀드리겠습니다. 이러한 도전 과제에서는 투명성이 중요하다고 생각하기 때문입니다. 저는 단순히 완성된 제품에 Copilot의 마법을 뿌린 것이 아닙니다. 저는 부활 과정 전체에 걸쳐 Copilot을 **사고 파트너 (thinking partner)**로 사용했습니다.
1~4시간 차: 아키텍처 재고 (Architecture Rethink)
3개월 사이에 기존 MCP Python SDK는 상당히 많이 변해 있었습니다. 임포트(import) 구조, 도구 등록(tool registration) 패턴, 심지어 베이스 클래스(base classes)까지 모두 달라져 있었습니다. 몇 시간 동안 문서를 읽는 대신, 저는 VS Code에서 SDK 소스 코드를 열고 MCP Python SDK에서 도구를 등록하는 현재 방식에 대해 Copilot과 대화를 시작했습니다.
Copilot은 제 워크스페이스에 있는 실제 SDK 코드를 참조하여 올바른 등록 패턴을 생성했습니다. 환각(hallucination)된 결과가 아니라, 실제로 작동하는 패턴이었습니다. 이것만으로도 문서를 뒤지는 데 드는 2~3시간을 아낄 수 있었습니다.
4~12시간 차: 핵심 도구 구현 (Core Tool Implementation)
이 단계에서 Copilot은 진정으로 빛을 발했습니다. 각 Dev.to API 엔드포인트(endpoint)는 유사한 패턴을 따릅니다: URL 구축, 파라미터(params) 추가, 요청(request) 수행, 응답(response) 처리, MCP 형식으로 포맷팅. 하지만 문제는 디테일에 있었습니다. 페이지네이션(pagination) 파라미터가 엔드포인트마다 다르고, 에러 코드(error codes)의 의미가 제각각이며, 어떤 엔드포인트는 인증(authentication)이 필요하지만 어떤 곳은 그렇지 않았습니다.
저는 기준이 될 구현체로서 첫 번째 도구(search_articles)를 수동으로 작성했습니다. 그런 다음 Copilot이 그 패턴을 바탕으로 나머지 11개를 생성하도록 했고, 제가 이를 수정해 나갔습니다. 워크플로우는 다음과 같았습니다:
- 도구가 수행해야 할 작업을 설명하는 주석을 작성합니다.
- Copilot이 구현 코드를 생성합니다.
- 제가 검토하고, 예외 케이스(edge cases)를 수정하며, 유효성 검사(validation)를 추가합니다.
- 테스트를 실행하고, 문제가 발생한 부분을 수정합니다.
- 다음 도구로 넘어갑니다.
이러한 반복적인 접근 방식 덕분에 약 8시간의 집중적인 작업만으로 12개의 도구를 구현할 수 있었습니다. Copilot이 없었다면 20~25시간 정도 걸렸을 것이라고 예상합니다. 코드가 복잡해서가 아니라, 비슷하면서도 조금씩 다른 수많은 API 엔드포인트 사이에서 패턴을 매칭하는 작업이 매우 지루하기 때문입니다.
12~20시간 차: 에러 처리 및 예외 케이스 (Error Handling & Edge Cases)
여기서 Copilot이 놀라울 정도로 잘하는 것이 하나 있는데, 바로 예외 케이스를 예측하는 것입니다. 제가 create_article 도구를 작성할 때, Copilot은 다음과 같은 상황에 대한 처리를 제안했습니다:
- 빈
body_markdown(Dev.to에서 거부됨) - 4개 태그 제한을 초과하는 태그
- 유효하지 않은 커버 이미지 URL
- 속도 제한 (Rate limiting, 429 응답)
- 환경 변수에서 API 키 누락
결국에는 발견했겠지만, 구현 과정에서 이러한 문제들이 선제적으로 드러난 덕분에 나중에 디버깅(Debugging)을 할 필요가 없었습니다.
20~30시간 차: 테스트 및 문서화 (Testing & Documentation)
Copilot은 제가 미처 생각하지 못했을 테스트 케이스(Test cases)들을 생성해 주었습니다. 예를 들어, 사용자가 특수 문자가 포함된 태그(c++, c#, .net)를 검색할 때 어떤 일이 발생하는지 테스트할 것을 제안했습니다. 이러한 태그들은 잘못 처리할 경우 깨질 수 있는 URL 인코딩 (URL encoding)이 필요합니다. 또한 Copilot은 README 구조를 생성하고, AI 에이전트(AI agents)가 실제로 이해할 수 있는 명확한 도구 설명(Tool descriptions)을 작성하는 데 도움을 주었습니다.
30~48시간 차: 다듬기 및 출시 (Polish & Ship)
마지막 단계는 설정(Configuration), 패키징(Packaging), 그리고 서버가 여러 MCP 클라이언트(Claude Desktop, Cursor, Windsurf)와 제대로 작동하는지 확인하는 것이었습니다. 각 클라이언트마다 설정 파일 형식이 약간씩 달랐지만, Copilot은 그 형식을 모두 알고 있었습니다.
GitHub Copilot 사용 경험
저는 Copilot이 무엇을 잘했고 무엇을 잘하지 못했는지 구체적으로 말씀드리고 싶습니다. 과장된 찬사나 무조건적인 부정보다는 미묘한 차이가 있는 진실이 더 유용하다고 생각하기 때문입니다.
Copilot이 매우 잘해낸 점
1. 패턴 전파 (Pattern Propagation)
하나의 도구에 대한 패턴을 설정하면, Copilot은 유사한 도구들에 대해 매우 높은 정확도로 이를 복제할 수 있었습니다. 이는 기계적이지만 까다로운 작업으로, 가장 많은 시간이 소요되고 정신적으로 지치게 만드는 작업입니다. Copilot은 이 작업을 단순 노동에서 검토(Review) 작업으로 바꾸어 놓았습니다.
2. API 지식 (API Knowledge)
Copilot은 MCP 프로토콜 사양(Protocol spec)과 Dev.to의 API 모두에 대해 놀라울 정도로 정확한 지식을 가지고 있었습니다. 제가
4. 설정 생성 (Configuration Generation)
다양한 클라이언트(Claude Desktop의 claude_desktop_config.json, Cursor의 mcp.json 등)를 위한 MCP 서버 설정은 까다롭고 문서화가 잘 되어 있지 않습니다. Copilot은 제가 테스트한 세 가지 클라이언트 모두에 대해 정확한 설정을 생성해 주었습니다.
Copilot이 제대로 하지 못한 부분 (또는 전혀 하지 않은 부분)
1. 아키텍처 결정 (Architecture Decisions)
"도구 등록(tool registration)을 위해 클래스 기반(class-based) 방식을 사용해야 할까요, 아니면 함수 기반(function-based) 방식을 사용해야 할까요?"라고 물었을 때, Copilot은 두 가지 옵션을 모두 제시했지만 저의 구체적인 사용 사례(use case)에는 어떤 것이 더 나은지는 알려주지 못했습니다. 저는 유지보수성(maintainability)과 MCP SDK의 디자인 패턴(design patterns)을 바탕으로 직접 결정을 내려야 했습니다.
2. 속도 제한 전략 (Rate Limit Strategy)
Copilot은 요청 사이에 간단한 time.sleep(1)을 사용할 것을 제안했습니다. 이는 기술적으로는 맞지만 순진한(naive) 접근입니다. 저는 지수 백오프(exponential backoff), 지터(jitter), 그리고 엔드포인트별 속도 제한 추적(per-endpoint rate limit tracking)을 직접 구현해야 했습니다. Copilot이 제안한 코드는 낮은 트래픽에서는 작동하겠지만, 규모가 커지면 실패할 것입니다.
3. 보안 검토 (Security Review)
Copilot은 환경 변수(environment variables)에 API 키를 저장하는 것이 (로컬 개발 시에는 괜찮지만) 프로덕션 배포(production deployment)를 위해서는 다른 처리가 필요하다는 점을 지적하지 않았습니다. 보안 고려 사항은 제가 직접 추가해야 했습니다.
4. 테스트 커버리지 공백 (Test Coverage Gaps)
생성된 테스트는 해피 패스(happy paths)는 잘 다루었지만, 몇 가지 중요한 실패 모드(failure modes)를 놓쳤습니다. 예를 들어, Dev.to API가 예상치 못한 JSON 구조를 반환할 때(가끔 발생하는 일입니다) 어떻게 되는지에 대한 부분입니다. 저는 이러한 테스트를 수동으로 추가해야 했습니다.
솔직한 수치
| 지표 | Copilot 사용 시 | 미사용 시 예상 |
|---|---|---|
| 총 소요 시간 | ~48시간 | ~80-100시간 |
| ... |
Copilot이 저를 대신해 코드를 작성해 준 것은 아닙니다. Copilot은 지루하지만 필수적인 개발 단계들을 가속화해 주었고, 덕분에 저는 인간의 판단이 필요한 부분, 즉 아키텍처, 보안, UX, 그리고 언제 "충분히 괜찮은(good enough)" 상태가 실제로 충분한지를 판단하는 일에 집중할 수 있었습니다.
기술적 심층 분석 (The Technical Deep Dive)
실제 구현 방식을 이해하고 싶은 분들을 위해, 서버가 내부적으로 어떻게 작동하는지 설명하겠습니다.
MCP 서버 아키텍처 (MCP Server Architecture)
import os
import httpx
from mcp.server import Server
...
도구 등록 패턴 (Tool Registration Pattern)
각 도구는 일관된 등록 패턴을 따릅니다. search_articles가 작동하는 방식은 다음과 같습니다:
@app.list_tools()
async def list_tools() -> list[Tool]:
return [
...
인증 흐름 (Authentication Flow)
제가 특히 자랑스럽게 생각하는 부분 중 하나는, 인증 흐름이 인증된 요청과 인증되지 않은 요청을 모두 유연하게 처리한다는 점입니다. 많은 Dev.to 엔드포인트는 API 키 없이도 작동하지만(공개된 기사, 사용자 프로필 등), 기사를 생성하거나 편집하려면 키가 필요합니다. 서버는 키를 확인하며, 인증이 필요한 엔드포인트가 키 없이 호출될 경우 명확한 에러 메시지를 반환합니다:
async def require_auth() -> dict | None:
if not get_api_key():
return {
...
사용 방법 (How to Use It)
설치 (Installation)
git clone https://github.com/zeroknowledge0x/devto-mcp
cd devto-mcp
pip install -e .
설정 (Configuration)
MCP 클라이언트 설정에 추가하세요. Claude Desktop (claude_desktop_config.json)의 경우:
{
"mcpServers": {
"devto": {
...
Cursor (.cursor/mcp.json)의 경우:
{
"mcpServers": {
"devto": {
...
에이전트 워크플로우 예시 (Example Agent Workflow)
설정이 완료되면, AI 에이전트가 다음과 같은 작업들을 수행할 수 있습니다:
- 트렌드 주제 조사: "'python' 및 'ai' 태그가 달린 급상승 기사를 검색해줘. 상위 5개 테마를 요약해줘."
- 초안 작성 및 게시: "MCP 서버에 관한 1500단어 분량의 기사를 작성하고, 'ai', 'mcp', 'tutorial' 태그를 달아서 초안으로 게시해줘."
- 참여도 분석: "내 최근 기사 10개를 가져와서 반응(reactions) 순으로 정렬해줘. 어떤 패턴이 보이니?"
- 경쟁 조사: "이번 달에 게시된 'MCP server' 관련 기사를 검색해줘. 아직 다뤄지지 않은 주제는 무엇이니?"
교훈: 시작한 일을 끝내는 법 (Lessons Learned: Finishing What You Start)
1. 40%의 벽은 실재한다 (The 40% Wall Is Real)
모든 방치된 프로젝트에는 "40%의 벽 (40% wall)"이 존재합니다. 초기 흥분이 가라앉고 남은 작업이 온통 배관 작업(plumbing)뿐인 지점 말입니다. 인증 (Authentication), 에러 처리 (error handling), 예외 케이스 (edge cases), 문서화 (documentation). 소프트웨어를 실제로 "작동"하게 만들지만, 구축하는 과정은 즐겁지 않은 작업들입니다. Copilot의 가장 큰 기여는 이러한 기계적인 부분들을 자동화함으로써 이 벽을 덜 위협적으로 만들어 준 것이었습니다.
2. README 주도 개발 (README-Driven Development)은 함정이다
제 원래 저장소(repo)에는 존재하지도 않는 기능들을 설명하는 200줄짜리 README가 있었습니다. 이것은 마치 진전이 있는 것처럼 "느껴지기" 때문에 유혹적입니다. 하지만 실제로는 그렇지 않습니다. 프로젝트를 재개했을 때, 저는 README를 삭제하고 단 한 줄로 대체했습니다: "Dev.to API를 위한 MCP 서버. 12개의 도구. 작동함." 저는 코드가 제대로 작동한 이후에야 비로소 내용을 확장했습니다.
3. 방치된 코드도 여전히 유용하다
3개월 전에 작성했던 40%의 코드는 낭비되지 않았습니다. API 엔드포인트 URL, 데이터 모델에 대한 이해, 도구 명명 규칙 (tool naming conventions) — 이 모든 맥락이 그대로 이어졌습니다. 심지어 형편없는 코드조차 문제 영역 (problem space)에 대해 가르쳐 줍니다. 방치된 저장소를 삭제하지 마세요. 다시 살펴보세요.
4. AI 페어 프로그래밍 (AI Pair Programming)이 계산법을 바꾼다
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기