lending-data-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@lending-data-mcp-serverShow me the portfolio summary."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Lending Data MCP Server
Stack: Python · MCP (Model Context Protocol) · httpx · FastMCP
An MCP server that exposes a lending portfolio - loans, customers, risk-tier history - to any MCP-compatible AI client (a desktop AI assistant, a LangGraph agent, any future agent framework) through a single standardized protocol, instead of a bespoke integration per client.
The business problem: A lending team wants to let an AI assistant answer questions about loans and customers - "how many high-risk loans do we have," "has this customer's risk tier changed" - instead of someone pulling a report by hand. The bank already has a hard rule for this kind of thing: nothing touches the loan database directly. Every system that reads it goes through one gateway that checks who's asking, limits how often they can ask, and logs every request - the same control that exists around any sensitive customer data. The problem is that this rule makes adding a new AI tool slow: today, connecting a new assistant means writing custom, one-off integration code against that gateway, then getting it security-reviewed before anyone can use it. Do that for a desktop assistant, then again for a different agent framework six months later, and again for whatever comes after that - each one is bespoke, each one is a fresh review, and each one is a place someone under deadline pressure could quietly cut a corner around the gateway's safeguards to ship faster.
The technical solution: Wrap the existing gateway in an MCP server - a small translation layer speaking the emerging industry-standard protocol (MCP) for connecting AI assistants to tools and data. Build the safe connection once, and any MCP-compatible client gets it immediately, with no new integration code and no new security review each time. This server exposes three things: Tools to query loans/customers/portfolio and run validated SQL, a Resource exposing the DB schema as readable reference data, and a Prompt template for a common analysis task. The gateway itself is untouched - this project adds a protocol layer in front of it, not a new access path into the data.
Architecture
flowchart LR
subgraph clients["MCP Clients"]
CD["MCP Desktop Client\n(this build's demo surface)"]
AG["Future LangGraph agent\n(same protocol, no new integration)"]
end
subgraph mcp["This Project - MCP Server"]
T["Tools\nget_loan · list_loans · get_customer\nget_customer_loan_history\nget_portfolio_summary · run_validated_query"]
R["Resource\nlending://schema"]
P["Prompt\ncustomer_risk_narrative"]
end
subgraph gw["lending-data-api (unmodified, external project)"]
AUTH["X-API-Key auth\n+ per-key rate limiting"]
SQL["/query/validated\n3-layer SQL safety"]
SCHEMA["/schema"]
end
subgraph db["PostgreSQL"]
MARTS["dim_customers · dim_customers_history\nfct_loans_type2\n(from scd-type2-lending dbt models)"]
end
clients -->|"stdio (MCP protocol)"| mcp
T -->|"HTTP + X-API-Key"| AUTH
R -->|"HTTP + X-API-Key"| SCHEMA
AUTH --> SQL --> MARTS
SCHEMA --> MARTSPortfolio chain: scd-type2-lending (dbt SCD2 marts) → lending-data-api (governed gateway) → this MCP server → any MCP client.
Demo - natural-language question answered live via the tools above:

