portfolio-mcp
Portfolio MCP
Salman Buttのポートフォリオで使用されているSupabaseバックエンドのエンジニアリングブログを管理するための、スタンドアロンのModel Context Protocol (MCP)サーバー。
公開されているNext.jsポートフォリオは読み取り専用のままです。このサービスが特権的なブログ管理インターフェースを担い、Supabaseのシークレットキーをフロントエンドのデプロイメントの外に保持します。
公開する機能
記事ツール
list_blog_postsget_blog_postcreate_blog_postupdate_blog_postpublish_blog_postunpublish_blog_postdelete_blog_post
画像ツール
upload_blog_imagereplace_blog_imagedelete_blog_imageget_blog_image_url
このサーバーは、任意のSQLや無制限のSupabaseアクセスを公開しません。
Related MCP server: Self-Hosted Supabase MCP Server
アーキテクチャ
ChatGPT / remote MCP host / local MCP client
|
| Streamable HTTP or stdio
v
portfolio-mcp service
|
+--> MCP token authentication (HTTP)
|
+--> MCP SDK v2 tool layer
|
+--> Supabase REST: public.blogs
|
+--> Supabase Storage: blog-images
Public visitors
|
v
Next.js portfolio --> Supabase anon read-only access要件
Node.js 22以上
ポートフォリオの
blogsテーブルを含むSupabaseプロジェクトブログテーブルとStorageバケットにアクセスできるサーバーサイドのSupabaseシークレットキー
ChatGPT用: このMCPサーバーのHTTPSでアクセス可能なリモートデプロイメント
セットアップ
git clone https://github.com/salman0butt/portfolio-mcp.git
cd portfolio-mcp
npm ci
cp .env.example .env.envを設定します:
SUPABASE_URL=https://YOUR_PROJECT.supabase.co
SUPABASE_SECRET_KEY=sb_secret_REPLACE_ME
SUPABASE_BLOG_BUCKET=blog-images
PORTFOLIO_MCP_TOKEN=replace-with-long-random-bearer-token
PORTFOLIO_MCP_URL_TOKEN=replace-with-different-long-random-url-token
PORT=3000
HOST=0.0.0.0
MCP_ALLOWED_ORIGINS=*
MCP_MAX_REQUEST_BYTES=5242880HTTPおよびstdioエントリポイントは、ローカルの.envファイルが存在する場合に自動的に読み込みます。デプロイメントプラットフォームが注入する環境変数は引き続き正常に動作します。
MCPトークンの生成
このコマンドを2回実行します:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"2つの異なる出力を使用します:
PORTFOLIO_MCP_TOKEN—Authorizationヘッダーを送信できるクライアント用のベアラートークン。PORTFOLIO_MCP_URL_TOKEN— 静的なカスタムヘッダーの設定が不便なクライアント用の使い捨てトークン。
両方のトークンは少なくとも32文字以上で、互いに異なる必要があります。
絶対にSupabaseのシークレットキーをMCPトークンとして使用しないでください。SUPABASE_SECRET_KEYをChatGPTコネクタのURLに入れないでください。
Supabase認証
最新のSupabaseサーバーサイドシークレットキーを推奨します:
sb_secret_...このサービスは、最新のsb_secret_*キーをSupabaseのapikeyヘッダーでのみ送信します。これらのキーは不透明なAPIキーであり、Authorization: Bearer JWTとしては送信されません。
レガシーなJWTベースのservice_roleキーは移行互換性のために引き続きサポートされますが、新しいデプロイメントではsb_secret_*を使用してください。
開発
リモートHTTPモード:
npm run dev:httpMCPエンドポイント:
http://localhost:3000/mcpヘルスチェック:
http://localhost:3000/healthzローカルstdioモード:
npm run dev:stdiostdioモードでは、アクセスはサーバーを起動するローカルプロセスによって制御されるため、HTTP MCPトークンは使用されません。
本番デプロイメント
直接ビルドして実行:
npm run build
npm startまたはDockerを使用:
docker build -t portfolio-mcp .
docker run --rm -p 3000:3000 --env-file .env portfolio-mcpコンテナはpackage-lock.jsonから依存関係をインストールし、非rootのnodeユーザーとして実行され、/healthz Dockerヘルスチェックを公開します。
このサービスを、Railway、Render、Fly.io、Kubernetes、VPSなど、長時間実行されるNode HTTPプロセス/コンテナをサポートするプラットフォームにデプロイしてください。現在の実装はVercelのサーバーレス関数エントリポイントではありません。
ChatGPTの場合、デプロイされたMCPエンドポイントはHTTPS経由で到達可能である必要があります。例:
https://portfolio-mcp.example.com/mcpHTTP認証
リクエストヘッダーをサポートするクライアントは次を使用してください:
Authorization: Bearer <PORTFOLIO_MCP_TOKEN>静的なベアラーヘッダーの設定が不便なクライアントの場合、エンドポイントは次も受け入れます:
https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKENクエリ文字列の認証情報はインフラストラクチャ/アクセスログに表示される可能性があります。PORTFOLIO_MCP_URL_TOKENは使い捨てとして扱い、漏洩した場合はローテーションしてください。MCPクライアントがサポートする場合はベアラー認証を優先してください。
ChatGPTへの接続
ChatGPTはリモートMCPサーバーに接続します。localhostのみで実行されているサーバーには接続しません。
このリポジトリの更新時点(2026年8月)では、OpenAIはChatGPT Business、Enterprise、EduワークスペースのWeb向けに、書き込み/変更アクションを含む完全なカスタムMCPサポートを文書化しています。可用性は変更される可能性があるため、UIが異なる場合は現在のOpenAI ChatGPTカスタムアプリ/MCPドキュメントを確認してください。
ChatGPTワークスペースでカスタムMCPアプリ/コネクタが公開されている場合:
このリポジトリをHTTPSエンドポイントにデプロイします。
すべてのサーバー環境変数をデプロイメントプラットフォームで設定します。
ChatGPTで、ワークスペースの権限に応じて開発者モード/カスタムアプリを有効にします。
カスタムMCPアプリを作成します。
ChatGPTのフォームに静的なカスタムベアラーヘッダーフィールドがない場合は、URLトークンエンドポイントを使用します:
https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKENChatGPTでそのコネクタにNo Authを選択します。認証はこのサーバーによってURLトークンを介して引き続き強制されます。
Scan Toolsを選択します。サーバーは上記の記事ツールと画像ツールを公開するはずです。
新しいチャットでアプリを追加/有効化し、書き込みアクションをテストする前に
list_blog_postsなどの読み取りアクションをテストします。ChatGPTは、ワークスペース/アプリの権限とツールの注釈に基づいて、書き込み/破壊的アクションの確認を要求する場合があります。
SUPABASE_SECRET_KEYをChatGPTに入力しないでください。ChatGPTに必要なのはリモートMCPエンドポイントのみです(このURLトークン設定では、使い捨てのMCP URLトークンも必要です)。
推奨されるChatGPTテスト手順
コネクタのスキャンが成功した後:
List my portfolio blog posts.次に:
Create a draft blog post titled "MCP Connection Test". Do not publish it.次にそれを確認します:
Get the MCP Connection Test draft and show me its metadata.最後に、明示的に削除する意図がある場合にのみ、テストドラフトを削除します。
CORS / オリジン
MCP_ALLOWED_ORIGINSはカンマ区切りのリストを受け入れます:
MCP_ALLOWED_ORIGINS=https://example.com,https://another-client.exampleHTTPサーバーは、ブラウザのCORSプリフライトでMcp-Protocol-Version、Mcp-Method、Mcp-Name、Mcp-Session-Idなどの現在のMCPリクエストヘッダーをサポートします。
デフォルトの*は互換性を最大化しますが、トークン認証は必須のままです。サービスを呼び出す必要がある正確なブラウザオリジンがわかっている場合は、リストを絞り込んでください。
リクエストと画像の制限
デフォルトのHTTP MCPリクエスト上限は5 MiBです:
MCP_MAX_REQUEST_BYTES=5242880これは、base64が約3分の1のオーバーヘッドとJSONフレーミングを追加するため、3 MiBのデコード済み画像制限よりも意図的に大きくなっています。
受け入れられる画像コンテンツタイプ:
PNG
JPEG
WebP
GIF
AVIF
ストレージパスは正規化され、../などのトラバーサルを拒否します。画像ペイロードには有効なbase64が含まれている必要があります。
推奨されるオブジェクトパス:
senior-software-engineer/cover.webp
production-rag-systems/architecture.webp
nextjs-at-scale/performance.webpブログ記事を削除しても、その画像は自動的に削除されません。これは、共有または再利用される可能性のあるメディアの誤削除を防ぐためです。
ブログワークフロー
推奨される公開フロー:
記事を下書きとして作成します。
必要に応じてカバー/図解画像をアップロードします。
返された公開画像URLで下書きを更新します。
タイトル、抜粋、Markdown、カテゴリ、タグ、公開日を確認します。
publish_blog_postを使用して公開します。後で必要に応じて更新または非公開にします。
明示的な意図がある場合にのみ、記事または画像を削除します。
published_atはISO 8601の日付または日時を受け入れます。例:
2026-08-25
2026-08-25T12:00:00+05:00セキュリティモデル
Supabaseのシークレット認証情報はサーバーサイドのみです。
最新の
sb_secret_*キーはSupabase APIキーとして送信され、JWTベアラートークンとしては送信されません。Next.jsポートフォリオは、公開された読み取り専用のSupabaseアクセスモデルを維持します。
HTTP MCPリクエストにはベアラートークンまたはURLトークンが必要です。
MCPトークンは強力で、互いに異なる必要があります。
トークン比較にはタイミングセーフな等価性を使用します。
汎用のSQL/クエリ実行は公開されません。
スラッグ、公開日、画像パス、画像タイプ、base64ペイロード、画像サイズ、HTTPリクエストサイズが検証されます。
上書き、非公開、置換、削除ツールは、リスクに適したMCP注釈を使用します。
シャットダウンは新しいトラフィックの受け入れを停止し、MCPリソースが閉じられる前にアクティブなリクエストに制限付きのドレイン期間を与えます。
シークレットはGitHubにコミットしてはなりません。
MCPプロトコル
HTTPサーバーは安定版のMCP TypeScript SDK v2を使用し、/mcpでStreamable HTTPを公開します。ローカルMCPホスト用にstdioエントリポイントが含まれています。
リモートHTTPラッパーは、クライアント互換性を最大化するために、最新のMCPトラフィックとSDKのステートレスなレガシーフォールバックの両方をサポートします。
検証
CIで使用されるものと同じ検証を実行します:
npm run checkこれにより以下が実行されます:
厳格なTypeScript型チェック
ランタイム回帰テスト
本番用TypeScriptビルド
ランタイムテストは、Supabaseシークレットキーの処理、HTTP認証、CORS、リクエスト制限、環境変数の読み込み、トークン検証、およびリモートHTTPアダプターを通じた実際のMCP tools/listリクエストをカバーします。
GitHub Actionsは、コミットされたロックファイルからnpm ciを使用して正確な依存関係グラフをインストールします。
This server cannot be installed
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
- AlicenseNot gradedqualityDmaintenanceManage your Ghost blog content directly from Claude, Cursor, or any MCP-compatible client, allowing you to create, edit, search, and delete posts with support for tag management and analytics.14MIT
- FlicenseNot gradedqualityDmaintenanceEnables developers to interact with self-hosted Supabase instances, providing database introspection, migration management, auth user operations, storage management, and TypeScript type generation directly from MCP-compatible development environments.
- AlicenseAqualityFmaintenanceEnables AI tools to programmatically manage Substack content, including creating drafts, publishing posts, and posting to Substack Notes. It supports image uploads, live blogging, and document formatting compatible with Substack's ProseMirror editor.118MIT
- AlicenseNot gradedqualityDmaintenanceManages Supabase projects, databases, edge functions, secrets, and branches across organizations using the Supabase Management API with 24 tools.MIT
Related MCP Connectors
Publish and manage articles, series, comments, reactions, newsletters and blog analytics.
Manage Supabase projects end to end across database, auth, storage, realtime, and migrations. Moni…
Manage Appwrite projects, databases, auth, storage, functions, and messaging; search Appwrite docs
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/salman0butt/portfolio-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server