mcp-resource-server
mcp-resource-server
Ein MCP-Server, der überwiegend lesende Tools über zehn Mock-Vertikalen (Bankwesen, Gesundheitswesen, Regierung, Fertigung, Einzelhandel, Sportartikel, Universität, Arbeitskräfte, Abercrombie & Fitch, Fluggesellschaften) sowie eine Reihe von Investment-Tools bereitstellt. Jede Vertikale liest ihre eigene gebündelte SQLite-Datenbank – kein anderer Dienst ist erforderlich, um sie auszuführen. Investment-Tools können optional an eine von Ihnen bereitgestellte Banking-API weiterleiten (siehe unten).
Voraussetzungen
Docker + Docker Compose
Eine PingOne-Umgebung zum Erstellen und Verifizieren von Bearer-Tokens (oder ein beliebiger OAuth-AS, der ein JWT mit den richtigen
aud/scope-Claims ausstellen und einen JWKS-Endpunkt veröffentlichen kann – dieser Server verlässt sich nur auf standardmäßige OIDC-Erkennung, nicht auf etwas PingOne-Spezifisches).
Related MCP server: mock-mcp
Schnellstart
cp .env.example .envBearbeiten Sie .env: Setzen Sie MCP_RESOURCE_SERVER_RESOURCE_URI, PINGONE_ENVIRONMENT_ID und PINGONE_REGION für Ihre eigene PingOne-Umgebung. Lassen Sie PINGONE_ISSUER auskommentiert, bis Sie echte Tokens haben (siehe „Auth-Modi“).
docker compose up --buildDer Server lauscht auf http://localhost:8081. SQLite-Datenbanken werden in ./data gespeichert (beim ersten Gebrauch aus seed/ befüllt; ein Neustart befüllt eine nicht leere Datenbank nie erneut).
Überprüfen, ob er läuft
curl http://localhost:8081/health
curl http://localhost:8081/.well-known/oauth-protected-resourceDer zweite Aufruf gibt die beworbenen Scopes der Ressource und, wenn PINGONE_ENVIRONMENT_ID/PINGONE_REGION gesetzt sind, deren Autorisierungsserver zurück – dies sind die RFC-9728-Metadaten, die ein MCP-Client für die OAuth-Erkennung verwendet.
Auth-Modi
Ob die Signatur eines Tokens verifiziert wird, entscheidet sich danach, ob eine JWKS-Quelle konfiguriert ist – nicht durch STRICT_AUTH:
JWKS-Quelle gesetzt (
PINGONE_ISSUER,PINGONE_JWKS_URIoderPINGONE_BASE_URL) – jedes Token wird gegen die Schlüssel Ihrer PingOne-Umgebung verifiziert und bei Fehlschlag abgelehnt.STRICT_AUTHhat keine Wirkung. Führen Sie es so aus, sobald echte Tokens fließen.Keine JWKS-Quelle –
STRICT_AUTH=false(die mitgelieferte Standardeinstellung) akzeptiert ein wohlgeformtes Token mit einer Konsolenwarnung, sodass Sie jedes Tool mit einem handgemachten Token testen können, bevor PingOne angeschlossen ist;STRICT_AUTH=truelehnt stattdessen jedes Token ab. Lassen Sie die Standardeinstellung nicht für andere als Sie erreichbar.
.env.example wird mit allen drei JWKS-Variablen auskommentiert geliefert – kommentieren Sie eine aus, wenn Sie echte Tokens haben.
Ein Bearer-Token erhalten
Jeder Tool-Aufruf benötigt ein Bearer-Token, dessen aud-Claim mit MCP_RESOURCE_SERVER_RESOURCE_URI übereinstimmt und dessen scope-Claim das aufgerufene Tool abdeckt (siehe tools/list für die maßgebliche, aktuelle Liste – sie wird aus der eigenen Registrierung dieses Servers generiert).
Lokales Testen (STRICT_AUTH=false) – jedes wohlgeformte JWT mit den richtigen Claims funktioniert; die Signatur wird nicht geprüft.
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+'.');
"(tauschen Sie aud gegen Ihren eigenen MCP_RESOURCE_SERVER_RESOURCE_URI-Wert und scope gegen das/die Tool(s), das/die Sie testen)
Echte Tokens (STRICT_AUTH=true) – erstellen Sie eines aus Ihrer PingOne-Umgebung. Ein Client-Credentials-Grant gegen Ihren PingOne-Token-Endpunkt, der die Audience dieses Servers als Ressource anfordert:
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>"Dies erfordert, dass die App dieses Clients für diese Ressource und diese Scopes in PingOne autorisiert ist (Applications → Ihre App → Resources) – ein PingOne-seitiger Einrichtungsschritt, den dieser Server nicht für Sie übernimmt.
Ein Tool direkt aufrufen (Sanity-Check)
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":{}}}'Einen MCP-Client verbinden
Der Server spricht MCP sowohl über WebSocket als auch über HTTP (streamable, POST /mcp) auf demselben Port – ws://localhost:8081 oder http://localhost:8081/mcp.
MCP Inspector (das offizielle Entwickler-Tool – funktioniert mit jedem Server und ermöglicht das Setzen eines manuellen Headers, daher ist es der zuverlässigste Weg, diesen zu testen):
npx @modelcontextprotocol/inspectorSetzen Sie Transport auf „Streamable HTTP“, URL auf http://localhost:8081/mcp und fügen Sie vor dem Verbinden einen Authorization: Bearer <token>-Header in den Verbindungseinstellungen des Inspectors hinzu.
Claude Desktop / Cursor / Windsurf (statische Konfiguration, HTTP-Transport):
{
"mcpServers": {
"mcp-resource-server": {
"url": "http://localhost:8081/mcp",
"transport": "http"
}
}
}Claude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.jsonCursor:
.cursor/mcp.jsonin Ihrem ProjektstammWindsurf:
~/.codeium/windsurf/mcp_config.json
Diese Konfigurationen haben kein Feld für ein statisches Bearer-Token – wenn der Client ein geschütztes Tool aufruft, liest er /.well-known/oauth-protected-resource, findet Ihre PingOne-Umgebung als Autorisierungsserver und fordert Sie zur Anmeldung auf. Das funktioniert nur, wenn Ihre PingOne-Umgebung einen OAuth-Client für diese spezifische MCP-Client-App registriert hat, unter Verwendung der Redirect-URI, die in der Dokumentation dieses Clients angegeben ist – ein PingOne-seitiger Einrichtungsschritt außerhalb dieses Servers. Starten Sie den Client nach dem Bearbeiten seiner Konfiguration neu.
Investment-Tools
get_investment_accounts, get_investment_balance, get_portfolio_summary und get_investment_transactions funktionieren sofort aus einer gebündelten SQLite-Datenbank (data/invest.db, beim ersten Gebrauch aus seed/invest.seed.json befüllt), genau wie jede andere Vertikale.
Setzen Sie BANKING_API_BASE_URL nur, wenn Sie eine eigene Banking-API betreiben und möchten, dass diese vier Tools das Bearer-Token des Aufrufers an sie weiterleiten und zurückgeben, was auch immer sie zurückgibt. Wenn es gesetzt ist, wird die gebündelte Invest-Datenbank nicht verwendet.
Ein Tool hinzufügen
Tools sind Code, keine Konfiguration. Der Katalog (tools/list), das Pro-Tool-Scope-Gate und die in /.well-known/oauth-protected-resource beworbenen scopes_supported werden alle aus ALL_TOOLS in src/tools/registry.ts abgeleitet. Ein Tool, das Sie zur Liste einer Vertikale hinzufügen, ist also überall live, sobald Sie das Image neu erstellen (der --build-Befehl im Schnellstart).
1. Ein Tool zu einer bestehenden Vertikale hinzufügen
Zwei Änderungen, keine Registrierungsänderung:
Fügen Sie eine Tool-Definition zum Array
src/tools/<vertical>Tools.tsdieser Vertikale hinzu, z. B. insportingGoodsTools.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 },Fügen Sie einen passenden
case 'gear_return_status':zumswitchinsrc/tools/<vertical>ToolHandler.tshinzu. Der Handler gibt nur JSON zurück – lesen Sie aussrc/db/<vertical>Db.tsdieser Vertikale oder etwas anderem.
2. Eine neue Vertikale hinzufügen
Gleiche zwei Dateien wie oben (src/tools/<vertical>Tools.ts, die ein <VERTICAL>_TOOLS: McpToolDef[] exportiert, und src/tools/<vertical>ToolHandler.ts, die dispatch<Vertical>Tool exportiert), plus:
Daten (optional):
src/db/<vertical>Db.ts+seed/<vertical>.seed.json. Kopieren SiesportingGoodsDb.ts– es öffnetdata/<vertical>.db, erstellt das Schema und wendet den Seed nur an, wenn die Tabellen leer sind.Dockerfilekopiert bereitsseed/, und die Compose-Datei mountet bereitsdata/.Registrieren in
src/tools/registry.ts: Importieren Sie die beiden Exporte, verteilen Sie<VERTICAL>_TOOLSinALL_TOOLS, fügen Sie einconst <VERTICAL>_TOOL_NAMES = new Set(<VERTICAL>_TOOLS.map((t) => t.name))hinzu und eine Zeile indispatch():if (<VERTICAL>_TOOL_NAMES.has(toolName)) return dispatch<Vertical>Tool(toolName, args, subject);(subjectist dassubdes Tokens – akzeptieren Sie es in Ihrem Handler, wenn Lesezugriffe auf den Aufrufer beschränkt sein müssen, wie bei Banking und Fluggesellschaften.)Ressourcen (optional):
tools/listist automatisch, aber MCP-Ressourcen (resources/list,resources/read) stammen aus dem manuell gepflegtenRESOURCE_CATALOGinsrc/index.ts– fügen Sie dort einen Eintrag hinzu, wenn die Vertikale ihr List-Tool auch als Ressource bereitstellen soll.
Dinge, die beißen
requiredScopesmüssen Scopes sein, die Ihre PingOne-Ressource tatsächlich gewährt. Ein Token, dem eines davon fehlt, erhält 403 beitools/call, undtools/listverbirgt das Tool für dieses Token vollständig.Tool-Namen sind global.
dispatch()leitet anhand des ersten Namenssatzes weiter, der übereinstimmt. Ein Name, der in zwei Vertikalen wiederverwendet wird, geht also stillschweigend an diejenige, die zuerst geprüft wird.Verwenden Sie eine datengestützte Vertikale (z. B. Sportartikel) als Vorlage, nicht invest – invest ist der
dispatch()-Fallthrough und trägt einen Proxy-vs-SQLite-Schalter, den Sie nicht benötigen.
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