Skip to main content
Glama
Yunwcy

Portfolio MCP Server

by Yunwcy

Portfolio MCP Server

Ein MCP (Model Context Protocol) Server, der Cheng-Yun Wus Portfolio – Projekte, Fähigkeiten und Lebenslauf – als Werkzeuge bereitstellt, die jeder MCP-kompatible KI-Assistent (Claude Desktop, Claude.ai Connectors, MCP Inspector usw.) direkt aufrufen kann, anstatt eine Website zu scrapen.

Warum das existiert

Ich wollte wirklich verstehen, wie MCP von Anfang bis Ende funktioniert, nicht nur darüber lesen – also habe ich einen kleinen Server gebaut, der den Inhalt meiner Portfolio-Seite in strukturierte Werkzeuge verwandelt. Es ist auch ein bewusster Vorwand, zwei Dinge anzugehen, die ich vorher kaum angefasst hatte: Docker und eine grundlegende CI/CD-Pipeline, die beide in Stellenausschreibungen, auf die ich abziele, immer wieder auftauchen.

Related MCP server: personal-mcp

Was ist MCP, kurz erklärt

MCP ist ein offenes Protokoll (von Anthropic), das es einem KI-Assistenten erlaubt, externe "Werkzeuge" aufzurufen – typisierte Funktionen mit einem Namen, einer Beschreibung und einem Schema – um Live-Informationen abzurufen oder Aktionen auszuführen, anstatt sich nur auf das zu verlassen, was in seinen Trainingsdaten oder einem eingefügten Dokument steht. Ein Server deklariert seine Werkzeuge; jeder MCP-fähige Client kann sie entdecken und aufrufen. Dieses Projekt ist ein solcher Server: Er deklariert vier Werkzeuge, die auf meinen eigenen Portfolio-Daten basieren.

Werkzeuge

Werkzeug

Was es tut

list_projects()

Jedes Portfolio-Element – ausgelieferte Systeme, Wettbewerbsbeiträge, Forschungsprojekte, veröffentlichte Papers und Kursberichte, nicht nur die Flaggschiff-Fallstudien – mit ID, Name, Untertitel, Kategorie, Jahr, einzeiliger Zusammenfassung und den Links direkt in der Auflistung (Live-System, GitHub, Bericht, Demovideo usw.)

get_project_details(name)

Vollständiger Datensatz für ein Element. Für ein Flaggschiff-Projekt: Rolle, Technologie-Stack, Problem, Herausforderungen und Lösungen, Ergebnis, Links. Für ein leichteres Element: was immer vorhanden ist – mindestens eine Beschreibung und Links. Die Zuordnung ist nachsichtig und alias-bewusst ("lab handover"ifit-lab-handover; "NTPU OPE Assistant" → das Thesensystem, das es tatsächlich ist)

search_skills(keyword)

Schlüsselwortsuche über die Fähigkeiten-Taxonomie, nach Relevanz geordnet, jedes Ergebnis nennt die Projekte, die es demonstrieren

get_resume_summary(length)

Selbstvorstellung bei "short" / "medium" / "long", plus Kontaktinformationen

Der Docstring jedes Werkzeugs ist das, was der KI-Assistent tatsächlich liest, um zu entscheiden, wann er es aufrufen soll – siehe src/portfolio_mcp/server.py.

Abdeckung: data/projects.json enthält alle 31 Portfolio-Elemente – 7 tiefgehende Fallstudien (ausgelieferte Systeme, die Thesis, das NSTC-Forschungsprojekt, ein preisgekröntes Paper) plus 24 leichtere Einträge (andere Wettbewerbsbeiträge, Kursberichte, Konferenzpapiere). Jeder einzelne hat mindestens einen Link. Berichte im Kursstadium und Begleitpapiere enthalten eine related_project-ID, die auf die umfassendere Fallstudie verweist, zu der sie gehören, sodass ein Assistent von einem Bericht aus in die vollständige Geschichte eintauchen kann.

