mcp-resource-server
mcp-resource-server
Un servidor MCP que expone herramientas de solo lectura en diez verticales simuladas (banca, sanidad, gobierno, fabricación, comercio minorista, artículos deportivos, universidad, fuerza laboral, Abercrombie & Fitch, aerolíneas) además de un conjunto de herramientas de inversión. Cada vertical lee su propia base de datos SQLite incluida; no se requiere ningún otro servicio para ejecutarlo. Las herramientas de inversión pueden, opcionalmente, actuar como proxy hacia una API bancaria que usted proporcione (ver más abajo).
Requisitos previos
Docker + Docker Compose
Un entorno PingOne para emitir y verificar tokens de portador (o cualquier AS OAuth que pueda emitir un JWT con las reclamaciones
aud/scopecorrectas y publicar un endpoint JWKS — este servidor solo depende del descubrimiento OIDC estándar, no de nada específico de PingOne)
Related MCP server: mock-mcp
Inicio rápido
cp .env.example .envEdite .env: establezca MCP_RESOURCE_SERVER_RESOURCE_URI, PINGONE_ENVIRONMENT_ID y PINGONE_REGION para su propio entorno PingOne. Deje PINGONE_ISSUER comentado hasta que tenga tokens reales (ver "Modos de autenticación").
docker compose up --buildEl servidor escucha en http://localhost:8081. Las bases de datos SQLite persisten en ./data (sembradas en el primer uso desde seed/; un reinicio nunca vuelve a sembrar una base de datos no vacía).
Verificar que está en ejecución
curl http://localhost:8081/health
curl http://localhost:8081/.well-known/oauth-protected-resourceLa segunda llamada devuelve los ámbitos anunciados del recurso y, si PINGONE_ENVIRONMENT_ID/PINGONE_REGION están establecidos, su servidor de autorización — esta es la metainformación RFC 9728 que un cliente MCP utiliza para el descubrimiento OAuth.
Modos de autenticación
Si la firma de un token se verifica o no se decide por si hay una fuente JWKS configurada — no por STRICT_AUTH:
Fuente JWKS establecida (
PINGONE_ISSUER,PINGONE_JWKS_URIoPINGONE_BASE_URL) — cada token se verifica contra las claves de su entorno PingOne y se rechaza si falla.STRICT_AUTHno tiene efecto. Ejecute de esta manera una vez que fluyan tokens reales.Sin fuente JWKS —
STRICT_AUTH=false(el valor predeterminado incluido) acepta un token bien formado con una advertencia en la consola, para que pueda ejercitar cada herramienta con un token hecho a mano antes de conectar PingOne;STRICT_AUTH=truerechaza todos los tokens en su lugar. No deje el valor predeterminado accesible a más de lo necesario.
.env.example incluye las tres variables JWKS comentadas por esa razón — descomente una cuando tenga tokens reales.
Obtener un token de portador
Cada llamada a una herramienta necesita un token de portador cuya reclamación aud coincida con MCP_RESOURCE_SERVER_RESOURCE_URI y cuya reclamación scope cubra la herramienta que está llamando (consulte tools/list para la lista actual y autoritativa — se genera a partir del propio registro de este servidor).
Pruebas locales (STRICT_AUTH=false) — cualquier JWT bien formado con las reclamaciones correctas funciona; la firma no se comprueba.
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+'.');
"(cambie aud por su propio valor de MCP_RESOURCE_SERVER_RESOURCE_URI, y scope por la(s) herramienta(s) que esté probando)
Tokens reales (STRICT_AUTH=true) — genere uno desde su entorno PingOne. Una concesión de credenciales de cliente contra el endpoint de tokens de su PingOne, solicitando la audiencia de este servidor como recurso:
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>"Esto requiere que la aplicación de ese cliente esté autorizada para este recurso y esos ámbitos en PingOne (Applications → su aplicación → Resources) — un paso de configuración del lado de PingOne que este servidor no hace por usted.
Llamar a una herramienta directamente (comprobación de cordura)
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":{}}}'Conectar un cliente MCP
El servidor habla MCP tanto por WebSocket como por HTTP (transmisible, POST /mcp) en el mismo puerto — ws://localhost:8081 o http://localhost:8081/mcp.
MCP Inspector (la herramienta oficial de desarrollo — funciona con cualquier servidor y le permite establecer un encabezado manual, por lo que es la forma más fiable de probar este):
npx @modelcontextprotocol/inspectorEstablezca Transport en "Streamable HTTP", URL en http://localhost:8081/mcp, y añada un encabezado Authorization: Bearer <token> en la configuración de conexión del Inspector antes de conectar.
Claude Desktop / Cursor / Windsurf (configuración estática, transporte HTTP):
{
"mcpServers": {
"mcp-resource-server": {
"url": "http://localhost:8081/mcp",
"transport": "http"
}
}
}Claude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.jsonCursor:
.cursor/mcp.jsonen la raíz de su proyectoWindsurf:
~/.codeium/windsurf/mcp_config.json
Estas configuraciones no tienen campo para un token de portador estático — cuando el cliente llama a una herramienta protegida, lee /.well-known/oauth-protected-resource, encuentra su entorno PingOne como servidor de autorización y le pide que inicie sesión. Eso solo funciona una vez que su entorno PingOne tenga un cliente OAuth registrado para esa aplicación de cliente MCP específica, usando el URI de redirección que especifica la documentación de ese cliente — un paso de configuración del lado de PingOne fuera de este servidor. Reinicie el cliente después de editar su configuración.
Herramientas de inversión
get_investment_accounts, get_investment_balance, get_portfolio_summary y get_investment_transactions funcionan de fábrica desde una base de datos SQLite incluida (data/invest.db, sembrada desde seed/invest.seed.json en el primer uso), exactamente igual que cualquier otra vertical.
Establezca BANKING_API_BASE_URL solo si ejecuta una API bancaria propia y desea que estas cuatro herramientas reenvíen el token de portador del llamante a ella y devuelvan lo que ella devuelva. Con esto establecido, la base de datos de inversión incluida no se utiliza.
Añadir una herramienta
Las herramientas son código, no configuración. El catálogo (tools/list), la puerta de ámbito por herramienta y los scopes_supported anunciados en /.well-known/oauth-protected-resource se derivan todos de ALL_TOOLS en src/tools/registry.ts, por lo que una herramienta que añada a la lista de una vertical está activa en todas partes una vez que reconstruya la imagen (el comando --build en Inicio rápido).
1. Añadir una herramienta a una vertical existente
Dos ediciones, sin cambio de registro:
Añada una definición de herramienta al array de
src/tools/<vertical>Tools.tsde esa vertical, por ejemplo ensportingGoodsTools.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 },Añada un
case 'gear_return_status':correspondiente alswitchensrc/tools/<vertical>ToolHandler.ts. El manejador solo devuelve JSON — lea desde elsrc/db/<vertical>Db.tsde esa vertical, o cualquier otra cosa.
2. Añadir una nueva vertical
Los mismos dos archivos que arriba (src/tools/<vertical>Tools.ts exportando un <VERTICAL>_TOOLS: McpToolDef[], y src/tools/<vertical>ToolHandler.ts exportando dispatch<Vertical>Tool), además de:
Datos (opcional):
src/db/<vertical>Db.ts+seed/<vertical>.seed.json. CopiesportingGoodsDb.ts— abredata/<vertical>.db, crea el esquema y aplica la semilla solo cuando las tablas están vacías. ElDockerfileya copiaseed/, y el archivo compose ya montadata/.Registro en
src/tools/registry.ts: importe las dos exportaciones, extienda<VERTICAL>_TOOLSenALL_TOOLS, añada unconst <VERTICAL>_TOOL_NAMES = new Set(<VERTICAL>_TOOLS.map((t) => t.name)), y una línea endispatch():if (<VERTICAL>_TOOL_NAMES.has(toolName)) return dispatch<Vertical>Tool(toolName, args, subject);(subjectes elsubdel token — acéptelo en su manejador cuando las lecturas deban estar limitadas al llamante, como hacen banca y aerolíneas.)Recursos (opcional):
tools/listes automático, pero los recursos MCP (resources/list,resources/read) provienen delRESOURCE_CATALOGmantenido manualmente ensrc/index.ts— añada una entrada allí si la vertical también debe exponer su herramienta de lista como recurso.
Cosas que muerden
requiredScopesdeben ser ámbitos que su recurso PingOne realmente conceda. Un token que carezca de alguno de ellos recibe 403 entools/call, ytools/listoculta la herramienta por completo a ese token.Los nombres de herramienta son globales.
dispatch()enruta por el primer conjunto de nombres que coincida, por lo que un nombre reutilizado en dos verticales va silenciosamente a la que se compruebe primero.Use una vertical respaldada por datos (por ejemplo, artículos deportivos) como plantilla, no invest — invest es el caso de respaldo de
dispatch()y lleva un interruptor proxy-vs-SQLite que no necesita.
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