Vaani-Pay MCP Server
Vaani Pay Assistant
一个安全、实时、多用户、**双语(英语 + 印地语)**的支付支持聊天机器人:用户使用自己的账户注册/登录,然后可以咨询自己的支付、订单、退款、交易、欺诈风险和统计数据——通过MCP工具层强制执行严格的每用户数据隔离,使用真实的SQLite数据库,并通过实时WebSocket状态流展示代理正在做什么。
该项目最初是黑客松的静态演示构建(硬编码用户、固定令牌、仅支持英语),现已升级为一个数据库驱动、多用户、安全、双语的平台,且没有改变那些已经正常工作的部分:WebSocket协议、MCP工具架构和核心代理逻辑与之前完全相同——只是底层的数据源和认证模型发生了变化。
架构
Browser (chat UI + login/signup/profile)
│ REST (/auth, /users/me, /transactions) │ WebSocket (/ws)
▼ ▼
FastAPI — auth endpoints, profile endpoints FastAPI — WebSocket handler
│ │
▼ ▼
app/auth.py (register / login / sessions) AI Agent (app/agent.py)
│ NLU (Grok API) → intent + entities
│ Tool selection → MCP tool
▼ │
app/db.py — SQLite │ MCP (stdio transport)
users, sessions, chat_history, ▼
payments, orders, refunds, transactions MCP Server (mcp_server/server.py)
▲ get_payment_status │ get_order_details
│ get_refund_status │ get_customer_details
└───────────── same DB, same ownership ──── get_transaction_history │ check_fraud_risk
checks on every query get_payment_statistics
│
▼
mcp_server/data_layer.py
— ownership check on every lookup,
now backed by SQLite instead of JSONRelated MCP server: nexi-xpay-mcp-server
1. 账户与数据隐私
真实账户。
POST /auth/register在SQLite中创建一个用户行,密码经过安全哈希处理(PBKDF2-HMAC-SHA256,每个密码独立的随机盐,26万次迭代——参见app/security.py)。明文密码永远不会存储或记录在任何地方。真实登录会话。
POST /auth/login验证凭据,并颁发一个不透明、不可猜测的会话令牌(app/security.py的generate_token(),256位熵),存储在sessions表中并带有过期时间(.env中的SESSION_TTL_HOURS,默认为24小时)。过期或未知的令牌在所有检查处都会被拒绝。每个查找特定资源的MCP工具(
get_payment_status、get_order_details、get_refund_status、check_fraud_risk)都需要一个requesting_user_id参数,并在mcp_server/data_layer.py中验证该资源确实属于该用户——现在通过参数化SQLWHERE ... AND user_id = ?子句——然后才返回任何内容。如果资源属于其他人,或者根本不存在,两种情况都会返回相同的通用响应:
"Access denied. You are not authorized to access this information."如果对"未找到"和"他人的数据"返回不同的消息,用户就可以通过观察收到哪个错误来枚举有效ID——这关闭了该侧信道。requesting_user_id始终是调用方的已认证身份(在WebSocket认证时/REST请求时一次性解析——参见app/auth.py),绝不是从聊天消息、URL参数或请求体中解析出来的值。app/nlu.py的提取模式中根本没有user_id字段,因此任何消息(即使是对抗性的)都无法将其他身份偷偷塞入工具调用中。get_customer_details、get_transaction_history和get_payment_statistics完全不接受资源ID——它们始终返回调用方自己的数据,因此这三个工具完全没有任何ID操纵的攻击面。账户删除(
DELETE /users/me)需要重新输入当前密码作为确认,然后删除该用户行——ON DELETE CASCADE外键会随之删除该用户的所有会话、聊天记录、支付、订单、退款和交易。
直接验证数据隔离:
python3 test_offline.py这会以两个不同的演示用户身份运行真实的工具调用(针对实际的MCP服务器,从真实的SQLite数据库读取数据),并断言:跨用户访问尝试会被拒绝、每个用户的交易历史只包含自己的数据、双语回复能正确渲染。
2. 注册、登录与账户管理
POST /auth/register— 姓名、邮箱、密码、可选电话,以及语言偏好。密码必须至少8个字符,并且包含字母和数字的组合(app/security.py)。POST /auth/login— 返回一个会话令牌 + 用户资料。POST /auth/logout— 在服务端撤销当前会话令牌。GET /users/me/PUT /users/me— 查看/更新资料(姓名、电话)。POST /users/me/change-password— 需要当前密码;更改后会使所有现有会话失效(强制所有地方重新登录),因此泄露的旧令牌将不再有效。GET /users/me/preferences/PUT /users/me/preferences— 读取/更新语言偏好(en/hi),持久化存储在数据库中,因此在退出/登录后仍然保留。DELETE /users/me— 永久删除账户(需要密码 + 显式的confirm: true)。
所有这些功能也可以通过聊天界面本身顶部的⚙️按钮访问(资料查看/编辑、语言切换、更改密码、退出登录、删除账户)。
3. 聊天界面
static/index.html — 一个单页应用:
在可以进行任何聊天之前,会显示登录/注册选项卡。
资料与设置面板(姓名/电话编辑、更改密码、语言切换、退出登录、带确认步骤的账户删除)。
输入框上方可折叠的建议菜单,使用与界面其余部分相同的翻译字符串字典渲染。
聊天气泡、实时状态行和顶部状态指示器——与原始设计保持一致。
4. 实时通信
聊天仍然通过单个WebSocket(/ws)进行——协议形态不变,只是认证令牌现在是一个由数据库支持的真实会话令牌,而不是静态值:
{"type": "auth", "token": "<session token from /auth/login>"}
↓
{"type": "auth_success", "user_id": "...", "name": "...", "language": "en"}对于每条聊天消息,服务器按以下顺序流式发送状态事件,然后给出最终的(本地化的)答案:
🔍 Understanding your request...
🔧 Checking payment information...
✓ Payment information retrieved
🤖 Generating response...
<final answer, in the user's selected language>每一轮聊天(用户消息和助手消息)也会持久化到 chat_history 表中(app/main.py 的 _persist_chat_turn),作用域限定为已认证用户。
5. 基于MCP的架构
mcp_server/server.py 正好公开了这7个工具,拆分为 mcp_server/tools/ 下的领域模块:
工具 | 文件 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
所有这些都由SQLite数据库(mcp_server/data_layer.py → app/db.py)支持,而不是静态JSON。工具签名、代理和前端与原始设计保持一致——只有 data_layer.py 底层的数据源发生了变化,这正是原始架构设计所允许的。
6. 双语支持(英语 + 印地语)
界面字符串:
app/i18n.py的UI_STRINGS字典,通过GET /i18n/{lang}提供。前端在加载时以及每次语言切换时获取一次,并通过data-i18n/data-i18n-placeholder属性应用——HTML/JS中没有硬编码任何翻译字符串。AI助手回复:
app/i18n.py的AGENT_STRINGS(固定消息,如问候语)和REPLY_TEMPLATES(插值消息,如支付状态)。app/agent.py通过它们渲染每一条回复——代理中没有直接硬编码的英文文本。NLU:
app/nlu.py的提示词明确要求Grok模型处理印地语/英语/混合输入,并在内部始终翻译为英语以进行意图/实体提取,因此助手无论用哪种语言提问都能理解问题,并以用户偏好的语言回复。持久化:语言偏好存储在数据库的
users.language字段中(注册时设置,可随时通过PUT /users/me/preferences更改),因此在退出/登录后仍然保留。动态切换:在设置中更改语言会立即更新界面并重新连接WebSocket,因此下一条聊天回复就会以新语言返回——无需重新加载页面。
7. 安全要求
需求 | 实现位置 |
身份验证 |
|
授权 |
|
用户/会话隔离 |
|
MCP 级权限检查 | 在 MCP 工具内部强制执行( |
输入验证 |
|
SQL 注入防护 |
|
速率限制 |
|
安全的 CORS |
|
安全的密码哈希 |
|
令牌过期 |
|
通用的身份验证错误消息 |
|
安全的错误处理 |
|
防止 ID 篡改 | 用户可以输入任何 |
8. 数据库模式
users id, name, email, phone, password_hash, language, created_at, updated_at, last_login
sessions token, user_id, created_at, expires_at
chat_history id, user_id, conversation_id, role, message, timestamp
payments payment_id, user_id, status, amount, method, failure_reason, date
orders order_id, user_id, status, total, items (JSON), date
refunds refund_id, user_id, payment_id, amount, status, date
transactions txn_id, user_id, type, amount, status, date
-- Wallet: the real money-movement system (see section 9 below)
payment_accounts id, user_id, payment_id, account_number, ifsc, balance, currency, status, created_at
wallet_transactions id, transaction_id, sender_account_id, receiver_account_id, amount, transaction_type,
status, description, sender_name, receiver_name, recipient_account_number,
recipient_ifsc, failure_reason, created_at, updated_at
beneficiaries id, user_id, recipient_name, account_number, ifsc, created_at要获取包含外键和索引的完整 DDL,请参阅 app/db.py 的 SCHEMA。
9. 钱包:支付账户、充值与转账
每个注册用户都会得到一个真实、可用的钱包——而不仅仅是一个交易历史查看器。这是在数据库/身份验证升级之上最大的一项新增功能,它作为独立模块(app/wallet.py)构建,REST API 和 AI/MCP 工具都会调用它,因此只有这一处地方强制执行资金移动规则。
自动创建账户。 POST /auth/register 在同一个数据库事务中创建用户行和 payment_accounts 行(参见 app/auth.py 的 register() 调用 app/wallet.py 的 insert_account_row())——用户不可能在没有钱包的情况下存在,钱包也绝不会作为一个独立的、可单独失败的步骤被创建。每个账户都会获得:
一个唯一的支付 ID(
PAY...,内部标识符),一个唯一的 12 位账号,
一个固定的IFSC(
VPAY0000001—— Vaani Pay 是一个单分支虚拟钱包,所以每个账户共享同一个 IFSC,就像真正的数字银行的虚拟账户通常那样),起始余额为 ₹0。
注册响应中会包含一条 message: "Your payment account has been successfully created." 确认消息,以及新的账户详情,这些信息会立即显示给用户(既出现在 API 响应中,也出现在注册页面的确认消息中)。
充值。 POST /wallet/add-money(或钱包界面中的“充值”按钮,或要求 AI 助手“向我的账户充值 ₹5,000”)——校验金额(> ₹0,每笔交易 ≤ ₹2,00,000 —— app/wallet.py 中的 MAX_ADD_MONEY),然后以原子方式更新余额,并向 wallet_transactions 追加一行 CREDIT。hackathon 版本没有接入真正的支付网关——这是一个明确模拟的充值,符合需求文档中“安全的模拟资金流转”的要求。
转账——始终需要两步确认。 REST API 和 AI 助手都不会在一次调用中就移动资金:
POST /wallet/transfers(app/wallet.py中的initiate_transfer)校验收款人和发送者的余额,并创建一行PENDING状态的wallet_transactions——暂不变动余额。它会返回一个确认预览(收款人、掩码后的账号、IFSC、金额、手续费、总扣款)——这就是“确认转账”界面所渲染的内容。POST /wallet/transfers/{id}/confirm(confirm_transfer)是唯一真正移动资金的调用。它会在确认时重新校验发送者的余额和账户状态(而不仅仅在发起时校验,以防期间发生变化——例如连续发起两笔转账),然后在由进程级锁保护的一个原子 SQLite 事务中,扣减发送者;如果收款人是真实的 Vaani Pay 账户,则同时为其入账。如果中途任何一步失败,整个事务都会回滚——一笔转账永远不会出现“已扣款但未入账”的情况。POST /wallet/transfers/{id}/cancel取消一笔仍处于PENDING状态的转账,且不会影响任何余额。
向系统中不存在的账号转账仍然会成功(作为一次模拟的外部转账——发送者被扣款,只是没有 Vaani Pay 账户可入账),这符合需求文档中“如果收款人在模拟系统中存在,则为其余额入账”的要求。
收款人校验。 POST /wallet/validate-recipient(validate_recipient)会检查:账号格式(9–18 位数字)、IFSC 格式(^[A-Z]{4}0[A-Z0-9]{6}$)、如果收款人是内部账户则其 IFSC 必须与账号匹配,以及——关键的一点——发送者不能向自己的账号转账。如果只提供了收款人姓名(没有账号),则会在调用者自己保存的收款人列表中查找该姓名,如果恰好只有一个匹配项,就自动解析出来。
已保存的收款人。 转账成功后,UI 会提供“保存此收款人?”—— POST /beneficiaries 仅将收款人保存给已认证用户本人(绝不做全局/共享存储),这样下次用户(或 AI 助手,当被要求“给 Rahul 转账 ₹2,000”时)就可以仅凭姓名完成转账。
交易历史与筛选。 GET /wallet/transactions?filter=...(all / add_money / sent / received / failed / pending)——全部实时从 wallet_transactions 计算得出,绝不硬编码。钱包界面的“历史”标签页和 AI 的“显示我的钱包交易”/“我这个月花了多少钱”都读取完全相同的函数(app/wallet.py 中的 get_wallet_transactions / get_spending_summary)。
余额始终是派生出来的,绝不会被直接设置。 代码库中有意不提供任何 set_balance() 函数——余额发生变化的唯一方式是通过 add_money() 或 confirm_transfer() 的副作用,而这两者都会在同一个原子步骤中追加一行不可变的 wallet_transactions。前端只会显示 GET /wallet/account 返回的内容;它无法影响余额。
钱包安全(具体说明)
规则 | 执行方式 |
用户永远不能直接修改自己的余额 | 除了 Add Money / confirm_transfer 的副作用之外,没有任何公共函数会设置余额;两者都会对金额进行校验,并生成一条审计记录 |
用户永远不能修改其他用户的余额 | 每个钱包函数都会获取调用者认证后的 |
用户永远不能确认/取消他人的转账 |
|
自我转账会被阻止 |
|
金额无法在处理过程中被操纵 | 在 |
未经明确确认,AI 无法转移资金 |
|
原子性 |
|
10. 双语支付流程
钱包完全支持双语,使用与应用程序其他部分相同的 app/i18n.py 机制——Add Money、Send Money(全部三个步骤)、确认界面、交易状态,以及所有关于余额/转账的 AI 响应,都通过 t()/tpl() 渲染,在 app/wallet.py、app/agent.py 或 static/index.html 的钱包 UI 中没有任何硬编码的英文。例如,用印地语/印英混合语向 AI 说 "Rahul ko ₹2,000 bhejo",会经历与英文版完全相同的解析 → 确认 → 执行流程,所有消息——包括确认界面——都以印地语渲染。
设置
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Add your Grok API key (get one at https://console.x.ai)数据库会在首次运行时自动创建(并且仅在数据库为空时,预置两个演示用户——见下文);本地开发无需单独的迁移步骤。如需提前显式创建:
python3 -m app.db在打开浏览器之前,请先验证:
python3 diagnose_setup.py运行
uvicorn app.main:app --reload --port 8000打开 http://localhost:8000。注册一个新账户,或使用某个内置演示账户登录:
邮箱 | 密码 |
|
|
|
|
然后可以试试建议菜单,询问类似 "check payment status pay_1001" 或 "मेरा भुगतान pay_1001 का स्टेटस क्या है?" 的问题,在 Settings 中切换语言,或者尝试以某个用户身份登录后,询问另一个用户的支付/订单/退款 ID(pay_1003、ord_2002、rfnd_3002 属于 Priya),以查看访问被拒绝的响应。
要试用钱包:点击标题栏中的 💰 Wallet 按钮。两个演示账户都有初始余额(Ramesh ₹8,500,Priya ₹8,000),并且各自的历史记录中已有一条演示转账。可以试试 "Add Money",或向另一个演示账户的账号(可在其各自的 Wallet 界面中看到)"Send Money",也可以直接询问 AI 助手:"what's my balance?"、"add ₹5,000 to my account"、"send ₹2,000 to Priya Stores"(第一次它会要求提供她的账号 + IFSC,转账成功后会提议将她保存为收款人——之后只需提供她的名字即可),或用印地语说 "Mera current balance kitna hai?"。
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 gradedqualityAmaintenanceEnables AI agents to interact with Juspay's payment processing APIs and merchant dashboard for managing orders, transactions, refunds, customers, gateways, and reporting through natural language.21Apache 2.0- AlicenseAqualityDmaintenanceEnables AI assistants to query orders, transaction details, warnings/anomalies, and payment methods from your Nexi XPay merchant account.4MIT

AlipayPlus MCP Serverofficial
AlicenseAqualityDmaintenanceIntegrates Ant International's AlipayPlus payment APIs, enabling AI assistants to handle payment and refund operations seamlessly.68MIT- FlicenseNot gradedqualityCmaintenanceEnables AI to query a business database for customers, orders, and revenue using natural language through safe, well-defined tools.
Related MCP Connectors
Taiwan payments (ECPay 綠界 + NewebPay 藍新) & e-invoices for AI agents. Stateless, never holds funds.
Korea payments for AI agents — card, KakaoPay/NaverPay, 가상계좌 via Toss Payments. Never holds funds.
Let AI agents add Yolfi crypto checkout, paylinks, webhooks, and status checks.
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/divyaupadhyay56/Vaani-Pay'
If you have feedback or need assistance with the MCP directory API, please join our Discord server