Architektur

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)
  • Transport: Streamable HTTP, nicht stdio – der Punkt ist, dass ein entfernter Client (z.B. Claude.ai Connectors) diesen Server über eine öffentliche URL erreichen kann, nicht nur über einen lokal gestarteten Prozess. Stdio wird für lokale Tests mit Claude Desktop / MCP Inspector weiterhin unterstützt.

  • Datenschicht: drei flache JSON-Dateien unter data/, einmal geladen und zwischengespeichert (functools.lru_cache). Keine Datenbank – die Daten sind klein, öffentlich und ändern sich selten.

  • Werkzeuglogik vs. MCP-Verdrahtung: absichtlich getrennt (tools.py vs. server.py), sodass die Logik ohne einen laufenden MCP-Server oder Transport unit-testbar ist.

  • SDK-Hinweis: Das offizielle mcp Python SDK hat seine High-Level-Server-API mit v2.0.0 von FastMCP auf mcp.server.mcpserver.MCPServer umgestellt – dieses Projekt zielt auf mcp>=2.0.0 und diese aktuelle API ab. Wenn Sie ältere MCP-Tutorials gesehen haben, die from mcp.server.fastmcp import FastMCP verwenden, ist das die API vor 2.0 und kann nicht gegen das importieren, was pip install mcp Ihnen heute liefert.

Projektstruktur

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

Lokales Ausführen

# from the repo root
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

Option A — stdio, mit MCP Inspector

npx @modelcontextprotocol/inspector python -m portfolio_mcp.server

Öffnet eine lokale Web-Oberfläche, in der Sie jedes Werkzeug direkt aufrufen und die Anfrage/Antwort inspizieren können.

Option B — stdio, mit Claude Desktop

Fügen Sie den mcpServers-Eintrag aus claude_desktop_config.json in Ihre eigene Claude Desktop-Konfiguration ein (Einstellungen → Entwickler → Konfiguration bearbeiten), passen Sie die Pfade für Ihren Rechner an, starten Sie dann Claude Desktop neu und fragen Sie etwas wie "An welchen Projekten hat diese Person gearbeitet?"

Option C — Streamable HTTP, lokal

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

Tests

pytest -v
ruff check .

Ausführen mit Docker

docker build -t portfolio-mcp-server .
docker run -p 8000:8000 portfolio-mcp-server

Der Container bedient immer Streamable HTTP (das ist der Sinn der Containerisierung – eine portable, öffentlich bereitstellbare Einheit, kein an einen Rechner gebundener stdio-Prozess).

Bereitstellen (Render)

Ausgewähltes Bereitstellungsziel: Render, Free-Tier – es führt langlebige Container aus (keine serverlosen Funktionen mit Ausführungszeit-Limits), die die persistenten Verbindungen von Streamable HTTP benötigen, und es braucht keine Kreditkarte zum Starten.

  1. Pushen Sie dieses Repository zu GitHub.

  2. Auf render.com: Neu → Web Service → dieses Repository verbinden.

  3. Render erkennt automatisch die Dockerfile und baut/führt sie als Container aus.

  4. Wählen Sie den Free-Instanztyp → Sie erhalten eine https://<etwas>.onrender.com-URL.

  5. Überprüfen Sie, ob sie läuft:

    npx @modelcontextprotocol/inspector https://<something>.onrender.com/mcp
  6. (Optional) Aktivieren Sie Render's GitHub Auto-Deploy, sodass git push auf main automatisch neu bereitstellt – zusammen mit dem CI-Workflow unten ist das die vollständige CI/CD-Geschichte.

Free-Tier-Hinweis: Render's kostenlose Webdienste schlafen nach etwa 15 Minuten Inaktivität ein und brauchen 30-60s zum Aufwachen bei der nächsten Anfrage. In Ordnung für eine Portfolio-Demo; erwähnenswert als bewusster Kosten/Latenz-Kompromiss, falls gefragt.

Live-Bereitstellung: https://yun-portfolio-mcp.onrender.com/mcp – verbinden Sie einen MCP-Client mit dieser URL (beachten Sie den /mcp-Pfad; die bloße Domain gibt einen 404-Fehler, das ist erwartet – Streamable HTTP bedient nur diesen einen Pfad). Überprüfen Sie es selbst mit npx @modelcontextprotocol/inspector https://yun-portfolio-mcp.onrender.com/mcp.

Wenn Sie dies forken: Die Host-Header-Whitelist in server.py ist standardmäßig fest auf yun-portfolio-mcp.onrender.com codiert (DNS-Rebinding-Schutz lehnt jeden anderen Host-Header mit einem 421 ab). Setzen Sie die Umgebungsvariable MCP_ALLOWED_HOSTS auf den Hostnamen Ihrer eigenen Bereitstellung oder bearbeiten Sie ALLOWED_HOSTS direkt.

Chat-Endpunkt (/chat) – das Q&A-Widget der Portfolio-Seite

