内容
# 看板 + MCP 服务器
一款使用 Next.js 16、TypeScript、Prisma 7 和 PostgreSQL 构建的现代化看板应用。提供直观的拖拽式界面用于管理列和卡片,同时包含一个功能齐全的 MCP(模型上下文协议)服务器,用于与 MCP 客户端集成。
## 技术栈
- **框架**:Next.js 16(应用路由器)
- **语言**:TypeScript
- **数据库**:PostgreSQL 16(通过 Docker)
- **ORM**:Prisma 7,搭配 PrismaPg 适配器
- **拖拽**:dnd-kit
- **MCP 服务器**:@modelcontextprotocol/sdk
- **UI**:Lucide React(图标)
- **验证**:Zod
- **测试**:Vitest
## 要求
- Node.js 18+
- Docker 及 Docker Compose
- npm 9+
## 本地安装
### 1. 克隆仓库
```bash
git clone <仓库 URL>
cd board-kanban
```
### 2. 安装依赖
```bash
npm install
```
`postinstall` 脚本会自动执行 `prisma generate`。
### 3. 启动数据库
```bash
npm run db:up
```
这将启动一个 PostgreSQL 容器,监听 5432 端口,默认凭证为:
- 用户名:`kanban`
- 密码:`kanban`
- 数据库:`kanban`
### 4. 配置环境变量
根据 `.env.example` 创建一个 `.env` 文件:
```bash
cp .env.example .env
```
编辑 `.env` 以设置您的凭证:
```bash
DATABASE_URL="postgresql://kanban:kanban@localhost:5432/kanban?schema=public"
MCP_TOKEN="您的 MCP token"
```
要生成一个安全的 `MCP_TOKEN`(推荐用于生产环境):
```bash
openssl rand -hex 24
```
### 5. 执行迁移
```bash
npm run db:migrate
```
### 6. 数据库种子(初始数据)
```bash
npm run db:seed
```
用一个标准的看板、列、示例卡片、用户和标签填充数据库。
### 7. 启动开发服务器
```bash
npm run dev
```
在浏览器中访问 [http://localhost:3000](http://localhost:3000)。
## npm 脚本
| 脚本 | 描述 |
|--------|-----------|
| `npm run dev` | 启动 Next.js 开发服务器 |
| `npm run build` | 为生产环境创建优化构建 |
| `npm start` | 以生产模式启动服务器 |
| `npm run lint` | 对代码执行 ESLint 检查 |
| `npm test` | 运行测试套件(Vitest) |
| `npm run db:up` | 启动 PostgreSQL 容器(Docker Compose) |
| `npm run db:migrate` | 执行待处理的 Prisma 迁移 |
| `npm run db:seed` | 用初始数据填充数据库 |
## 架构
### 层
- **UI** (`src/app/`): Next.js 页面,包含 React 服务器组件和客户端组件
- **REST API** (`src/app/api/`): 列、卡片和评论的 CRUD 路由
- **MCP 服务器** (`src/mcp/`): 具有 9 种工具的 MCP 服务器
- **领域** (`src/server/`): REST 和 MCP 共用的逻辑层
- **数据库** (`src/lib/db.ts`): 带有 PrismaPg 适配器的 Prisma 客户端
- **库** (`src/lib/`): 实用工具(定位、类型等)
### 数据流
```
客户端(UI/MCP)
↓
REST API 或 MCP 服务器
↓
领域层(src/server/cards.ts)
↓
Prisma ORM
↓
PostgreSQL
```
## 环境变量
| 变量 | 描述 | 示例 |
|----------|-----------|---------|
| `DATABASE_URL` | PostgreSQL 连接字符串 | `postgresql://user:pass@localhost:5432/kanban?schema=public` |
| `MCP_TOKEN` | MCP 身份验证令牌 | `abc123def456...`(使用 `openssl rand -hex 24` 生成) |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | Clerk 公共密钥 | `pk_test_...`(Clerk 仪表板) |
| `CLERK_SECRET_KEY` | Clerk 私钥 | `sk_test_...`(Clerk 仪表板) |
## 身份验证(Clerk)
看板和 REST API **需要登录**(Clerk)。`/api/mcp` **不** 需要 —— 代理通过 `Authorization: Bearer $MCP_TOKEN` 而非 Clerk 会话(`src/proxy.ts` 将 `/api/mcp` 标记为公共路由)。
**设置:**
1. 在 [Clerk 仪表板](https://dashboard.clerk.com) 上创建应用(或运行 `npx clerk@latest init`,它会创建应用并填充 `.env` 文件)。
2. 启用登录方法:**电子邮件**(勾选 **"电子邮件验证链接"** 以使用真正的 magic link 而非代码)+ **谷歌**(社交连接)。
3. 设置 `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` 和 `CLERK_SECRET_KEY`(本地存储在 `.env` 中,在 Vercel 上存储在环境变量中)。
**路由:** `/sign-in`,`/sign-up`(Clerk 组件)。未登录用户会被重定向到 `/sign-in`。顶部栏中的 `<UserButton>` 提供注销/个人资料功能。
**用户同步:** 在首次登录时,`syncCurrentUser()`(`src/server/users.ts`)会将 Clerk 用户插入/更新到 `User` 表(按 `clerkId`)→ 登录用户变为实际的指派者/作者。
## 数据模型
### 主要实体
- **看板**:列的顶级分组
- **列**:带有卡片的看板列
- **卡片**:带有标题、描述、优先级、指派者、标签和评论的任务/项目
- **用户**:可以是卡片的指派者或评论作者
- **标签**:用于分类卡片
- **评论**:卡片上的评论
### 枚举
- **优先级**:`高`,`中`,`低`
## MCP 服务器
MCP 服务器在 `POST|GET|DELETE /api/mcp` 上可用,并受 Bearer 身份验证保护。
### 身份验证
```
Authorization: Bearer <MCP_TOKEN>
```
### 可用工具
| 工具 | 描述 |
|-----------|-----------|
| `list_columns` | 列出所有列及其卡片 |
| `list_cards` | 按列、指派者或优先级过滤卡片 |
| `get_card` | 获取卡片的完整详情(带评论) |
| `create_card` | 在列中创建新卡片 |
| `update_card` | 更新卡片字段 |
| `move_card` | 将卡片移动到另一列/位置 |
| `add_comment` | 向卡片添加评论 |
| `list_users` | 列出所有用户 |
| `list_labels` | 列出所有标签 |
### MCP 客户端配置示例
如果您使用支持 MCP 的工具(例如 Claude Code),请在您的 `~/.claude/settings.json` 或 MCP 配置文件中添加以下配置:
```json
{
"mcpServers": {
"board-kanban": {
"type": "http",
"url": "http://localhost:3000/api/mcp",
"headers": { "Authorization": "Bearer 您的 MCP_TOKEN" }
}
}
}
```
对于生产部署:
```json
{
"mcpServers": {
"board-kanban": {
"type": "http",
"url": "https://<您的域名>/api/mcp",
"headers": { "Authorization": "Bearer 您的生产 MCP_TOKEN" }
}
}
}
```
### 使用示例
#### 列出列
```bash
curl -X POST http://localhost:3000/api/mcp \
-H "Authorization: Bearer <MCP_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_columns"}}'
```
#### 创建卡片
```bash
curl -X POST http://localhost:3000/api/mcp \
-H "Authorization: Bearer <MCP_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"tools/call",
"params":{
"name":"create_card",
"arguments":{
"columnName":"待做",
"title":"新任务",
"priority":"高"
}
}
}'
```
## Vercel 部署
### 前提条件
1. **托管数据库**:配置 PostgreSQL 数据库(Vercel Storage、Neon、Railway 等)
2. **环境变量**:在 Vercel 面板上定义
### 步骤
1. **推送到 GitHub**:
```bash
git push origin main
```
2. **连接到 Vercel**:[https://vercel.com/new](https://vercel.com/new)
3. **在 Vercel 面板上配置环境变量**:
- `DATABASE_URL`:您的托管 PostgreSQL 连接字符串
- `MCP_TOKEN`:使用 `openssl rand -hex 24` 生成
4. **自动部署**:Vercel 检测更改并自动部署
5. **部署后配置**:
- `postinstall` 脚本自动运行 `prisma generate`
- 您可以使用 Vercel CLI 手动运行迁移:
```bash
vercel env pull
npm run db:migrate
```
### 考虑因素
- `NODE_ENV` 自动设置为 `production`(由 Vercel 设置)
- Prisma 客户端在构建过程中生成
- 确保 `DATABASE_URL` 公开可访问
## 测试
运行完整的测试套件:
```bash
npm test
```
### 覆盖率
- ✅ 位置测试(`src/lib/positions.test.ts`)
- ✅ 领域层测试(`src/server/cards.test.ts`)
- ✅ MCP 测试(`src/mcp/server.test.ts`)
- ✅ REST API 测试(`src/app/api/cards/route.test.ts`)
- ✅ MCP 身份验证测试(`src/app/api/mcp/route.test.ts`)
测试使用 **Vitest**,并内置 TypeScript 支持。
## 开发
### 文件结构
```
board-kanban/
├── src/
│ ├── app/ # Next.js 应用路由器
│ │ ├── page.tsx # 带有 UI 的主页面
│ │ └── api/ # API 路由(REST + MCP)
│ ├── server/ # 领域层
│ │ ├── cards.ts # 共享逻辑
│ │ ├── cards.test.ts # 层测试
│ │ └── types.ts # 输入/输出类型
│ ├── mcp/ # MCP 服务器
│ │ ├── server.ts # MCP 构造函数
│ │ └── server.test.ts # MCP 测试
│ └── lib/ # 实用工具
│ ├── db.ts # Prisma 客户端
│ ├── positions.ts # 定位逻辑
│ └── positions.test.ts # 实用工具测试
├── prisma/
│ ├── schema.prisma # 模式定义
│ ├── migrations/ # 迁移历史
│ └── seed.ts # 种子脚本
├── docker-compose.yml # 本地数据库定义
├── prisma.config.ts # Prisma 7 配置
└── package.json # 依赖和脚本
```
### 添加新列/字段
1. **更新模式**(`prisma/schema.prisma`)
2. **创建迁移**:`npm run db:migrate`
3. **更新类型**(`src/server/types.ts`)
4. **更新领域层**(`src/server/cards.ts`)
5. **更新 MCP 工具**(`src/mcp/server.ts`)
6. **根据需要更新 UI**
7. **更新测试** 以涵盖新行为
## 故障排除
### 错误:“未找到列”
检查数据库中是否存在看板:
```bash
npm run db:seed
```
### 错误:“需要 MCP_TOKEN”
定义环境变量:
```bash
export MCP_TOKEN="您的 token"
```
### 连接 PostgreSQL 时出错
检查容器是否正在运行:
```bash
docker ps | grep postgres
npm run db:up # 如果未运行
```
### 生产环境构建失败
确保 `DATABASE_URL` 已配置:
```bash
vercel env ls # 检查变量
```
## 贡献
1. 创建分支:`git checkout -b feat/您的功能`
2. 提交清晰的原子提交
3. 运行测试:`npm test`
4. 运行 linter:`npm run lint`
5. 推送并打开 PR
## 许可证
MIT
## 联系方式
如有疑问或问题,请在仓库中提出 issue。