Skip to main content
Glama
Yunwcy

Portfolio MCP Server

by Yunwcy

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: Bijon Portfolio MCP Server

MCP 간략 설명

MCP는 AI 어시스턴트가 훈련 데이터나 붙여넣은 문서에만 의존하지 않고, 라이브 정보를 가져오거나 작업을 수행하기 위해 외부 "도구"(이름, 설명, 스키마가 있는 타입화된 함수)를 호출할 수 있도록 하는 Anthropic의 오픈 프로토콜입니다. 서버는 자신의 도구를 선언하고, MCP를 인식하는 모든 클라이언트가 이를 발견하고 호출할 수 있습니다. 이 프로젝트는 그러한 서버 중 하나로, 제 포트폴리오 데이터를 기반으로 하는 네 가지 도구를 선언합니다.

도구

도구

기능

list_projects()

플래그십 케이스 스터디뿐만 아니라 출시된 시스템, 대회 출품작, 연구 프로젝트, 출판 논문, 과제 보고서 등 모든 포트폴리오 항목을 ID, 이름, 태그라인, 카테고리, 연도, 한 줄 요약, 그리고 목록에 바로 표시되는 링크(라이브 시스템, GitHub, 보고서, 데모 비디오 등)와 함께 제공합니다.

get_project_details(name)

한 항목의 전체 기록. 플래그십 프로젝트의 경우: 역할, 기술 스택, 문제, 도전 과제 및 해결책, 결과, 링크. 가벼운 항목의 경우: 파일에 있는 모든 정보 — 최소한 설명과 링크를 제공합니다. 매칭은 관대하며 별칭을 인식합니다("lab handover" → ifit-lab-handover; "NTPU OPE Assistant" → 실제로 그런 논문 시스템으로 연결).

search_skills(keyword)

기술 분류 체계에서 키워드를 검색하여 관련성 순으로 정렬하고, 각 결과에 해당 기술을 입증하는 프로젝트 이름을 표시합니다.

get_resume_summary(length)

"short" / "medium" / "long" 길이의 자기소개와 연락처 정보를 제공합니다.

각 도구의 독스트링은 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.py vs. server.py). 로직을 실행 중인 MCP 서버나 전송 방식 없이도 단위 테스트할 수 있도록 하기 위함입니다.

  • SDK 참고: 공식 mcp Python 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의 지속적인 연결에 필요한 긴 실행 시간을 제공하는 장기 실행 컨테이너(실행 시간 제한이 있는 서버리스 함수가 아님)를 실행하며, 시작하는 데 신용카드가 필요하지 않습니다.

  1. 이 저장소를 GitHub에 푸시합니다.

  2. render.com에서: New → Web Service → 이 저장소를 연결합니다.

  3. Render가 Dockerfile을 자동 감지하여 컨테이너로 빌드 및 실행합니다.

  4. Free 인스턴스 유형을 선택하면 https://<something>.onrender.com URL을 받게 됩니다.

  5. 작동 중인지 확인합니다:

    npx @modelcontextprotocol/inspector https://<something>.onrender.com/mcp
  6. (선택 사항) 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로 전송합니다.

설정 (이 엔드포인트가 작동하기 전에 필요):

  1. Anthropic Console에서 API 키를 받아 Render의 ANTHROPIC_API_KEY 환경 변수로 추가합니다(Render 대시보드 → 이 서비스 → 환경). 이것이 없으면 /chat은 서버가 충돌하는 대신 503 {"error": "not_configured"}를 반환합니다.

  2. CHAT_ALLOWED_ORIGINS(쉼표로 구분)가 CORS를 제어합니다 — 기본값은 https://yunwcy.github.io입니다. 위젯이 다른 곳에 있는 경우 설정하세요.

  3. ANTHROPIC_CHAT_MODEL(기본값 claude-opus-5) — 가장 강력한 범용 선택이지만, 이는 단순하고 잠재적으로 트래픽이 많으며 비용에 민감한 공개 위젯이므로, 특별히 claude-haiku-4-5를 여기서 고려할 가치가 있습니다. 이는 서버를 실행하는 사람이 결정할 의도적인 선택이며 하드코딩되지 않았습니다.

  4. 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가 매칭하는 안정적인 식별자입니다. 다른 모든 필드는 자유 형식입니다. 콘텐츠 업데이트를 위한 코드 변경은 필요하지 않습니다.

