内容
# ESolution — AI 驱动的发票平台
> 面向自由职业者的发票网络应用,自然语言 AI 助手可以 **读取、创建和管理真实发票** — 将 7 个手动点击转化为一句话。助手通过 **生产级 MCP 服务器** 运行,该服务器使用 OAuth 2.1、RS256 JWT、每个工具的作用域、速率限制和审计日志进行保护。
<p align="center">
<a href="#"><img alt="实时演示" src="https://img.shields.io/badge/实时演示-Vercel-black?logo=vercel"></a>
<img alt="Next.js" src="https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs">
<img alt="Python" src="https://img.shields.io/badge/Python-3.11-blue?logo=python">
<img alt="测试" src="https://img.shields.io/badge/测试-119_passing-brightgreen">
<img alt="许可证" src="https://img.shields.io/badge/许可证-MIT-green">
</p>
**🔗 实时演示:** _在此处添加您的 Vercel URL_ · **🎥 演示视频:** _在此处添加您的 Loom/YouTube 链接_
---
## 概述
自由职业者在仪表板、电子邮件客户端和心理数学之间进行发票管理:创建发票、发送发票、追踪逾期付款、判断客户是否值得信赖、计算逾期罚款、在收到付款后在 LinkedIn 上发布消息。 **ESolution** 将所有这些功能合并到一个聊天框中。
有趣的工程不是“它调用了一个 LLM”。而是 **AI 如何安全地获得对真实生产系统的写入权限**,而不成为安全漏洞。 AI 与单独的 **MCP(模型上下文协议)服务器** 作为经过适当身份验证的 API 客户端进行通信 — 每个工具调用都经过身份验证、按作用域授权、速率限制、验证和审计日志。只有约 8.5% 的公共 MCP 服务器实现了 OAuth,而本服务器将安全视为核心功能。
> _“为 Rahul 创建一张发票,金额 ₹50,000,15 天后到期”_ → 代理检查客户的付款历史,计算到期日,将行写入 Google Sheets,并返回付款链接 — 实时的,在一条消息中。
---
## 功能
- **💬 自然语言发票管理** — 通过聊天创建、列出、过滤、标记为已付和提醒。流式传输响应(SSE)并为 AI 运行的每个工具显示透明的卡片。
- **🔐 安全加固的 MCP 服务器** — OAuth 2.1 客户端凭证 + RS256 JWT(受众/颁发者绑定),8 个默认拒绝权限作用域,令牌桶速率限制,SSRF 防护,输入验证和 **每个** 工具调用的结构化审计日志。
- **📊 实时仪表板** — 未付款 / 逾期 / 收入一目了然,状态,逾期天数和逾期罚款根据原始数据重新计算(从不信任存储)。
- **⭐ 客户“卡玛”声誉** — 隐私保护(MD5 哈希电子邮件)0–5 星评分,根据付款历史记录; AI 在向高风险客户开具发票之前发出警告。
- **📧 情感感知提醒** — 根据 AI 情感分析或基于天数的层级(温和 → 坚定 → 紧急 → 合法)选择语气,并进行批量“逾期扫描”,尊重限制。
- **🧾 文档** — Puppeteer 生成的 PDF 发票和完成证书; Groq 编写的 LinkedIn 帖子,用于已付项目; Gemini 撰写的法律通知(需 30+ 天逾期)。
- **✅ 119 个自动化测试**,涵盖 JWT/身份验证、作用域、SSRF、速率限制、输入验证和跨语言业务逻辑一致性。
---
## 架构
三个独立进程共享一个 Google Sheets 作为真实来源。网站和 MCP 服务器是同一个电子表格的 **共同租户** — AI 永远不会调用网站的 cookie 保护的 API 路由。
```mermaid
flowchart TD
subgraph 浏览器
UI["ESolution 网站 UI<br/>(仪表板 · 发票 · AI 助手)"]
end
subgraph Vercel["Vercel — Next.js (:3000)"]
API["22 个 REST API 路由"]
RELAY["/api/mcp-chat<br/>(会话保护的 SSE 中继)"]
end
subgraph Render["Render — Python 后端"]
AGENT["LangGraph 代理 (:8002)<br/>Groq Llama 3.3 70B<br/>+ 会话记忆"]
MCP["MCP 服务器 (:8811)<br/>OAuth 2.1 · JWT · 作用域<br/>速率限制 · SSRF · 审计日志<br/>16 个工具 / 2 个资源 / 4 个提示"]
end
SHEET[("Google Sheets<br/>发票 + 卡玛数据库")]
EXT["Gmail · Gemini · Groq"]
UI -->|点击| API
UI -->|聊天, SSE| RELAY
RELAY -->|转发| AGENT
AGENT -->|OAuth 持有者 JWT<br/>MCP 通过 HTTP| MCP
API -->|读/写| SHEET
MCP -->|读/写| SHEET
MCP --> EXT
API --> EXT
```
**安全链在每次工具调用中运行:
```mermaid
flowchart LR
A[工具调用] --> B[身份验证<br/>RS256 JWT]
B --> C[速率限制<br/>每个客户端]
C --> D[作用域检查<br/>默认拒绝]
D --> E[执行<br/>业务逻辑]
E --> F[审计日志<br/>结构化 JSON]
```
---
## 技术栈
| 层 | 技术 |
|---|---|
| **前端** | Next.js 16(应用路由器),React 19,NextAuth v4(Google OAuth),Framer Motion,styled-jsx |
| **AI 代理** | LangGraph,Groq Llama 3.3 70B,langchain-mcp-adapters,FastAPI(SSE) |
| **MCP 服务器** | FastMCP,OAuth 2.1 + RS256 JWT(PyJWT),pydantic-settings,structlog |
| **数据和服务** | Google Sheets(gspread / google-spreadsheet),Gmail(smtplib / Nodemailer),Gemini 2.0 Flash,Puppeteer(PDF/证书) |
| **测试** | pytest,pytest-asyncio — 119 个测试 |
| **部署** | Vercel(网站)· Render(Python 后端) |
---
## 文件结构
```
esolution-invoice-ai/
├── src/ # Next.js 网站
│ ├── app/
│ │ ├── dashboard/ # 发票仪表板
│ │ ├── invoices/ # 创建 / 查看发票
│ │ ├── ai-assistant/ # AI 聊天页面
│ │ ├── pay/ · portal/ # 客户端付款页面
│ │ └── api/ # 22 个 REST 路由(+ /api/mcp-chat 中继)
│ ├── components/ # 侧边栏,聊天界面,工具调用卡,统计卡…
│ └── lib/ # sheets.js, email.js, gemini.js, karma-calculator.js…
│
└── project_2/ # Python AI 后端
├── mcp-server/
│ └── src/
│ ├── server.py # FastMCP 入口点
│ ├── auth/ # OAuth 服务器,JWT 处理器,作用域,中间件
│ ├── security/ # 速率限制器,SSRF 防护,输入验证器,审计日志
│ ├── sheets/ # gspread 客户端 + 发票/卡玛模型(镜像 sheets.js)
│ ├── services/ # Gmail, Gemini, Groq
│ └── tools/ # 16 个发票域 MCP 工具
├── agent/ # LangGraph 代理 + FastAPI SSE API
├── start.sh # 运行两个 Python 服务(Render)
└── render.yaml # Render 蓝图
```
---
## 本地设置
**先决条件:** Node 20+,Python 3.11+,具有 Sheets 访问权限的 Google 服务帐户,Gmail 应用密码,以及来自 [Groq](https://console.groq.com) 和 [Google AI Studio](https://aistudio.google.com) 的免费 API 密钥。
### 1. 网站
```bash
git clone https://github.com/Eeshan842004/esolution-invoice-ai.git
cd esolution-invoice-ai
npm install
cp .env.example .env.local # 填写您的值
npm run dev # → http://localhost:3000
```
### 2. AI 后端(用于聊天页面)
```bash
cd project_2
python -m venv .venv
.venv/Scripts/pip install -e mcp-server -e agent # (.venv/bin/pip 在 macOS/Linux 上)
bash scripts/generate_keys.sh # 用于 JWT 签名的 RSA 密钥
# 终端 1 — MCP 服务器 (:8811)
cd mcp-server && ../.venv/Scripts/python -m src.server http
# 终端 2 — 代理 (:8002)
cd agent && ../.venv/Scripts/python -m uvicorn src.api:app --port 8002
```
MCP 服务器和代理自动读取存储库根目录下的 `.env.local`。运行测试:`cd project_2/mcp-server && ../.venv/Scripts/python -m pytest`(119 个通过)。
---
## 部署
应用是 **两个托管目标** — 网站在 Vercel 上完全可用;Python 后端在 Render 上仅为 AI 聊天页面提供支持。
### 网站 → Vercel
1. 在 [vercel.com](https://vercel.com) 上导入存储库(自动检测 Next.js)。
2. 添加 `.env.example` 中的所有变量。设置 `NEXTAUTH_URL` 和 `NEXT_PUBLIC_BASE_URL` 为您的 Vercel 域名。
3. 在 Google Cloud Console 中,将 `https://<your-app>.vercel.app/api/auth/callback/google` 添加到 OAuth 客户端的 **授权重定向 URI**。
4. 部署。
### Python 后端 → Render
1. 新 **Web 服务** → 根目录 `project_2`,构建 `pip install -e mcp-server -e agent`,启动 `bash start.sh`,健康检查 `/health`。(附带 [`render.yaml`](project_2/render.yaml) 蓝图。)
2. 添加 Google / Gmail / Groq / Gemini 环境变量 + 一个强 `OAUTH_CLIENT_SECRET`。
3. 将服务网址复制到网站的 `AGENT_URL` 并重新部署到 Vercel。
> Render 的免费层在空闲 15 分钟后进入睡眠状态 → 在睡眠后,第一个 AI 消息需要 ~40 秒才能唤醒。
---
## 截图
| 仪表板 | AI 助手 |
|---|---|
| _`docs/screenshot-dashboard.png`_ | _`docs/screenshot-ai-chat.png`_ |
| 创建发票 | 工具调用透明度 |
|---|---|
| _`docs/screenshot-new-invoice.png`_ | _`docs/screenshot-toolcards.png`_ |
> _用真实截图替换上面的占位符(将图像拖入 GitHub 问题以获取托管网址,或在 `docs/` 下提交它们)。_
---
## 演示视频
> 🎥 _在此处添加 60–90 秒的演练(Loom / YouTube):通过聊天创建发票 → 检查客户卡玛 → 发送提醒 → 生成 LinkedIn 帖子._
---
## 许可证
[MIT](LICENSE) © Eeshan