Portfolio MCP Server
Portfolio MCP Server
MCP(Model Context Protocol)サーバーで、Cheng-Yun Wuのポートフォリオ(プロジェクト、スキル、履歴書)をツールとして公開します。MCP互換のAIアシスタント(Claude Desktop、Claude.ai Connectors、MCP Inspectorなど)は、ウェブサイトをスクレイピングする代わりに、これらのツールを直接呼び出すことができます。
なぜこれを作ったか
MCPが実際にどのように動作するかを、読むだけでなく理解したいと思ったからです。そこで、自分のポートフォリオサイトのコンテンツを構造化されたツールに変換する小さなサーバーを構築しました。また、これまであまり触れてこなかったDockerと基本的なCI/CDパイプラインを学ぶための、意図的なきっかけでもあります。これらは、私が応募している求人情報で頻繁に登場するスキルです。
Related MCP server: personal-mcp
MCPとは(簡単に)
MCPは(Anthropicによる)オープンプロトコルで、AIアシスタントが外部の「ツール」(名前、説明、スキーマを持つ型付き関数)を呼び出して、トレーニングデータや貼り付けられたドキュメントだけに頼るのではなく、ライブ情報を取得したりアクションを実行したりできるようにします。サーバーは自身のツールを宣言し、MCP対応クライアントはそれらを発見して呼び出すことができます。このプロジェクトはそのようなサーバーの1つで、自身のポートフォリオデータに基づく4つのツールを宣言しています。
ツール
ツール | 機能 |
| すべてのポートフォリオ項目(リリース済みシステム、コンテスト参加作品、研究プロジェクト、出版論文、コースレポート。主要なケーススタディだけでなく)を、id、名前、タグライン、カテゴリ、年、1行の概要、そしてリスト内にリンク(ライブシステム、GitHub、レポート、デモ動画など)とともに表示します。 |
| 1つの項目の完全なレコード。主要プロジェクトの場合:役割、技術スタック、問題、課題と解決策、成果、リンク。軽量な項目の場合:ファイルにある情報(最低でも説明とリンク)。マッチングは寛容でエイリアスに対応しています( |
| スキル分類全体のキーワード検索。関連性でランク付けされ、各結果はそのスキルを示すプロジェクトを表示します。 |
|
|
各ツールのdocstringは、AIアシスタントがいつ呼び出すかを判断するために実際に読み取るものです。詳細は src/portfolio_mcp/server.py を参照してください。
カバレッジ: data/projects.json には全31件のポートフォリオ項目が含まれています。7件の詳細なケーススタディ(リリース済みシステム、論文、NSTC研究プロジェクト、受賞論文)と、24件の軽量な項目(その他のコンテスト参加作品、コースレポート、会議論文)です。すべての項目に少なくとも1つのリンクが含まれています。コース段階のレポートや関連論文には、所属する詳細なケーススタディを指す 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)トランスポート: Streamable HTTP(stdioではありません)。ポイントは、リモートクライアント(例:Claude.aiのConnectors)がローカルで起動されたプロセスだけでなく、公開URL経由でこのサーバーにアクセスできることです。ローカルのClaude Desktop / MCP Inspectorテスト用にstdioもサポートしています。
データ層:
data/の下にある3つのフラットなJSONファイル。一度ロードされ、キャッシュされます(functools.lru_cache)。データベースはありません。データは小さく、公開されており、変更は稀です。ツールロジックと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.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各ツールを直接呼び出し、リクエスト/レスポンスを検査できるローカルWeb 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を提供します(コンテナ化のポイントはこれです — ポータブルで公開可能なユニットであり、1台のマシンに縛られたstdioプロセスではありません)。
デプロイ(Render)
選択したデプロイ先: Render、無料枠。長時間実行されるコンテナ(実行時間制限のあるサーバーレス関数ではない)を実行します。これはStreamable HTTPの永続的な接続に必要であり、開始にクレジットカードは不要です。
このリポジトリをGitHubにプッシュします。
render.com で: New → Web Service → このリポジトリに接続。
Renderが
Dockerfileを自動検出し、コンテナとしてビルド/実行します。Free インスタンスタイプを選択 →
https://<something>.onrender.comのURLが取得できます。動作確認:
npx @modelcontextprotocol/inspector https://<something>.onrender.com/mcp(オプション)RenderのGitHub自動デプロイを有効にすると、
git pushをmainに実行するたびに自動的に再デプロイされます。以下のCIワークフローと組み合わせることで、完全なCI/CDストーリーが完成します。
無料枠の注意: Renderの無料Webサービスは、約15分間アイドル状態が続くとスリープし、次のリクエストで起動するのに30〜60秒かかります。ポートフォリオのデモには問題ありませんが、尋ねられた場合に意図的なコスト/レイテンシのトレードオフとして言及する価値があります。
ライブデプロイ: https://yun-portfolio-mcp.onrender.com/mcp — MCPクライアントをこのURLに接続してください(/mcp パスに注意。ベアドメインは404になります。これは想定内です — Streamable HTTPはその1つのパスのみを提供します)。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サービス上の2つ目の独立したドアで、yunwcy.github.io に埋め込まれたプレーンなチャットウィジェット用です。上記のMCPプロトコルサーフェスの一部ではありません。 ブラウザが {"message": "..."} を /chat に POST すると、サーバーはAnthropic Tool Runnerを使用して、Claudeに同じ4つのツールのどれを呼び出すかを決定させ(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ダッシュボード → このサービス → Environment)。これがない場合、/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ごとの制限で、1人の訪問者が単独で請求額を増やせないようにします。再起動/再デプロイのたびにリセットされ、インスタンス間で共有されません。低トラフィックの個人サイトには十分ですが、一般的な悪用防止策ではありません。
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