Eine zweite, separate Tür auf demselben Render-Dienst, für ein einfaches Chat-Widget, das auf yunwcy.github.io eingebettet ist – nicht Teil der oben beschriebenen MCP-Protokolloberfläche. Ein Browser POSTet {"message": "..."} an /chat; der Server verwendet den Anthropic Tool Runner, um Claude entscheiden zu lassen, welches der gleichen vier Werkzeuge aufgerufen werden soll (indem tools.py direkt aufgerufen wird – kein MCP-Handshake erforderlich), und gibt dann {"reply": "..."} zurück. Siehe src/portfolio_mcp/chat.py für die vollständige Implementierung.

Warum dies ein echtes Backend braucht und GitHub Pages allein es nicht kann: Das Antworten in natürlicher Sprache bedeutet, dass ein LLM die Frage sehen und entscheiden muss, welches Werkzeug aufgerufen werden soll, was einen Anthropic-API-Schlüssel erfordert – und ein Schlüssel kann niemals in clientseitigem JavaScript auf einer statischen Seite sein, da jeder den Quelltext einsehen und das Konto leerräumen kann. /chat hält den Schlüssel serverseitig (eine Render-Umgebungsvariable, die niemals an den Browser gesendet wird) und liefert nur das Widget, das der Browser braucht, an GitHub Pages aus.

Einrichtung (erforderlich, bevor dieser Endpunkt funktioniert):

  1. Holen Sie sich einen API-Schlüssel von der Anthropic Console und fügen Sie ihn in Render als Umgebungsvariable ANTHROPIC_API_KEY hinzu (Render-Dashboard → dieser Dienst → Environment). Ohne ihn gibt /chat 503 {"error": "not_configured"} zurück, anstatt den Server abstürzen zu lassen.

  2. CHAT_ALLOWED_ORIGINS (kommagetrennt) steuert CORS – standardmäßig https://yunwcy.github.io. Setzen Sie es, wenn das Widget jemals woanders lebt.

  3. ANTHROPIC_CHAT_MODEL (Standard claude-opus-5) – die stärkste Allzweckwahl, aber dies ist ein einfaches, potenziell hochfrequentes, kostensensibles öffentliches Widget, daher ist claude-haiku-4-5 hier speziell eine Überlegung wert. Dies ist eine bewusste Entscheidung, die demjenigen überlassen wird, der den Server betreibt, nicht fest codiert.

  4. CHAT_RATE_LIMIT_PER_HOUR (Standard 30) – eine einfache In-Memory-pro-IP-Begrenzung, damit ein einzelner Besucher nicht allein die Rechnung in die Höhe treiben kann. Sie setzt sich bei jedem Neustart/Neubereitstellung zurück und wird nicht über Instanzen hinweg geteilt – ausreichend für eine wenig frequentierte persönliche Seite, keine allgemeine Missbrauchsabwehr.

CI/CD

.github/workflows/ci.yml wird bei jedem Push/PR auf main ausgeführt: installiert das Paket, lintet mit ruff und führt die pytest-Suite aus. Render's GitHub Auto-Deploy (siehe oben) übernimmt die CD-Hälfte.

Sicherheits-/Kostenhinweise

  • Die MCP-Werkzeugoberfläche (/mcp) ruft selbst kein LLM auf – sie liest nur lokales JSON und gibt es zurück. Wer sich verbindet (sein Claude, seine Tokens), trägt diese Kosten, nicht dieser Server.

  • Der /chat-Endpunkt ruft ein LLM auf, und zwar mit dem eigenen Anthropic-API-Schlüssel dieses Servers – das ist der ganze Sinn (ein Browser kann einen Schlüssel nicht sicher halten). Die Kosten werden durch eine Pro-IP-Ratenbegrenzung, effort: "low" und ein kleines max_tokens begrenzt; siehe den Abschnitt zum Chat-Endpunkt oben für die Stellschrauben.

  • Alle Daten sind bereits auf meiner Portfolio-Seite öffentlich – auf keinem Endpunkt ist eine Authentifizierung implementiert, da es nichts Privates zu schützen gibt. Die CORS-Whitelist von /chat dient dazu, zu kontrollieren, wer das API-Budget ausgeben kann, nicht um die Daten zu schützen.

Aktualisieren der Daten

Bearbeiten Sie die JSON-Dateien unter data/ direkt – id ist der stabile Bezeichner, mit dem get_project_details abgleicht; jedes andere Feld ist frei gestaltbar. Für Inhaltsaktualisierungen sind keine Codeänderungen erforderlich.

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    -
    quality
    C
    maintenance
    Exposes 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.
    11
    1
    MIT
  • F
    license
    -
    quality
    B
    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
    -
    quality
    C
    maintenance
    Transforms professional data (CV, projects) into MCP tools for LLMs to query, list, match job descriptions, and ask about experience.
    77
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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