Related MCP server: Crescender MCP Server
Tools, Resource, and Prompt
Type | Name | Wraps | Notes |
Tool |
|
| Single loan lookup |
Tool |
|
| Filter by status, risk tier, date range |
Tool |
|
| Current profile |
Tool |
|
| Full SCD2 tier history |
Tool |
|
| Aggregate stats |
Tool |
|
| Read-only SQL; validated server-side by the gateway |
Resource |
|
| Table/column reference, read once per session rather than re-fetched as a tool call every time |
Prompt |
| - | Guided template: pull a customer's tier history + loans, narrate the risk story |
No write tool is exposed (POST /loans/ has no MCP equivalent) - this server is read-only by design, discussed below.
Key Design Decisions
1. Wrap the existing gateway instead of connecting to the database directly
The gateway already enforces per-consumer auth, rate limiting, a 3-layer SQL validator (no DDL, no writes for read-only keys, table whitelist), and audit logging. A direct database connection from this server would duplicate that logic in a second place - and second implementations of a safety layer drift out of sync with the first. Every tool call here goes out over HTTP with the same X-API-Key header any other consumer team uses. MCP is a protocol layer on top of a governed path, not a new path.
Trade-off: one extra network hop per call versus a direct DB connection. Worth it - the alternative is two independently-maintained SQL validators.
2. Read-only tool surface, by design
POST /loans/ (loan creation, finance-key only) has no corresponding MCP tool. An AI agent with a create-loan capability is a materially bigger blast radius than one that can only query - and none of this server's target use cases (an analyst asking questions, a Text-to-SQL agent) need to write. If a future use case needs it, it should be a deliberate, separately-reviewed addition, not something that ships by default because the underlying endpoint existed.
3. All three MCP primitives, not just Tools
Most MCP servers are tools-only. lending://schema is deliberately a Resource, not a seventh tool - schema is reference data an agent reads once and holds in context, not an action it repeatedly invokes. customer_risk_narrative is a Prompt - a reusable analysis template, versioned and named, rather than the same instructions retyped into every conversation.
4. Reused API key, not a dedicated consumer profile
This server authenticates with the gateway's existing read-only underwriting key rather than a new dedicated key. The gateway's consumer config only defines three profiles (underwriting, collections, finance) - none scoped to "AI/MCP traffic" specifically. Adding one would mean changing the gateway itself, which this project deliberately leaves untouched. Documented here as the honest state of things, not fixed silently.
Production alternative: add a fourth consumer profile (e.g. mcp_agent) to the gateway's config with its own key and rate limit, isolating MCP traffic from Underwriting's operational queries - the same reasoning that justified giving Underwriting, Collections, and Finance separate keys in the first place.
5. Absolute-path launch, not a relative one
MCP clients (desktop AI assistants, and presumably most others) launch a server by an absolute path to its entry file, with no guarantee about the working directory. A plain from app.lending_client import ... breaks the moment the project root isn't already on sys.path - which is exactly what happens when the client, not a developer's shell, starts the process. The server resolves its own project root from __file__ and inserts it into sys.path before the package-style imports, so it works regardless of how or from where it's launched.
Who Else Has This Problem
Industry | Same Pattern |
Healthcare | Patient record systems already gate access per care team; an MCP wrapper lets a clinical AI assistant query the same governed path instead of a bespoke EHR integration |
Insurance | Claims data serving fraud, actuarial, and customer service teams - same gateway-plus-protocol shape for an AI claims assistant |
HR / HRIS | Employee data APIs with strict read/write separation - an internal AI assistant becomes just another consumer, not a new access route |
Retail | Order/inventory APIs already serving multiple internal systems - same wrapper pattern for a merchandising or demand-forecasting agent |
Production Gaps
Gap | This project | Production alternative |
MCP consumer identity | Reuses the gateway's | Dedicated |
Transport |
| Add |
Secrets | API key in a local | AWS Secrets Manager / Vault, matching the gateway's own production-gap note |
Observability | No tracing | Wire tracing (e.g. Langfuse) around each tool call once this feeds an actual agent, not just a desktop client |
SQL validation | Delegated entirely to the gateway (by design) | No change needed - this is the correct place for it to live |
How to Run
1. Start the gateway
In the multi-consumer-ai-data-gateway project (separate repo, not part of this one):
docker compose up --build
docker compose exec api python scripts/seed_db.pyConfirm it's up: curl http://localhost:8000/health
If seeding via
docker compose execfails becausescripts/isn't present in the running container, copy it in first:docker cp scripts/. <container_name>:/app/scripts/, then re-run. If a local Postgres is already listening on port 5432 outside of Docker, seeding from the host can silently write to the wrong database - seed from inside the container to be sure.
2. Set up this project
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in the gateway's base URL + an API key3. Test it stand-alone (MCP Inspector)
mcp dev app/server.pyOpens an interactive browser UI - call get_portfolio_summary, list_loans, read the lending://schema resource, and try the customer_risk_narrative prompt without needing any AI client.
4. Connect a real MCP client (desktop AI assistant)
Add to your MCP client's config file (most desktop AI assistants use a similar JSON structure):
{
"mcpServers": {
"lending-data": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["/absolute/path/to/app/server.py"],
"env": {
"LENDING_API_BASE_URL": "http://localhost:8000",
"LENDING_API_KEY": "your-underwriting-key-here"
}
}
}
}Restart the desktop client fully (quit, not just close the window - MCP servers are spawned at app startup). Then ask something like "Show me high-risk loans" or "What's the current portfolio summary?"
Sample Output
Three real exchanges from a live session, unedited apart from trimming for length.
1. "Show me high-risk loans" - list_loans(risk_tier="High-Risk")
Here are all 17 loans tagged High-Risk at origination: [17-row table: loan ID, customer, type, principal, origination date, status]
A few things worth noting:
Customer 27 has the most exposure - 6 loans, including the one defaulted loan (#104) and two large Home/SMB loans.
Customer 40 holds two very large Home loans (~$9.4M and ~$9.1M), both still active.
Customer 42 has the largest single loan in this list - an SMB loan for ~$3.5M.
This reflects risk tier at origination. If a customer's tier has since changed, their current risk status may differ - I can pull a customer's tier history if you want to check that for anyone specific.
Correctly distinguished "risk tier at origination" from current tier without being asked to - the exact SCD2 nuance get_customer_loan_history exists to resolve - and offered the follow-up instead of assuming.
2. "What's customer 6's risk profile and history? Has anything changed over time?" - get_customer + get_customer_loan_history + get_loan
Here's the full picture for Customer 6 - Arunima Setty (Delhi, member since Dec 5, 2025):
Risk tier history
Tier
From
To
Standard
2025-12-05
2026-11-10
Premium (current)
2026-11-10
-
So yes - something has changed. Arunima started as Standard risk when she joined and was upgraded to Premium as of Nov 10, 2026 - a positive shift.
Loan portfolio: one loan (#12, $268,695.71, originated 2025-12-12, active) - originated during her Standard tier window, before the Premium upgrade, so it was underwritten at Standard risk, not Premium.
Three separate tool calls chained into one coherent narrative from a single natural-language question, correctly reasoning about when the loan originated relative to the tier change - not just listing both facts side by side.
3. "Give me a risk narrative for customer 15" - the customer_risk_narrative Prompt, not a single tool call
Here's the risk narrative for Customer 15 - Wriddhish Bhardwaj (Pune):
Tier trajectory
High-Risk: Jan 8, 2026 – Aug 11, 2026 (initial tier since becoming a member)
Standard (current): Aug 11, 2026 – present
This is a customer who has migrated down in risk - moved from High-Risk to Standard within about 7 months of joining, suggesting improved repayment behavior or credit profile.
Loan portfolio (4 loans, all currently active) - total outstanding exposure: ~$2.37M, heavily concentrated in one large SMB loan ($1.73M - about 73% of total exposure).
Key observations:
No defaults or closures - all four loans remain active and current, a positive signal despite the High-Risk origination tier.
Data flag: all four loans originated between Sep 2024 and May 2025, but the customer's
member_sincedate is Jan 8, 2026 - the same date the tier history begins. These loans predate the tier history on file, so the tier that actually applied at each loan's origination can't be confirmed from this data. Worth checking with the data team if this is a backfill/migration artifact.Concentration risk: the SMB loan dominates total exposure - worth weighing alongside the recent tier improvement, not instead of it.
Bottom line: presents as a High-Risk-to-Standard "improving" borrower with a clean active-loan track record, but a meaningful chunk of exposure sits in one large facility, and there's a data gap around tier-at-origination that's worth resolving before treating the "improving risk" story as fully verified.

This is the Prompt template doing its job: one canned instruction produced a structured, multi-part risk write-up (trajectory → portfolio → concentration → observations) instead of a one-off free-form answer - the reusable-analysis-template value a Prompt is meant to add over Tools alone. It also caught something worth catching: a genuine data-consistency question (loan dates predating the tier history) that a simpler tool-call response wouldn't have surfaced, instead of accepting the "improving risk" narrative at face value.
Stats
6 Tools, 1 Resource, 1 Prompt
0 write operations exposed - read-only by design
1 external dependency (the gateway) - no direct database access
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.
Latest Blog Posts
- 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/ro-kannan/lending-data-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server