Available Tools

4 tools
get_project_detailsA

Get the full record for one portfolio item. For a flagship project this includes role, tech stack, the problem it solved, challenges and how they were solved, outcomes, and links; for a lighter item (a course report, a smaller competition entry) it returns whatever is on file — at minimum a description and its links.

Args: name: A project name, id, or known alias/alternate name — e.g. "IM Your Buddy", "knovyra", "lab handover", "NTPU OPE Assistant", or a competition name like "North Taiwan University Alliance AI Agent Competition". Matching is forgiving (case-insensitive, partial, alias-aware), so you don't need the exact id from list_projects — but calling list_projects first helps pick the right one when unsure.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully bears the burden of behavioral disclosure. It clearly conveys the tool's non-destructive, read-only nature by stating it retrieves records. However, it does not disclose potential side effects like logging, or rate limits, which slightly limits transparency. The indication that matching is forgiving and alias-aware adds valuable behavioral context, justifying a 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured, front-loading the tool's purpose in the first sentence, then elaborating on behavioral nuance (flagship vs lighter items) in a natural flow. Every sentence adds value, and the Args section is clearly separated and self-contained. There is no wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has only one parameter, no annotations, and no output schema, the description provides sufficient context for an AI agent to select and invoke the tool correctly. It covers input semantics, matching behavior, variation in returned data, and even suggests a complementary sibling tool (list_projects). The description is complete for this single-param retrieval tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage and only one parameter ('name'), so the description must fully compensate. It excels by describing acceptable inputs (project name, id, alias, or competition name), provides concrete examples, and explains matching behavior (case-insensitive, partial, alias-aware). This adds rich semantics far beyond the schema's bare type declaration.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool retrieves the full record for one portfolio item, differentiating between flagship projects (returns detailed fields like role, tech stack, outcomes) and lighter items (returns description and links). This clear verb+resource+variation makes the purpose highly specific and distinct from siblings like list_projects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool (to get full details of a single portfolio item) and includes a clear when-not alternative: it advises calling list_projects first to select the right item when unsure about the name. This pre-emptive guidance prevents misuse and clarifies the tool's role in a workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_resume_summaryA

Get a self-introduction / resume summary, plus name, title, and contact info. Use this to answer "tell me about yourself" or "give me a summary of this person's background" style questions.

Args: length: "short" for 1-2 sentences, "medium" for a paragraph, or "long" for a full narrative summary covering research, shipped projects, publications, and certifications. Defaults to "short".

ParametersJSON Schema
NameRequiredDescriptionDefault
lengthNoshort

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must fully disclose behavioral traits. It explains what the tool returns (self-introduction, name, title, contact info) and the length parameter's effect. However, it does not mention whether the operation is read-only, any authentication requirements, or rate limits. For a simple get operation, this is adequate but not exceptional.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded: two sentences of purpose followed by a clear parameter definition. Every sentence adds value, and there is no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, no output schema), the description is largely complete. It covers what the tool returns and how to use the length parameter. It could be slightly more explicit about the return format or structure, but it is sufficient for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the lack of parameter info. It does so excellently by explaining the 'length' parameter with three concrete options ('short', 'medium', 'long') and their meanings. This adds significant value beyond the schema's bare type and default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get a self-introduction / resume summary, plus name, title, and contact info.' It also provides concrete use cases ('tell me about yourself' or 'give me a summary of this person's background'). This distinguishes it from sibling tools like list_projects and search_skills.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use the tool: 'Use this to answer... style questions.' This gives clear context. However, it does not explicitly state when not to use it or point to alternative tools, which would be a minor improvement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_projectsA

