内容
<!--
Sankhya Ajuda MCP - Skills IT - Solucoes em Tecnologia
https://www.skillsit.com.br | (63) 3224-4925 | Palmas-TO-Brasil
-->
# Sankhya Ajuda MCP
> **状态:** ✅ 在线 · **版本:** 1.5.6 · **默认端点:** `http://<host>:3105/mcp` · **工具:** 11 · **资源:** 6 · **提示:** 4 · **开发者:** [Skills IT](https://www.skillsit.com.br)
[](./LICENSE)
[](https://modelcontextprotocol.io)
[](https://nodejs.org)
[](https://www.python.org)
[](https://www.postgresql.org/)
> **MCP 服务器(模型上下文协议)**,使 **Sankhya** ERP 的两个公共知识库可搜索 - **帮助中心**(6,125 篇文章,`ajuda.sankhya.com.br`)和 **社区**(7,619 篇问答帖子,`community.sankhya.com.br`)- 通过 **混合搜索**(基于 `pgvector` 的 Reciprocal Rank Fusion + `unaccent` 的 FTS PT-BR),包括 **统一源感知搜索**,涵盖两个来源。
---
## 📋 目录
1. [概述](#概述)
2. [为什么我们开发这个 MCP?](#为什么我们开发这个MCP)
3. [架构](#架构)
4. [快速安装](#快速安装)
5. [客户端配置](#客户端配置)
6. [工具、资源和提示](#工具、资源和提示)
7. [使用示例](#使用示例)
8. [嵌入式:提供者切换](#嵌入式提供者切换)
9. [安全性和身份验证](#安全性和身份验证)
10. [操作和监控](#操作和监控)
11. [故障排除](#故障排除)
12. [技术栈](#技术栈)
13. [免责声明](#免责声明)
14. [相关文档](#相关文档)
15. [有用链接](#有用链接)
---
## 概述
**Sankhya Ajuda MCP** 是 **Skills IT** 内部开发的服务器,实现 **模型上下文协议(MCP)**,使 **Sankhya** ERP 的公共知识库可搜索。
索引 **两个互补的来源** 到一个 PostgreSQL + pgvector 数据库:
- 📚 **帮助中心** (`ajuda.sankhya.com.br`, Zendesk) - **6,125 篇文章**,14 类别 / 230 个章节
- 💬 **社区** (`community.sankhya.com.br`, Bettermode) - **7,619 篇问答帖子** (问题 + 答案),33 个公共空间
该服务器允许 **AI 助手** (**Claude Desktop, Claude Code, Cursor, VS Code Copilot, ChatGPT/OpenAI Responses API**,以及任何兼容的 MCP 客户端)对两个知识库进行结构化查询,返回:
- 🔍 **混合搜索**,具有相关性排名(语义 + 关键词),在每个来源中
- 🔗 **统一源感知搜索** (`sankhya_ajuda_search_knowledge_unified`) - 结合帮助中心 + 社区,通过来源进行 RRF,标题重复,官方来源标签
- 📖 **完整内容**,Markdown 文章和问答帖子
- 🗂️ **类别和章节层次结构** (14 + 230 + 59 子章节) 和社区空间 (33)
- 🤖 **命名工作流**,用于故障排除,查找,模块解释和比较
- 📊 **同步状态** (两个来源) 通过公共端点 `/health`
### 用例
| 配置文件 | 利益 |
|---|---|
| **N1/N2 技术支持** | 快速解决方案搜索,错误代码,程序 |
| **顾问** | 模块结构化解释,用于会议和培训 |
| **新合作伙伴** | 教学大纲,官方文章按教学顺序排列 |
| **分析师** | 文章比较,旧内容审计 |
| **机器人/集成** | 统一 MCP API,用于与 Slack/Teams/CrewAI/LangChain 集成 |
---
## 为什么我们开发这个 MCP?
**Sankhya** 的官方 AI 工具 (**BIA — Business Intelligence Assistant**) 存在质量和覆盖范围的局限性。这个 MCP 是为了解决这些问题而开发的:
| 特性 | BIA(官方) | Sankhya Ajuda MCP(Skills IT) |
|---|---|---|
| **内容覆盖范围** | 有限 | ✅ 6,125 篇文章(帮助中心)+ 7,619 篇问答帖子(社区)索引 |
| **统一搜索(帮助 + 社区)** | ❌ | ✅ `sankhya_ajuda_search_knowledge_unified`,带有 RRF 按来源 + 重复 + 来源标签 |
| **语义搜索** | 受限 | ✅ pgvector + Qwen3 / OpenAI(相互排斥) |
| **错误代码搜索** | 不准确 | ✅ FTS PT-BR,带有 `unaccent` |
| **可通过外部 AI 访问** | ❌ | ✅ Claude,ChatGPT,Cursor,Copilot 等 |
| **历史记录/本地缓存** | ❌ | ✅ PostgreSQL |
### 独家功能
1. **混合搜索 RRF** - Reciprocal Rank Fusion(k=60),结合语义相似性和 FTS PT-BR
2. **跨模型防护栏** - 自动检测嵌入式提供者与索引不匹配,并带有可见警告(v1.5.4)
3. **透明故障转移模式** - `keyword_fallback`,`keyword_index_mismatch`,带有可见标签
4. **嵌入式提供者切换** - `vllm`(本地),`openai`(云)或 `none`(仅 FTS,无成本)
5. **工具桥** - 适配器,将 `resources/*` 和 `prompts/*` 公开为常规工具,以实现最大兼容性
6. **4 个预配置提示** - 引导工作流(故障排除,快速查找,模块解释,文章比较)
7. **经验校准** - 默认 `limit=15`,`max_body_chars=8000`,基于实际语料分布(P50-P99)和类别密度(2 类别中的 64%)
8. **双源统一搜索** - 帮助中心(Zendesk)+ 社区(Bettermode/GraphQL)在同一个数据库中;`sankhya_ajuda_search_knowledge_unified` 融合两个来源,通过来源进行 RRF,按标题重复和官方来源标签(防止对话帖子“埋葬”官方文章)
9. **可扩展和弹性同步** - 独立 ETL(帮助 03:00,社区 04:00),带有共享 `flock`,序列化访问 Postgres + vLLM;通过来源分离同步状态(`sync_state` / `community_sync_state`)
---
## 架构
该项目由 **两个解耦阶段** 组成,仅通过 PostgreSQL 模式进行通信。
```
┌─────────────────────────────────────────────────────────────────────────┐
│ AI 客户端(Claude, ChatGPT, Cursor, Copilot, 脚本...) │
│ │
│ Streamable HTTP + Bearer(授权标头)+ MCP-Protocol-Version │
└─────────────────────────────────────────────────────────────────────────┘
│
│ MCP 2025-11-25
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Sankhya Ajuda MCP 服务器(阶段 2 — Node 22 + TypeScript 5) │
│ 默认端口:3105 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ 7 个工具 │ │ 4 个桥接工具 │ │ 6 个资源 │ │ 4 个提示 │ │
│ │ (领域 + │ │ 工具 │ │ sankhya- │ │ 命名字符串 │ │
│ │ 社区) │ │ │ │ 帮助:// │ │ 工作流 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Auth(timingSafeEqual) │ 公共 `/health` │ OAuth 404 JSON │ │
│ │ 会话生命周期(30 分钟空闲) │ 响应上限 400 KB │ │
│ │ 跨模型索引提供者防护栏(v1.5.4) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
│ SQL(pgvector + FTS)
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ PostgreSQL 16+,带有 pgvector + unaccent + pg_trgm │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ 帮助中心(Zendesk): │ │
│ │ 类别(14) │ 章节(230,59 个嵌套) │ │
│ │ 文章(6,125) │ 嵌入式 HALFVEC(2560)+ FTS PT-BR │ │
│ │ 同步状态 │ 跳过的文章 │ 文章导航视图 │ │
│ │ │ │
│ │ 社区(Bettermode): │ │
│ │ 社区空间(33 个公共) │ 社区帖子(7,619) │ │
│ │ 同步状态 │ 跳过的帖子 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ 索引:HNSW pgvector + GIN FTS + btree partial outdated │
└─────────────────────────────────────────────────────────────────────────┘
▲
│ 每天 03:00(SHA256 检测)
│
┌─────────────────────────────────────────────────────────────────────────┐
│ Sankhya Ajuda ETL(阶段 1 — Python 3.13) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 帮助中心(03:00 同步) │ │
│ │ Zendesk 帮助中心 API(公共,无身份验证) │ │
│ │ → httpx → BeautifulSoup(HTML 剥离) │ │
│ │ → SHA256 差异 → vLLM/OpenAI 嵌入 → PostgreSQL 更新 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 社区(04:00 同步) │ │
│ │ Bettermode GraphQL(运行时访客令牌,无 API 密钥) │ │
│ │ → httpx → 问答线程组成 + Markdown │ │
│ │ → SHA256 差异 → vLLM/OpenAI 嵌入 → PostgreSQL 更新 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
▲
│
https://ajuda.sankhya.com.br(帮助)
https://community.sankhya.com.br(社区)
```
### 组件
| 组件 | 功能 | 技术 |
|---|---|---|
| **阶段 1 — ETL** | 每天抓取,生成嵌入,填充数据库 | Python 3.13,`httpx`,`psycopg`,`pgvector`,`beautifulsoup4`,`structlog` |
| **阶段 2 — MCP 服务器** | 通过 HTTP 公开 MCP 工具/资源/提示 | Node 22 LTS,TypeScript 5,MCP SDK ≥ 1.18,Express,`zod`,`pino`,`pg` |
| **数据库** | 专用模式 `sankhya_ajuda` | PostgreSQL 16+ + `pgvector`(halfvec 2560d)+ `unaccent` + `pg_trgm` |
| **嵌入** | 索引和查询中的向量生成 | vLLM(Qwen3-Embedding-4B)或 OpenAI `text-embedding-3-large @ 2560` |
| **传输** | 流式 HTTP MCP 2025-11-25 | 带有 `crypto.timingSafeEqual` 的 Bearer 身份验证,SSE 进行分段响应 |
| **编排** | 部署 | Docker Compose(带有 `gpu` 配置文件) **或** 原生 PM2 |
> **最小耦合度:** 阶段 1 和阶段 2 仅通过 PostgreSQL 模式进行通信。每个都可以独立更新。
---
## 快速安装
### 5 个支持的场景
| 场景 | 堆栈 | 时间 | 成本 |
|---|---|---|---|
| **#1 — 快速测试** | Docker,无 GPU,无 DB | 5 分钟 | 免费 |
| **#2 — 生产服务器(PM2)** | 现有 PostgreSQL | 30 分钟 | 免费(自有基础设施) |
| **#3 — 带有 NVIDIA GPU** | Docker + nvidia-docker,vLLM | 10 分钟 | 免费 |
| **#4 — 带有 TLS 的生产环境** | PM2 + Caddy/Nginx + 备份 | 1 小时 | 免费 |
| **#5 — 仅 FTS(零成本)** | Docker,无嵌入 | 5 分钟 | 免费 |
📖 **逐步说明:** [`docs/INSTALL.md`](./docs/INSTALL.md)
### 快速测试(场景 #1)
```bash
git clone https://github.com/DevSkillsIT/Skills-MCP-Sankhya-Ajuda.git
cd Skills-MCP-Sankhya-Ajuda
cp .env.example .env
# 编辑 .env:使用 `openssl rand -hex 32` 生成 MCP_AUTH_TOKEN
# 对于零成本,请设置 EMBEDDING_PROVIDER=none
docker compose up -d # 启动 postgres + mcp
docker compose run --rm etl sankhya-sync # 首次索引
curl http://localhost:3105/health # 验证状态
```
完整 ~10 分钟。查看 [`docs/INSTALL.md`](./docs/INSTALL.md) 以获取详细信息。
### 生产环境(场景 #2 — 使用现有的 PostgreSQL)
```bash
git clone https://localhost.com:3105/Skills-MCP-Sankhya-Ajuda.git
cd Skills-MCP-Sankhya-Ajuda
# 阶段 1 — Python ETL
python3.13 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env && $EDITOR .env
.venv/bin/python -m sync.sync --full
# 阶段 2 — Node MCP 服务器
cd mcp-server && npm install && npm run build
cp .env.example .env && $EDITOR .env
pm2 start ecosystem.http.config.cjs
pm2 save
```
更多信息见 [`docs/DEPLOY.md`](./docs/DEPLOY.md).
---
## 客户端配置
> **通用原则:** 每个 MCP 客户端都需要 **3 个数据**:URL (`http://<host>:3105/mcp`),`Authorization` 头部中的 Bearer `<MCP_AUTH_TOKEN>`,以及(理想情况下)`2025-11-25` 协议版本。
### Claude Desktop
文件:`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) 或 `%APPDATA%\Claude\claude_desktop_config.json` (Windows).
```json
{
"mcpServers": {
"sankhya-ajuda": {
"type": "http",
"url": "http://mcp.example.com:3105/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
```
重启 Claude Desktop。`sankhya_ajuda_*` 工具将出现在面板中。
### Claude Code(CLI)
文件:`.mcp.json` 在项目根目录 **或** `~/.claude/.mcp.json` 全局。
```json
{
"mcpServers": {
"sankhya-ajuda": {
"type": "http",
"url": "http://mcp.example.com:3105/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
```
重启 Claude Code。命令:`claude --debug "mcp"` 以验证连接。
### Cursor
文件:`~/.cursor/mcp.json` 或项目设置。
```json
{
"mcpServers": {
"sankhya-ajuda": {
"transport": "http",
"url": "http://mcp.example.com:3105/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
```
### VS Code Copilot
文件:`.vscode/mcp.json` 在工作区 **或** `settings.json` 全局。
```json
{
"servers": {
"sankhya-ajuda": {
"type": "http",
"url": "http://mcp.example.com:3105/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
}
}
}
}
```
### OpenAI Responses API(ChatGPT / GPT-4.1+)
自 2025-05 起可用。使用调用中的 `mcp` 类型。
**Python:**
```python
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-4.1",
input="如何解决 Sankhya 中的 E0004 错误?",
tools=[{
"type": "mcp",
"server_label": "sankhya-ajuda",
"server_url": "http://mcp.example.com:3105/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_AUTH_TOKEN"
},
"require_approval": "never"
}]
)
print(response.output_text)
```
**curl:**
```bash
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1",
"input": "Sankhya, 如何取消发票?",
"tools": [{
"type": "mcp",
"server_label": "sankhya-ajuda",
"server_url": "http://mcp.example.com:3105/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_AUTH_TOKEN" },
"require_approval": "never"
}]
}'
```
### ChatGPT(企业/团队 — 自定义连接器)
ChatGPT 企业和团队支持 **自定义 MCP 连接器** 通过管理员面板。配置:
- **类型:** 远程 MCP 服务器
- **URL:** `http://mcp.example.com:3105/mcp`
- **身份验证:** Bearer 头部 `Authorization: Bearer <MCP_AUTH_TOKEN>`
- **协议版本:** `2025-11-25`
> 添加后,由管理员查看, 用户在 **Tools** 菜单中看到连接器。
### 其他兼容的 MCP 客户端
任何实现 **MCP 2025-11-25** 带 **Streamable HTTP** 的应用程序都可以使用此服务器。默认配置:
| 字段 | 值 |
|---|---|
| 传输 | `http` 或 `streamable-http` |
| URL | `http://<host>:3105/mcp` |
| 头部 | `Authorization: Bearer <token>` |
| 协议版本 | `2025-11-25` |
确认的客户端示例: **mcp-cli**,**Cline(VS Code)**,**Zed**,**Continue.dev**,**LibreChat**,**Open WebUI**。
### 测试连接
```bash
# 健康检查(无身份验证,公共)
curl http://localhost:3105/health | jq
# 预期:
# {
# "status": "ok",
# "version": "1.0.0",
# "articles_count": 6125,
# "with_embedding_count": 6125,
# "last_sync_status": "ok",
# ...
# }
```
# 测试工具列表(带有身份验证)
```bash
curl -s -X POST http://localhost:3105/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 您的令牌" \
-H "MCP-Protocol-Version: 2025-11-25" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": { "name": "curl-test", "version": "1.0" }
}
}'
```
## 工具、资源和提示
📖 **完整参考:** [`docs/TOOLS.md`](./docs/TOOLS.md)
### 11 个工具(仅限阅读)
| 工具 | 类别 | 功能 |
|---|---|---|
| ~~`sankhya_ajuda_search_articles`~~ | _已在 v1.2.0 中移除_ | 已被 `sankhya_ajuda_search_knowledge_unified` (下一行)取代;源代码保留 |
| `sankhya_ajuda_get_article_details` | 领域 | 完整的 Markdown 文章(可配置字符数上限) |
| `sankhya_ajuda_list_categories` | 领域 | 列出 14 个顶级类别 |
| `sankhya_ajuda_list_sections` | 领域 | 列出 230 个章节(可选 `category_id` 和 `parent_section_id`) |
| `sankhya_ajuda_search_knowledge_unified` | 社区 + 帮助 | 跨源搜索帮助中心 + 社区,带有 RRF 去重和来源标签 |
| `sankhya_ajuda_get_community_post` | 社区 | 获取 Bettermode 社区的 Q&A 线程(带答案) |
| `sankhya_ajuda_list_community_spaces` | 社区 | 列出公共社区空间(不包括私有空间) |
| `sankhya_ajuda_list_mcp_resources` | 桥接 | 列出可用的 `sankhya-ajuda://` URIs |
| `sankhya_ajuda_read_resource_by_uri` | 桥接 | 读取 `sankhya-ajuda://` URI 的内容 |
| `sankhya_ajuda_list_prompt_catalog` | 桥接 | 列出带有参数的 4 个提示 |
| `sankhya_ajuda_get_prompt_by_name` | 桥接 | 执行参数化的提示 |
### 6 个资源(`sankhya-ajuda://` 方案)
| URI | 类型 | 内容 |
|---|---|---|
| `sankhya-ajuda://categories` | 静态 Markdown | 14 个类别的表格 |
| `sankhya-ajuda://sections` | 静态 Markdown | 230 个章节的表格 |
| `sankhya-ajuda://sync_state` | 静态 JSON | 最后一次同步的状态 |
| `sankhya-ajuda://categories/{id}` | 模板 Markdown | 1 个类别的详细信息 |
| `sankhya-ajuda://sections/{id}` | 模板 Markdown | 1 个章节的详细信息 |
| `sankhya-ajuda://articles/{id}` | 模板 Markdown | 完整的文章 |
### 4 个提示(命名的工作流)
| 提示 | 功能 | 参数 |
|---|---|---|
| `sankhya_troubleshoot` | 分步问题排查 | `problem` (错误描述) |
| `sankhya_quick_lookup` | 快速搜索,压缩答案 | `term` (术语、代码、屏幕) |
| `sankhya_explain_module` | 模块结构化解释 | `module_name` (例如:“发票”) |
| `sankhya_compare_articles` | 比较多个文章 | `article_ids` (CSV ID) |
## 使用示例
📖 **详细场景:** [`docs/EXAMPLES.md`](./docs/EXAMPLES.md)
### 示例 1 — 快速错误代码支持
**客户端 MCP 中的提示:**
```
Sankhya,NF-e 中的 E0004 错误代码是什么意思?
```
**发生了什么:**
1. LLM 调用 `sankhya_ajuda_search_knowledge_unified({query: "E0004 NF-e", source: "all"})`
2. 接收前 15 个项目(默认),混合官方帮助 + 社区,带有 `#` 权威排名、相似性和 URL 列
3. 确定最相关的项目(`#1`)并呈现具有原因、解决方案和官方链接的答案
> 💡 **默认 `limit=15`** (最大 50)。使用 `limit=3-5` 进行快速搜索(例如 `sankhya_quick_lookup` 提示),使用 `limit=25-50` 进行比较分析或广泛探索。针对超过 6,000 篇文章,64% 集中在 2 个类别中进行校准。
---
### 示例 2 — 结构化故障排除(命名提示)
**在 Claude Code 中:
```
/sankhya_troubleshoot problem="客户报告 '服务未配置' 错误时发出 NF-e"
```
**在任何其他客户端:
调用 `sankhya_ajuda_get_prompt_by_name`,`name="sankhya_troubleshoot"` 和 `arguments={problem: "..."}`。
**预期响应:**具有可能原因、逐步解决方案和参考文章的结构化调查。
---
### 示例 3 — 为会议解释模块
```
Sankhya,请给我一个发票模块的概述。
```
LLM 在内部使用 `sankhya_explain_module` 提示,并生成:
- 它是什么
- 何时使用
- 先决条件
- 主要屏幕(带有链接)
- 常见错误(带有链接)
---
### 示例 4 — 技术比较
```
Sankhya,比较以下 3 篇文章:360045123456、360067891234、360011223344
```
使用 `sankhya_compare_articles` 提示并生成具有收敛、发散和空白的表格。
---
### 示例 5 — 税改
```
Sankhya,我应该注意 TGF(交易类型)有哪些与税务改革相关的注意事项?
```
按类别“税务改革”(42 篇文章)进行过滤搜索。
---
📖 **在 [`docs/EXAMPLES.md`](./docs/EXAMPLES.md) 中有 15+ 个配置文件(支持 N1、支持 N2、咨询、入职培训、技术分析、比较、税务改革案例、编程使用(Python/Node/curl)、反幻觉模式)
---
## 嵌入式:提供者切换
服务器支持 **3 个相互排斥的嵌入式提供者**,通过 `.env` 中的 `EMBEDDING_PROVIDER` 配置。
| 提供者 | 模型 | 维度 | 何时使用 | 成本 |
|---|---|---|---|---|
| **`vllm`** (默认) | Qwen3-Embedding-4B | 2560 | 本地 GPU 与 vLLM | 零(GPU 后) |
| **`openai`** | text-embedding-3-large | 2560 (通过 Matryoshka 截断) | 无 GPU,可用 OpenAI 密钥 | ~$0.03 / 6k 文章 + $0.00001/查询 |
| **`none`** | — | — | 无 vLLM 和无 OpenAI | 零 |
### ⚠️ 跨模型防护(v1.5.4)
**在不重新索引数据库的情况下更改 `EMBEDDING_PROVIDER` 会破坏语义搜索** - 不同模型的向量生活在不兼容的向量空间中。服务器在启动时自动检测并:
- 记录结构化的 `warn`
- 强制 `mode=hybrid|semantic` 降低为 `keyword_index_mismatch`
- 在响应中显示可见的标签
📖 **完整的架构决策:** [`docs/EMBEDDINGS-PROVIDER.md`](./docs/EMBEDDINGS-PROVIDER.md)
📖 **回退策略(RF07):** [`docs/FALLBACK_STRATEGY.md`](./docs/FALLBACK_STRATEGY.md)
---
## 安全性和身份验证
### 承载令牌(Authorization Header)
所有 `/mcp` 调用都需要以下头部:
```
Authorization: Bearer <MCP_AUTH_TOKEN>
```
比较使用 **`crypto.timingSafeEqual`** (恒定时间,避免计时攻击)。
### 令牌轮换
```bash
# 1. 生成新令牌
NOVO=$(openssl rand -hex 32)
# 2. 更新服务器 .env
sed -i "s/^MCP_AUTH_TOKEN=.*/MCP_AUTH_TOKEN=$NOVO/" .env
# 3. 更新所有客户端(Claude、Cursor 等)
# 4. 重启服务器
pm2 restart mcp-sankhya-ajuda # PM2
# 或
docker compose restart mcp-server # Docker
```
### 公共端点
`GET /health` **故意公开**,用于外部健康检查(Prometheus、Uptime Kuma 等)。 **从不公开凭证** - 仅状态、计数器和时间戳。
### OAuth 发现
服务器在 `/.well-known/oauth-*` 上响应 **JSON 404**,以指示 **不支持 OAuth** (仅静态承载)。现代 MCP 客户端检测到这一点并自动回退到承载。
### 无 Sankhya ERP 访问权限
此 MCP **仅使用 help center 的公共内容** (`ajuda.sankhya.com.br`)。 **不访问:
- ❌ Sankhya ERP 的业务 API
- ❌ 客户数据库
- ❌ 财务数据、订单、客户档案
- ❌ Zendesk 私有/内部文章(仅公开)
### 安全层
| 层 | 实现 |
|---|---|
| **身份验证** | 通过 `Authorization` 头的 Bearer 令牌 |
| **恒定时间比较** | `crypto.timingSafeEqual` (Node.js 原生) |
| **会话生命周期** | 空闲超时 30 分钟(可配置),定期回收 |
| **响应上限** | 每响应 400 KB(防止大规模外泄) |
| **只读** | 工具无写入数据库 |
| **输入验证** | 所有参数的 `zod` 模式 |
| **日志中无机密** | 带有编辑的 PIN;令牌从不出现在日志中 |
| **错误无内部信息泄露** | 在 `INTERNAL_ERROR` 中,工具和 `/health` 对客户端返回通用消息;原始详细信息(SQL、模式、路径)**仅**在服务器上记录 |
---
## 操作和监控
📖 **完整的运行手册:** [`docs/OPERATIONS.md`](./docs/OPERATIONS.md)
### 健康检查
```bash
curl -s http://localhost:3105/health | jq
```
预期响应:
```json
{
"status": "ok",
"version": "1.0.0",
"uptime_sec": 3600,
"sessions": 0,
"tenant": "skillsit",
"last_sync_status": "ok",
"last_sync_at": "2026-05-16T03:00:00.000Z",
"articles_count": 6125,
"with_embedding_count": 6125
}
```
可能的状态:`ok`(健康)、`degraded`(数据库离线或同步错误)、`error`(内部异常)。
### PM2 命令
```bash
pm2 status mcp-sankhya-ajuda
pm2 logs mcp-sankhya-ajuda --lines 50
pm2 restart mcp-sankhya-ajuda
pm2 stop mcp-sankhya-ajuda
pm2 monit
```
### Docker 命令
```bash
docker compose ps
docker compose logs -f mcp-server
docker compose restart mcp-server
docker compose run --rm etl sankhya-sync # 强制重新同步
```
### 手动同步
```bash
# 原生
cd /path/to/sankhya-ajuda-mcp
.venv/bin/python -m sync.sync --full
# Docker
docker compose run --rm etl sankhya-sync
```
### 每日 Cron
两个作业计划(共享 Postgres + vLLM,因此时间不同):
```cron
# 帮助中心 @ 03:00
0 3 * * * cd /path/to/sankhya-ajuda-mcp && .venv/bin/python -m sync.sync --full >> /var/log/sankhya_ajuda_sync.log 2>&1
# 社区(Bettermode)@ 04:00
0 4 * * * cd /path/to/sankhya-ajuda-mcp && .venv/bin/python -m sync.community_sync --full >> /var/log/sankhya_ajuda_community_sync.log 2>&1
```
`scripts/sankhya_ajuda_sync.cron` 和 `scripts/sankhya_ajuda_community_sync.cron` + logrotate 每个文件可用。安装见 [`docs/DEPLOY.md`](./docs/DEPLOY.md#步骤 4 - 每日 Cron)。
### 推荐的警报
| 条件 | 严重程度 |
|---|---|
| `sync_state.error_count >= 3` | 高 |
| `last_sync_at < now() - 36h` | 高 |
| `with_embedding_count < articles_count - 10` | 中 |
| `/health` 返回 503 > 5 分钟 | 严重 |
---
## 故障排除
### 错误:`401 unauthorized`
**原因:** Bearer 令牌不正确或丢失。
**解决方案:**
1. 确认 `.env` 中的 `MCP_AUTH_TOKEN` 与客户端的 `Authorization: Bearer ...` 头部相同
2. 检查令牌中是否有额外的空格或换行符
3. 在编辑 `.env` 后重启服务器```bash
# 手动测试
curl -i -H "Authorization: Bearer $MCP_AUTH_TOKEN" http://localhost:3105/mcp
```
### 错误:`:3105` 连接被拒绝
**原因:** MCP 服务器未运行。
**解决方案:```bash
# Docker
docker compose ps
docker compose logs mcp-server --tail 30
# 或 `docker compose logs mcp-sankhya-ajuda --lines 30`
# PM2
pm2 status
pm2 logs mcp-sankhya-ajuda --lines 30
```
### 错误:`EMBEDDING_UNAVAILABLE` 在语义模式下
**原因:** vLLM 或 OpenAI 不可用。
**解决方案:**
1. 检查提供者的连接性 (`curl $VLLM_BASE_URL/health`)
2. 暂时使用 `mode=keyword` 或 `mode=hybrid` (`hybrid` 自动降低为 `keyword_fallback`)
3. 检查提供者的日志
### 响应带有标签 `keyword (index mismatch)`
**原因:** 在不重新索引数据库的情况下更改了 `EMBEDDING_PROVIDER`。
**解决方案:** [在提供者之间迁移](./docs/EMBEDDINGS-PROVIDER.md#如何迁移提供者) - 使用新模型重新索引数据库。
### 健康状况返回 `articles_count: 0`
**原因:** 尚未运行同步。
**解决方案:
```bash
docker compose run --rm etl sankhya-sync # Docker
# 或
sankhya-sync # 原生(激活 venv)
```
### MCP 客户端看不到工具
**解决方案:**
1. 使用正确的 URL 和令牌确认 `.mcp.json` / 设置
2. 重启客户端(Claude Desktop、Cursor、VS Code 等)
3. 使用 `--debug "mcp"` 命令(Claude Code)检查握手
4. 使用 `curl` 手动测试(参见 [测试连接](#测试连接) 部分)
### 错误:`RESPONSE_TOO_LARGE`
**原因:** 响应超过 400 KB(保护上限)。
**解决方案:** 减少 `limit`(在 `sankhya_ajuda_search_knowledge_unified` 中)或 `max_body_chars`(在 `sankhya_ajuda_get_article_details` / `sankhya_ajuda_get_community_post` 中)。
📖 **完整的故障排除:** [`docs/OPERATIONS.md`](./docs/OPERATIONS.md#troubleshooting)
---
## 技术栈
| 层级 | 技术 | 版本 |
|---|---|---|
| **ETL(第一阶段)** | Python | 3.13 |
| | httpx, psycopg, pgvector, beautifulsoup4, structlog, pytest | 最新稳定版 |
| **数据库** | PostgreSQL | 16+ |
| | 扩展 | `vector` ≥0.8, `unaccent`, `pg_trgm` |
| **嵌入式** | Qwen3-Embedding-4B 采用 vLLM(2560d) | 运行时选择 |
| | **或** OpenAI `text-embedding-3-large @ 2560` | |
| **MCP 服务器(第二阶段)** | Node.js | 22 LTS |
| | TypeScript | 5(严格) |
| | MCP SDK | ≥ 1.18 |
| | Express, zod, pino, vitest | 最新稳定版 |
| **传输** | Streamable HTTP(MCP 2025-11-25) | Bearer 认证,SSE |
| **编排** | Docker Compose 采用配置文件 | **或** PM2 |
| **TLS(生产)** | Caddy / Nginx + `acme.sh + dns_cpanel` | 通配符 |
---
## 免责声明
> 本项目 **不隶属于、背书或赞助** 由 Sankhya Gestão de Negócios S/A 提供。 它仅使用 `ajuda.sankhya.com.br` 上公开的帮助中心内容(托管在 Zendesk 上)。 “Sankhya” 是其各自所有者的商标,仅在此引用以识别所处理的文档域。
>
> **不访问** Sankhya ERP 的业务、财务或个人数据。 **不访问** 客户数据库。
> **不访问** ERP Sankhya 的财务数据、订单、客户档案。
> **不访问** Zendesk 的私有/内部文章(仅公开)
### 支持和联系
实施和维护:**[Skills IT — 技术解决方案](https://www.skillsit.com.br)**
- 🌐 [www.skillsit.com.br](https://www.skillsit.com.br)
- 📱 **(63) 3224-4925** — WhatsApp / 电话
- 📍 **Palmas — TO — 巴西**
- ✉️ 支持邮箱:suporte@skillsit.com.br
如有技术问题,请在 GitHub 上提交问题(发布后)或直接联系上述渠道。
---
## 相关文档
| 文档 | 内容 |
|---|---|
| [`docs/TOOLS.md`](./docs/TOOLS.md) | 每个工具、资源和提示的详细参考 |
| [`docs/EXAMPLES.md`](./docs/EXAMPLES.md) | 20+ 个配置文件示例(按角色划分:支持、顾问、技术人员) |
| [`docs/INSTALL.md`](./docs/INSTALL.md) | 5 种情景下的逐步安装 |
| [`docs/DEPLOY.md`](./docs/DEPLOY.md) | 高级部署(Docker + PM2 + TLS) |
| [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) | 技术架构(第 1 阶段 + 第 2 阶段) |
| [`docs/SCHEMA.md`](./docs/SCHEMA.md) | PostgreSQL + pgvector 架构 |
| [`docs/EMBEDDINGS-PROVIDER.md`](./docs/EMBEDDINGS-PROVIDER.md) | 如何选择和迁移提供者(vllm/openai/none) |
| [`docs/FALLBACK_STRATEGY.md`](./docs/FALLBACK_STRATEGY.md) | 提供者内部的回退策略(RF07) |
| [`docs/OPERATIONS.md`](./docs/OPERATIONS.md) | 运行手册和监控 |
| [`docs/ACCEPTANCE_REPORT.md`](./docs/ACCEPTANCE_REPORT.md) | 第一阶段(ETL)验收报告 |
| [`CHANGELOG.md`](./CHANGELOG.md) | 完整的版本历史记录 |
| [`CONTRIBUTING.md`](./CONTRIBUTING.md) | 如何贡献该项目 |
---
## 有用的链接
- 📘 [Sankhya 帮助中心](https://ajuda.sankhya.com.br/) — 索引源
- 🔧 [Sankhya — 官方网站](https://www.sankhya.com.br/) — 源 ERP
- 📦 [模型上下文协议(MCP)](https://modelcontextprotocol.io/) — 协议规范
- 🤖 [Claude Desktop](https://claude.ai/download) · [Claude Code](https://claude.com/claude-code)
- 🛠 [Cursor](https://cursor.com/) · [VS Code Copilot](https://github/features/copilot)
- 🚀 [OpenAI 响应 API 采用 MCP](https://platform.openai.com/docs/guides/tools-remote-mcp)
- 🧠 [pgvector](https://github.com/pgvector/pgvector) — PostgreSQL 中的向量相似性搜索
- ⚡ [vLLM](https://github.com/vllm-project/vllm) — 高吞吐量 LLM 推理引擎
- 🏢 [Skills IT](https://www.skillsit.com.br) — 我们的公司
---
## 许可
[MIT](./LICENSE) — © 2026 Skills IT — 技术解决方案
---
<div align="center">
**由 Skills IT 使用 🛠 构建**
🌐 [www.skillsit.com.br](https://www.skillsit.com.br) · 📱 (63) 3224-4925 (WhatsApp/Phone) · 📍 Palmas — TO — 巴西
*此 MCP 由 Skills IT 开发和维护,作为对巴西 Sankhya 社区的贡献。*
</div>
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器