Portfolio MCP Server
Portfolio MCP Server
Cheng-Yun Wu의 포트폴리오(프로젝트, 기술, 이력서)를 MCP 호환 AI 어시스턴트(Claude Desktop, Claude.ai Connectors, MCP Inspector 등)가 웹사이트를 스크래핑하지 않고 직접 호출할 수 있는 도구로 제공하는 MCP(Model Context Protocol) 서버입니다.
존재 이유
MCP의 작동 방식을 단순히 읽기만 하는 것이 아니라 처음부터 끝까지 실제로 이해하고 싶어서 포트폴리오 사이트의 콘텐츠를 구조화된 도구로 변환하는 작은 서버를 구축했습니다. 또한 제가 거의 다뤄보지 않았던 Docker와 기본 CI/CD 파이프라인을 익힐 의도적인 핑계이기도 합니다. 이 두 가지는 제가 목표로 하는 채용 공고에서 반복적으로 등장하는 기술입니다.
Related MCP server: personal-mcp
MCP 간략 설명
MCP는 AI 어시스턴트가 훈련 데이터나 붙여넣은 문서에만 의존하지 않고, 라이브 정보를 가져오거나 작업을 수행하기 위해 외부 "도구"(이름, 설명, 스키마가 있는 타입화된 함수)를 호출할 수 있도록 하는 Anthropic의 오픈 프로토콜입니다. 서버는 자신의 도구를 선언하고, MCP를 인식하는 모든 클라이언트가 이를 발견하고 호출할 수 있습니다. 이 프로젝트는 그러한 서버 중 하나로, 제 포트폴리오 데이터를 기반으로 하는 네 가지 도구를 선언합니다.
도구
도구 | 기능 |
| 플래그십 케이스 스터디뿐만 아니라 출시된 시스템, 대회 출품작, 연구 프로젝트, 출판 논문, 과제 보고서 등 모든 포트폴리오 항목을 ID, 이름, 태그라인, 카테고리, 연도, 한 줄 요약, 그리고 목록에 바로 표시되는 링크(라이브 시스템, GitHub, 보고서, 데모 비디오 등)와 함께 제공합니다. |
| 한 항목의 전체 기록. 플래그십 프로젝트의 경우: 역할, 기술 스택, 문제, 도전 과제 및 해결책, 결과, 링크. 가벼운 항목의 경우: 파일에 있는 모든 정보 — 최소한 설명과 링크를 제공합니다. 매칭은 관대하며 별칭을 인식합니다( |
| 기술 분류 체계에서 키워드를 검색하여 관련성 순으로 정렬하고, 각 결과에 해당 기술을 입증하는 프로젝트 이름을 표시합니다. |
|
|
각 도구의 독스트링은 AI 어시스턴트가 실제로 읽어서 언제 호출할지 결정하는 내용입니다. src/portfolio_mcp/server.py에서 확인할 수 있습니다.
범위: data/projects.json에는 총 31개의 포트폴리오 항목이 있습니다 — 7개의 심층 분석 케이스 스터디(출시된 시스템, 학위 논문, NSTC 연구 프로젝트, 수상 논문)와 24개의 가벼운 항목(기타 대회 출품작, 과제 보고서, 학술대회 논문). 모든 항목에는 최소한 하나의 링크가 포함되어 있습니다. 과제 단계 보고서와 관련 논문은 속한 더 완전한 케이스 스터디를 가리키는 related_project ID를 가지고 있어, 어시스턴트가 보고서에서 전체 이야기로 드릴다운할 수 있습니다.
아키텍처
Claude Desktop / Claude.ai / MCP Inspector
│ (stdio locally, or Streamable HTTP remotely)
▼
MCPServer instance (server.py)
│ registers 4 tools
▼
tools.py (pure, unit-tested logic)
│
▼
data_loader.py → data/*.json (projects, skills, resume)전송 방식: stdio가 아닌 Streamable HTTP — 원격 클라이언트(예: Claude.ai의 Connectors)가 로컬에서 실행되는 프로세스뿐만 아니라 공개 URL을 통해 이 서버에 접근할 수 있도록 하기 위함입니다. 로컬 Claude Desktop / MCP Inspector 테스트를 위해 stdio도 계속 지원됩니다.
데이터 계층:
data/디렉토리 아래 세 개의 평면 JSON 파일로, 한 번 로드되어 캐시됩니다(functools.lru_cache). 데이터베이스는 사용하지 않습니다 — 데이터가 작고 공개적이며 변경이 드물기 때문입니다.도구 로직 vs. MCP 연결: 의도적으로 분리되어 있습니다(
tools.pyvs.server.py). 로직을 실행 중인 MCP 서버나 전송 방식 없이도 단위 테스트할 수 있도록 하기 위함입니다.SDK 참고: 공식
mcpPython SDK는 v2.0.0에서 고수준 서버 API를FastMCP에서mcp.server.mcpserver.MCPServer로 변경했습니다. 이 프로젝트는mcp>=2.0.0과 해당 최신 API를 대상으로 합니다.from mcp.server.fastmcp import FastMCP를 사용하는 이전 MCP 튜토리얼을 보셨다면, 그것은 v2.0 이전 API로 오늘날pip install mcp로 설치되는 것과는 호환되지 않습니다.
프로젝트 구조
portfolio-mcp-server/
├── data/ # projects.json, skills.json, resume.json
├── src/portfolio_mcp/
│ ├── server.py # MCPServer app: registers tools, stdio/HTTP entrypoints, /chat route
│ ├── tools.py # MCP tool logic (testable, no MCP dependency)
│ ├── chat.py # /chat: Claude + Tool Runner over the same data, for the site's Q&A widget
│ └── data_loader.py # cached JSON loading
├── tests/ # pytest suite run in CI (tools, server security, chat, chat route)
├── Dockerfile # python:3.12-slim + uvicorn, Streamable HTTP
├── .github/workflows/ci.yml # lint (ruff) + test (pytest) on every push
└── claude_desktop_config.json # example config for local stdio testing로컬 실행
# from the repo root
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"옵션 A — stdio, MCP Inspector 사용
npx @modelcontextprotocol/inspector python -m portfolio_mcp.server각 도구를 직접 호출하고 요청/응답을 검사할 수 있는 로컬 웹 UI가 열립니다.
옵션 B — stdio, Claude Desktop 사용
claude_desktop_config.json의 mcpServers 항목을 자신의 Claude Desktop 설정(설정 → 개발자 → 구성 편집)에 병합하고, 사용자 컴퓨터에 맞게 경로를 수정한 후 Claude Desktop을 다시 시작하고 *"이 사람이 작업한 프로젝트는 무엇인가요?"*와 같은 질문을 해보세요.
옵션 C — Streamable HTTP, 로컬
TRANSPORT=http python -m portfolio_mcp.server
# equivalent — both serve the exact same ASGI app, /chat included:
uvicorn portfolio_mcp.server:app --host 0.0.0.0 --port 8000테스트
pytest -v
ruff check .Docker로 실행
docker build -t portfolio-mcp-server .
docker run -p 8000:8000 portfolio-mcp-server컨테이너는 항상 Streamable HTTP를 제공합니다(컨테이너화의 목적 — 한 컴퓨터에 종속된 stdio 프로세스가 아닌, 이식 가능하고 공개적으로 서비스 가능한 유닛).
배포 (Render)
선택한 배포 대상: Render 프리 티어 — Streamable HTTP의 지속적인 연결에 필요한 긴 실행 시간을 제공하는 장기 실행 컨테이너(실행 시간 제한이 있는 서버리스 함수가 아님)를 실행하며, 시작하는 데 신용카드가 필요하지 않습니다.
이 저장소를 GitHub에 푸시합니다.
render.com에서: New → Web Service → 이 저장소를 연결합니다.
Render가
Dockerfile을 자동 감지하여 컨테이너로 빌드 및 실행합니다.Free 인스턴스 유형을 선택하면
https://<something>.onrender.comURL을 받게 됩니다.작동 중인지 확인합니다:
npx @modelcontextprotocol/inspector https://<something>.onrender.com/mcp(선택 사항) Render의 GitHub 자동 배포를 활성화하여
main브랜치에git push하면 자동으로 재배포되도록 합니다 — 아래의 CI 워크플로우와 결합하여 완전한 CI/CD 환경을 구성합니다.
프리 티어 참고: Render의 무료 웹 서비스는 약 15분 동안 유휴 상태면 절전 모드로 전환되고, 다음 요청 시 30-60초 정도 깨어나는 데 시간이 걸립니다. 포트폴리오 데모용으로는 괜찮습니다. 비용/지연 시간 절충점으로 언급할 가치가 있습니다.
라이브 배포: https://yun-portfolio-mcp.onrender.com/mcp — MCP 클라이언트를 이 URL에 연결하세요(/mcp 경로에 주의; 루트 도메인은 404가 발생합니다. 이는 정상입니다 — Streamable HTTP는 해당 경로 하나만 제공합니다). npx @modelcontextprotocol/inspector https://yun-portfolio-mcp.onrender.com/mcp로 직접 확인할 수 있습니다.
이 저장소를 포크하는 경우:
server.py의 Host 헤더 허용 목록은 기본적으로yun-portfolio-mcp.onrender.com으로 하드코딩되어 있습니다(DNS-리바인딩 보호로 다른 Host 헤더는 421로 거부).MCP_ALLOWED_HOSTS환경 변수를 자신의 배포 호스트명으로 설정하거나ALLOWED_HOSTS를 직접 편집하세요.
채팅 엔드포인트 (/chat) — 포트폴리오 사이트의 Q&A 위젯
동일한 Render 서비스의 두 번째 별도 진입점으로, yunwcy.github.io에 임베드된 일반 채팅 위젯을 위한 것입니다. 위에서 설명한 MCP 프로토콜 표면의 일부가 아닙니다. 브라우저가 {"message": "..."}를 /chat에 POST하면, 서버가 Anthropic Tool Runner를 사용하여 Claude가 동일한 네 가지 도구 중 어떤 것을 호출할지 결정하도록 한 후(MCP 핸드셰이크 없이 tools.py를 직접 호출), {"reply": "..."}를 반환합니다. 전체 구현은 src/portfolio_mcp/chat.py에서 확인할 수 있습니다.
실제 백엔드가 필요하고 GitHub Pages만으로는 할 수 없는 이유: 자연어로 답변하려면 LLM이 질문을 보고 어떤 도구를 호출할지 결정해야 하며, 이를 위해서는 Anthropic API 키가 필요합니다. 그리고 키는 정적 사이트의 클라이언트 측 JS에 절대 포함될 수 없습니다. 누구나 소스 코드를 보고 계정을 탕진할 수 있기 때문입니다. /chat은 키를 서버 측(Render 환경 변수, 브라우저로 전송되지 않음)에 안전하게 보관하고, 브라우저에 필요한 위젯만 GitHub Pages로 전송합니다.
설정 (이 엔드포인트가 작동하기 전에 필요):
Anthropic Console에서 API 키를 받아 Render의
ANTHROPIC_API_KEY환경 변수로 추가합니다(Render 대시보드 → 이 서비스 → 환경). 이것이 없으면/chat은 서버가 충돌하는 대신503 {"error": "not_configured"}를 반환합니다.CHAT_ALLOWED_ORIGINS(쉼표로 구분)가 CORS를 제어합니다 — 기본값은https://yunwcy.github.io입니다. 위젯이 다른 곳에 있는 경우 설정하세요.ANTHROPIC_CHAT_MODEL(기본값claude-opus-5) — 가장 강력한 범용 선택이지만, 이는 단순하고 잠재적으로 트래픽이 많으며 비용에 민감한 공개 위젯이므로, 특별히claude-haiku-4-5를 여기서 고려할 가치가 있습니다. 이는 서버를 실행하는 사람이 결정할 의도적인 선택이며 하드코딩되지 않았습니다.CHAT_RATE_LIMIT_PER_HOUR(기본값30) — 한 명의 방문자가 혼자서 청구 금액을 늘리지 못하도록 하는 간단한 메모리 내 IP당 제한입니다. 재시작/재배포 시마다 초기화되며 인스턴스 간에 공유되지 않습니다 — 트래픽이 적은 개인 사이트에는 충분하지만 일반적인 남용 방어책은 아닙니다.
CI/CD
.github/workflows/ci.yml은 main 브랜치에 대한 모든 푸시/PR 시 실행됩니다: 패키지 설치, ruff로 린트 검사, pytest 스위트 실행. Render의 GitHub 자동 배포(위 참조)가 CD 부분을 처리합니다.
보안 / 비용 참고 사항
MCP 도구 표면(
/mcp)은 자체적으로 LLM을 호출하지 않습니다. — 로컬 JSON만 읽어서 반환합니다. 연결하는 사람(그들의 Claude, 그들의 토큰)이 비용을 부담하며, 이 서버가 부담하지 않습니다./chat엔드포인트는 LLM을 호출합니다. 이 서버 자체의 Anthropic API 키를 사용합니다 — 이것이 바로 그 목적입니다(브라우저는 키를 안전하게 보관할 수 없습니다). 비용은 IP당 속도 제한,effort: "low", 작은max_tokens으로 제한됩니다. 자세한 내용은 위의 채팅 엔드포인트 섹션을 참조하세요.모든 데이터는 이미 제 포트폴리오 사이트에서 공개되어 있습니다 — 보호할 비공개 정보가 없으므로 어느 엔드포인트에도 인증이 구현되어 있지 않습니다.
/chat의 CORS 허용 목록은 데이터 보호가 아닌 누가 API 예산을 사용할 수 있는지 제어하기 위해 존재합니다.
데이터 업데이트
data/ 디렉토리 아래의 JSON 파일을 직접 편집하세요. id는 get_project_details가 매칭하는 안정적인 식별자입니다. 다른 모든 필드는 자유 형식입니다. 콘텐츠 업데이트를 위한 코드 변경은 필요하지 않습니다.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceExposes a person's structured professional profile as MCP tools, enabling Claude and other MCP clients to answer questions about that person based on real data.111MIT
- Flicense-qualityBmaintenanceExposes personal portfolio data as tools for Claude to answer questions about the developer, including profile, skills, experience, projects, and contact information.
- Alicense-qualityCmaintenanceTransforms professional data (CV, projects) into MCP tools for LLMs to query, list, match job descriptions, and ask about experience.77MIT
- FlicenseAqualityCmaintenanceExposes a personal portfolio's resume, projects, skills, certifications, and live GitHub repositories as tools for AI assistants to query via natural language.61
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
The personal context layer for AI: your profile and files, read by any MCP client over OAuth.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Yunwcy/portfolio-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server