List every item in the portfolio — shipped systems, competition entries, research projects, published papers, and course reports, not just the flagship case studies — with id, name, tagline, category, year, a one-sentence summary, and its links (live system, GitHub, report, demo video, etc., whichever apply). Links are included right here, so a system or report can be pointed to without a second call. An entry's related_project (when present) is the id of a fuller case study it's a stage or companion piece of — pass that id to get_project_details for the deep-dive version. Call this first for any broad question like "what has this person worked on?" or "does a system exist for X?".

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full transparency burden. It explains that links are included to avoid a second call, and describes the related_project field and its purpose. It does not mention any side effects (none expected), but could be more explicit about the read-only nature. Still, it provides useful behavioral context beyond a simple list.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear topic sentence, then enumeration of fields, an explanation of related_project, and usage guidance. Every sentence adds value. It is slightly long but not verbose; it could be tightened slightly (e.g., remove 'whichever apply' as it's implied).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the tool has no parameters and an output schema exists, the description is quite complete. It explains the output fields, the role of related_project, and when to use it. However, it does not mention ordering or limiting of results, and the portfolio size is assumed small. For most use cases, this is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so schema coverage is 100% trivially. The baseline for no parameters is 4, as the description does not need to add parameter semantics. However, it does describe the output fields, which is beneficial for understanding the tool's result but not directly about input parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists every item in the portfolio with specific fields, and distinguishes itself from the sibling 'get_project_details' by emphasizing that links and related_project are included for a comprehensive overview. The verb 'List' and resource 'projects' are specific, and the mention of 'not just the flagship case studies' clarifies scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit usage guidance is provided: 'Call this first for any broad question like "what has this person worked on?" or "does a system exist for X?".' This tells the agent when to use this tool and implicitly when not to (e.g., deep-dive should use get_project_details). No exclusions or alternatives needed beyond the sibling context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_skillsA

Search the skills/technology taxonomy by keyword and return matches ranked by relevance, each with the projects that demonstrate it. Use this to answer questions like "does this person know RAG / Docker / vector databases / iOS development?".

Args: keyword: A skill, technology, or category to search for, e.g. "RAG", "Docker", "vector database", "iOS", "Next.js".

ParametersJSON Schema
NameRequiredDescriptionDefault
keywordYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses that results are ranked by relevance and include projects, but does not explicitly state that the tool is read-only, mention any authentication needs, rate limits, or edge cases like no matches. It is adequate but lacks depth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with two paragraphs: the main purpose and the args section. Every sentence adds value, and the examples are front-loaded. There is no waste, and the structure is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (single parameter, output schema exists), the description is complete. It explains the search behavior, relevance ranking, and inclusion of projects. Since an output schema is present, there is no need to detail return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has a single parameter 'keyword' with 0% description coverage. The description compensates fully by providing clear examples ('e.g., "RAG", "Docker", "vector database", "iOS", "Next.js"') and explaining the expected format, which adds significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('search') and resource ('skills/technology taxonomy'), states it returns matches ranked by relevance with projects, and provides example questions like 'does this person know RAG / Docker / vector databases / iOS development?' This clearly distinguishes it from sibling tools (list_projects, get_project_details, get_resume_summary).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use this to answer questions like...' which gives clear context for when to use the tool. While it does not mention when not to use it or name alternatives, the sibling tools are not related to skills search, so the context is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedget_project_details
    • First observedget_resume_summary
    • First observedlist_projects
    • First observedsearch_skills

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a distinct, well-defined purpose. list_projects provides an overview, get_project_details provides deep dives on individual entries, search_skills queries the technology taxonomy, and get_resume_summary returns background info. There is no overlap or ambiguity between any of these tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (list_projects, get_project_details, search_skills, get_resume_summary). The naming clearly indicates what action is being taken and on what resource, making the API predictable and easy to navigate.

Tool Count5/5

With exactly 4 tools covering portfolio browsing, detail retrieval, skill search, and resume summary, the number is well-scoped for a personal portfolio MCP server. No tools are missing, and every tool serves a distinct, necessary function without redundancy.

Completeness5/5

The tool set provides a complete coverage of the portfolio domain: listing all entries, retrieving full details for any entry, searching across skills/tags, and providing a professional summary. There are no obvious gaps—a user can explore projects, drill into details, assess expertise, and get background information.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Exposes personal portfolio data as tools for Claude to answer questions about the developer, including profile, skills, experience, projects, and contact information.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes a structured professional resume as a set of AI-queryable tools, enabling AI clients like Claude Desktop to query summary, experience, skills, projects, and tailor resumes to job descriptions.
    1
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    MCP server that exposes a resume as callable tools and resources, enabling AI agents to query experience, skills, projects, and contact information via natural language.
    3
    -