mcp-resource-server
mcp-resource-server
10のモック業界(銀行、ヘルスケア、政府、製造、小売、スポーツ用品、大学、ワークフォース、Abercrombie & Fitch、航空)にわたる読み取り中心のツールと、一連の投資ツールを公開するMCPサーバーです。各業界は独自のバンドルされたSQLiteデータベースを読み取ります。実行に他のサービスは必要ありません。投資ツールは、必要に応じて、提供する銀行APIにプロキシすることもできます(下記参照)。
前提条件
Docker + Docker Compose
ベアラートークンを発行・検証するためのPingOne環境(または、正しい
aud/scopeクレームを持つJWTを発行し、JWKSエンドポイントを公開できる任意のOAuth AS。このサーバーは標準のOIDCディスカバリのみに依存しており、PingOne固有のものには依存しません)
Related MCP server: mock-mcp
クイックスタート
cp .env.example .env.envを編集します。MCP_RESOURCE_SERVER_RESOURCE_URI、PINGONE_ENVIRONMENT_ID、PINGONE_REGIONを自分のPingOne環境に合わせて設定します。実際のトークンができるまでPINGONE_ISSUERはコメントアウトしたままにします(「認証モード」を参照)。
docker compose up --buildサーバーはhttp://localhost:8081で待ち受けます。SQLiteデータベースは./dataに永続化されます(初回使用時にseed/からシードされます。再起動しても空でないデータベースは再シードされません)。
実行確認
curl http://localhost:8081/health
curl http://localhost:8081/.well-known/oauth-protected-resource2番目の呼び出しは、リソースのアドバタイズされたスコープと、PINGONE_ENVIRONMENT_ID/PINGONE_REGIONが設定されている場合はその認可サーバーを返します。これは、MCPクライアントがOAuthディスカバリに使用するRFC 9728メタデータです。
認証モード
トークンの署名が検証されるかどうかは、JWKSソースが設定されているかどうかで決まります。STRICT_AUTHではありません。
JWKSソース設定あり(
PINGONE_ISSUER、PINGONE_JWKS_URI、またはPINGONE_BASE_URL)— すべてのトークンはPingOne環境のキーに対して検証され、失敗した場合は拒否されます。STRICT_AUTHは効果がありません。実際のトークンが流れ始めたらこの方法で実行します。JWKSソースなし —
STRICT_AUTH=false(同梱のデフォルト)は、コンソール警告付きで整形式のトークンを受け入れます。PingOneを配線する前に手作りのトークンですべてのツールを試すことができます。STRICT_AUTH=trueは代わりにすべてのトークンを拒否します。デフォルトを自分以外の人が到達できる状態にしないでください。
.env.exampleには、その理由から3つのJWKS変数すべてがコメントアウトされて同梱されています。実際のトークンができたら1つをコメント解除してください。
ベアラートークンの取得
すべてのツール呼び出しには、audクレームがMCP_RESOURCE_SERVER_RESOURCE_URIと一致し、scopeクレームが呼び出すツールをカバーするベアラートークンが必要です(最新の権威あるリストはtools/listを参照してください。これはこのサーバー自身のレジストリから生成されます)。
ローカルテスト(STRICT_AUTH=false) — 正しいクレームを持つ整形式のJWTであれば機能します。署名はチェックされません。
node -e "
const b64 = s => Buffer.from(JSON.stringify(s)).toString('base64url');
const header = b64({alg:'none',typ:'JWT'});
const payload = b64({sub:'test-user',scope:'airlines:read',aud:'your-resource-uri',exp:Math.floor(Date.now()/1000)+3600});
console.log(header+'.'+payload+'.');
"(audを自分のMCP_RESOURCE_SERVER_RESOURCE_URIの値に、scopeをテストするツールに合わせて置き換えてください)
実トークン(STRICT_AUTH=true) — PingOne環境から発行します。PingOneトークンエンドポイントに対するクライアントクレデンシャルグラントで、このサーバーのオーディエンスをリソースとして要求します:
curl -s -X POST "https://auth.pingone.<region>/<env-id>/as/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<your PingOne worker app client id>" \
-d "client_secret=<your PingOne worker app client secret>" \
-d "scope=<space-separated scopes, e.g. banking:read airlines:read>" \
-d "resource=<MCP_RESOURCE_SERVER_RESOURCE_URI value>"これには、そのクライアントのアプリがPingOneでこのリソースとそれらのスコープに対して認可されている必要があります(Applications → アプリ → Resources)。これはこのサーバーが代わりに行うPingOne側のセットアップ手順です。
ツールを直接呼び出す(動作確認)
TOKEN="<paste a token from above>"
curl -s -X POST http://localhost:8081/mcp \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_airline_bookings","arguments":{}}}'MCPクライアントの接続
サーバーは同じポートでWebSocketとHTTP(ストリーミング可能、POST /mcp)の両方でMCPを話します — ws://localhost:8081またはhttp://localhost:8081/mcp。
MCP Inspector(公式開発ツール。任意のサーバーで動作し、手動ヘッダーを設定できるため、これをテストする最も信頼性の高い方法です):
npx @modelcontextprotocol/inspectorTransportを「Streamable HTTP」に、URLをhttp://localhost:8081/mcpに設定し、接続設定でInspectorにAuthorization: Bearer <token>ヘッダーを追加してから接続します。
Claude Desktop / Cursor / Windsurf(静的設定、HTTPトランスポート):
{
"mcpServers": {
"mcp-resource-server": {
"url": "http://localhost:8081/mcp",
"transport": "http"
}
}
}Claude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.jsonCursor: プロジェクトルートの
.cursor/mcp.jsonWindsurf:
~/.codeium/windsurf/mcp_config.json
これらの設定には静的ベアラートークンのフィールドがありません。クライアントが保護されたツールを呼び出すと、/.well-known/oauth-protected-resourceを読み取り、認可サーバーとしてPingOne環境を見つけ、サインインを促します。これは、PingOne環境にその特定のMCPクライアントアプリ用のOAuthクライアントが登録され、そのクライアント自身のドキュメントで指定されたリダイレクトURIを使用している場合にのみ機能します。これはこのサーバーの外部にあるPingOne側のセットアップ手順です。設定を編集した後、クライアントを再起動してください。
投資ツール
get_investment_accounts、get_investment_balance、get_portfolio_summary、get_investment_transactionsは、他のすべての業界と同様に、バンドルされたSQLiteデータベース(初回使用時にseed/invest.seed.jsonからシードされるdata/invest.db)からそのまま動作します。
BANKING_API_BASE_URLは、独自の銀行APIを実行していて、これらの4つのツールが呼び出し元のベアラートークンをそのAPIに転送し、そのAPIが返すものを返すようにしたい場合にのみ設定します。設定すると、バンドルされた投資データベースは使用されません。
ツールの追加
ツールはコードであり、設定ではありません。カタログ(tools/list)、ツールごとのスコープゲート、/.well-known/oauth-protected-resourceでアドバタイズされるscopes_supportedはすべてsrc/tools/registry.tsのALL_TOOLSから派生します。したがって、業界のリストに追加したツールは、イメージを再ビルドすると(クイックスタートの--buildコマンド)どこでも有効になります。
1. 既存の業界にツールを追加する
2つの編集で、レジストリの変更はありません:
その業界の
src/tools/<vertical>Tools.ts配列にツール定義を追加します。例:sportingGoodsTools.ts内:{ name: 'gear_return_status', description: 'Show the status of a sporting-goods return.', inputSchema: { type: 'object', properties: { orderId: { type: 'string', description: 'Order ID' } }, required: ['orderId'], }, requiredScopes: ['read'], // the bearer token must carry every scope listed readOnly: true, intentHints: ['check my gear return'], // required — tests/registry.test.ts asserts it },src/tools/<vertical>ToolHandler.tsのswitchに一致するcase 'gear_return_status':を追加します。ハンドラーはJSONを返すだけです。その業界のsrc/db/<vertical>Db.tsから読み取るか、他の何かから読み取ります。
2. 新しい業界を追加する
上記と同じ2つのファイル(<VERTICAL>_TOOLS: McpToolDef[]をエクスポートするsrc/tools/<vertical>Tools.tsと、dispatch<Vertical>Toolをエクスポートするsrc/tools/<vertical>ToolHandler.ts)に加えて:
データ(オプション):
src/db/<vertical>Db.ts+seed/<vertical>.seed.json。sportingGoodsDb.tsをコピーします。これはdata/<vertical>.dbを開き、スキーマを作成し、テーブルが空の場合にのみシードを適用します。Dockerfileはすでにseed/をコピーし、composeファイルはすでにdata/をマウントします。登録:
src/tools/registry.tsで、2つのエクスポートをインポートし、<VERTICAL>_TOOLSをALL_TOOLSにスプレッドし、const <VERTICAL>_TOOL_NAMES = new Set(<VERTICAL>_TOOLS.map((t) => t.name))を追加し、dispatch()に1行追加します:if (<VERTICAL>_TOOL_NAMES.has(toolName)) return dispatch<Vertical>Tool(toolName, args, subject);(subjectはトークンのsubです。銀行や航空のように、読み取りが呼び出し元にスコープされる必要がある場合は、ハンドラーでそれを受け入れます。)リソース(オプション):
tools/listは自動ですが、MCP リソース(resources/list、resources/read)はsrc/index.tsの手動管理されたRESOURCE_CATALOGから来ます。業界がそのリストツールをリソースとしても公開する必要がある場合は、そこにエントリを追加します。
注意点
requiredScopesは、PingOneリソースが実際に付与するスコープである必要があります。いずれかが欠けているトークンはtools/callで403になり、tools/listはそのトークンからツールを完全に隠します。ツール名はグローバルです。
dispatch()は最初に一致する名前セットでルーティングするため、2つの業界で名前を再利用すると、最初にチェックされた方に黙って送られます。テンプレートには、investではなくデータバックアップの業界(例:スポーツ用品)を使用してください。investは
dispatch()のフォールスルーであり、不要なプロキシ対SQLiteの切り替えを伴います。
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 gradedqualityDmaintenanceA lightweight MCP server that simulates financial data interactions with dummy authentication and static JSON datasets for testing financial applications.2MIT
- FlicenseNot gradedqualityBmaintenanceA production-grade MCP server for a fictional digital bank, exposing tools for an AI copilot to service customers across the full risk spectrum from read-only lookups to money movement and destructive admin actions, with OAuth 2.1 security and a realistic dataset.131
- FlicenseNot gradedqualityDmaintenanceA Test/Sandbox MCP server that integrates with the SnapTrade API Sandbox environment to provide portfolio oversight, market data, and trading capabilities.
Related MCP Connectors
Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.
Multi-tenant FastMCP server for Charles Schwab brokerage data, monetized via DPYC Tollbooth
MCP server exposing the Backtest360 engine API as tools for AI agents.
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/curtismu7/mcp-resource-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server