내 포트폴리오가 단순한 링크 목록처럼 보이는 게 지겨워져서, 이를 위한 MCP 서버를 구축했습니다.
요약
정적인 포트폴리오를 넘어 AI와 대화할 수 있는 MCP(Model Context Protocol) 서버 구축 사례를 소개합니다. Python의 FastMCP를 사용하여 프로젝트 정보를 실시간으로 조회할 수 있는 도구들을 구현했습니다.
핵심 포인트
- MCP를 활용해 포트폴리오를 대화 가능한 인터랙티브 도구로 전환
- FastMCP와 Python을 사용하여 5개의 프로젝트 조회 도구 구현
- Claude Desktop과 MCP 서버 연결 시 발생하는 설정 및 환경 이슈 해결 팁 제공
“내 프로젝트들이 다 비슷해 보인다”는 문제에 대한 명백한 해결책은 더 나은 README를 만드는 것입니다. 더 많은 스크린샷, 더 명확한 설명, 혹은 비교 테이블 같은 것들 말이죠. 저도 5분 정도 고민해 봤지만, 결국 그것 역시 그저 더 보기 좋은 링크 목록일 뿐이라는 결론을 내렸습니다.
포트폴리오 프로젝트를 실제로 다르게 '느껴지게' 만드는 방법은, 읽는 대상이 아니라 대화할 수 있는 대상으로 만드는 것이었습니다. 그것이 바로 MCP (Model Context Protocol)가 만들어진 목적입니다. MCP는 Claude Desktop과 같은 AI 클라이언트가 단순히 텍스트를 처리하는 것을 넘어, 외부 도구(tools)를 직접 호출할 수 있게 해주는 표준입니다. 그래서 저는 제 9개의 프로젝트를 정적인 항목이 아닌, 쿼리가 가능한 도구로 노출하는 서버를 구축했습니다.
MCP란 무엇이며, 왜 여기서 중요한가
제가 본 거의 모든 AI 개발자 포트폴리오는 링크 목록이었습니다. 하지만 이제 제 포트폴리오는 실제로 '대화할 수 있는' 무언가를 포함하고 있습니다. Claude Desktop을 열고, 제 서버에 연결한 뒤, "Ayush가 FastAPI로 무엇을 만들었나요?"라고 물어보세요. 그러면 AI는 캐시된 README를 보고 추측하는 것이 아니라, 실제 도구를 호출하여 구조화된 실시간 데이터로부터 답변을 제공합니다.
내가 만든 것
5개의 도구를 노출하는 Python MCP 서버 (FastMCP, stdio transport)를 구축했습니다:
list_projects— 9개 프로젝트 전체에 대한 짧은 요약get_project_details(project_name)— 특정 프로젝트에 대한 전체 스택, GitHub 링크, 데모 URL을 제공하며, 이름으로 퍼지 매칭(fuzzy-matched)됩니다.search_projects_by_stack(technology)— "Groq를 사용한 모든 것을 보여줘" 또는 "LangGraph" 또는 "React"와 같은 검색get_flagship_project— 가장 먼저 살펴봐야 할 단 하나의 최고의 프로젝트get_resume_summary— 배경, 목표 역할, 핵심 스택
데이터 자체는 현재 일반적인 Python 딕셔너리(dictionaries)에 저장되어 있습니다. 이 정도 규모에서는 데이터베이스가 필요하지 않습니다. 각 도구는 해당 데이터를 감싸는 얇은 함수이며, @mcp.tool() 데코레이터가 적용되어 있습니다.
@mcp.tool()
def search_projects_by_stack(technology: str) -> list[dict]:
"""특정 기술이나 도구를 사용하는 모든 프로젝트를 찾습니다."""
...
실제로 문제가 된 부분
개념은 간단합니다. 하지만 설정 과정에서 네 가지 별개의 난관(rabbit holes)이 있었습니다.
1. MCP Inspector가 일반 Python이 아닌 uv를 기본값으로 사용합니다. mcp dev server.py를 실행하면 프로젝트가 기본적으로 uv 패키지 매니저를 사용한다고 가정하는 UI가 열립니다. 만약 일반적인 venv + pip 설정을 사용 중이라면, 명령 필드를 python으로 수동 변경하고 인자로 server.py를 지정해야 하며, 그렇지 않으면 연결되지 않습니다.
2. Windows Store 앱으로 설치된 Claude Desktop은 완전히 다른 설정 경로를 사용합니다. 저는 처음에 Microsoft Store를 통해 설치했습니다. 표준 설정 안내는 모두 %APPDATA%\Claude\claude_desktop_config.json을 가리키지만, Store 버전에는 이 경로가 존재하지 않으며 대신 AppData\Local\Packages\... 하위 어딘가에 설정을 저장합니다. claude.ai/download에서 직접 .exe 파일을 다운로드하여 삭제 후 재설치하니 문제가 해결되었습니다.
3. 거의 동일하게 생긴 두 개의 설정 파일. 실제 앱을 설치하고 나면, 본인의 프로젝트 폴더에 있는 (참조용) 설정 스니펫 (snippet) 파일과 (Settings → Developer → Edit Config를 통해 찾을 수 있는) 실제 앱 설정 파일이 존재합니다. 언뜻 보면 두 파일이 똑같아 보일 수 있습니다. 저는 탭의 경로 표시(breadcrumb)를 통해 어떤 것이 실제 파일인지 확인하기 전까지, 잘못된 파일을 두 번이나 수정했습니다.
4. 모델이 연결되었다고 해서 항상 도구(tool)를 호출하는 것은 아닙니다. 저의 첫 번째 테스트인 "Ayush가 FastAPI로 구축한 프로젝트는 무엇인가요?"라는 질문에 대해, Claude는 실제로 제 서버를 호출하는 대신 자신의 내부적인 추측으로 답변을 내놓았고, 그 결과 세부 사항 하나가 틀렸습니다 (ResumeIQ를 FastAPI 프로젝트라고 불렀는데, 실제로는 Flask입니다). 프롬프트에 도구나 서버의 이름을 명시적으로 지정하면 ("portfolio tool을 사용하여 ...를 검색하세요") 실제 도구 호출이 강제되었고, 이후에는 매번 정확한 데이터를 반환했습니다.
작동 모습 확인
연결이 완료되면, 실제 세션은 다음과 같은 모습으로 나타납니다:
나: Ayush의 대표 프로젝트는 무엇이고, 왜 그게 대표 프로젝트인가요?
(Claude Desktop에 표시됨: "Claude가 portfolio에서 Get flagship project를 사용하려고 합니다" — 항상 허용 / 거부)
Claude: 당신의 대표 프로젝트는 SalesAgent입니다. 이는 LinkedIn URL을 입력받아 잠재 고객을 조사하고, 머신러닝 (ML) 모델(정확도 84/100)로 점수를 매긴 뒤, 45초 이내에 초개인화된 콜드 이메일 (cold email) 초안을 작성하는 자율형 B2B 영업 에이전트입니다. 이것이 대표 프로젝트인 이유: 단순한 LLM 호출을 감싸는 얇은 API 래퍼 (wrapper)가 아니라, 풀스택 복잡성 (LangGraph + FastAPI + React + scikit-learn scoring)을 갖추고 있기 때문입니다...
그 권한 대화 상자가 중요한 이유는, 이것이 스크립트로 짜여진 응답이 아니라 실제로 실행 중인 실시간 샌드박스 도구 호출 (sandboxed tool call)임을 증명하기 때문입니다.
직접 시도해보세요
Repo: https://github.com/ayush-s-tomar/portfolio-mcp-server
10분 이내에 본인의 Claude Desktop에 연결할 수 있습니다 — 자세한 설정 방법은 README에 있습니다.
만약 당신이 AI 개발자 포트폴리오를 구축 중인데, 모든 프로젝트가 이전 프로젝트와 똑같은 형태라면, 이것은 구조적으로 다른 무언가를 추가할 수 있는 저렴한 방법입니다. 또 다른 에이전트를 만드는 것이 아니라, 다른 에이전트들이 당신이 만든 것을 실제로 사용할 수 있게 해주는 배관 (plumbing)을 만드는 것입니다.
당신이 자신을 위한 이런 서버를 구축한다면, 무엇을 공개하시겠습니까?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기