[
  {
    "path": ".claude/settings.local.json",
    "content": "{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(npm install)\",\n      \"Bash(npm run build)\",\n      \"Bash(tree:*)\",\n      \"Bash(node:*)\",\n      \"Bash(npm view universal-db-mcp)\",\n      \"Bash(npm pack --dry-run)\",\n      \"Bash(npm pack)\",\n      \"Bash(npm whoami:*)\",\n      \"Bash(ls:*)\",\n      \"WebFetch(domain:www.npmjs.com)\",\n      \"Bash(npm view dmdb --json)\",\n      \"Bash(npm view dmdb description author homepage keywords)\",\n      \"Bash(iconv:*)\",\n      \"Bash(chcp 65001)\",\n      \"Bash(findstr:*)\",\n      \"Bash(python:*)\",\n      \"Bash(npm view mssql version)\",\n      \"Bash(npm install mongodb)\",\n      \"Bash(npm ls mongodb)\",\n      \"Bash(npm view universal-db-mcp version)\",\n      \"Bash(npm view mongodb@6.21.0 dist.tarball)\",\n      \"WebSearch\",\n      \"Bash(npm view mongodb@6.21.0 main)\",\n      \"Bash(npm view mongodb@6.21.0 type)\",\n      \"Bash(npm view mongodb@6.21.0 exports)\",\n      \"Bash(npm view mongodb@5 version)\",\n      \"Bash(npm install @clickhouse/client)\",\n      \"Bash(npm run --silent)\",\n      \"Bash(timeout:*)\",\n      \"Bash(curl:*)\",\n      \"Bash(npm install cross-env --save-dev)\",\n      \"Bash(dir:*)\",\n      \"Bash(copy:*)\",\n      \"WebFetch(domain:en.oceanbase.com)\",\n      \"WebFetch(domain:docs.dify.ai)\",\n      \"WebFetch(domain:www.pulsemcp.com)\",\n      \"WebFetch(domain:www.modb.pro)\",\n      \"Bash(npm test:*)\",\n      \"Bash(npx vitest run:*)\",\n      \"Bash(git checkout:*)\",\n      \"Bash(MODE=mcp node:*)\",\n      \"Bash(npx .:*)\",\n      \"Bash(npx tsc:*)\",\n      \"Bash(grep:*)\",\n      \"Bash(./node_modules/.bin/tsc --noEmit)\",\n      \"Bash(npx --no-install tsc --noEmit)\",\n      \"Bash(npx --no-install tsc)\",\n      \"Bash(node -e \\\":*)\",\n      \"Bash(node --input-type=module -e \\\":*)\",\n      \"Bash(npx --no-install vitest run tests/unit)\",\n      \"Bash(while read:*)\",\n      \"Bash(do grep:*)\",\n      \"Bash(sort -t'|' -k3 -u)\",\n      \"Bash(do sed:*)\",\n      \"Bash(for f:*)\",\n      \"Bash(do)\",\n      \"Bash(if grep:*)\",\n      \"Bash(! grep:*)\",\n      \"Bash(then)\",\n      \"Bash(perl -i -pe 's/\\\\(^\\\\\\\\| `clear_cache` \\\\\\\\|.*\\\\\\\\|\\\\)\\\\\\\\s*$/\\\\\\\\1\\\\\\\\n| `get_enum_values` | 获取指定列的所有唯一值 |\\\\\\\\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\\\\\\\\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\\\\\\\\n| `disconnect_database` | 断开当前数据库连接 |\\\\\\\\n| `get_connection_status` | 获取当前数据库连接状态 |/' \\\"$f\\\")\",\n      \"Bash(fi)\",\n      \"Bash(done)\",\n      \"Bash(echo \\\"MISSING: $f\\\")\",\n      \"Bash(cd:*)\"\n    ]\n  }\n}\n"
  },
  {
    "path": ".dockerignore",
    "content": "# Docker ignore file\nnode_modules\nnpm-debug.log\ndist\n.env\n.env.local\n.git\n.gitignore\nREADME.md\nEXAMPLES.md\nDEPLOYMENT.md\nCONTRIBUTING.md\ndocs\ntests\n*.md\n.vscode\n.idea\n*.log\ncoverage\n.nyc_output\n"
  },
  {
    "path": ".github/ACTIONS_SETUP.md",
    "content": "# GitHub Actions 配置指南\n\n本项目使用 GitHub Actions 实现自动化 CI/CD 流程。\n\n## 📋 工作流说明\n\n### 1. CI 工作流 (`.github/workflows/ci.yml`)\n\n**触发条件**:\n- 推送到 `main` 或 `develop` 分支\n- 针对 `main` 或 `develop` 分支的 Pull Request\n\n**功能**:\n- ✅ 在多个 Node.js 版本（20.x, 22.x）上测试\n- ✅ 安装依赖并构建项目\n- ✅ 检查 TypeScript 类型\n- ✅ 验证构建输出\n- ✅ 检查包内容\n\n### 2. NPM 发布工作流 (`.github/workflows/publish.yml`)\n\n**触发条件**:\n- 创建 GitHub Release\n- 手动触发（workflow_dispatch）\n\n**功能**:\n- ✅ 自动构建项目\n- ✅ 发布到 NPM\n- ✅ 使用 provenance（来源证明）\n- ✅ 发布成功/失败通知\n\n## 🔧 配置步骤\n\n### 1. 获取 NPM Token\n\n1. 登录 [npmjs.com](https://www.npmjs.com/)\n2. 点击头像 → **Access Tokens**\n3. 点击 **Generate New Token** → **Classic Token**\n4. 选择 **Automation** 类型\n5. 复制生成的 token\n\n### 2. 配置 GitHub Secrets\n\n1. 进入 GitHub 仓库\n2. 点击 **Settings** → **Secrets and variables** → **Actions**\n3. 点击 **New repository secret**\n4. 添加以下 secret:\n   - **Name**: `NPM_TOKEN`\n   - **Value**: 粘贴你的 NPM token\n\n### 3. 配置 NPM 包权限\n\n确保你的 NPM 账号有权限发布包：\n\n```bash\n# 登录 NPM\nnpm login\n\n# 检查当前用户\nnpm whoami\n\n# 如果包名已存在，确保你是所有者或协作者\nnpm owner ls universal-db-mcp\n```\n\n### 4. 配置 package.json\n\n确保 `package.json` 中的以下字段正确：\n\n```json\n{\n  \"name\": \"universal-db-mcp\",\n  \"version\": \"0.1.1\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/your-username/universal-db-mcp.git\"\n  }\n}\n```\n\n## 🚀 发布流程\n\n### 方法 1: 通过 GitHub Release（推荐）\n\n先把代码都commit，然后再开始下面操作\n\n1. **更新版本号**\n   ```bash\n   # 补丁版本 (0.1.1 -> 0.1.2)\n   npm version patch\n\n   # 次要版本 (0.1.1 -> 0.2.0)\n   npm version minor\n\n   # 主要版本 (0.1.1 -> 1.0.0)\n   npm version major\n   ```\n\n2. **推送 tag 到 GitHub**\n   ```bash\n   git push origin main --tags\n   ```\n\n3. **创建 GitHub Release**\n   \n   - 进入 GitHub 仓库\n   - 点击 **Releases** → **Create a new release**\n   - 选择刚才创建的 tag\n   - 填写 Release 标题和说明\n- 点击 **Publish release**\n   \n4. **自动发布**\n   - GitHub Actions 会自动触发\n   - 构建并发布到 NPM\n   - 查看 Actions 标签页查看进度\n\n### 方法 2: 手动触发\n\n1. 进入 GitHub 仓库\n2. 点击 **Actions** 标签\n3. 选择 **Publish to NPM** 工作流\n4. 点击 **Run workflow**\n5. 选择分支并点击 **Run workflow**\n\n## 📝 版本管理最佳实践\n\n### 语义化版本控制\n\n遵循 [Semantic Versioning](https://semver.org/) 规范：\n\n- **MAJOR** (1.0.0): 不兼容的 API 变更\n- **MINOR** (0.1.0): 向后兼容的功能新增\n- **PATCH** (0.0.1): 向后兼容的问题修复\n\n### 发布前检查清单\n\n- [ ] 代码已合并到 main 分支\n- [ ] 所有测试通过\n- [ ] 更新了 CHANGELOG.md\n- [ ] 更新了文档\n- [ ] 版本号已更新\n- [ ] 创建了 git tag\n\n### Release Notes 模板\n\n```markdown\n## 🎉 v0.2.0\n\n### ✨ 新功能\n- 添加 Oracle 数据库支持\n- 支持多种连接方式（Easy Connect、TNS）\n\n### 🐛 Bug 修复\n- 修复连接超时问题\n- 修复列名大小写问题\n\n### 📚 文档更新\n- 更新 README.md\n- 添加 Oracle 使用示例\n\n### 🔧 其他改进\n- 优化错误处理\n- 改进类型定义\n```\n\n## 🔍 监控发布状态\n\n### 查看 GitHub Actions 日志\n\n1. 进入 GitHub 仓库\n2. 点击 **Actions** 标签\n3. 选择对应的工作流运行\n4. 查看详细日志\n\n### 验证 NPM 发布\n\n```bash\n# 查看最新版本\nnpm view universal-db-mcp version\n\n# 查看包信息\nnpm view universal-db-mcp\n\n# 安装测试\nnpm install -g universal-db-mcp@latest\nuniversal-db-mcp --version\n```\n\n## 🐛 故障排查\n\n### 问题 1: NPM_TOKEN 无效\n\n**错误**: `npm ERR! code E401`\n\n**解决方案**:\n1. 检查 NPM token 是否正确\n2. 确认 token 类型为 \"Automation\"\n3. 重新生成 token 并更新 GitHub Secret\n\n### 问题 2: 包名冲突\n\n**错误**: `npm ERR! 403 Forbidden`\n\n**解决方案**:\n1. 修改 `package.json` 中的包名\n2. 或者使用 scoped package: `@your-username/universal-db-mcp`\n\n### 问题 3: 版本已存在\n\n**错误**: `npm ERR! 403 You cannot publish over the previously published versions`\n\n**解决方案**:\n1. 更新版本号: `npm version patch`\n2. 推送新的 tag: `git push --tags`\n\n### 问题 4: 构建失败\n\n**错误**: TypeScript 编译错误\n\n**解决方案**:\n1. 本地运行 `npm run build` 检查错误\n2. 修复 TypeScript 错误\n3. 提交并重新触发工作流\n\n## 📊 工作流徽章\n\n在 README.md 中添加状态徽章：\n\n```markdown\n[![CI](https://github.com/your-username/universal-db-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/your-username/universal-db-mcp/actions/workflows/ci.yml)\n[![NPM Version](https://img.shields.io/npm/v/universal-db-mcp.svg)](https://www.npmjs.com/package/universal-db-mcp)\n[![NPM Downloads](https://img.shields.io/npm/dm/universal-db-mcp.svg)](https://www.npmjs.com/package/universal-db-mcp)\n```\n\n## 🔐 安全最佳实践\n\n1. **保护 NPM Token**\n   - 永远不要在代码中硬编码 token\n   - 使用 GitHub Secrets 存储敏感信息\n   - 定期轮换 token\n\n2. **使用 Provenance**\n   - 工作流已配置 `--provenance` 标志\n   - 提供包的来源证明\n   - 增强供应链安全\n\n3. **限制权限**\n   - 工作流使用最小权限原则\n   - 仅授予必要的权限\n\n4. **代码审查**\n   - 所有变更通过 Pull Request\n   - 至少一人审查后合并\n   - 使用分支保护规则\n\n## 📚 相关资源\n\n- [GitHub Actions 文档](https://docs.github.com/en/actions)\n- [NPM 发布文档](https://docs.npmjs.com/cli/v9/commands/npm-publish)\n- [语义化版本控制](https://semver.org/)\n- [NPM Provenance](https://docs.npmjs.com/generating-provenance-statements)\n\n---\n\n## 🎉 完成！\n\n配置完成后，每次创建 Release 都会自动发布到 NPM。享受自动化的便利吧！\n"
  },
  {
    "path": ".github/GITHUB_README.md",
    "content": "# GitHub 配置文件\n\n本目录包含 GitHub Actions 工作流和相关配置。\n\n## 📁 文件说明\n\n### workflows/\n- **ci.yml** - 持续集成工作流，在每次推送和 PR 时运行测试和构建\n- **publish.yml** - NPM 发布工作流，在创建 Release 时自动发布到 NPM\n\n### 文档\n- **ACTIONS_SETUP.md** - GitHub Actions 详细配置指南\n\n## 🚀 快速开始\n\n1. 阅读 [ACTIONS_SETUP.md](./ACTIONS_SETUP.md) 了解如何配置\n2. 在 GitHub 仓库设置中添加 `NPM_TOKEN` secret\n3. 创建 Release 即可自动发布到 NPM\n\n## 📚 更多信息\n\n查看 [ACTIONS_SETUP.md](./ACTIONS_SETUP.md) 获取完整的配置指南和故障排查。\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [main, develop]\n  pull_request:\n    branches: [main, develop]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [20.x, 22.x]\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: 'npm'\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Build project\n        run: npm run build\n\n      - name: Check TypeScript types\n        run: npx tsc --noEmit\n\n      - name: Verify build output\n        run: |\n          if [ ! -d \"dist\" ]; then\n            echo \"❌ Build failed: dist directory not found\"\n            exit 1\n          fi\n          echo \"✅ Build successful\"\n\n      - name: Check package files\n        run: |\n          echo \"📦 Checking package contents...\"\n          npm pack --dry-run\n\n  lint:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          cache: 'npm'\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Check code formatting\n        run: |\n          echo \"✅ Code formatting check passed\"\n          # 如果有 prettier 或 eslint，可以在这里添加\n          # npm run lint\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish to NPM\n\non:\n  release:\n    types: [created]\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'Version to publish (leave empty to use package.json version)'\n        required: false\n        type: string\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: read\n      id-token: write\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          registry-url: 'https://registry.npmjs.org'\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Build project\n        run: npm run build\n\n      - name: Check package version\n        id: version\n        run: |\n          PACKAGE_VERSION=$(node -p \"require('./package.json').version\")\n          echo \"version=$PACKAGE_VERSION\" >> $GITHUB_OUTPUT\n          echo \"📦 Package version: $PACKAGE_VERSION\"\n\n      - name: Publish to NPM\n        run: npm publish --provenance --access public\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n      - name: Success notification\n        if: success()\n        run: |\n          echo \"✅ Successfully published version ${{ steps.version.outputs.version }} to NPM\"\n          echo \"📦 Package: https://www.npmjs.com/package/universal-db-mcp\"\n\n      - name: Failure notification\n        if: failure()\n        run: |\n          echo \"❌ Failed to publish to NPM\"\n          echo \"Please check the logs above for details\"\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\ndist/\n*.log\n.DS_Store\n.env\n*.tsbuildinfo\ncoverage/\n.vscode/\n.idea/\n"
  },
  {
    "path": ".npmignore",
    "content": "# 源代码文件（只发布编译后的 dist 目录）\nsrc/\n*.ts\n!*.d.ts\n\n# 开发文件\ntsconfig.json\n.claude/\n.vscode/\n.idea/\n\n# 测试文件\nsrc/test.ts\ndist/test.*\ntest.js\ntest.d.ts\n\n# Git 相关\n.git/\n.gitignore\n\n# 依赖\nnode_modules/\n\n# 日志\n*.log\nnpm-debug.log*\n\n# 临时文件\n*.tmp\n*.swp\n.DS_Store\n\n# 构建产物（保留 dist 目录）\n*.tsbuildinfo\n\n# 环境变量\n.env\n.env.local\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# 更新日志\n\n本文档记录 Universal DB MCP 的版本更新历史。\n\n## [2.14.0] - 2026\n\n### 新增\n- **MCP stdio 模式动态数据库连接** - 支持在对话中动态连接/切换数据库，无需写死配置\n  - **新增 3 个 MCP Tool**：\n    - `connect_database`：动态连接数据库，支持全部 17 种数据库类型，已有连接时自动断开旧连接\n    - `disconnect_database`：断开当前数据库连接\n    - `get_connection_status`：查看当前连接状态（类型、地址、权限模式、缓存状态）\n  - **`--type` 参数改为可选**：不指定则以无连接模式启动，等待 AI 通过 `connect_database` 动态连接\n  - **零配置启动**：`claude_desktop_config.json` 中只需 `\"args\": [\"universal-db-mcp\"]`，对话中告诉 AI 数据库信息即可\n  - **向后兼容**：传了 `--type` 参数的用户行为完全不变\n  - **影响范围**：仅 MCP stdio 模式，HTTP/SSE/Streamable HTTP 模式不受影响\n  - **改动文件**：`src/mcp/mcp-server.ts`、`src/mcp/mcp-index.ts`\n\n#### 用户使用指南\n\n**方式 A：零配置启动（新增能力）**\n\n在 `claude_desktop_config.json` 中无需指定数据库参数：\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\"universal-db-mcp\"]\n    }\n  }\n}\n```\n\n然后在对话中直接告诉 AI 数据库信息：\n- \"帮我连接 192.168.1.100 的 MySQL，用户名 root，密码 123456，数据库 order_db\"\n- \"切换到 10.0.0.5 的 PostgreSQL，端口 5432，数据库 analytics\"\n- \"断开当前数据库连接\"\n- \"当前连的是哪个库？\"\n\nAI 会自动调用 `connect_database`、`disconnect_database`、`get_connection_status` 工具。\n\n**方式 B：带默认连接启动（向后兼容，行为不变）**\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n启动时自动连接指定数据库，对话中仍可通过 `connect_database` 切换到其他数据库。\n\n## [2.13.0] - 2026\n\n### 修复\n\n- **stdio 进程优雅退出** - 修复 stdio MCP server 在客户端（如 Codex CLI）关闭会话后进程挂起的问题\n  - **问题表现**：Codex CLI 执行 `/exit` 后终端提示符不返回，必须手动 `Ctrl+C`\n  - **根因**：未监听 `process.stdin` 的 `end`/`close` 事件；`stop()` 方法未调用 `server.close()` 释放 transport 资源\n  - **修复方案**：\n    - `mcp-server.ts`：`stop()` 中新增 `server.close()` 调用，释放 stdin/stdout 监听器\n    - `mcp-index.ts`：新增统一 `gracefulShutdown()` 函数，监听 `SIGINT`/`SIGTERM`/`stdin end`/`stdin close`\n    - 防重入保护（`shuttingDown` 标志）+ 5 秒超时兜底\n  - **影响范围**：stdio 模式直接修复；SSE/Streamable HTTP 模式间接受益（`cleanupSession()` 调用的 `stop()` 现在正确关闭 MCP Server）\n\n## [2.12.0] - 2026\n\n### 修复\n- **多 Schema 支持** - 修复 8 个适配器只能获取默认 Schema 下的表信息的问题\n  - **影响的适配器**：PostgreSQL、GaussDB、KingbaseES、Vastbase、HighGo、SQL Server、Oracle、达梦\n  - **问题表现**：`get_schema`、`get_table_info`、`get_enum_values`、`get_sample_data` 只返回默认 Schema（如 PostgreSQL 的 `public`、SQL Server 的 `dbo`、Oracle/达梦的当前用户）下的表\n  - **修复方案**：\n    - 适配器 SQL 查询改为排除系统 Schema，自动发现所有用户 Schema\n    - 非默认 Schema 的表名使用 `schema.table_name` 格式（如 `analytics.events`）\n    - 默认 Schema 的表名保持不变，向后兼容\n    - `get_table_info` 等工具支持 `schema.table_name` 格式精确指定表\n  - **核心服务层**：`DatabaseService.getTableInfo()` 新增 3 级表名匹配（精确匹配 → Schema 拆分匹配 → 基础名唯一匹配）\n  - **标识符引用**：`quoteIdentifier()` 支持自动拆分 `schema.table` 格式并分别引用\n\n#### 用户视角的变化\n\n**如果只使用默认 Schema（public/dbo/当前用户），使用体验完全不变。** 以下变化仅体现在拥有多 Schema 的数据库上。\n\n**之前**：假设 PostgreSQL 数据库中有 `public.users`、`public.orders`、`analytics.events`、`analytics.page_views` 四张表，调用 `get_schema` 只能看到 `users` 和 `orders`，`analytics` 下的表完全不可见。\n\n**现在**：调用 `get_schema` 可以看到全部四张表：`users`、`orders`、`analytics.events`、`analytics.page_views`。\n\n| 变化点 | 之前 | 现在 |\n|--------|------|------|\n| `get_schema` 返回的表 | 只有默认 Schema 的表 | 所有用户 Schema 的表 |\n| 非默认 Schema 表的命名 | 不可见 | `schema.table_name` 格式（如 `analytics.events`） |\n| 默认 Schema 表的命名 | `users` | `users`（不变） |\n| 查询非默认 Schema 的表 | 不支持 | 使用 `schema.table_name` 格式即可（如 `analytics.events`） |\n\n**新增能力**：\n- \"查看 `analytics.events` 表的结构\" → `get_table_info(\"analytics.events\")`\n- \"查看 `analytics.events` 表 `event_type` 列有哪些值\" → `get_enum_values(\"analytics.events\", \"event_type\")`\n- \"查看 `analytics.events` 表的示例数据\" → `get_sample_data(\"analytics.events\")`\n\n**无需任何配置变更**：不需要修改启动参数、配置文件或学习新工具，升级后自动生效。\n\n## [2.11.0] - 2026\n\n### 改进\n- **连接稳定性增强** - 全面升级数据库连接管理，彻底解决 `Can't add new command when connection is in closed state` 错误\n  - **连接池化** - 12 个网络数据库适配器从单连接升级为连接池\n    - MySQL 系列（MySQL、TiDB、OceanBase、PolarDB、GoldenDB）：使用 `mysql2` 连接池，配置 `enableKeepAlive` + `connectionLimit: 3`\n    - PostgreSQL 系列（PostgreSQL、KingbaseES、GaussDB、Vastbase、HighGo）：使用 `pg.Pool`，配置 `keepAlive` + `max: 3`\n    - Oracle：使用 `oracledb.createPool()`，配置 `poolPingInterval: 30`\n  - **心跳保活** - 达梦适配器使用定时心跳（30 秒间隔）保持连接活跃\n  - **断线自动重试** - 所有网络数据库适配器新增 `withRetry` 机制，连接断开后自动重试一次\n  - **TCP Keep-Alive** - 所有连接池启用 TCP Keep-Alive，防止连接被服务端或中间件超时关闭\n- 不需要修改的适配器（已有内置机制）：SQL Server（连接池）、Redis（自动重连）、MongoDB（内置连接池）、SQLite（本地文件）、ClickHouse（HTTP 协议）\n\n## [2.10.0] - 2026\n\n### 新增\n- **细粒度权限控制** - 支持自定义操作权限组合，不再只有\"只读\"和\"完全写入\"两种模式\n  - **权限模式** - 新增 `--permission-mode` 参数\n    - `safe`（默认）：只读模式，仅允许 SELECT\n    - `readwrite`：读写模式，允许 SELECT/INSERT/UPDATE，禁止 DELETE 和 DDL\n    - `full`：完全控制，等价于原来的 `--danger-allow-write`\n    - `custom`：自定义模式，配合 `--permissions` 使用\n  - **自定义权限** - 新增 `--permissions` 参数，支持逗号分隔的权限列表\n    - `read`：SELECT 查询（始终包含）\n    - `insert`：INSERT, REPLACE\n    - `update`：UPDATE\n    - `delete`：DELETE, TRUNCATE\n    - `ddl`：CREATE, ALTER, DROP, RENAME\n  - **向后兼容** - `--danger-allow-write` 仍然有效，等价于 `--permission-mode=full`\n  - **HTTP API 支持** - REST API 和 MCP SSE/Streamable HTTP 端点同样支持新权限参数\n\n### 改进\n- 更新 `DbConfig` 类型，新增 `permissionMode` 和 `permissions` 字段\n- 重构 `safety.ts`，支持细粒度权限检查\n- 更新命令行帮助信息，添加新参数说明\n- 更新 README 文档（中英文），添加权限模式说明\n\n### 文档\n- **完善权限配置文档** - 添加不同传输方式的权限参数命名说明\n  - STDIO 模式（Claude Desktop）：使用连字符命名 `--permission-mode`、`--permissions`\n  - SSE 模式（Dify 等）：使用驼峰命名 `permissionMode`、`permissions`（URL Query）\n  - Streamable HTTP 模式：使用连字符命名 `X-DB-Permission-Mode`、`X-DB-Permissions`（HTTP Header）\n  - REST API 模式：使用驼峰命名 `permissionMode`、`permissions`（JSON Body）\n- 更新以下文档：\n  - `docs/getting-started/configuration.md` - 添加传输方式权限配置汇总表\n  - `docs/guides/security.md` - 添加各传输方式的权限配置示例\n  - `docs/http-api/API_REFERENCE.md` / `API_REFERENCE.zh-CN.md` - 添加权限参数说明\n  - `docs/integrations/DIFY.md` / `DIFY.zh-CN.md` - 添加 SSE 和 Streamable HTTP 权限参数\n  - `docs/integrations/CLAUDE-DESKTOP.md` / `CLAUDE-DESKTOP.zh-CN.md` - 添加参数命名提示\n  - `docs/integrations/COZE.md` / `COZE.zh-CN.md` - 添加 REST API 权限参数\n  - `README.md` / `README.zh-CN.md` - 添加传输方式权限配置汇总表\n\n## [2.9.0] - 2026\n\n### 新增\n- **按需增强工具** - 新增两个 MCP 工具，帮助 LLM 更好地理解数据内容\n  - **`get_enum_values`** - 获取指定列的所有唯一值\n    - 适用于枚举类型列、状态列等有限值集合\n    - 支持 limit 参数控制返回数量\n    - 返回值包含 `isComplete` 标识是否返回了全部值\n  - **`get_sample_data`** - 获取表的示例数据\n    - 自动数据脱敏，保护敏感信息（手机号、邮箱、身份证、银行卡等）\n    - 支持按列名模式匹配和按值格式自动检测两种脱敏方式\n    - 可通过 `masking` 参数控制是否启用脱敏\n- **数据脱敏工具** - 新增 `DataMasker` 工具类（`src/utils/data-masking.ts`）\n  - 支持 7 种脱敏类型：phone、email、idcard、bankcard、password、partial、full\n  - 支持自定义脱敏规则\n  - 自动检测敏感数据格式\n- **REST API 端点** - 新增两个 HTTP API 端点\n  - `GET /api/enum-values` - 获取枚举值\n  - `GET /api/sample-data` - 获取示例数据\n\n### 改进\n- 新增 `EnumValuesResult` 和 `SampleDataResult` 类型定义\n- 更新 API 参考文档（中英文），添加新端点说明\n- 新增 20 个数据脱敏单元测试\n\n## [2.8.0] - 2026\n\n### 新增\n- **Schema 核心增强** - 提升 LLM 对数据库结构的理解，提高 Text2SQL 准确性\n  - **表注释支持** - Schema 信息现在包含表级别注释（`comment` 字段）\n    - 支持的数据库：MySQL、PostgreSQL、Oracle、SQL Server、TiDB、达梦、KingbaseES、GaussDB、OceanBase、PolarDB、Vastbase、HighGo、GoldenDB、ClickHouse（14个）\n    - 不支持：Redis、MongoDB（NoSQL）、SQLite（无原生表注释）\n  - **隐式关系推断** - 基于列命名规则自动推断表间关系\n    - 支持模式：`xxx_id` → `xxxs.id`、`xxxId` → `xxxs.id`（驼峰）、`xxx_code` → `xxxs.code`、`xxx_no` → `xxxs.xxx_no`\n    - 推断规则：不覆盖显式外键、验证目标表存在、验证目标列存在\n    - 置信度评分：0.7-0.95，LLM 可根据置信度判断关系可靠性\n  - **关系类型细化** - 通过检查唯一约束区分 `one-to-one` 和 `many-to-one`\n  - **关系来源标注** - `source` 字段区分 `foreign_key`（显式外键）和 `inferred`（推断关系）\n\n### 改进\n- 新增 `SchemaEnhancer` 工具类（`src/utils/schema-enhancer.ts`）\n- 更新 `RelationshipInfo` 类型，添加 `source` 和 `confidence` 字段\n- 更新 `TableInfo` 类型，添加 `comment` 字段\n- 更新 14 个数据库适配器，添加表注释查询支持\n\n## [2.7.0] - 2026\n\n### 新增\n- **外键关系支持** - Schema 信息现在包含外键和表关系数据，帮助 LLM 更好地理解数据库结构\n  - `foreignKeys` - 表级别外键约束信息，包含约束名、列、引用表、引用列、ON DELETE/UPDATE 规则\n  - `relationships` - 全局关系视图，展示所有表之间的关联关系\n  - 支持的数据库：MySQL、PostgreSQL、Oracle、SQL Server、SQLite、达梦、KingbaseES、GaussDB、OceanBase、TiDB、PolarDB、Vastbase、HighGo、GoldenDB\n  - NoSQL 数据库（Redis、MongoDB、ClickHouse）不支持传统外键，返回结果中不包含这些字段\n\n### 改进\n- 更新 API 参考文档（中英文），添加外键和关系字段的示例\n- 更新数据库功能支持表，添加\"外键关系\"功能行\n\n## [2.6.0] - 2026\n\n### 新增\n- **MCP SSE/Streamable HTTP 传输支持** - 在 HTTP 模式下新增 MCP 协议端点\n  - `/sse` - SSE 传输端点（传统方式），支持通过 URL 参数配置数据库连接\n  - `/sse/message` - SSE 消息接收端点\n  - `/mcp` (POST) - Streamable HTTP 端点（MCP 2025 规范，推荐），支持通过请求头配置数据库连接\n  - `/mcp` (GET) - Streamable HTTP 的 SSE 流端点\n  - `/mcp` (DELETE) - 关闭会话端点\n- Dify 等平台现在可以直接通过 MCP 协议连接，无需使用自定义 API 工具\n- 灵活架构：2 种启动模式（stdio/http），4 种接入方式（MCP stdio、MCP SSE、MCP Streamable HTTP、REST API）\n- **统一 API Key 认证** - MCP SSE/Streamable HTTP 端点现在也支持 API Key 认证，与 REST API 保持一致\n\n### 改进\n- 更新架构文档，清晰区分启动模式和接入方式\n- 更新 Dify 集成指南，添加 MCP 协议集成方式（SSE 和 Streamable HTTP）\n- 更新 API 参考文档，添加 MCP 协议端点说明\n\n### 安全\n- 所有 HTTP 端点（包括 MCP SSE/Streamable HTTP）现在统一使用 API Key 认证\n- 如果未配置 `API_KEYS` 环境变量，则跳过认证（开发模式）\n\n## [2.5.0] - 2026\n\n### 新增\n- Oracle 11g 及以前老版本支持（通过 Thick 模式）\n\n## [2.3.8] - 2026\n\n### 修复\n- Oracle、达梦执行 SQL 去掉分号\n\n## [2.3.7] - 2026\n\n### 修复\n- 达梦 get_schema 问题修复\n\n## [2.3.6] - 2026\n\n### 修复\n- 达梦 get_schema 问题修复\n\n## [2.3.5] - 2026\n\n### 修复\n- 达梦 get_schema 问题修复\n\n## [2.3.4] - 2026\n\n### 修复\n- 达梦 get_schema 问题修复\n\n## [2.3.3] - 2026\n\n### 修复\n- 达梦 get_schema 问题，达梦不使用批量查询优化功能\n\n## [2.3.2] - 2026\n\n### 修复\n- 达梦 get_schema 返回 table 为空问题处理\n\n## [2.3.1] - 2026\n\n### 修复\n- 达梦适配器修复列名规范化、空值检查、类型安全\n\n## [2.3.0] - 2026\n\n### 性能优化\n- 为 Oracle、达梦增加批量查询优化功能\n\n## [2.2.0] - 2026\n\n### 性能优化\n- 批量查询优化，大幅提升 Schema 获取性能\n- 支持的数据库：MySQL、PostgreSQL、SQL Server、Oracle、达梦等 13 个适配器\n\n### 性能提升\n| 表数量 | 优化前 | 优化后 | 提升 |\n|--------|--------|--------|------|\n| 50 张表 | ~5 秒 | ~200 毫秒 | 25x |\n| 100 张表 | ~10 秒 | ~300 毫秒 | 33x |\n| 500 张表 | ~50 秒 | ~500 毫秒 | 100x |\n\n## [2.1.0] - 2026\n\n### 新增\n- Schema 缓存机制\n- 缓存 TTL 配置\n- 强制刷新功能\n- 缓存统计信息\n\n## [2.0.0] - 2026\n\n### 新增\n- HTTP API 模式\n- 双模式架构（MCP + HTTP）\n- API Key 认证\n- 速率限制\n- CORS 配置\n- Docker 部署支持\n- Serverless 部署配置（阿里云、腾讯云、AWS、Vercel）\n- PaaS 部署配置（Railway、Render、Fly.io）\n\n### 文档\n- HTTP API 参考文档\n- 部署指南\n- 集成指南（Coze、n8n、Dify）\n\n## [1.0.0] - 2026\n\n### 新增\n- 支持 17 种数据库\n  - MySQL、PostgreSQL、Redis、Oracle、SQL Server\n  - MongoDB、SQLite、达梦、KingbaseES、GaussDB\n  - OceanBase、TiDB、ClickHouse、PolarDB\n  - Vastbase、HighGo、GoldenDB\n- MCP 协议支持\n- 只读安全模式\n- Claude Desktop 集成\n\n---\n\n## 版本号说明\n\n本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)：\n\n- **主版本号**：不兼容的 API 修改\n- **次版本号**：向下兼容的功能性新增\n- **修订号**：向下兼容的问题修正\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# 贡献指南\n\n感谢你对 MCP 数据库万能连接器的关注！我们欢迎所有形式的贡献。\n\n## 🤝 如何贡献\n\n### 报告 Bug\n\n如果你发现了 Bug，请在 [GitHub Issues](https://github.com/yourusername/universal-db-mcp/issues) 中提交，并包含：\n\n- 详细的问题描述\n- 复现步骤\n- 预期行为 vs 实际行为\n- 环境信息（操作系统、Node.js 版本、数据库版本）\n\n### 提交功能建议\n\n我们欢迎新功能建议！请先在 Issues 中讨论，确保该功能符合项目方向。\n\n### 提交代码\n\n1. **Fork 本仓库**\n2. **创建特性分支**: `git checkout -b feature/amazing-feature`\n3. **编写代码**: 遵循下面的代码规范\n4. **提交更改**: `git commit -m '添加某某功能'`\n5. **推送分支**: `git push origin feature/amazing-feature`\n6. **创建 Pull Request**\n\n## 📝 代码规范\n\n- 使用 TypeScript 严格模式\n- 关键架构决策需要添加中文注释\n- 用户可见的消息必须使用简体中文\n- 遵循现有的代码风格\n\n## 🔌 添加新数据库支持\n\n如果你想添加新的数据库支持（如 MongoDB、SQLite），请按以下步骤：\n\n1. 在 `src/adapters/` 下创建新文件（如 `mongodb.ts`）\n2. 实现 `DbAdapter` 接口\n3. 在 `src/index.ts` 中添加对应的 case 分支\n4. 在 `src/types/adapter.ts` 中更新类型定义\n5. 更新 `README.md` 的支持列表\n6. 添加相应的 npm 依赖\n\n### 参考示例\n\n可以参考现有的适配器实现：\n- **MySQL** (`src/adapters/mysql.ts`) - SQL 数据库的基础模式\n- **PostgreSQL** (`src/adapters/postgres.ts`) - 复杂的 Schema 查询\n- **Redis** (`src/adapters/redis.ts`) - NoSQL 数据库的适配\n- **Oracle** (`src/adapters/oracle.ts`) - 企业级数据库的完整实现\n- **达梦** (`src/adapters/dm.ts`) - 国产数据库适配，兼容 Oracle\n- **SQL Server** (`src/adapters/sqlserver.ts`) - 微软数据库，支持 Azure SQL\n- **MongoDB** (`src/adapters/mongodb.ts`) - 文档型 NoSQL 数据库\n- **SQLite** (`src/adapters/sqlite.ts`) - 轻量级嵌入式数据库\n- **KingbaseES** (`src/adapters/kingbase.ts`) - 国产数据库，兼容 PostgreSQL\n- **GaussDB** (`src/adapters/gaussdb.ts`) - 华为国产数据库，兼容 PostgreSQL\n- **OceanBase** (`src/adapters/oceanbase.ts`) - 分布式数据库，兼容 MySQL\n- **TiDB** (`src/adapters/tidb.ts`) - 分布式 NewSQL 数据库，兼容 MySQL 5.7\n- **ClickHouse** (`src/adapters/clickhouse.ts`) - 列式 OLAP 数据库，使用 HTTP 协议\n- **PolarDB** (`src/adapters/polardb.ts`) - 云原生数据库，兼容 MySQL\n- **Vastbase** (`src/adapters/vastbase.ts`) - 国产数据库，兼容 PostgreSQL\n- **HighGo** (`src/adapters/highgo.ts`) - 国产数据库，兼容 PostgreSQL\n- **GoldenDB** (`src/adapters/goldendb.ts`) - 国产分布式数据库，兼容 MySQL\n\n### 示例结构\n\n```typescript\n// src/adapters/mongodb.ts\nimport type { DbAdapter, QueryResult, SchemaInfo } from '../types/adapter.js';\n\nexport class MongoDBAdapter implements DbAdapter {\n  async connect(): Promise<void> {\n    // 实现连接逻辑\n  }\n\n  async disconnect(): Promise<void> {\n    // 实现断开连接逻辑\n  }\n\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    // 实现查询逻辑\n  }\n\n  async getSchema(): Promise<SchemaInfo> {\n    // 实现获取结构逻辑\n  }\n\n  isWriteOperation(query: string): boolean {\n    // 实现写操作检测\n  }\n}\n```\n\n## ✅ 提交前检查清单\n\n- [ ] 代码通过 TypeScript 编译 (`npm run build`)\n- [ ] 关键逻辑添加了中文注释\n- [ ] 用户可见消息使用简体中文\n- [ ] 更新了相关文档\n- [ ] 测试了基本功能\n\n## 📄 许可证\n\n提交代码即表示你同意将代码以 MIT 许可证开源。\n\n## 💬 联系方式\n\n如有疑问，欢迎在 Issues 中讨论或联系维护者。\n\n---\n\n再次感谢你的贡献！🎉\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2026 Universal DB MCP Contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"assets/logo.png\" alt=\"Universal DB MCP Logo\" width=\"200\">\n</p>\n\n<h1 align=\"center\">Universal DB MCP</h1>\n\n<p align=\"center\">\n  <strong>Connect AI to Your Database with Natural Language</strong>\n</p>\n\n<p align=\"center\">\n  A universal database connector implementing the Model Context Protocol (MCP) and HTTP API, enabling AI assistants to query and analyze your databases using natural language. Works with Claude Desktop, Cursor, Windsurf, VS Code, ChatGPT, and 50+ other platforms.\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/universal-db-mcp\"><img src=\"https://img.shields.io/npm/v/universal-db-mcp.svg?style=flat-square&color=blue\" alt=\"npm version\"></a>\n  <a href=\"https://www.npmjs.com/package/universal-db-mcp\"><img src=\"https://img.shields.io/npm/dm/universal-db-mcp.svg?style=flat-square&color=green\" alt=\"npm downloads\"></a>\n  <a href=\"https://opensource.org/licenses/MIT\"><img src=\"https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square\" alt=\"License: MIT\"></a>\n  <a href=\"https://nodejs.org/\"><img src=\"https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen?style=flat-square\" alt=\"Node.js Version\"></a>\n  <a href=\"https://github.com/Anarkh-Lee/universal-db-mcp/stargazers\"><img src=\"https://img.shields.io/github/stars/Anarkh-Lee/universal-db-mcp?style=flat-square\" alt=\"GitHub Stars\"></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"#-features\">Features</a> •\n  <a href=\"#-quick-start\">Quick Start</a> •\n  <a href=\"#-supported-databases\">Databases</a> •\n  <a href=\"#-documentation\">Docs</a> •\n  <a href=\"#-contributing\">Contributing</a>\n</p>\n\n<p align=\"center\">\n  <a href=\"./README.md\">English</a> | <a href=\"./README.zh-CN.md\">中文文档</a>\n</p>\n\n---\n\n## Why Universal DB MCP?\n\nImagine asking your AI assistant: *\"Show me the top 10 customers by order value this month\"* and getting instant results from your database - no SQL writing required. Universal DB MCP makes this possible by bridging AI assistants with your databases through the Model Context Protocol (MCP) and HTTP API.\n\n```\nYou: \"What's the average order value for users who signed up in the last 30 days?\"\n\nAI: Let me query that for you...\n\n┌─────────────────────────────────────┐\n│ Average Order Value: $127.45        │\n│ Total New Users: 1,247              │\n│ Users with Orders: 892 (71.5%)      │\n└─────────────────────────────────────┘\n```\n\n## ✨ Features\n\n- **17 Database Support** - MySQL, PostgreSQL, Redis, Oracle, SQL Server, MongoDB, SQLite, and 10 Chinese domestic databases\n- **55+ Platform Integrations** - Works with Claude Desktop, Cursor, VS Code, ChatGPT, Dify, and [50+ other platforms](#-supported-platforms)\n- **Flexible Architecture** - 2 startup modes (stdio/http) with 4 access methods: MCP stdio, MCP SSE, MCP Streamable HTTP, and REST API\n- **Security First** - Read-only mode by default prevents accidental data modifications\n- **Intelligent Caching** - Schema caching with configurable TTL for blazing-fast performance\n- **Batch Query Optimization** - Up to 100x faster schema retrieval for large databases\n- **Schema Enhancement** - Table comments, implicit relationship inference for better Text2SQL accuracy\n- **Multi-Schema Support** - Automatic discovery of all user schemas (PostgreSQL, SQL Server, Oracle, DM, and more)\n- **Data Masking** - Automatic sensitive data protection (phone, email, ID card, bank card, etc.)\n- **Connection Stability** - Connection pooling, TCP Keep-Alive, and automatic reconnection for long-running sessions\n\n### Performance Improvements\n\n| Tables | Before | After | Improvement |\n|--------|--------|-------|-------------|\n| 50 tables | ~5s | ~200ms | **25x faster** |\n| 100 tables | ~10s | ~300ms | **33x faster** |\n| 500 tables | ~50s | ~500ms | **100x faster** |\n\n## 🚀 Quick Start\n\n### Installation\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n### MCP Mode (Claude Desktop)\n\nAdd to your Claude Desktop configuration file:\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\nRestart Claude Desktop and start asking questions:\n\n- *\"Show me the structure of the users table\"*\n- *\"Count orders from the last 7 days\"*\n- *\"Find the top 5 products by sales\"*\n\n### HTTP API Mode\n\n```bash\n# Set environment variables\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key\n\n# Start the server\nnpx universal-db-mcp\n```\n\n```bash\n# Test the API\ncurl http://localhost:3000/api/health\n```\n\n### MCP SSE Mode (Dify and Remote Access)\n\nWhen running in HTTP mode, the server also exposes MCP protocol endpoints via SSE (Server-Sent Events) and Streamable HTTP. This allows platforms like Dify to connect using the MCP protocol directly.\n\n**SSE Endpoint (Legacy):**\n```\nGET http://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=xxx&database=mydb\n```\n\n**Streamable HTTP Endpoint (MCP 2025 Spec, Recommended):**\n```\nPOST http://localhost:3000/mcp\nHeaders:\n  X-DB-Type: mysql\n  X-DB-Host: localhost\n  X-DB-Port: 3306\n  X-DB-User: root\n  X-DB-Password: your_password\n  X-DB-Database: your_database\nBody: MCP JSON-RPC request\n```\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/sse` | GET | Establish SSE connection (legacy) |\n| `/sse/message` | POST | Send message to SSE session |\n| `/mcp` | POST | Streamable HTTP endpoint (recommended) |\n| `/mcp` | GET | SSE stream for Streamable HTTP |\n| `/mcp` | DELETE | Close session |\n\nSee [Dify Integration Guide](./docs/integrations/DIFY.md) for detailed setup instructions.\n\n## 📊 Supported Databases\n\n| Database | Type | Default Port | Category |\n|----------|------|--------------|----------|\n| MySQL | `mysql` | 3306 | Open Source |\n| PostgreSQL | `postgres` | 5432 | Open Source |\n| Redis | `redis` | 6379 | NoSQL |\n| Oracle | `oracle` | 1521 | Commercial |\n| SQL Server | `sqlserver` | 1433 | Commercial |\n| MongoDB | `mongodb` | 27017 | NoSQL |\n| SQLite | `sqlite` | - | Embedded |\n| Dameng (达梦) | `dm` | 5236 | Chinese |\n| KingbaseES | `kingbase` | 54321 | Chinese |\n| GaussDB | `gaussdb` | 5432 | Chinese (Huawei) |\n| OceanBase | `oceanbase` | 2881 | Chinese (Ant) |\n| TiDB | `tidb` | 4000 | Distributed |\n| ClickHouse | `clickhouse` | 8123 | OLAP |\n| PolarDB | `polardb` | 3306 | Cloud (Alibaba) |\n| Vastbase | `vastbase` | 5432 | Chinese |\n| HighGo | `highgo` | 5866 | Chinese |\n| GoldenDB | `goldendb` | 3306 | Chinese (ZTE) |\n\n## 🏗️ Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         Universal DB MCP                                 │\n├─────────────────────────────────────────────────────────────────────────┤\n│                                                                          │\n│  Startup Modes:                                                          │\n│  ┌────────────────────────────┬────────────────────────────────────┐    │\n│  │ stdio mode                 │ http mode                          │    │\n│  │ (npm run start:mcp)        │ (npm run start:http)               │    │\n│  └─────────────┬──────────────┴───────────────┬────────────────────┘    │\n│                │                              │                          │\n│                ▼                              ▼                          │\n│  ┌─────────────────────────┐    ┌───────────────────────────────────┐   │\n│  │      MCP Protocol       │    │           HTTP Server             │   │\n│  │    (stdio transport)    │    │                                   │   │\n│  │                         │    │  ┌─────────────────────────────┐  │   │\n│  │  Tools:                 │    │  │      MCP Protocol           │  │   │\n│  │  • execute_query        │    │  │  (SSE / Streamable HTTP)    │  │   │\n│  │  • get_schema           │    │  │                             │  │   │\n│  │  • get_table_info       │    │  │  Tools: (same as stdio)     │  │   │\n│  │  • clear_cache          │    │  │  • execute_query            │  │   │\n│  │  • get_enum_values      │    │  │  • get_schema               │  │   │\n│  │  • get_sample_data      │    │  │  • get_table_info           │  │   │\n│  │  • connect_database     │    │  │  • clear_cache              │  │   │\n│  │  • disconnect_database  │    │  │  • get_enum_values          │  │   │\n│  │  • get_connection_status│    │  │  • get_sample_data          │  │   │\n│  │                         │    │  │  • connect_database         │  │   │\n│  │  For: Claude Desktop,   │    │  │  • disconnect_database      │  │   │\n│  │       Cursor, etc.      │    │  │  • get_connection_status    │  │   │\n│  └─────────────┬───────────┘    │  │                             │  │   │\n│                │                │  │  For: Dify, Remote Access   │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                │                 │                 │   │\n│                │                │  ┌──────────────┴──────────────┐  │   │\n│                │                │  │        REST API             │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  Endpoints:                 │  │   │\n│                │                │  │  • /api/connect             │  │   │\n│                │                │  │  • /api/query               │  │   │\n│                │                │  │  • /api/schema              │  │   │\n│                │                │  │  • ... (10+ endpoints)      │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  For: Coze, n8n, Custom     │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                └─────────────────┼─────────────────┘   │\n│                │                                  │                     │\n│                └──────────────────┬───────────────┘                     │\n│                                   ▼                                     │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                     Core Business Logic                           │  │\n│  │  • Query Execution    • Schema Caching                           │  │\n│  │  • Safety Validation  • Connection Management                    │  │\n│  └──────────────────────────────────┬───────────────────────────────┘  │\n│                                     ▼                                   │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                    Database Adapter Layer                         │  │\n│  │  MySQL │ PostgreSQL │ Redis │ Oracle │ MongoDB │ SQLite │ ...    │  │\n│  │        (Connection Pool + TCP Keep-Alive + Auto-Retry)           │  │\n│  └──────────────────────────────────────────────────────────────────┘  │\n│                                                                          │\n└─────────────────────────────────────────────────────────────────────────┘\n```\n\n## 🔒 Security\n\nBy default, Universal DB MCP runs in **read-only mode**, blocking all write operations (INSERT, UPDATE, DELETE, DROP, etc.).\n\n### Permission Modes\n\nFine-grained permission control is supported for flexible configuration:\n\n| Mode | Allowed Operations | Description |\n|------|-------------------|-------------|\n| `safe` (default) | SELECT | Read-only, safest |\n| `readwrite` | SELECT, INSERT, UPDATE | Read/write but no delete |\n| `full` | All operations | Full control (dangerous!) |\n| `custom` | Custom combination | Specify via `--permissions` |\n\n**Permission Types:**\n- `read` - SELECT queries (always included)\n- `insert` - INSERT, REPLACE\n- `update` - UPDATE\n- `delete` - DELETE, TRUNCATE\n- `ddl` - CREATE, ALTER, DROP, RENAME\n\n**Usage Examples:**\n\n```bash\n# Read-only mode (default)\nnpx universal-db-mcp --type mysql ...\n\n# Read/write but no delete\nnpx universal-db-mcp --type mysql --permission-mode readwrite ...\n\n# Custom: only read and insert\nnpx universal-db-mcp --type mysql --permissions read,insert ...\n\n# Full control (equivalent to --danger-allow-write)\nnpx universal-db-mcp --type mysql --permission-mode full ...\n```\n\n**Permission Configuration by Transport:**\n\n> ⚠️ Different transports use different parameter naming conventions!\n\n| Transport | Parameter Location | Permission Mode | Custom Permissions |\n|-----------|-------------------|-----------------|-------------------|\n| STDIO (Claude Desktop) | CLI args | `--permission-mode` | `--permissions` |\n| SSE (Dify, etc.) | URL Query | `permissionMode` | `permissions` |\n| Streamable HTTP | HTTP Header | `X-DB-Permission-Mode` | `X-DB-Permissions` |\n| REST API | JSON Body | `permissionMode` | `permissions` |\n\n**Best Practices:**\n- Never enable write mode in production\n- Use dedicated read-only database accounts\n- Connect through VPN or bastion hosts\n- Regularly audit query logs\n\n## 🔌 Supported Platforms\n\nUniversal DB MCP works with any platform that supports the MCP protocol or REST API. Here's a comprehensive list:\n\n### AI-Powered Code Editors & IDEs\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Cursor](https://cursor.sh/) | MCP stdio | AI-powered code editor with built-in MCP support | [EN](./docs/integrations/CURSOR.md) / [中文](./docs/integrations/CURSOR.zh-CN.md) |\n| [Windsurf](https://codeium.com/windsurf) | MCP stdio | Codeium's AI IDE with Cascade agent | [EN](./docs/integrations/WINDSURF.md) / [中文](./docs/integrations/WINDSURF.zh-CN.md) |\n| [VS Code](https://code.visualstudio.com/) | MCP stdio / REST API | Via GitHub Copilot agent mode or Cline/Continue extensions | [EN](./docs/integrations/VSCODE.md) / [中文](./docs/integrations/VSCODE.zh-CN.md) |\n| [Zed](https://zed.dev/) | MCP stdio | High-performance open-source code editor | [EN](./docs/integrations/ZED.md) / [中文](./docs/integrations/ZED.zh-CN.md) |\n| [IntelliJ IDEA](https://www.jetbrains.com/idea/) | MCP stdio | JetBrains IDE with MCP support (2025.1+) | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [PyCharm](https://www.jetbrains.com/pycharm/) | MCP stdio | JetBrains Python IDE | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [WebStorm](https://www.jetbrains.com/webstorm/) | MCP stdio | JetBrains JavaScript IDE | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [Android Studio](https://developer.android.com/studio) | MCP stdio | Via JetBrains MCP plugin | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [Neovim](https://neovim.io/) | MCP stdio | Via MCPHub.nvim plugin | [EN](./docs/integrations/NEOVIM.md) / [中文](./docs/integrations/NEOVIM.zh-CN.md) |\n| [Emacs](https://www.gnu.org/software/emacs/) | MCP stdio | Via mcp.el package | [EN](./docs/integrations/EMACS.md) / [中文](./docs/integrations/EMACS.zh-CN.md) |\n\n### AI Coding Assistants\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Claude Code](https://claude.ai/code) | MCP stdio | Anthropic's agentic coding tool | [EN](./docs/integrations/CLAUDE-CODE.md) / [中文](./docs/integrations/CLAUDE-CODE.zh-CN.md) |\n| [GitHub Copilot](https://github.com/features/copilot) | MCP stdio | Agent mode in VS Code/JetBrains | [EN](./docs/integrations/GITHUB-COPILOT.md) / [中文](./docs/integrations/GITHUB-COPILOT.zh-CN.md) |\n| [Cline](https://github.com/cline/cline) | MCP stdio / REST API | Autonomous coding agent for VS Code | [EN](./docs/integrations/CLINE.md) / [中文](./docs/integrations/CLINE.zh-CN.md) |\n| [Continue](https://continue.dev/) | MCP stdio | Open-source AI code assistant | [EN](./docs/integrations/CONTINUE.md) / [中文](./docs/integrations/CONTINUE.zh-CN.md) |\n| [Roo Code](https://github.com/roovet/roo-code) | MCP stdio | Fork of Cline for VS Code | [EN](./docs/integrations/ROO-CODE.md) / [中文](./docs/integrations/ROO-CODE.zh-CN.md) |\n| [Sourcegraph Cody](https://sourcegraph.com/cody) | MCP stdio | AI coding assistant | [EN](./docs/integrations/SOURCEGRAPH-CODY.md) / [中文](./docs/integrations/SOURCEGRAPH-CODY.zh-CN.md) |\n| [Amazon Q Developer](https://aws.amazon.com/q/developer/) | MCP stdio | AWS AI coding assistant | [EN](./docs/integrations/AMAZON-Q-DEVELOPER.md) / [中文](./docs/integrations/AMAZON-Q-DEVELOPER.zh-CN.md) |\n| [Devin](https://devin.ai/) | MCP stdio | AI software engineer | [EN](./docs/integrations/DEVIN.md) / [中文](./docs/integrations/DEVIN.zh-CN.md) |\n| [Goose](https://github.com/block/goose) | MCP stdio | Block's AI coding agent | [EN](./docs/integrations/GOOSE.md) / [中文](./docs/integrations/GOOSE.zh-CN.md) |\n| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | MCP stdio | Google's command-line AI tool | [EN](./docs/integrations/GEMINI-CLI.md) / [中文](./docs/integrations/GEMINI-CLI.zh-CN.md) |\n\n### Desktop AI Chat Applications\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Claude Desktop](https://claude.ai/download) | MCP stdio | Anthropic's official desktop app | [EN](./docs/integrations/CLAUDE-DESKTOP.md) / [中文](./docs/integrations/CLAUDE-DESKTOP.zh-CN.md) |\n| [ChatGPT Desktop](https://openai.com/chatgpt/desktop/) | MCP SSE/Streamable HTTP | OpenAI's desktop app with MCP connectors | [EN](./docs/integrations/CHATGPT.md) / [中文](./docs/integrations/CHATGPT.zh-CN.md) |\n| [Cherry Studio](https://github.com/kangfenmao/cherry-studio) | MCP stdio | Multi-model desktop chat app | [EN](./docs/integrations/CHERRY-STUDIO.md) / [中文](./docs/integrations/CHERRY-STUDIO.zh-CN.md) |\n| [LM Studio](https://lmstudio.ai/) | MCP stdio | Run local LLMs with MCP support | [EN](./docs/integrations/LM-STUDIO.md) / [中文](./docs/integrations/LM-STUDIO.zh-CN.md) |\n| [Jan](https://jan.ai/) | MCP stdio | Open-source ChatGPT alternative | [EN](./docs/integrations/JAN.md) / [中文](./docs/integrations/JAN.zh-CN.md) |\n| [Msty](https://msty.app/) | MCP stdio | Desktop AI chat application | [EN](./docs/integrations/MSTY.md) / [中文](./docs/integrations/MSTY.zh-CN.md) |\n| [LibreChat](https://github.com/danny-avila/LibreChat) | MCP stdio | Open-source chat interface | [EN](./docs/integrations/LIBRECHAT.md) / [中文](./docs/integrations/LIBRECHAT.zh-CN.md) |\n| [Witsy](https://witsy.app/) | MCP stdio | Desktop AI assistant | [EN](./docs/integrations/WITSY.md) / [中文](./docs/integrations/WITSY.zh-CN.md) |\n| [5ire](https://github.com/5ire-tech/5ire) | MCP stdio | Cross-platform AI chat | [EN](./docs/integrations/5IRE.md) / [中文](./docs/integrations/5IRE.zh-CN.md) |\n| [ChatMCP](https://github.com/daodao97/chatmcp) | MCP stdio | MCP-focused chat UI | [EN](./docs/integrations/CHATMCP.md) / [中文](./docs/integrations/CHATMCP.zh-CN.md) |\n| [HyperChat](https://github.com/BigSweetPotatoStudio/HyperChat) | MCP stdio | Multi-platform chat app | [EN](./docs/integrations/HYPERCHAT.md) / [中文](./docs/integrations/HYPERCHAT.zh-CN.md) |\n| [Tome](https://github.com/runebook/tome) | MCP stdio | macOS app for local LLMs | [EN](./docs/integrations/TOME.md) / [中文](./docs/integrations/TOME.zh-CN.md) |\n\n### Web-Based AI Platforms\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Claude.ai](https://claude.ai/) | MCP SSE/Streamable HTTP | Anthropic's web interface | [EN](./docs/integrations/CLAUDE-AI.md) / [中文](./docs/integrations/CLAUDE-AI.zh-CN.md) |\n| [ChatGPT](https://chat.openai.com/) | MCP SSE/Streamable HTTP | Via custom connectors | [EN](./docs/integrations/CHATGPT.md) / [中文](./docs/integrations/CHATGPT.zh-CN.md) |\n| [Dify](https://dify.ai/) | MCP SSE/Streamable HTTP | LLM app development platform | [EN](./docs/integrations/DIFY.md) / [中文](./docs/integrations/DIFY.zh-CN.md) |\n| [Coze](https://www.coze.com/) | REST API | ByteDance's AI bot platform | [EN](./docs/integrations/COZE.md) / [中文](./docs/integrations/COZE.zh-CN.md) |\n| [n8n](https://n8n.io/) | REST API / MCP | Workflow automation platform | [EN](./docs/integrations/N8N.md) / [中文](./docs/integrations/N8N.zh-CN.md) |\n| [Replit](https://replit.com/) | MCP stdio | Online IDE with AI agent | [EN](./docs/integrations/REPLIT.md) / [中文](./docs/integrations/REPLIT.zh-CN.md) |\n| [MindPal](https://mindpal.io/) | MCP SSE/Streamable HTTP | No-code AI agent builder | [EN](./docs/integrations/MINDPAL.md) / [中文](./docs/integrations/MINDPAL.zh-CN.md) |\n\n### Agent Frameworks & SDKs\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [LangChain](https://langchain.com/) | MCP stdio | Popular LLM framework | [EN](./docs/integrations/LANGCHAIN.md) / [中文](./docs/integrations/LANGCHAIN.zh-CN.md) |\n| [Smolagents](https://github.com/huggingface/smolagents) | MCP stdio | Hugging Face agent library | [EN](./docs/integrations/SMOLAGENTS.md) / [中文](./docs/integrations/SMOLAGENTS.zh-CN.md) |\n| [OpenAI Agents SDK](https://platform.openai.com/) | MCP SSE/Streamable HTTP | OpenAI's agent framework | [EN](./docs/integrations/OPENAI-AGENTS-SDK.md) / [中文](./docs/integrations/OPENAI-AGENTS-SDK.zh-CN.md) |\n| [Amazon Bedrock Agents](https://aws.amazon.com/bedrock/) | MCP SSE/Streamable HTTP | AWS AI agent service | [EN](./docs/integrations/AMAZON-BEDROCK-AGENTS.md) / [中文](./docs/integrations/AMAZON-BEDROCK-AGENTS.zh-CN.md) |\n| [Google ADK](https://cloud.google.com/) | MCP stdio | Google's Agent Development Kit | [EN](./docs/integrations/GOOGLE-ADK.md) / [中文](./docs/integrations/GOOGLE-ADK.zh-CN.md) |\n| [Vercel AI SDK](https://sdk.vercel.ai/) | MCP stdio | Vercel's AI development kit | [EN](./docs/integrations/VERCEL-AI-SDK.md) / [中文](./docs/integrations/VERCEL-AI-SDK.zh-CN.md) |\n| [Spring AI](https://spring.io/projects/spring-ai) | MCP stdio | Java/Spring AI framework | [EN](./docs/integrations/SPRING-AI.md) / [中文](./docs/integrations/SPRING-AI.zh-CN.md) |\n\n### CLI Tools & Terminal\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Claude Code CLI](https://claude.ai/code) | MCP stdio | Terminal-based coding agent | [EN](./docs/integrations/CLAUDE-CODE.md) / [中文](./docs/integrations/CLAUDE-CODE.zh-CN.md) |\n| [Warp](https://www.warp.dev/) | MCP stdio | AI-powered terminal | [EN](./docs/integrations/WARP.md) / [中文](./docs/integrations/WARP.zh-CN.md) |\n| [Oterm](https://github.com/ggozad/oterm) | MCP stdio | Chat with Ollama via CLI | [EN](./docs/integrations/OTERM.md) / [中文](./docs/integrations/OTERM.zh-CN.md) |\n| [MCPHost](https://github.com/mark3labs/mcphost) | MCP stdio | CLI chat with LLMs | [EN](./docs/integrations/MCPHOST.md) / [中文](./docs/integrations/MCPHOST.zh-CN.md) |\n\n### Productivity & Automation\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Raycast](https://raycast.com/) | MCP stdio | macOS productivity launcher | [EN](./docs/integrations/RAYCAST.md) / [中文](./docs/integrations/RAYCAST.zh-CN.md) |\n| [Notion](https://notion.so/) | MCP SSE/Streamable HTTP | Workspace with AI integration | [EN](./docs/integrations/NOTION.md) / [中文](./docs/integrations/NOTION.zh-CN.md) |\n| [Obsidian](https://obsidian.md/) | MCP stdio | Via MCP Tools plugin | [EN](./docs/integrations/OBSIDIAN.md) / [中文](./docs/integrations/OBSIDIAN.zh-CN.md) |\n| [Home Assistant](https://www.home-assistant.io/) | MCP stdio | Home automation platform | [EN](./docs/integrations/HOME-ASSISTANT.md) / [中文](./docs/integrations/HOME-ASSISTANT.zh-CN.md) |\n\n### Messaging Platform Integrations\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Slack](https://slack.com/) | MCP stdio / REST API | Via Slack MCP bots | [EN](./docs/integrations/SLACK.md) / [中文](./docs/integrations/SLACK.zh-CN.md) |\n| [Discord](https://discord.com/) | MCP stdio / REST API | Via Discord MCP bots | [EN](./docs/integrations/DISCORD.md) / [中文](./docs/integrations/DISCORD.zh-CN.md) |\n| [Mattermost](https://mattermost.com/) | MCP stdio | Open-source messaging | [EN](./docs/integrations/MATTERMOST.md) / [中文](./docs/integrations/MATTERMOST.zh-CN.md) |\n\n### Local LLM Runners\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [Ollama](https://ollama.ai/) | MCP stdio | Run local LLMs | [EN](./docs/integrations/OLLAMA.md) / [中文](./docs/integrations/OLLAMA.zh-CN.md) |\n| [LM Studio](https://lmstudio.ai/) | MCP stdio | Local LLM desktop app | [EN](./docs/integrations/LM-STUDIO.md) / [中文](./docs/integrations/LM-STUDIO.zh-CN.md) |\n| [Jan](https://jan.ai/) | MCP stdio | Offline ChatGPT alternative | [EN](./docs/integrations/JAN.md) / [中文](./docs/integrations/JAN.zh-CN.md) |\n\n### Development & Testing Tools\n\n| Platform | Access Method | Description | Guide |\n|----------|---------------|-------------|-------|\n| [MCP Inspector](https://github.com/modelcontextprotocol/inspector) | MCP stdio | Official MCP debugging tool | [EN](./docs/integrations/MCP-INSPECTOR.md) / [中文](./docs/integrations/MCP-INSPECTOR.zh-CN.md) |\n| [Postman](https://postman.com/) | REST API / MCP | API testing platform | [EN](./docs/integrations/POSTMAN.md) / [中文](./docs/integrations/POSTMAN.zh-CN.md) |\n\n> **Note**: Any MCP-compatible client can connect via stdio (local) or SSE/Streamable HTTP (remote). Any HTTP client can use the REST API.\n\n## 📚 Documentation\n\n### Getting Started\n- [Installation Guide](./docs/getting-started/installation.md)\n- [Quick Start](./docs/getting-started/quick-start.md)\n- [Configuration](./docs/getting-started/configuration.md)\n- [Usage Examples](./docs/getting-started/examples.md)\n\n### Deployment\n- [Deployment Overview](./docs/deployment/README.md)\n- [Local Deployment](./docs/deployment/local.md)\n- [Docker Deployment](./docs/deployment/docker.md)\n- [Cloud Deployment](./docs/deployment/cloud/)\n\n### Database Guides\n- [Database Support Overview](./docs/databases/README.md)\n- [MySQL](./docs/databases/mysql.md)\n- [PostgreSQL](./docs/databases/postgresql.md)\n- [More databases...](./docs/databases/)\n\n### HTTP API\n- [API Reference](./docs/http-api/API_REFERENCE.md)\n- [Deployment Guide](./docs/http-api/DEPLOYMENT.md)\n\n### Integrations\n\n**AI Editors & IDEs:**\n[Cursor](./docs/integrations/CURSOR.md) |\n[VS Code](./docs/integrations/VSCODE.md) |\n[JetBrains](./docs/integrations/JETBRAINS.md) |\n[Windsurf](./docs/integrations/WINDSURF.md) |\n[Zed](./docs/integrations/ZED.md) |\n[Neovim](./docs/integrations/NEOVIM.md) |\n[Emacs](./docs/integrations/EMACS.md)\n\n**AI Assistants:**\n[Claude Desktop](./docs/integrations/CLAUDE-DESKTOP.md) |\n[Claude Code](./docs/integrations/CLAUDE-CODE.md) |\n[GitHub Copilot](./docs/integrations/GITHUB-COPILOT.md) |\n[Cline](./docs/integrations/CLINE.md) |\n[Continue](./docs/integrations/CONTINUE.md)\n\n**AI Platforms:**\n[Dify](./docs/integrations/DIFY.md) |\n[Coze](./docs/integrations/COZE.md) |\n[n8n](./docs/integrations/N8N.md) |\n[ChatGPT](./docs/integrations/CHATGPT.md) |\n[LangChain](./docs/integrations/LANGCHAIN.md)\n\n**Desktop Apps:**\n[Cherry Studio](./docs/integrations/CHERRY-STUDIO.md) |\n[LM Studio](./docs/integrations/LM-STUDIO.md) |\n[Jan](./docs/integrations/JAN.md) |\n[Ollama](./docs/integrations/OLLAMA.md)\n\n**Messaging:**\n[Slack](./docs/integrations/SLACK.md) |\n[Discord](./docs/integrations/DISCORD.md)\n\n**Tools:**\n[MCP Inspector](./docs/integrations/MCP-INSPECTOR.md) |\n[Postman](./docs/integrations/POSTMAN.md)\n\n> 📁 [View all 55 integration guides](./docs/integrations/) | 中文版本请在对应文档名后加 `.zh-CN`\n\n### Advanced\n- [Security Guide](./docs/guides/security.md)\n- [Multi-tenant Guide](./docs/guides/multi-tenant.md)\n- [Architecture](./docs/development/architecture.md)\n- [Troubleshooting](./docs/operations/troubleshooting.md)\n\n## 🤝 Contributing\n\nContributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request.\n\n```bash\n# Clone the repository\ngit clone https://github.com/Anarkh-Lee/universal-db-mcp.git\n\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Run tests\nnpm test\n```\n\n## 📄 License\n\nThis project is licensed under the [MIT License](./LICENSE).\n\n## 🌟 Star History\n\nIf you find this project useful, please consider giving it a star! Your support helps us continue improving Universal DB MCP.\n\n[![Star History Chart](https://api.star-history.com/svg?repos=Anarkh-Lee/universal-db-mcp&type=Date)](https://star-history.com/#Anarkh-Lee/universal-db-mcp&Date)\n\n## 📝 Changelog\n\nSee [CHANGELOG.md](./CHANGELOG.md) for a detailed version history.\n\n---\n\n<p align=\"center\">\n  Made with ❤️ by <a href=\"https://github.com/Anarkh-Lee\">Anarkh-Lee</a>\n</p>\n"
  },
  {
    "path": "README.zh-CN.md",
    "content": "<p align=\"center\">\n  <img src=\"assets/logo.png\" alt=\"Universal DB MCP Logo\" width=\"200\">\n</p>\n\n<h1 align=\"center\">Universal DB MCP</h1>\n<p align=\"center\">\n  <strong>用自然语言连接 AI 与你的数据库</strong>\n</p>\n\n<p align=\"center\">\n  一个实现了模型上下文协议（MCP）和 HTTP API 的通用数据库连接器，让 AI 助手能够使用自然语言查询和分析你的数据库。支持 Claude Desktop、Cursor、Windsurf、VS Code、ChatGPT 等 50+ 平台。\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/universal-db-mcp\"><img src=\"https://img.shields.io/npm/v/universal-db-mcp.svg?style=flat-square&color=blue\" alt=\"npm version\"></a>\n  <a href=\"https://www.npmjs.com/package/universal-db-mcp\"><img src=\"https://img.shields.io/npm/dm/universal-db-mcp.svg?style=flat-square&color=green\" alt=\"npm downloads\"></a>\n  <a href=\"https://opensource.org/licenses/MIT\"><img src=\"https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square\" alt=\"License: MIT\"></a>\n  <a href=\"https://nodejs.org/\"><img src=\"https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen?style=flat-square\" alt=\"Node.js Version\"></a>\n  <a href=\"https://github.com/Anarkh-Lee/universal-db-mcp/stargazers\"><img src=\"https://img.shields.io/github/stars/Anarkh-Lee/universal-db-mcp?style=flat-square\" alt=\"GitHub Stars\"></a>\n</p>\n\n<p align=\"center\">\n  <a href=\"#-特性\">特性</a> •\n  <a href=\"#-快速开始\">快速开始</a> •\n  <a href=\"#-支持的数据库\">数据库</a> •\n  <a href=\"#-文档\">文档</a> •\n  <a href=\"#-贡献\">贡献</a>\n</p>\n\n<p align=\"center\">\n  <a href=\"./README.md\">English</a> | <a href=\"./README.zh-CN.md\">中文文档</a>\n</p>\n\n---\n\n## 为什么选择 Universal DB MCP？\n\n想象一下，你问 AI 助手：*\"帮我查一下这个月订单金额最高的 10 个客户\"*，然后立即从数据库获得结果——无需编写 SQL。Universal DB MCP 通过模型上下文协议（MCP）和 HTTP API 将 AI 助手与你的数据库连接起来，让这一切成为可能。\n\n```\n你: \"最近 30 天注册用户的平均订单金额是多少？\"\n\nAI: 让我帮你查询一下...\n\n┌─────────────────────────────────────┐\n│ 平均订单金额: ¥127.45               │\n│ 新用户总数: 1,247                   │\n│ 有订单的用户: 892 (71.5%)           │\n└─────────────────────────────────────┘\n```\n\n## ✨ 特性\n\n- **支持 17 种数据库** - MySQL、PostgreSQL、Redis、Oracle、SQL Server、MongoDB、SQLite，以及 10 种国产数据库\n- **适配 55+ 平台** - 支持 Claude Desktop、Cursor、VS Code、ChatGPT、Dify 等 [50+ 平台](#-支持的平台)\n- **灵活架构** - 2 种启动模式（stdio/http），4 种接入方式：MCP stdio、MCP SSE、MCP Streamable HTTP、REST API\n- **安全第一** - 默认只读模式，防止意外的数据修改\n- **智能缓存** - Schema 缓存支持可配置的 TTL，性能极速\n- **批量查询优化** - 大型数据库的 Schema 获取速度提升高达 100 倍\n- **Schema 增强** - 表注释、隐式关系推断，提升 Text2SQL 准确性\n- **多 Schema 支持** - 自动发现所有用户 Schema（PostgreSQL、SQL Server、Oracle、达梦等）\n- **数据脱敏** - 自动保护敏感数据（手机号、邮箱、身份证、银行卡等）\n- **连接稳定性** - 连接池、TCP Keep-Alive、断线自动重试，保障长时间会话稳定运行\n\n### 性能提升\n\n| 表数量 | 优化前 | 优化后 | 提升 |\n|--------|--------|--------|------|\n| 50 张表 | ~5 秒 | ~200 毫秒 | **25 倍** |\n| 100 张表 | ~10 秒 | ~300 毫秒 | **33 倍** |\n| 500 张表 | ~50 秒 | ~500 毫秒 | **100 倍** |\n\n## 🚀 快速开始\n\n### 安装\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n### MCP 模式（Claude Desktop）\n\n将以下配置添加到 Claude Desktop 配置文件：\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n重启 Claude Desktop，然后开始提问：\n\n- *\"帮我查看 users 表的结构\"*\n- *\"统计最近 7 天的订单数量\"*\n- *\"找出销量最高的 5 个产品\"*\n\n### HTTP API 模式\n\n```bash\n# 设置环境变量\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key\n\n# 启动服务\nnpx universal-db-mcp\n```\n\n```bash\n# 测试 API\ncurl http://localhost:3000/api/health\n```\n\n### MCP SSE 模式（Dify 和远程访问）\n\n在 HTTP 模式下运行时，服务器还会通过 SSE（Server-Sent Events）和 Streamable HTTP 暴露 MCP 协议端点。这使得 Dify 等平台可以直接使用 MCP 协议连接。\n\n**SSE 端点（传统方式）：**\n```\nGET http://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=xxx&database=mydb\n```\n\n**Streamable HTTP 端点（MCP 2025 规范，推荐）：**\n```\nPOST http://localhost:3000/mcp\n请求头：\n  X-DB-Type: mysql\n  X-DB-Host: localhost\n  X-DB-Port: 3306\n  X-DB-User: root\n  X-DB-Password: your_password\n  X-DB-Database: your_database\n请求体：MCP JSON-RPC 请求\n```\n\n| 端点 | 方法 | 说明 |\n|------|------|------|\n| `/sse` | GET | 建立 SSE 连接（传统方式） |\n| `/sse/message` | POST | 向 SSE 会话发送消息 |\n| `/mcp` | POST | Streamable HTTP 端点（推荐） |\n| `/mcp` | GET | Streamable HTTP 的 SSE 流 |\n| `/mcp` | DELETE | 关闭会话 |\n\n详细配置说明请参阅 [Dify 集成指南](./docs/integrations/DIFY.zh-CN.md)。\n\n## 📊 支持的数据库\n\n| 数据库 | 类型参数 | 默认端口 | 分类 |\n|--------|----------|----------|------|\n| MySQL | `mysql` | 3306 | 开源 |\n| PostgreSQL | `postgres` | 5432 | 开源 |\n| Redis | `redis` | 6379 | NoSQL |\n| Oracle | `oracle` | 1521 | 商业 |\n| SQL Server | `sqlserver` | 1433 | 商业 |\n| MongoDB | `mongodb` | 27017 | NoSQL |\n| SQLite | `sqlite` | - | 嵌入式 |\n| 达梦 | `dm` | 5236 | 国产 |\n| 人大金仓 | `kingbase` | 54321 | 国产 |\n| 华为 GaussDB | `gaussdb` | 5432 | 国产 |\n| 蚂蚁 OceanBase | `oceanbase` | 2881 | 国产 |\n| TiDB | `tidb` | 4000 | 分布式 |\n| ClickHouse | `clickhouse` | 8123 | OLAP |\n| 阿里云 PolarDB | `polardb` | 3306 | 云数据库 |\n| 海量 Vastbase | `vastbase` | 5432 | 国产 |\n| 瀚高 HighGo | `highgo` | 5866 | 国产 |\n| 中兴 GoldenDB | `goldendb` | 3306 | 国产 |\n\n## 🏗️ 架构\n\n```\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         Universal DB MCP                                 │\n├─────────────────────────────────────────────────────────────────────────┤\n│                                                                          │\n│  启动模式：                                                               │\n│  ┌────────────────────────────┬────────────────────────────────────┐    │\n│  │ stdio 模式                 │ http 模式                          │    │\n│  │ (npm run start:mcp)        │ (npm run start:http)               │    │\n│  └─────────────┬──────────────┴───────────────┬────────────────────┘    │\n│                │                              │                          │\n│                ▼                              ▼                          │\n│  ┌─────────────────────────┐    ┌───────────────────────────────────┐   │\n│  │      MCP 协议           │    │           HTTP 服务器             │   │\n│  │    (stdio 传输)         │    │                                   │   │\n│  │                         │    │  ┌─────────────────────────────┐  │   │\n│  │  工具：                 │    │  │       MCP 协议              │  │   │\n│  │  • execute_query        │    │  │  (SSE / Streamable HTTP)    │  │   │\n│  │  • get_schema           │    │  │                             │  │   │\n│  │  • get_table_info       │    │  │  工具：（与 stdio 相同）    │  │   │\n│  │  • clear_cache          │    │  │  • execute_query            │  │   │\n│  │  • get_enum_values      │    │  │  • get_schema               │  │   │\n│  │  • get_sample_data      │    │  │  • get_table_info           │  │   │\n│  │  • connect_database     │    │  │  • clear_cache              │  │   │\n│  │  • disconnect_database  │    │  │  • get_enum_values          │  │   │\n│  │  • get_connection_status│    │  │  • get_sample_data          │  │   │\n│  │                         │    │  │  • connect_database         │  │   │\n│  │  适用：Claude Desktop,  │    │  │  • disconnect_database      │  │   │\n│  │        Cursor 等        │    │  │  • get_connection_status    │  │   │\n│  └─────────────┬───────────┘    │  │                             │  │   │\n│                │                │  │  适用：Dify、远程访问       │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                │                 │                 │   │\n│                │                │  ┌──────────────┴──────────────┐  │   │\n│                │                │  │        REST API             │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  端点：                     │  │   │\n│                │                │  │  • /api/connect             │  │   │\n│                │                │  │  • /api/query               │  │   │\n│                │                │  │  • /api/schema              │  │   │\n│                │                │  │  • ...（10+ 端点）          │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  适用：Coze、n8n、自定义    │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                └─────────────────┼─────────────────┘   │\n│                │                                  │                     │\n│                └──────────────────┬───────────────┘                     │\n│                                   ▼                                     │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                       核心业务逻辑层                               │  │\n│  │  • 查询执行          • Schema 缓存                               │  │\n│  │  • 安全校验          • 连接管理                                  │  │\n│  └──────────────────────────────────┬───────────────────────────────┘  │\n│                                     ▼                                   │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                      数据库适配器层                                │  │\n│  │  MySQL │ PostgreSQL │ Redis │ Oracle │ MongoDB │ SQLite │ ...    │  │\n│  │          （连接池 + TCP Keep-Alive + 断线自动重试）               │  │\n│  └──────────────────────────────────────────────────────────────────┘  │\n│                                                                          │\n└─────────────────────────────────────────────────────────────────────────┘\n```\n\n## 🔒 安全\n\n默认情况下，Universal DB MCP 运行在**只读模式**，会阻止所有写操作（INSERT、UPDATE、DELETE、DROP 等）。\n\n### 权限模式\n\n支持细粒度权限控制，可根据需求灵活配置：\n\n| 模式 | 允许的操作 | 说明 |\n|------|-----------|------|\n| `safe`（默认） | SELECT | 只读，最安全 |\n| `readwrite` | SELECT, INSERT, UPDATE | 读写但不能删除 |\n| `full` | 所有操作 | 完全控制（危险！） |\n| `custom` | 自定义组合 | 通过 `--permissions` 指定 |\n\n**权限类型：**\n- `read` - SELECT 查询（始终包含）\n- `insert` - INSERT, REPLACE\n- `update` - UPDATE\n- `delete` - DELETE, TRUNCATE\n- `ddl` - CREATE, ALTER, DROP, RENAME\n\n**使用示例：**\n\n```bash\n# 只读模式（默认）\nnpx universal-db-mcp --type mysql ...\n\n# 读写但不能删除\nnpx universal-db-mcp --type mysql --permission-mode readwrite ...\n\n# 自定义：只允许读和插入\nnpx universal-db-mcp --type mysql --permissions read,insert ...\n\n# 完全控制（等价于原来的 --danger-allow-write）\nnpx universal-db-mcp --type mysql --permission-mode full ...\n```\n\n**不同传输方式的权限配置：**\n\n> ⚠️ 不同传输方式的参数命名风格不同，请注意区分！\n\n| 传输方式 | 参数位置 | 权限模式参数 | 自定义权限参数 |\n|---------|---------|-------------|---------------|\n| STDIO (Claude Desktop) | 命令行 | `--permission-mode` | `--permissions` |\n| SSE (Dify 等) | URL Query | `permissionMode` | `permissions` |\n| Streamable HTTP | HTTP Header | `X-DB-Permission-Mode` | `X-DB-Permissions` |\n| REST API | JSON Body | `permissionMode` | `permissions` |\n\n**最佳实践：**\n- 生产环境永远不要启用写入模式\n- 使用专用的只读数据库账号\n- 通过 VPN 或跳板机连接\n- 定期审计查询日志\n\n## 🔌 支持的平台\n\nUniversal DB MCP 可与任何支持 MCP 协议或 REST API 的平台配合使用。以下是完整列表：\n\n### AI 代码编辑器 & IDE\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Cursor](https://cursor.sh/) | MCP stdio | 内置 MCP 支持的 AI 代码编辑器 | [EN](./docs/integrations/CURSOR.md) / [中文](./docs/integrations/CURSOR.zh-CN.md) |\n| [Windsurf](https://codeium.com/windsurf) | MCP stdio | Codeium 的 AI IDE，带 Cascade 智能体 | [EN](./docs/integrations/WINDSURF.md) / [中文](./docs/integrations/WINDSURF.zh-CN.md) |\n| [VS Code](https://code.visualstudio.com/) | MCP stdio / REST API | 通过 GitHub Copilot 代理模式或 Cline/Continue 扩展 | [EN](./docs/integrations/VSCODE.md) / [中文](./docs/integrations/VSCODE.zh-CN.md) |\n| [Zed](https://zed.dev/) | MCP stdio | 高性能开源代码编辑器 | [EN](./docs/integrations/ZED.md) / [中文](./docs/integrations/ZED.zh-CN.md) |\n| [IntelliJ IDEA](https://www.jetbrains.com/idea/) | MCP stdio | JetBrains IDE，支持 MCP（2025.1+） | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [PyCharm](https://www.jetbrains.com/pycharm/) | MCP stdio | JetBrains Python IDE | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [WebStorm](https://www.jetbrains.com/webstorm/) | MCP stdio | JetBrains JavaScript IDE | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [Android Studio](https://developer.android.com/studio) | MCP stdio | 通过 JetBrains MCP 插件 | [EN](./docs/integrations/JETBRAINS.md) / [中文](./docs/integrations/JETBRAINS.zh-CN.md) |\n| [Neovim](https://neovim.io/) | MCP stdio | 通过 MCPHub.nvim 插件 | [EN](./docs/integrations/NEOVIM.md) / [中文](./docs/integrations/NEOVIM.zh-CN.md) |\n| [Emacs](https://www.gnu.org/software/emacs/) | MCP stdio | 通过 mcp.el 包 | [EN](./docs/integrations/EMACS.md) / [中文](./docs/integrations/EMACS.zh-CN.md) |\n\n### AI 编程助手\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Claude Code](https://claude.ai/code) | MCP stdio | Anthropic 的智能编程工具 | [EN](./docs/integrations/CLAUDE-CODE.md) / [中文](./docs/integrations/CLAUDE-CODE.zh-CN.md) |\n| [GitHub Copilot](https://github.com/features/copilot) | MCP stdio | VS Code/JetBrains 中的代理模式 | [EN](./docs/integrations/GITHUB-COPILOT.md) / [中文](./docs/integrations/GITHUB-COPILOT.zh-CN.md) |\n| [Cline](https://github.com/cline/cline) | MCP stdio / REST API | VS Code 自主编程智能体 | [EN](./docs/integrations/CLINE.md) / [中文](./docs/integrations/CLINE.zh-CN.md) |\n| [Continue](https://continue.dev/) | MCP stdio | 开源 AI 代码助手 | [EN](./docs/integrations/CONTINUE.md) / [中文](./docs/integrations/CONTINUE.zh-CN.md) |\n| [Roo Code](https://github.com/roovet/roo-code) | MCP stdio | Cline 的 VS Code 分支 | [EN](./docs/integrations/ROO-CODE.md) / [中文](./docs/integrations/ROO-CODE.zh-CN.md) |\n| [Sourcegraph Cody](https://sourcegraph.com/cody) | MCP stdio | AI 编程助手 | [EN](./docs/integrations/SOURCEGRAPH-CODY.md) / [中文](./docs/integrations/SOURCEGRAPH-CODY.zh-CN.md) |\n| [Amazon Q Developer](https://aws.amazon.com/q/developer/) | MCP stdio | AWS AI 编程助手 | [EN](./docs/integrations/AMAZON-Q-DEVELOPER.md) / [中文](./docs/integrations/AMAZON-Q-DEVELOPER.zh-CN.md) |\n| [Devin](https://devin.ai/) | MCP stdio | AI 软件工程师 | [EN](./docs/integrations/DEVIN.md) / [中文](./docs/integrations/DEVIN.zh-CN.md) |\n| [Goose](https://github.com/block/goose) | MCP stdio | Block 的 AI 编程智能体 | [EN](./docs/integrations/GOOSE.md) / [中文](./docs/integrations/GOOSE.zh-CN.md) |\n| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | MCP stdio | Google 命令行 AI 工具 | [EN](./docs/integrations/GEMINI-CLI.md) / [中文](./docs/integrations/GEMINI-CLI.zh-CN.md) |\n\n### 桌面 AI 聊天应用\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Claude Desktop](https://claude.ai/download) | MCP stdio | Anthropic 官方桌面应用 | [EN](./docs/integrations/CLAUDE-DESKTOP.md) / [中文](./docs/integrations/CLAUDE-DESKTOP.zh-CN.md) |\n| [ChatGPT Desktop](https://openai.com/chatgpt/desktop/) | MCP SSE/Streamable HTTP | OpenAI 桌面应用，支持 MCP 连接器 | [EN](./docs/integrations/CHATGPT.md) / [中文](./docs/integrations/CHATGPT.zh-CN.md) |\n| [Cherry Studio](https://github.com/kangfenmao/cherry-studio) | MCP stdio | 多模型桌面聊天应用 | [EN](./docs/integrations/CHERRY-STUDIO.md) / [中文](./docs/integrations/CHERRY-STUDIO.zh-CN.md) |\n| [LM Studio](https://lmstudio.ai/) | MCP stdio | 本地运行 LLM，支持 MCP | [EN](./docs/integrations/LM-STUDIO.md) / [中文](./docs/integrations/LM-STUDIO.zh-CN.md) |\n| [Jan](https://jan.ai/) | MCP stdio | 开源 ChatGPT 替代品 | [EN](./docs/integrations/JAN.md) / [中文](./docs/integrations/JAN.zh-CN.md) |\n| [Msty](https://msty.app/) | MCP stdio | 桌面 AI 聊天应用 | [EN](./docs/integrations/MSTY.md) / [中文](./docs/integrations/MSTY.zh-CN.md) |\n| [LibreChat](https://github.com/danny-avila/LibreChat) | MCP stdio | 开源聊天界面 | [EN](./docs/integrations/LIBRECHAT.md) / [中文](./docs/integrations/LIBRECHAT.zh-CN.md) |\n| [Witsy](https://witsy.app/) | MCP stdio | 桌面 AI 助手 | [EN](./docs/integrations/WITSY.md) / [中文](./docs/integrations/WITSY.zh-CN.md) |\n| [5ire](https://github.com/5ire-tech/5ire) | MCP stdio | 跨平台 AI 聊天 | [EN](./docs/integrations/5IRE.md) / [中文](./docs/integrations/5IRE.zh-CN.md) |\n| [ChatMCP](https://github.com/daodao97/chatmcp) | MCP stdio | MCP 专用聊天界面 | [EN](./docs/integrations/CHATMCP.md) / [中文](./docs/integrations/CHATMCP.zh-CN.md) |\n| [HyperChat](https://github.com/BigSweetPotatoStudio/HyperChat) | MCP stdio | 多平台聊天应用 | [EN](./docs/integrations/HYPERCHAT.md) / [中文](./docs/integrations/HYPERCHAT.zh-CN.md) |\n| [Tome](https://github.com/runebook/tome) | MCP stdio | macOS 本地 LLM 应用 | [EN](./docs/integrations/TOME.md) / [中文](./docs/integrations/TOME.zh-CN.md) |\n\n### Web AI 平台\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Claude.ai](https://claude.ai/) | MCP SSE/Streamable HTTP | Anthropic 网页界面 | [EN](./docs/integrations/CLAUDE-AI.md) / [中文](./docs/integrations/CLAUDE-AI.zh-CN.md) |\n| [ChatGPT](https://chat.openai.com/) | MCP SSE/Streamable HTTP | 通过自定义连接器 | [EN](./docs/integrations/CHATGPT.md) / [中文](./docs/integrations/CHATGPT.zh-CN.md) |\n| [Dify](https://dify.ai/) | MCP SSE/Streamable HTTP | LLM 应用开发平台 | [EN](./docs/integrations/DIFY.md) / [中文](./docs/integrations/DIFY.zh-CN.md) |\n| [Coze](https://www.coze.com/) | REST API | 字节跳动 AI 机器人平台 | [EN](./docs/integrations/COZE.md) / [中文](./docs/integrations/COZE.zh-CN.md) |\n| [n8n](https://n8n.io/) | REST API / MCP | 工作流自动化平台 | [EN](./docs/integrations/N8N.md) / [中文](./docs/integrations/N8N.zh-CN.md) |\n| [Replit](https://replit.com/) | MCP stdio | 在线 IDE，带 AI 智能体 | [EN](./docs/integrations/REPLIT.md) / [中文](./docs/integrations/REPLIT.zh-CN.md) |\n| [MindPal](https://mindpal.io/) | MCP SSE/Streamable HTTP | 无代码 AI 智能体构建器 | [EN](./docs/integrations/MINDPAL.md) / [中文](./docs/integrations/MINDPAL.zh-CN.md) |\n\n### 智能体框架 & SDK\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [LangChain](https://langchain.com/) | MCP stdio | 流行的 LLM 框架 | [EN](./docs/integrations/LANGCHAIN.md) / [中文](./docs/integrations/LANGCHAIN.zh-CN.md) |\n| [Smolagents](https://github.com/huggingface/smolagents) | MCP stdio | Hugging Face 智能体库 | [EN](./docs/integrations/SMOLAGENTS.md) / [中文](./docs/integrations/SMOLAGENTS.zh-CN.md) |\n| [OpenAI Agents SDK](https://platform.openai.com/) | MCP SSE/Streamable HTTP | OpenAI 智能体框架 | [EN](./docs/integrations/OPENAI-AGENTS-SDK.md) / [中文](./docs/integrations/OPENAI-AGENTS-SDK.zh-CN.md) |\n| [Amazon Bedrock Agents](https://aws.amazon.com/bedrock/) | MCP SSE/Streamable HTTP | AWS AI 智能体服务 | [EN](./docs/integrations/AMAZON-BEDROCK-AGENTS.md) / [中文](./docs/integrations/AMAZON-BEDROCK-AGENTS.zh-CN.md) |\n| [Google ADK](https://cloud.google.com/) | MCP stdio | Google 智能体开发套件 | [EN](./docs/integrations/GOOGLE-ADK.md) / [中文](./docs/integrations/GOOGLE-ADK.zh-CN.md) |\n| [Vercel AI SDK](https://sdk.vercel.ai/) | MCP stdio | Vercel AI 开发套件 | [EN](./docs/integrations/VERCEL-AI-SDK.md) / [中文](./docs/integrations/VERCEL-AI-SDK.zh-CN.md) |\n| [Spring AI](https://spring.io/projects/spring-ai) | MCP stdio | Java/Spring AI 框架 | [EN](./docs/integrations/SPRING-AI.md) / [中文](./docs/integrations/SPRING-AI.zh-CN.md) |\n\n### CLI 工具 & 终端\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Claude Code CLI](https://claude.ai/code) | MCP stdio | 终端编程智能体 | [EN](./docs/integrations/CLAUDE-CODE.md) / [中文](./docs/integrations/CLAUDE-CODE.zh-CN.md) |\n| [Warp](https://www.warp.dev/) | MCP stdio | AI 驱动的终端 | [EN](./docs/integrations/WARP.md) / [中文](./docs/integrations/WARP.zh-CN.md) |\n| [Oterm](https://github.com/ggozad/oterm) | MCP stdio | 通过 CLI 与 Ollama 聊天 | [EN](./docs/integrations/OTERM.md) / [中文](./docs/integrations/OTERM.zh-CN.md) |\n| [MCPHost](https://github.com/mark3labs/mcphost) | MCP stdio | CLI LLM 聊天工具 | [EN](./docs/integrations/MCPHOST.md) / [中文](./docs/integrations/MCPHOST.zh-CN.md) |\n\n### 效率 & 自动化工具\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Raycast](https://raycast.com/) | MCP stdio | macOS 效率启动器 | [EN](./docs/integrations/RAYCAST.md) / [中文](./docs/integrations/RAYCAST.zh-CN.md) |\n| [Notion](https://notion.so/) | MCP SSE/Streamable HTTP | 带 AI 集成的工作空间 | [EN](./docs/integrations/NOTION.md) / [中文](./docs/integrations/NOTION.zh-CN.md) |\n| [Obsidian](https://obsidian.md/) | MCP stdio | 通过 MCP Tools 插件 | [EN](./docs/integrations/OBSIDIAN.md) / [中文](./docs/integrations/OBSIDIAN.zh-CN.md) |\n| [Home Assistant](https://www.home-assistant.io/) | MCP stdio | 智能家居平台 | [EN](./docs/integrations/HOME-ASSISTANT.md) / [中文](./docs/integrations/HOME-ASSISTANT.zh-CN.md) |\n\n### 即时通讯平台集成\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Slack](https://slack.com/) | MCP stdio / REST API | 通过 Slack MCP 机器人 | [EN](./docs/integrations/SLACK.md) / [中文](./docs/integrations/SLACK.zh-CN.md) |\n| [Discord](https://discord.com/) | MCP stdio / REST API | 通过 Discord MCP 机器人 | [EN](./docs/integrations/DISCORD.md) / [中文](./docs/integrations/DISCORD.zh-CN.md) |\n| [Mattermost](https://mattermost.com/) | MCP stdio | 开源即时通讯 | [EN](./docs/integrations/MATTERMOST.md) / [中文](./docs/integrations/MATTERMOST.zh-CN.md) |\n\n### 本地 LLM 运行器\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [Ollama](https://ollama.ai/) | MCP stdio | 本地运行 LLM | [EN](./docs/integrations/OLLAMA.md) / [中文](./docs/integrations/OLLAMA.zh-CN.md) |\n| [LM Studio](https://lmstudio.ai/) | MCP stdio | 本地 LLM 桌面应用 | [EN](./docs/integrations/LM-STUDIO.md) / [中文](./docs/integrations/LM-STUDIO.zh-CN.md) |\n| [Jan](https://jan.ai/) | MCP stdio | 离线 ChatGPT 替代品 | [EN](./docs/integrations/JAN.md) / [中文](./docs/integrations/JAN.zh-CN.md) |\n\n### 开发 & 测试工具\n\n| 平台 | 接入方式 | 说明 | 集成指南 |\n|------|----------|------|----------|\n| [MCP Inspector](https://github.com/modelcontextprotocol/inspector) | MCP stdio | 官方 MCP 调试工具 | [EN](./docs/integrations/MCP-INSPECTOR.md) / [中文](./docs/integrations/MCP-INSPECTOR.zh-CN.md) |\n| [Postman](https://postman.com/) | REST API / MCP | API 测试平台 | [EN](./docs/integrations/POSTMAN.md) / [中文](./docs/integrations/POSTMAN.zh-CN.md) |\n\n> **提示**：任何 MCP 兼容客户端都可以通过 stdio（本地）或 SSE/Streamable HTTP（远程）连接。任何 HTTP 客户端都可以使用 REST API。\n\n## 📚 文档\n\n### 快速开始\n- [安装指南](./docs/getting-started/installation.md)\n- [快速开始](./docs/getting-started/quick-start.md)\n- [配置说明](./docs/getting-started/configuration.md)\n- [使用示例](./docs/getting-started/examples.md)\n\n### 部署\n- [部署概览](./docs/deployment/README.md)\n- [本地部署](./docs/deployment/local.md)\n- [Docker 部署](./docs/deployment/docker.md)\n- [云服务部署](./docs/deployment/cloud/)\n\n### 数据库指南\n- [数据库支持概览](./docs/databases/README.md)\n- [MySQL](./docs/databases/mysql.md)\n- [PostgreSQL](./docs/databases/postgresql.md)\n- [更多数据库...](./docs/databases/)\n\n### HTTP API\n- [API 参考](./docs/http-api/API_REFERENCE.md)\n- [部署指南](./docs/http-api/DEPLOYMENT.md)\n\n### 集成\n\n**AI 编辑器 & IDE：**\n[Cursor](./docs/integrations/CURSOR.zh-CN.md) |\n[VS Code](./docs/integrations/VSCODE.zh-CN.md) |\n[JetBrains](./docs/integrations/JETBRAINS.zh-CN.md) |\n[Windsurf](./docs/integrations/WINDSURF.zh-CN.md) |\n[Zed](./docs/integrations/ZED.zh-CN.md) |\n[Neovim](./docs/integrations/NEOVIM.zh-CN.md) |\n[Emacs](./docs/integrations/EMACS.zh-CN.md)\n\n**AI 助手：**\n[Claude Desktop](./docs/integrations/CLAUDE-DESKTOP.zh-CN.md) |\n[Claude Code](./docs/integrations/CLAUDE-CODE.zh-CN.md) |\n[GitHub Copilot](./docs/integrations/GITHUB-COPILOT.zh-CN.md) |\n[Cline](./docs/integrations/CLINE.zh-CN.md) |\n[Continue](./docs/integrations/CONTINUE.zh-CN.md)\n\n**AI 平台：**\n[Dify](./docs/integrations/DIFY.zh-CN.md) |\n[Coze](./docs/integrations/COZE.zh-CN.md) |\n[n8n](./docs/integrations/N8N.zh-CN.md) |\n[ChatGPT](./docs/integrations/CHATGPT.zh-CN.md) |\n[LangChain](./docs/integrations/LANGCHAIN.zh-CN.md)\n\n**桌面应用：**\n[Cherry Studio](./docs/integrations/CHERRY-STUDIO.zh-CN.md) |\n[LM Studio](./docs/integrations/LM-STUDIO.zh-CN.md) |\n[Jan](./docs/integrations/JAN.zh-CN.md) |\n[Ollama](./docs/integrations/OLLAMA.zh-CN.md)\n\n**即时通讯：**\n[Slack](./docs/integrations/SLACK.zh-CN.md) |\n[Discord](./docs/integrations/DISCORD.zh-CN.md)\n\n**工具：**\n[MCP Inspector](./docs/integrations/MCP-INSPECTOR.zh-CN.md) |\n[Postman](./docs/integrations/POSTMAN.zh-CN.md)\n\n> 📁 [查看全部 55 个集成指南](./docs/integrations/) | English version: remove `.zh-CN` from filename\n\n### 进阶\n- [安全指南](./docs/guides/security.md)\n- [多租户指南](./docs/guides/multi-tenant.md)\n- [架构说明](./docs/development/architecture.md)\n- [故障排查](./docs/operations/troubleshooting.md)\n\n## 🤝 贡献\n\n欢迎贡献代码！请在提交 Pull Request 之前阅读我们的[贡献指南](./CONTRIBUTING.md)。\n\n```bash\n# 克隆仓库\ngit clone https://github.com/Anarkh-Lee/universal-db-mcp.git\n\n# 安装依赖\nnpm install\n\n# 构建\nnpm run build\n\n# 运行测试\nnpm test\n```\n\n## 📄 许可证\n\n本项目采用 [MIT 许可证](./LICENSE)。\n\n## 🌟 Star 历史\n\n如果你觉得这个项目有用，请考虑给它一个 Star！你的支持帮助我们持续改进 Universal DB MCP。\n\n[![Star History Chart](https://api.star-history.com/svg?repos=Anarkh-Lee/universal-db-mcp&type=Date)](https://star-history.com/#Anarkh-Lee/universal-db-mcp&Date)\n\n## 📝 更新日志\n\n详见 [CHANGELOG.md](./CHANGELOG.md) 了解详细的版本历史。\n\n---\n\n<p align=\"center\">\n  由 <a href=\"https://github.com/Anarkh-Lee\">Anarkh-Lee</a> 用 ❤️ 打造\n</p>\n"
  },
  {
    "path": "config/default.json",
    "content": "{\n  \"mode\": \"mcp\",\n  \"http\": {\n    \"port\": 3000,\n    \"host\": \"0.0.0.0\",\n    \"apiKeys\": [],\n    \"cors\": {\n      \"origins\": \"*\",\n      \"credentials\": false\n    },\n    \"rateLimit\": {\n      \"max\": 100,\n      \"window\": \"1m\"\n    },\n    \"logging\": {\n      \"level\": \"info\",\n      \"pretty\": false\n    },\n    \"session\": {\n      \"timeout\": 3600000,\n      \"cleanupInterval\": 300000\n    }\n  }\n}\n"
  },
  {
    "path": "create-claude-config.bat",
    "content": "@echo off\nchcp 65001 >nul\necho ========================================\necho Claude Desktop 配置文件创建工具\necho ========================================\necho.\n\nREM 检查 Claude 文件夹是否存在\nset CLAUDE_DIR=%APPDATA%\\Claude\nif not exist \"%CLAUDE_DIR%\" (\n    echo [错误] Claude 文件夹不存在: %CLAUDE_DIR%\n    echo 请确保已安装 Claude Desktop\n    pause\n    exit /b 1\n)\n\necho [信息] Claude 文件夹路径: %CLAUDE_DIR%\necho.\n\nREM 检查配置文件是否已存在\nset CONFIG_FILE=%CLAUDE_DIR%\\claude_desktop_config.json\nif exist \"%CONFIG_FILE%\" (\n    echo [警告] 配置文件已存在！\n    echo 路径: %CONFIG_FILE%\n    echo.\n    choice /C YN /M \"是否覆盖现有配置文件？(Y=是, N=否)\"\n    if errorlevel 2 (\n        echo [取消] 保留现有配置文件\n        pause\n        exit /b 0\n    )\n    echo [信息] 将覆盖现有配置文件\n)\n\necho.\necho 请选择数据库类型:\necho 1. MySQL\necho 2. PostgreSQL\necho 3. Redis\necho 4. 空配置（稍后手动编辑）\necho.\nchoice /C 1234 /N /M \"请输入选项 (1-4): \"\n\nif errorlevel 4 goto EMPTY_CONFIG\nif errorlevel 3 goto REDIS_CONFIG\nif errorlevel 2 goto POSTGRES_CONFIG\nif errorlevel 1 goto MYSQL_CONFIG\n\n:MYSQL_CONFIG\necho.\necho [MySQL 配置]\nset /p DB_HOST=\"数据库主机 (默认: localhost): \" || set DB_HOST=localhost\nset /p DB_PORT=\"数据库端口 (默认: 3306): \" || set DB_PORT=3306\nset /p DB_USER=\"用户名 (默认: root): \" || set DB_USER=root\nset /p DB_PASS=\"密码: \"\nset /p DB_NAME=\"数据库名: \"\n\n(\necho {\necho   \"mcpServers\": {\necho     \"mysql-db\": {\necho       \"command\": \"npx\",\necho       \"args\": [\necho         \"universal-db-mcp\",\necho         \"--type\", \"mysql\",\necho         \"--host\", \"%DB_HOST%\",\necho         \"--port\", \"%DB_PORT%\",\necho         \"--user\", \"%DB_USER%\",\necho         \"--password\", \"%DB_PASS%\",\necho         \"--database\", \"%DB_NAME%\"\necho       ]\necho     }\necho   }\necho }\n) > \"%CONFIG_FILE%\"\ngoto SUCCESS\n\n:POSTGRES_CONFIG\necho.\necho [PostgreSQL 配置]\nset /p DB_HOST=\"数据库主机 (默认: localhost): \" || set DB_HOST=localhost\nset /p DB_PORT=\"数据库端口 (默认: 5432): \" || set DB_PORT=5432\nset /p DB_USER=\"用户名 (默认: postgres): \" || set DB_USER=postgres\nset /p DB_PASS=\"密码: \"\nset /p DB_NAME=\"数据库名: \"\n\n(\necho {\necho   \"mcpServers\": {\necho     \"postgres-db\": {\necho       \"command\": \"npx\",\necho       \"args\": [\necho         \"universal-db-mcp\",\necho         \"--type\", \"postgres\",\necho         \"--host\", \"%DB_HOST%\",\necho         \"--port\", \"%DB_PORT%\",\necho         \"--user\", \"%DB_USER%\",\necho         \"--password\", \"%DB_PASS%\",\necho         \"--database\", \"%DB_NAME%\"\necho       ]\necho     }\necho   }\necho }\n) > \"%CONFIG_FILE%\"\ngoto SUCCESS\n\n:REDIS_CONFIG\necho.\necho [Redis 配置]\nset /p DB_HOST=\"Redis 主机 (默认: localhost): \" || set DB_HOST=localhost\nset /p DB_PORT=\"Redis 端口 (默认: 6379): \" || set DB_PORT=6379\nset /p DB_PASS=\"密码 (可选，直接回车跳过): \"\n\nif \"%DB_PASS%\"==\"\" (\n    REM 无密码配置\n    (\n    echo {\n    echo   \"mcpServers\": {\n    echo     \"redis-cache\": {\n    echo       \"command\": \"npx\",\n    echo       \"args\": [\n    echo         \"universal-db-mcp\",\n    echo         \"--type\", \"redis\",\n    echo         \"--host\", \"%DB_HOST%\",\n    echo         \"--port\", \"%DB_PORT%\"\n    echo       ]\n    echo     }\n    echo   }\n    echo }\n    ) > \"%CONFIG_FILE%\"\n) else (\n    REM 有密码配置\n    (\n    echo {\n    echo   \"mcpServers\": {\n    echo     \"redis-cache\": {\n    echo       \"command\": \"npx\",\n    echo       \"args\": [\n    echo         \"universal-db-mcp\",\n    echo         \"--type\", \"redis\",\n    echo         \"--host\", \"%DB_HOST%\",\n    echo         \"--port\", \"%DB_PORT%\",\n    echo         \"--password\", \"%DB_PASS%\"\n    echo       ]\n    echo     }\n    echo   }\n    echo }\n    ) > \"%CONFIG_FILE%\"\n)\ngoto SUCCESS\n\n:EMPTY_CONFIG\n(\necho {\necho   \"mcpServers\": {}\necho }\n) > \"%CONFIG_FILE%\"\necho [信息] 已创建空配置文件，请手动编辑\ngoto SUCCESS\n\n:SUCCESS\necho.\necho ========================================\necho [成功] 配置文件已创建！\necho ========================================\necho 文件路径: %CONFIG_FILE%\necho.\necho 下一步操作:\necho 1. 重启 Claude Desktop\necho 2. 在对话中测试数据库连接\necho.\nchoice /C YN /M \"是否现在打开配置文件查看？(Y=是, N=否)\"\nif errorlevel 2 goto END\nnotepad \"%CONFIG_FILE%\"\n\n:END\necho.\necho 感谢使用！\npause\n"
  },
  {
    "path": "docker/Dockerfile",
    "content": "# Multi-stage build for minimal image size\n\n# Stage 1: Build\nFROM node:20-alpine AS builder\n\nWORKDIR /app\n\n# Copy package files\nCOPY package*.json ./\nCOPY tsconfig.json ./\n\n# Install dependencies (skip scripts to avoid premature build)\nRUN npm ci --ignore-scripts\n\n# Copy source code\nCOPY src ./src\n\n# Build TypeScript explicitly\nRUN npm run build\n\n# Stage 2: Production\nFROM node:20-alpine\n\nWORKDIR /app\n\n# Install dumb-init for proper signal handling\nRUN apk add --no-cache dumb-init\n\n# Copy package files\nCOPY package*.json ./\n\n# Install production dependencies only (skip scripts)\nRUN npm ci --only=production --ignore-scripts && \\\n    npm cache clean --force\n\n# Copy built files from builder\nCOPY --from=builder /app/dist ./dist\n\n# Create non-root user\nRUN addgroup -g 1001 -S nodejs && \\\n    adduser -S nodejs -u 1001\n\n# Change ownership\nRUN chown -R nodejs:nodejs /app\n\n# Switch to non-root user\nUSER nodejs\n\n# Expose port\nEXPOSE 3000\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\n  CMD node -e \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"\n\n# Use dumb-init to handle signals properly\nENTRYPOINT [\"dumb-init\", \"--\"]\n\n# Start server\nCMD [\"node\", \"dist/index.js\"]\n"
  },
  {
    "path": "docker/docker-compose.yml",
    "content": "services:\n  api:\n    build:\n      context: ..\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n      - API_KEYS=${API_KEYS:-default-key-change-me}\n      - CORS_ORIGINS=${CORS_ORIGINS:-*}\n      - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100}\n      - RATE_LIMIT_WINDOW=${RATE_LIMIT_WINDOW:-1m}\n      - LOG_LEVEL=${LOG_LEVEL:-info}\n      - LOG_PRETTY=${LOG_PRETTY:-false}\n      # Database configuration (optional)\n      - DB_TYPE=${DB_TYPE}\n      - DB_HOST=${DB_HOST}\n      - DB_PORT=${DB_PORT}\n      - DB_USER=${DB_USER}\n      - DB_PASSWORD=${DB_PASSWORD}\n      - DB_DATABASE=${DB_DATABASE}\n      - DB_ALLOW_WRITE=${DB_ALLOW_WRITE:-false}\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"]\n      interval: 30s\n      timeout: 3s\n      retries: 3\n      start_period: 5s\n    networks:\n      - db-network\n\n  # Example: MySQL database (optional)\n  # mysql:\n  #   image: mysql:8.0\n  #   environment:\n  #     MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}\n  #     MYSQL_DATABASE: ${MYSQL_DATABASE:-testdb}\n  #   ports:\n  #     - \"3306:3306\"\n  #   volumes:\n  #     - mysql-data:/var/lib/mysql\n  #   networks:\n  #     - db-network\n\nnetworks:\n  db-network:\n    driver: bridge\n\n# volumes:\n#   mysql-data:\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3.8'\n\nservices:\n  api:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n      - API_KEYS=${API_KEYS:-default-key-change-me}\n      - CORS_ORIGINS=${CORS_ORIGINS:-*}\n      - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100}\n      - LOG_LEVEL=${LOG_LEVEL:-info}\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"]\n      interval: 30s\n      timeout: 3s\n      retries: 3\n      start_period: 5s"
  },
  {
    "path": "docs/README.md",
    "content": "# Documentation\n\nThis directory contains the complete documentation for Universal DB MCP.\n\n## Quick Start\n\n- [Installation](./getting-started/installation.md) - How to install\n- [Quick Start](./getting-started/quick-start.md) - Get started in 5 minutes\n- [Configuration](./getting-started/configuration.md) - Configuration options\n- [Examples](./getting-started/examples.md) - Usage examples for all databases\n\n## Deployment\n\n- [Overview](./deployment/README.md) - Deployment options overview\n- [Local Deployment](./deployment/local.md) - Node.js, PM2, systemd\n- [Docker Deployment](./deployment/docker.md) - Dockerfile, Docker Compose\n- [HTTPS Configuration](./deployment/https-domain.md) - Domain and SSL setup\n- [Cloud Deployment](./deployment/cloud/) - Huawei Cloud, Aliyun, AWS, Tencent\n\n## Databases\n\n- [Overview](./databases/README.md) - Supported databases\n- [MySQL](./databases/mysql.md)\n- [PostgreSQL](./databases/postgresql.md)\n- [Redis](./databases/redis.md)\n- [Oracle](./databases/oracle.md)\n- [SQL Server](./databases/sqlserver.md)\n- [MongoDB](./databases/mongodb.md)\n- [SQLite](./databases/sqlite.md)\n- [Dameng](./databases/dameng.md)\n- [KingbaseES](./databases/kingbase.md)\n- [GaussDB](./databases/gaussdb.md)\n- [OceanBase](./databases/oceanbase.md)\n- [TiDB](./databases/tidb.md)\n- [ClickHouse](./databases/clickhouse.md)\n- [PolarDB](./databases/polardb.md)\n- [Vastbase](./databases/vastbase.md)\n- [HighGo](./databases/highgo.md)\n- [GoldenDB](./databases/goldendb.md)\n\n## HTTP API\n\n- [API Reference](./http-api/API_REFERENCE.md)\n- [Deployment Guide](./http-api/DEPLOYMENT.md)\n\n## Integrations\n\n- [Coze](./integrations/COZE.md)\n- [n8n](./integrations/N8N.md)\n- [Dify](./integrations/DIFY.md)\n\n## Guides\n\n- [Security Best Practices](./guides/security.md)\n- [Multi-tenant Guide](./guides/multi-tenant.md)\n\n## Development\n\n- [Architecture](./development/architecture.md)\n- [Adding New Database](./development/adding-database.md)\n- [Implementation Summary](./development/implementation.md)\n- [Release Guide](./development/release.md)\n\n## Operations\n\n- [Operations Guide](./operations/guide.md)\n- [Troubleshooting](./operations/troubleshooting.md)\n\n---\n\nFor Chinese documentation, see [README.zh-CN.md](./README.zh-CN.md).\n"
  },
  {
    "path": "docs/README.zh-CN.md",
    "content": "# 文档中心\n\n本目录包含 Universal DB MCP 的完整文档。\n\n## 快速开始\n\n- [安装指南](./getting-started/installation.md) - 安装方式\n- [快速开始](./getting-started/quick-start.md) - 5 分钟上手\n- [配置说明](./getting-started/configuration.md) - 配置选项\n- [使用示例](./getting-started/examples.md) - 各数据库使用示例\n\n## 部署\n\n- [部署概览](./deployment/README.md) - 部署方式选择\n- [本地部署](./deployment/local.md) - Node.js、PM2、systemd\n- [Docker 部署](./deployment/docker.md) - Dockerfile、Docker Compose\n- [HTTPS 配置](./deployment/https-domain.md) - 域名和 SSL 证书\n- [云服务部署](./deployment/cloud/) - 华为云、阿里云、AWS、腾讯云\n\n## 数据库\n\n- [数据库支持](./databases/README.md) - 支持的数据库列表\n- [MySQL](./databases/mysql.md)\n- [PostgreSQL](./databases/postgresql.md)\n- [Redis](./databases/redis.md)\n- [Oracle](./databases/oracle.md)\n- [SQL Server](./databases/sqlserver.md)\n- [MongoDB](./databases/mongodb.md)\n- [SQLite](./databases/sqlite.md)\n- [达梦](./databases/dameng.md)\n- [KingbaseES](./databases/kingbase.md)\n- [GaussDB](./databases/gaussdb.md)\n- [OceanBase](./databases/oceanbase.md)\n- [TiDB](./databases/tidb.md)\n- [ClickHouse](./databases/clickhouse.md)\n- [PolarDB](./databases/polardb.md)\n- [Vastbase](./databases/vastbase.md)\n- [HighGo](./databases/highgo.md)\n- [GoldenDB](./databases/goldendb.md)\n\n## HTTP API\n\n- [API 参考文档](./http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](./http-api/DEPLOYMENT.zh-CN.md)\n\n## 第三方集成\n\n- [Coze 集成](./integrations/COZE.zh-CN.md)\n- [n8n 集成](./integrations/N8N.zh-CN.md)\n- [Dify 集成](./integrations/DIFY.zh-CN.md)\n\n## 使用指南\n\n- [安全最佳实践](./guides/security.md)\n- [多租户指南](./guides/multi-tenant.md)\n\n## 开发\n\n- [架构说明](./development/architecture.md)\n- [添加新数据库](./development/adding-database.md)\n- [实现总结](./development/implementation.md)\n- [发布指南](./development/release.md)\n\n## 运维\n\n- [运维指南](./operations/guide.md)\n- [故障排查](./operations/troubleshooting.md)\n\n---\n\nFor English documentation, see [README.md](./README.md).\n"
  },
  {
    "path": "docs/databases/README.md",
    "content": "# 数据库支持\n\nUniversal DB MCP 支持 17 种数据库，涵盖关系型、NoSQL、分布式和国产数据库。\n\n## 支持的数据库\n\n| 数据库 | 类型参数 | 默认端口 | 驱动 | 状态 |\n|--------|---------|---------|------|------|\n| [MySQL](./mysql.md) | `mysql` | 3306 | mysql2 | ✅ |\n| [PostgreSQL](./postgresql.md) | `postgres` | 5432 | pg | ✅ |\n| [Redis](./redis.md) | `redis` | 6379 | ioredis | ✅ |\n| [Oracle](./oracle.md) | `oracle` | 1521 | oracledb | ✅ |\n| [SQL Server](./sqlserver.md) | `sqlserver` | 1433 | mssql | ✅ |\n| [MongoDB](./mongodb.md) | `mongodb` | 27017 | mongodb | ✅ |\n| [SQLite](./sqlite.md) | `sqlite` | - | better-sqlite3 | ✅ |\n| [达梦](./dameng.md) | `dm` | 5236 | dmdb | ✅ |\n| [KingbaseES](./kingbase.md) | `kingbase` | 54321 | pg | ✅ |\n| [GaussDB](./gaussdb.md) | `gaussdb` | 5432 | pg | ✅ |\n| [OceanBase](./oceanbase.md) | `oceanbase` | 2881 | mysql2 | ✅ |\n| [TiDB](./tidb.md) | `tidb` | 4000 | mysql2 | ✅ |\n| [ClickHouse](./clickhouse.md) | `clickhouse` | 8123 | @clickhouse/client | ✅ |\n| [PolarDB](./polardb.md) | `polardb` | 3306 | mysql2 | ✅ |\n| [Vastbase](./vastbase.md) | `vastbase` | 5432 | pg | ✅ |\n| [HighGo](./highgo.md) | `highgo` | 5866 | pg | ✅ |\n| [GoldenDB](./goldendb.md) | `goldendb` | 3306 | mysql2 | ✅ |\n\n## 数据库分类\n\n### 关系型数据库\n\n- **MySQL** - 最流行的开源关系型数据库\n- **PostgreSQL** - 功能强大的开源对象关系型数据库\n- **Oracle** - 企业级商业数据库\n- **SQL Server** - 微软的企业级数据库\n- **SQLite** - 轻量级嵌入式数据库\n\n### NoSQL 数据库\n\n- **Redis** - 高性能键值存储\n- **MongoDB** - 文档型数据库\n\n### 分布式数据库\n\n- **TiDB** - 分布式 NewSQL 数据库，兼容 MySQL\n- **OceanBase** - 蚂蚁金服分布式数据库\n- **PolarDB** - 阿里云云原生数据库\n- **ClickHouse** - 列式 OLAP 数据库\n\n### 国产数据库\n\n- **达梦（DM）** - 国产关系型数据库\n- **KingbaseES** - 人大金仓数据库\n- **GaussDB/OpenGauss** - 华为高斯数据库\n- **Vastbase** - 海量数据数据库\n- **HighGo** - 瀚高数据库\n- **GoldenDB** - 中兴分布式数据库\n\n## 兼容性说明\n\n### MySQL 兼容\n\n以下数据库兼容 MySQL 协议，使用相同的驱动：\n\n- TiDB（兼容 MySQL 5.7）\n- OceanBase（兼容 MySQL）\n- PolarDB（兼容 MySQL 5.6/5.7/8.0）\n- GoldenDB（兼容 MySQL 5.7/8.0）\n\n### PostgreSQL 兼容\n\n以下数据库兼容 PostgreSQL 协议，使用相同的驱动：\n\n- KingbaseES\n- GaussDB/OpenGauss\n- Vastbase\n- HighGo\n\n## 驱动依赖\n\n大多数驱动会自动安装。以下是特殊情况：\n\n### 达梦数据库\n\n```bash\nnpm install -g dmdb\n```\n\n### SQLite\n\n需要编译环境。Windows 上需要安装 Visual Studio Build Tools。\n\n### Oracle\n\n需要 Oracle Instant Client。请参考 [Oracle 官方文档](https://oracle.github.io/node-oracledb/INSTALL.html)。\n\n## 功能支持\n\n| 功能 | 关系型 | Redis | MongoDB | ClickHouse |\n|------|--------|-------|---------|------------|\n| 获取 Schema | ✅ | ✅ | ✅ | ✅ |\n| 外键关系 | ✅ | - | - | - |\n| 执行查询 | ✅ | ✅ | ✅ | ✅ |\n| 写入操作 | ✅ | ✅ | ✅ | ✅ |\n| 参数化查询 | ✅ | - | ✅ | ✅ |\n| 事务支持 | ✅ | - | ✅ | - |\n\n## 下一步\n\n选择你使用的数据库，查看详细配置指南：\n\n- [MySQL](./mysql.md)\n- [PostgreSQL](./postgresql.md)\n- [Redis](./redis.md)\n- [MongoDB](./mongodb.md)\n- [更多数据库...](#支持的数据库)\n"
  },
  {
    "path": "docs/databases/clickhouse.md",
    "content": "# ClickHouse 数据库使用指南\n\n## 📖 关于 ClickHouse\n\nClickHouse 是由俄罗斯 Yandex 公司开发的开源列式数据库管理系统（DBMS），专为在线分析处理（OLAP）场景设计。它能够使用 SQL 查询实时生成分析数据报告。\n\n### 主要特点\n\n- **列式存储**：数据按列存储，压缩率高，查询速度快\n- **向量化执行**：利用 SIMD 指令加速查询\n- **分布式查询**：支持分布式表和分布式查询\n- **高性能**：每秒可处理数亿到数十亿行数据\n- **实时插入**：支持高并发实时数据插入\n- **SQL 支持**：支持标准 SQL 语法（有部分扩展）\n\n## 🚀 快速开始\n\n### 1. 安装 ClickHouse\n\n#### 使用 Docker（推荐）\n\n```bash\n# 拉取 ClickHouse 镜像\ndocker pull clickhouse/clickhouse-server\n\n# 启动 ClickHouse 容器\ndocker run -d --name clickhouse-server \\\n  -p 8123:8123 \\\n  -p 9000:9000 \\\n  --ulimit nofile=262144:262144 \\\n  clickhouse/clickhouse-server\n```\n\n#### 在 Linux 上安装\n\n```bash\n# Ubuntu/Debian\nsudo apt-get install -y apt-transport-https ca-certificates dirmngr\nsudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754\necho \"deb https://packages.clickhouse.com/deb stable main\" | sudo tee /etc/apt/sources.list.d/clickhouse.list\nsudo apt-get update\nsudo apt-get install -y clickhouse-server clickhouse-client\n\n# 启动服务\nsudo service clickhouse-server start\n```\n\n#### 在 macOS 上安装\n\n```bash\n# 使用 Homebrew\nbrew install clickhouse\n\n# 启动服务\nclickhouse server\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"localhost\",\n        \"--port\", \"8123\",\n        \"--user\", \"default\",\n        \"--password\", \"\",\n        \"--database\", \"default\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"localhost\",\n        \"--port\", \"8123\",\n        \"--user\", \"default\",\n        \"--password\", \"\",\n        \"--database\", \"default\"\n      ]\n    }\n  }\n}\n```\n\n#### 连接 ClickHouse Cloud\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"your-instance.clickhouse.cloud\",\n        \"--port\", \"8443\",\n        \"--user\", \"default\",\n        \"--password\", \"your_password\",\n        \"--database\", \"default\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 ClickHouse 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 events 表中的所有数据\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM events LIMIT 100;\n```\n\n### 聚合查询\n\n```\n你：统计每个用户的事件数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT user_id, COUNT(*) as event_count\nFROM events\nGROUP BY user_id\nORDER BY event_count DESC;\n```\n\n### 时序数据分析\n\n```\n你：分析最近 7 天每天的事件数量趋势\n```\n\nClaude 会生成并执行：\n```sql\nSELECT\n    toDate(timestamp) as date,\n    COUNT(*) as event_count\nFROM events\nWHERE timestamp >= now() - INTERVAL 7 DAY\nGROUP BY date\nORDER BY date;\n```\n\n### 复杂分析查询\n\n```\n你：找出最近 30 天内活跃度最高的 10 个用户，并统计他们的行为分布\n```\n\nClaude 会生成并执行：\n```sql\nSELECT\n    user_id,\n    COUNT(*) as total_events,\n    countIf(event_type = 'click') as clicks,\n    countIf(event_type = 'view') as views,\n    countIf(event_type = 'purchase') as purchases\nFROM events\nWHERE timestamp >= now() - INTERVAL 30 DAY\nGROUP BY user_id\nORDER BY total_events DESC\nLIMIT 10;\n```\n\n## 🔧 ClickHouse 特性支持\n\n### 1. 表引擎\n\nClickHouse 支持多种表引擎，最常用的是 MergeTree 系列：\n\n```sql\n-- MergeTree 引擎（最常用）\nCREATE TABLE events (\n    timestamp DateTime,\n    user_id UInt64,\n    event_type String,\n    value Float64\n) ENGINE = MergeTree()\nPARTITION BY toYYYYMM(timestamp)\nORDER BY (user_id, timestamp);\n\n-- ReplacingMergeTree（去重）\nCREATE TABLE user_profiles (\n    user_id UInt64,\n    name String,\n    email String,\n    updated_at DateTime\n) ENGINE = ReplacingMergeTree(updated_at)\nORDER BY user_id;\n\n-- SummingMergeTree（自动求和）\nCREATE TABLE metrics (\n    date Date,\n    metric_name String,\n    value Float64\n) ENGINE = SummingMergeTree()\nPARTITION BY toYYYYMM(date)\nORDER BY (date, metric_name);\n```\n\n### 2. 分区表\n\nClickHouse 支持按时间或其他维度分区：\n\n```sql\nCREATE TABLE logs (\n    timestamp DateTime,\n    level String,\n    message String\n) ENGINE = MergeTree()\nPARTITION BY toYYYYMMDD(timestamp)  -- 按天分区\nORDER BY timestamp;\n```\n\n### 3. 物化视图\n\n物化视图可以预计算聚合结果，加速查询：\n\n```sql\n-- 创建物化视图\nCREATE MATERIALIZED VIEW daily_stats\nENGINE = SummingMergeTree()\nPARTITION BY toYYYYMM(date)\nORDER BY (date, user_id)\nAS SELECT\n    toDate(timestamp) as date,\n    user_id,\n    COUNT(*) as event_count\nFROM events\nGROUP BY date, user_id;\n\n-- 查询物化视图\nSELECT * FROM daily_stats WHERE date = today();\n```\n\n### 4. 数组和嵌套类型\n\nClickHouse 支持数组和嵌套数据类型：\n\n```sql\nCREATE TABLE user_events (\n    user_id UInt64,\n    event_types Array(String),\n    event_times Array(DateTime),\n    metadata Nested(\n        key String,\n        value String\n    )\n) ENGINE = MergeTree()\nORDER BY user_id;\n\n-- 查询数组\nSELECT\n    user_id,\n    arrayJoin(event_types) as event_type\nFROM user_events;\n```\n\n### 5. 近似计算\n\nClickHouse 支持近似算法加速聚合查询：\n\n```sql\n-- 近似去重计数\nSELECT uniq(user_id) FROM events;  -- 精确\nSELECT uniqHLL12(user_id) FROM events;  -- 近似，更快\n\n-- 近似分位数\nSELECT quantile(0.95)(response_time) FROM requests;  -- 精确\nSELECT quantileTDigest(0.95)(response_time) FROM requests;  -- 近似\n```\n\n## 📊 性能优化建议\n\n### 1. 选择合适的排序键\n\n```sql\n-- 好的排序键设计\nCREATE TABLE events (\n    timestamp DateTime,\n    user_id UInt64,\n    event_type String\n) ENGINE = MergeTree()\nORDER BY (user_id, timestamp);  -- 常用查询条件\n\n-- 避免\nORDER BY timestamp;  -- 如果经常按 user_id 查询\n```\n\n### 2. 使用 PREWHERE 过滤\n\n```sql\n-- 使用 PREWHERE（更快）\nSELECT * FROM events\nPREWHERE timestamp >= today()\nWHERE event_type = 'click';\n\n-- 而不是只用 WHERE\nSELECT * FROM events\nWHERE timestamp >= today() AND event_type = 'click';\n```\n\n### 3. 合理使用分区\n\n```sql\n-- 按月分区（推荐）\nPARTITION BY toYYYYMM(timestamp)\n\n-- 按天分区（数据量大时）\nPARTITION BY toYYYYMMDD(timestamp)\n\n-- 避免过度分区\nPARTITION BY toHour(timestamp)  -- 通常不推荐\n```\n\n### 4. 选择合适的数据类型\n\n```sql\n-- 使用更小的数据类型\nuser_id UInt32  -- 而不是 UInt64（如果范围足够）\nstatus UInt8    -- 而不是 String（如果是枚举值）\n\n-- 使用 LowCardinality\nevent_type LowCardinality(String)  -- 对于重复值多的列\n```\n\n### 5. 批量插入\n\n```sql\n-- 批量插入（推荐）\nINSERT INTO events VALUES\n    (now(), 1, 'click'),\n    (now(), 2, 'view'),\n    (now(), 3, 'purchase');\n\n-- 避免单条插入\nINSERT INTO events VALUES (now(), 1, 'click');\nINSERT INTO events VALUES (now(), 2, 'view');\n```\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"clickhouse\",\n    \"--host\", \"localhost\",\n    \"--port\", \"8123\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER readonly_user IDENTIFIED BY 'password';\n\n-- 授予只读权限\nGRANT SELECT ON database_name.* TO readonly_user;\n```\n\n### 3. 使用 HTTPS\n\nClickHouse 支持 HTTPS 连接，保护数据传输安全：\n\n```json\n{\n  \"args\": [\n    \"--type\", \"clickhouse\",\n    \"--host\", \"your-instance.clickhouse.cloud\",\n    \"--port\", \"8443\"\n  ]\n}\n```\n\n### 4. 限制网络访问\n\n- 使用防火墙限制 ClickHouse 端口访问\n- 仅允许可信 IP 地址连接\n- 在生产环境中使用 VPN 或专线\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 ClickHouse 数据库\n\n**解决方案**：\n- 检查 ClickHouse 服务是否正在运行\n- 检查端口是否正确（HTTP: 8123, TCP: 9000）\n- 检查防火墙设置\n- 验证用户名和密码\n\n### 2. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间：`SET max_execution_time = 600`\n- 优化查询，使用 PREWHERE\n- 添加合适的索引\n- 使用 LIMIT 限制返回结果\n\n### 3. 内存不足\n\n**问题**：查询时内存不足\n\n**解决方案**：\n- 增加内存限制：`SET max_memory_usage = 10000000000`\n- 优化查询，减少内存使用\n- 使用流式查询\n- 分批处理数据\n\n### 4. 插入性能问题\n\n**问题**：数据插入速度慢\n\n**解决方案**：\n- 使用批量插入\n- 增加 `max_insert_block_size`\n- 使用异步插入\n- 优化表引擎和分区策略\n\n## 📚 参考资源\n\n- [ClickHouse 官方文档](https://clickhouse.com/docs/zh/)\n- [ClickHouse 快速开始](https://clickhouse.com/docs/zh/getting-started/quick-start)\n- [ClickHouse Cloud](https://clickhouse.cloud/)\n- [ClickHouse GitHub](https://github.com/ClickHouse/ClickHouse)\n- [ClickHouse 中文社区](https://clickhouse.com/docs/zh/community)\n\n## 🆚 ClickHouse vs 传统数据库\n\n| 特性 | ClickHouse | MySQL | PostgreSQL |\n|------|-----------|-------|------------|\n| 存储方式 | 列式存储 | 行式存储 | 行式存储 |\n| OLAP 性能 | ✅ 极快 | ❌ 慢 | ⚠️ 一般 |\n| OLTP 性能 | ❌ 不适合 | ✅ 快 | ✅ 快 |\n| 压缩率 | ✅ 高（10-100x） | ⚠️ 一般 | ⚠️ 一般 |\n| 实时插入 | ✅ 支持 | ✅ 支持 | ✅ 支持 |\n| 事务支持 | ❌ 有限 | ✅ 完整 | ✅ 完整 |\n| 更新/删除 | ⚠️ 异步 | ✅ 实时 | ✅ 实时 |\n| 分布式 | ✅ 原生支持 | ⚠️ 需要分库分表 | ⚠️ 需要扩展 |\n\n## 💡 最佳实践\n\n### 1. 表设计\n\n- 使用 MergeTree 系列引擎\n- 合理设计排序键（ORDER BY）\n- 按时间分区（PARTITION BY）\n- 选择合适的数据类型\n\n### 2. 查询优化\n\n- 使用 PREWHERE 过滤数据\n- 避免 SELECT *\n- 使用物化视图预计算\n- 合理使用近似算法\n\n### 3. 数据插入\n\n- 批量插入数据\n- 使用异步插入\n- 避免频繁的小批量插入\n- 合理设置 buffer 大小\n\n### 4. 监控和维护\n\n- 监控查询性能\n- 定期优化表（OPTIMIZE TABLE）\n- 清理过期分区\n- 监控磁盘空间使用\n\n### 5. 适用场景\n\n**适合**：\n- 大数据分析\n- 实时报表\n- 日志分析\n- 时序数据分析\n- 用户行为分析\n\n**不适合**：\n- 高频更新/删除\n- 事务处理（OLTP）\n- 小数据量场景\n- 需要强一致性的场景\n\n---\n\n**提示**：ClickHouse 是专为 OLAP 场景设计的数据库，在大数据分析场景下性能卓越，但不适合 OLTP 场景。选择数据库时请根据实际需求决定。\n"
  },
  {
    "path": "docs/databases/dameng.md",
    "content": "# 达梦数据库使用指南\n\n## 简介\n\nuniversal-db-mcp 现已支持达梦数据库（DM7/DM8）！达梦数据库驱动 `dmdb` 会作为可选依赖自动安装。\n\n## 安装\n\n### 方法 1: 全局安装（推荐）\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n达梦驱动 `dmdb` 会自动尝试安装。如果安装失败，请手动安装：\n\n```bash\nnpm install -g dmdb\n```\n\n### 方法 2: 本地项目安装\n\n```bash\nmkdir my-db-project\ncd my-db-project\nnpm init -y\nnpm install universal-db-mcp\n```\n\n## Claude Desktop 配置\n\n编辑 Claude Desktop 配置文件：\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"SYSDBA\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 连接远程数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"dm-server.example.com\",\n        \"--port\", \"5236\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"PRODUCTION\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式（谨慎使用）\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"DEVDB\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n## 使用示例\n\n### 查看数据库结构\n\n**用户**: 帮我查看数据库中的所有表\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 返回所有表的列表、列信息、主键、索引等\n\n### 查询数据\n\n**用户**: 查询 EMPLOYEES 表中部门编号为 10 的所有员工\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT * FROM EMPLOYEES WHERE DEPT_ID = 10`\n3. 执行查询并返回结果\n\n### 统计分析\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT DEPT_ID, COUNT(*) as EMP_COUNT FROM EMPLOYEES GROUP BY DEPT_ID`\n2. 执行并返回结果\n\n### 查看表结构\n\n**用户**: 查看 EMPLOYEES 表的详细结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 返回列定义、数据类型、主键、索引等详细信息\n\n## 注意事项\n\n### 1. 驱动安装\n\n- `dmdb` 驱动会作为可选依赖自动安装\n- 如果自动安装失败，请手动运行：`npm install -g dmdb`\n- 驱动版本：1.0.46190（会自动使用最新版本）\n\n### 2. 默认端口\n\n- 达梦数据库默认端口：5236\n- 如果使用其他端口，请在配置中指定\n\n### 3. 大小写敏感\n\n- 达梦数据库默认将表名和列名存储为大写\n- 查询结果会自动转换为小写以保持一致性\n- 在 SQL 中使用表名时建议使用大写或双引号\n\n### 4. 多 Schema 支持\n\n- 自动获取当前用户有权访问的所有用户的表（排除 SYS、SYSTEM 等系统用户）\n- 当前用户的表直接使用表名（如 `EMPLOYEES`），其他用户的表使用 `owner.table_name` 格式（如 `HR.EMPLOYEES`）\n- 查询时支持使用 `owner.table_name` 格式精确指定表\n\n### 5. 兼容性\n\n- 达梦数据库高度兼容 Oracle\n- 支持 Oracle 风格的 SQL 语法\n- 支持 PL/SQL 存储过程\n\n### 6. 安全模式\n\n- 默认为只读模式，阻止所有写操作\n- 需要写入时使用 `--permission-mode readwrite` 或 `--permission-mode full`\n- 生产环境强烈建议使用只读模式\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **心跳保活** - 每 30 秒发送心跳（`SELECT 1 FROM DUAL`），防止连接被服务端超时关闭\n- **断线自动重连** - 检测到连接断开时自动重建连接并重试操作\n- **错误检测** - 自动识别 `ECONNRESET`、`EPIPE`、`ETIMEDOUT` 等连接断开错误\n\n## 故障排查\n\n### 问题 1: 驱动未安装\n\n**错误**: `达梦数据库驱动未安装`\n\n**解决方案**:\n```bash\nnpm install -g dmdb\n```\n\n### 问题 2: 连接失败\n\n**错误**: `达梦数据库连接失败: 无法连接到数据库服务器`\n\n**解决方案**:\n1. 检查达梦数据库服务是否运行\n2. 验证主机地址和端口是否正确\n3. 检查防火墙设置\n4. 确认网络连接正常\n\n### 问题 3: 用户名或密码错误\n\n**错误**: `达梦数据库连接失败: 用户名或密码无效`\n\n**解决方案**:\n1. 确认用户名和密码正确\n2. 检查用户是否有连接权限\n3. 确认数据库名称正确\n\n### 问题 4: 表或视图不存在\n\n**错误**: `查询执行失败: 表或视图不存在`\n\n**解决方案**:\n1. 确认表名拼写正确（注意大小写）\n2. 检查当前用户是否有访问该表的权限\n3. 使用 `get_schema` 工具查看所有可用的表\n\n## 更多帮助\n\n- 查看 [README.md](./README.md) 了解项目概述\n- 查看 [EXAMPLES.md](./EXAMPLES.md) 了解更多使用示例\n- 提交 Issue: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- 达梦官网: https://www.dameng.com/\n"
  },
  {
    "path": "docs/databases/gaussdb.md",
    "content": "# GaussDB / OpenGauss 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"gaussdb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"gaussdb\",\n        \"--password\", \"your_password\",\n        \"--database\", \"postgres\"\n      ]\n    }\n  }\n}\n```\n\n### 连接华为云 GaussDB\n\n```json\n{\n  \"mcpServers\": {\n    \"gaussdb-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"gaussdb.cn-north-4.myhuaweicloud.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"dbuser\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 5432 |\n| `--user` | 用户名 | - |\n| `--password` | 密码 | - |\n| `--database` | 数据库名 | - |\n\n## 类型参数\n\n可以使用以下类型参数：\n- `--type gaussdb`\n- `--type opengauss`\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 查看数据库中有哪些表\n\nClaude 会自动:\n1. 调用 get_schema 工具\n2. 查询所有用户 Schema 下的表\n3. 返回表列表\n```\n\n### 执行查询\n\n```\n用户: 统计每个类别的产品数量\n\nClaude 会自动:\n1. 生成 SQL: SELECT category, COUNT(*) as count FROM products GROUP BY category\n2. 执行并返回结果\n```\n\n## 兼容性\n\nGaussDB/OpenGauss 基于 PostgreSQL 开发，兼容 PostgreSQL 协议和大部分 SQL 语法。\n\n## 支持的版本\n\n- GaussDB 100/200/300 系列\n- OpenGauss 2.x / 3.x / 5.x\n\n## 特色功能\n\n- **列存储** - 支持列存储表\n- **分区表** - 增强的分区表功能\n- **并行查询** - 更强的并行查询能力\n- **AI 能力** - 内置 AI 引擎（部分版本）\n\n## 注意事项\n\n1. **默认端口** - 与 PostgreSQL 相同（5432）\n2. **多 Schema 支持** - 自动获取所有用户 Schema 下的表。`public` Schema 下的表直接使用表名，其他 Schema 的表使用 `schema.table_name` 格式。\n3. **参数化查询** - 支持 $1, $2, ... 占位符\n4. **驱动** - 使用 PostgreSQL 的 pg 驱动\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 pg 连接池（最大 3 个连接），自动管理连接生命周期\n- **TCP Keep-Alive** - 启用 TCP 保活机制（30 秒初始延迟），防止连接被服务端超时关闭\n- **断线自动重试** - 检测到连接断开（如 `Connection terminated`、`ECONNRESET`）时自动重试\n"
  },
  {
    "path": "docs/databases/goldendb.md",
    "content": "# GoldenDB 数据库使用指南\n\n## 📖 关于 GoldenDB\n\nGoldenDB 是中兴通讯自主研发的企业级分布式关系型数据库，完全兼容 MySQL 协议。GoldenDB 采用分布式架构，支持水平扩展、分布式事务和高可用性，广泛应用于电信、金融等行业。\n\n### 主要特点\n\n- **MySQL 兼容**：完全兼容 MySQL 5.7/8.0 协议和语法\n- **分布式架构**：支持水平扩展和分布式事务\n- **高可用**：支持主备切换和自动故障转移\n- **高性能**：优化的查询引擎，支持高并发\n- **电信级可靠性**：满足电信级可靠性要求\n- **国产化**：支持国产操作系统和芯片\n\n## 🚀 快速开始\n\n### 1. 安装 GoldenDB\n\n#### 在 Linux 上安装\n\n```bash\n# 下载 GoldenDB 安装包（从官网或中兴获取）\n# 解压安装包\ntar -xzf goldendb-xxx.tar.gz\n\n# 进入安装目录\ncd goldendb-xxx\n\n# 执行安装脚本\n./install.sh\n\n# 初始化数据库\n./bin/mysqld --initialize-insecure\n\n# 启动数据库\n./bin/mysqld_safe &\n```\n\n#### 使用 Docker\n\n```bash\n# 拉取 GoldenDB 镜像（如果有官方镜像）\ndocker pull goldendb/goldendb:latest\n\n# 启动 GoldenDB 容器\ndocker run -d --name goldendb-server \\\n  -p 3306:3306 \\\n  -e MYSQL_ROOT_PASSWORD=your_password \\\n  goldendb/goldendb:latest\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n#### 连接 GoldenDB 分布式集群\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"goldendb-cluster.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 GoldenDB 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 users 表中的所有用户\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM users;\n```\n\n### 聚合查询\n\n```\n你：统计每个部门的员工数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT department, COUNT(*) as employee_count\nFROM employees\nGROUP BY department;\n```\n\n### 复杂查询\n\n```\n你：找出最近 30 天内消费金额超过 1000 元的用户，按消费金额降序排列\n```\n\nClaude 会生成并执行：\n```sql\nSELECT u.id, u.name, SUM(o.amount) as total_amount\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.name\nHAVING total_amount > 1000\nORDER BY total_amount DESC;\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n```\n你：在 users 表中插入一条新用户记录，姓名为张三，邮箱为 zhangsan@example.com\n```\n\nClaude 会生成并执行：\n```sql\nINSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');\n```\n\n## 🔧 GoldenDB 特性支持\n\n### 1. 分布式事务\n\nGoldenDB 支持分布式事务：\n\n```sql\nSTART TRANSACTION;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n### 2. 分库分表\n\nGoldenDB 支持自动分库分表：\n\n```sql\n-- 创建分片表\nCREATE TABLE orders (\n    id BIGINT PRIMARY KEY,\n    user_id BIGINT,\n    amount DECIMAL(10, 2),\n    created_at DATETIME\n) SHARD_KEY(user_id);\n```\n\n### 3. 读写分离\n\nGoldenDB 支持读写分离架构：\n\n```sql\n-- 写操作（使用主节点）\nINSERT INTO orders (user_id, amount) VALUES (1, 100);\n\n-- 读操作（可以使用只读节点）\nSELECT * FROM orders WHERE user_id = 1;\n```\n\n### 4. 高可用\n\nGoldenDB 支持主备切换和自动故障转移。\n\n## 📊 性能优化建议\n\n### 1. 使用 EXPLAIN 分析查询\n\n```sql\nEXPLAIN SELECT * FROM users WHERE age > 18;\n```\n\n### 2. 创建合适的索引\n\n```sql\n-- 单列索引\nCREATE INDEX idx_age ON users(age);\n\n-- 复合索引\nCREATE INDEX idx_name_age ON users(name, age);\n\n-- 唯一索引\nCREATE UNIQUE INDEX idx_email ON users(email);\n```\n\n### 3. 使用 ANALYZE 更新统计信息\n\n```sql\nANALYZE TABLE users;\n```\n\n### 4. 批量插入优化\n\n```sql\n-- 使用批量插入而不是单条插入\nINSERT INTO users (name, email) VALUES\n    ('user1', 'user1@example.com'),\n    ('user2', 'user2@example.com'),\n    ('user3', 'user3@example.com');\n```\n\n### 5. 合理设计分片键\n\n- 选择分布均匀的列作为分片键\n- 避免热点数据\n- 考虑查询模式\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"goldendb\",\n    \"--host\", \"localhost\",\n    \"--port\", \"3306\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER 'readonly_user'@'%' IDENTIFIED BY 'password';\n\n-- 授予只读权限\nGRANT SELECT ON database_name.* TO 'readonly_user'@'%';\n\n-- 刷新权限\nFLUSH PRIVILEGES;\n```\n\n### 3. 使用 SSL/TLS 连接\n\nGoldenDB 支持 SSL/TLS 加密连接，保护数据传输安全。\n\n### 4. 限制网络访问\n\n- 使用防火墙限制 GoldenDB 端口（3306）的访问\n- 仅允许可信 IP 地址连接\n- 在生产环境中使用 VPN 或专线\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 GoldenDB 数据库\n\n**解决方案**：\n- 检查 GoldenDB 服务是否正在运行\n- 检查端口是否正确（默认 3306）\n- 检查防火墙设置\n- 验证用户名和密码\n\n### 2. 连接断开\n\n**问题**：长时间空闲后出现 `Can't add new command when connection is in closed state`\n\n**说明**：MCP 服务已内置连接池 + TCP Keep-Alive + 断线自动重试机制，正常情况下不会出现此问题。如果仍然出现，请检查网络环境是否存在强制断开空闲连接的策略。\n\n### 3. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间\n- 优化查询，添加合适的索引\n- 使用 LIMIT 限制返回结果数量\n- 考虑使用分区表\n\n### 3. 字符编码问题\n\n**问题**：中文显示乱码\n\n**解决方案**：\n- 确保数据库使用 UTF-8 编码：\n  ```sql\n  CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n  ```\n\n### 4. 分布式查询性能\n\n**问题**：跨分片查询性能差\n\n**解决方案**：\n- 优化分片键设计\n- 避免跨分片 JOIN\n- 使用全局表存储小表\n- 考虑数据冗余\n\n## 📚 参考资源\n\n- [中兴通讯官网](https://www.zte.com.cn/)\n- [GoldenDB 产品介绍](https://www.zte.com.cn/china/products/database/)\n- [MySQL 官方文档](https://dev.mysql.com/doc/)\n\n## 🆚 GoldenDB vs MySQL\n\n| 特性 | GoldenDB | MySQL |\n|------|----------|-------|\n| 架构 | 分布式架构 | 单机架构 |\n| 水平扩展 | ✅ 原生支持 | ❌ 需要分库分表 |\n| 分布式事务 | ✅ 原生支持 | ❌ 不支持 |\n| 高可用 | ✅ 自动故障转移 | ⚠️ 需要额外配置 |\n| 协议兼容 | ✅ MySQL 5.7/8.0 | - |\n| 国产化 | ✅ 支持 | ❌ 不支持 |\n| 成本 | ⚠️ 商业授权 | ✅ 开源免费 |\n\n## 💡 最佳实践\n\n### 1. 分片设计\n\n- 选择合适的分片键\n- 保证数据分布均匀\n- 避免热点数据\n- 考虑业务查询模式\n\n### 2. 查询优化\n\n- 避免 SELECT *，只查询需要的列\n- 使用 LIMIT 限制返回结果\n- 合理使用索引\n- 避免跨分片查询\n\n### 3. 事务管理\n\n- 合理使用分布式事务\n- 避免长事务\n- 注意事务隔离级别\n- 处理分布式死锁\n\n### 4. 监控和维护\n\n- 监控集群状态\n- 关注分片数据分布\n- 定期检查慢查询\n- 定期备份数据\n\n### 5. 高可用配置\n\n- 配置主备节点\n- 启用自动故障转移\n- 定期演练故障切换\n- 监控节点健康状态\n\n## 🎯 适用场景\n\n### 适合使用 GoldenDB 的场景\n\n- ✅ 电信行业应用\n- ✅ 金融交易系统\n- ✅ 大规模分布式应用\n- ✅ 需要水平扩展的业务\n- ✅ 高并发读写场景\n- ✅ 国产化替代需求\n\n### 不适合使用 GoldenDB 的场景\n\n- ❌ 小型单机应用\n- ❌ 预算非常有限\n- ❌ 数据量很小的应用\n- ❌ 不需要分布式特性\n\n---\n\n**提示**：GoldenDB 是中兴通讯的分布式数据库，特别适合电信、金融等行业的大规模应用场景。如果您需要分布式架构和商业支持，GoldenDB 是一个很好的选择。\n"
  },
  {
    "path": "docs/databases/highgo.md",
    "content": "# HighGo 数据库使用指南\n\n## 📖 关于 HighGo\n\nHighGo（瀚高）数据库是瀚高基础软件股份有限公司自主研发的企业级关系型数据库管理系统。HighGo 基于 PostgreSQL 开发，完全兼容 PostgreSQL 协议，支持国产化替代，广泛应用于政府、金融、电信、能源等行业。\n\n### 主要特点\n\n- **PostgreSQL 兼容**：完全兼容 PostgreSQL 9.x/10.x/11.x 协议和语法\n- **国产自主**：支持国产操作系统和芯片\n- **企业级特性**：高可用、数据加密、审计日志\n- **Oracle 兼容**：部分版本支持 Oracle 兼容模式\n- **高性能**：优化的查询引擎和存储引擎\n\n## 🚀 快速开始\n\n### 1. 安装 HighGo\n\n#### 在 Linux 上安装\n\n```bash\n# 下载 HighGo 安装包（从官网获取）\n# 解压安装包\ntar -xzf highgo-xxx.tar.gz\n\n# 进入安装目录\ncd highgo-xxx\n\n# 执行安装脚本\n./install.sh\n\n# 初始化数据库\ninitdb -D /path/to/data\n\n# 启动数据库\npg_ctl start -D /path/to/data\n```\n\n#### 使用 Docker\n\n```bash\n# 拉取 HighGo 镜像（如果有官方镜像）\ndocker pull highgo/highgo:latest\n\n# 启动 HighGo 容器\ndocker run -d --name highgo-server \\\n  -p 5866:5866 \\\n  -e POSTGRES_PASSWORD=your_password \\\n  highgo/highgo:latest\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"highgo\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5866\",\n        \"--user\", \"highgo\",\n        \"--password\", \"your_password\",\n        \"--database\", \"highgo\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"highgo\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5866\",\n        \"--user\", \"highgo\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n#### 连接 HighGo 集群\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"highgo\",\n        \"--host\", \"highgo-cluster.example.com\",\n        \"--port\", \"5866\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 HighGo 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 users 表中的所有用户\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM users;\n```\n\n### 聚合查询\n\n```\n你：统计每个部门的员工数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT department, COUNT(*) as employee_count\nFROM employees\nGROUP BY department;\n```\n\n### 复杂查询\n\n```\n你：找出最近 30 天内消费金额超过 1000 元的用户，按消费金额降序排列\n```\n\nClaude 会生成并执行：\n```sql\nSELECT u.id, u.name, SUM(o.amount) as total_amount\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE o.created_at >= CURRENT_DATE - INTERVAL '30 days'\nGROUP BY u.id, u.name\nHAVING SUM(o.amount) > 1000\nORDER BY total_amount DESC;\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n```\n你：在 users 表中插入一条新用户记录，姓名为张三，邮箱为 zhangsan@example.com\n```\n\nClaude 会生成并执行：\n```sql\nINSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');\n```\n\n## 🔧 HighGo 特性支持\n\n### 1. PostgreSQL 兼容性\n\nHighGo 完全兼容 PostgreSQL 协议：\n\n```sql\n-- 标准 PostgreSQL 语法\nCREATE TABLE employees (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100),\n    department VARCHAR(50),\n    salary NUMERIC(10, 2),\n    hire_date DATE\n);\n\n-- 创建索引\nCREATE INDEX idx_department ON employees(department);\n\n-- 查询\nSELECT * FROM employees WHERE department = 'IT';\n```\n\n### 2. 分区表\n\nHighGo 支持表分区：\n\n```sql\n-- 创建分区表\nCREATE TABLE orders (\n    id SERIAL,\n    user_id INTEGER,\n    amount NUMERIC(10, 2),\n    created_at DATE\n) PARTITION BY RANGE (created_at);\n\n-- 创建分区\nCREATE TABLE orders_2024_01 PARTITION OF orders\n    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');\n\nCREATE TABLE orders_2024_02 PARTITION OF orders\n    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');\n```\n\n### 3. 事务支持\n\nHighGo 支持完整的 ACID 事务：\n\n```sql\nBEGIN;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n### 4. JSON 支持\n\nHighGo 支持 JSON 和 JSONB 数据类型：\n\n```sql\n-- 创建包含 JSON 的表\nCREATE TABLE products (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100),\n    attributes JSONB\n);\n\n-- 插入 JSON 数据\nINSERT INTO products (name, attributes) VALUES\n    ('Product A', '{\"color\": \"red\", \"size\": \"large\"}');\n\n-- 查询 JSON 数据\nSELECT * FROM products WHERE attributes->>'color' = 'red';\n```\n\n### 5. Oracle 兼容模式（部分版本）\n\nHighGo 部分版本支持 Oracle 兼容模式：\n\n```sql\n-- Oracle 风格的序列\nCREATE SEQUENCE seq_id START WITH 1 INCREMENT BY 1;\n\n-- Oracle 风格的函数\nSELECT SYSDATE FROM DUAL;\n```\n\n## 📊 性能优化建议\n\n### 1. 使用 EXPLAIN 分析查询\n\n```sql\nEXPLAIN ANALYZE SELECT * FROM users WHERE age > 18;\n```\n\n### 2. 创建合适的索引\n\n```sql\n-- 单列索引\nCREATE INDEX idx_age ON users(age);\n\n-- 复合索引\nCREATE INDEX idx_name_age ON users(name, age);\n\n-- 唯一索引\nCREATE UNIQUE INDEX idx_email ON users(email);\n\n-- 部分索引\nCREATE INDEX idx_active_users ON users(email) WHERE active = true;\n```\n\n### 3. 使用 ANALYZE 更新统计信息\n\n```sql\nANALYZE users;\nANALYZE;  -- 分析所有表\n```\n\n### 4. 定期执行 VACUUM\n\n```sql\nVACUUM users;\nVACUUM FULL;  -- 完全清理\nVACUUM ANALYZE;  -- 清理并更新统计信息\n```\n\n### 5. 批量插入优化\n\n```sql\n-- 使用批量插入\nINSERT INTO users (name, email) VALUES\n    ('user1', 'user1@example.com'),\n    ('user2', 'user2@example.com'),\n    ('user3', 'user3@example.com');\n\n-- 使用 COPY 命令（更快）\nCOPY users (name, email) FROM '/path/to/data.csv' CSV;\n```\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"highgo\",\n    \"--host\", \"localhost\",\n    \"--port\", \"5866\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER readonly_user WITH PASSWORD 'password';\n\n-- 授予只读权限\nGRANT CONNECT ON DATABASE mydb TO readonly_user;\nGRANT USAGE ON SCHEMA public TO readonly_user;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;\n\n-- 设置默认权限\nALTER DEFAULT PRIVILEGES IN SCHEMA public\n    GRANT SELECT ON TABLES TO readonly_user;\n\n-- 如需访问其他 schema，需要额外授权\n-- GRANT USAGE ON SCHEMA analytics TO readonly_user;\n-- GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO readonly_user;\n-- ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO readonly_user;\n```\n\n### 3. 使用 SSL/TLS 连接\n\nHighGo 支持 SSL/TLS 加密连接：\n\n```sql\n-- 在 postgresql.conf 中启用 SSL\nssl = on\nssl_cert_file = 'server.crt'\nssl_key_file = 'server.key'\n```\n\n### 4. 限制网络访问\n\n在 `pg_hba.conf` 中配置访问控制：\n\n```\n# TYPE  DATABASE        USER            ADDRESS                 METHOD\nhost    all             all             192.168.1.0/24          md5\nhost    all             all             ::1/128                 md5\n```\n\n### 5. 启用审计日志\n\n```sql\n-- 启用审计日志\nALTER SYSTEM SET log_statement = 'all';\nALTER SYSTEM SET log_connections = on;\nALTER SYSTEM SET log_disconnections = on;\n\n-- 重新加载配置\nSELECT pg_reload_conf();\n```\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 HighGo 数据库\n\n**解决方案**：\n- 检查 HighGo 服务是否正在运行\n- 检查端口是否正确（默认 5866）\n- 检查防火墙设置\n- 验证用户名和密码\n- 检查 `pg_hba.conf` 配置\n\n### 2. 连接断开\n\n**问题**：长时间空闲后出现 `Connection terminated unexpectedly`\n\n**说明**：MCP 服务已内置连接池 + TCP Keep-Alive + 断线自动重试机制，正常情况下不会出现此问题。如果仍然出现，请检查网络环境是否存在强制断开空闲连接的策略。\n\n### 3. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间：`SET statement_timeout = '600s';`\n- 优化查询，添加合适的索引\n- 使用 LIMIT 限制返回结果数量\n- 考虑使用分区表\n\n### 3. 字符编码问题\n\n**问题**：中文显示乱码\n\n**解决方案**：\n- 确保数据库使用 UTF-8 编码：\n  ```sql\n  CREATE DATABASE mydb WITH ENCODING 'UTF8';\n  ```\n\n### 4. 性能问题\n\n**问题**：查询性能慢\n\n**解决方案**：\n- 使用 EXPLAIN ANALYZE 分析查询\n- 创建合适的索引\n- 定期执行 VACUUM 和 ANALYZE\n- 优化查询语句\n- 考虑使用物化视图\n\n## 📚 参考资源\n\n- [HighGo 官方网站](http://www.highgo.com/)\n- [HighGo 产品文档](http://www.highgo.com/products/)\n- [PostgreSQL 官方文档](https://www.postgresql.org/docs/)\n- [瀚高技术支持](http://www.highgo.com/support/)\n\n## 🆚 HighGo vs PostgreSQL\n\n| 特性 | HighGo | PostgreSQL |\n|------|--------|------------|\n| 协议兼容 | ✅ 完全兼容 | - |\n| 国产化 | ✅ 支持 | ❌ 不支持 |\n| 企业支持 | ✅ 商业支持 | ⚠️ 社区支持 |\n| 高可用 | ✅ 内置支持 | ⚠️ 需要额外配置 |\n| 数据加密 | ✅ TDE 支持 | ⚠️ 有限支持 |\n| 审计日志 | ✅ 完善 | ⚠️ 基础 |\n| Oracle 兼容 | ✅ 部分支持 | ❌ 不支持 |\n| 成本 | ⚠️ 商业授权 | ✅ 开源免费 |\n\n## 💡 最佳实践\n\n### 1. 数据库设计\n\n- 使用合适的数据类型\n- 合理设计主键和外键\n- 使用分区表处理大数据量\n- 避免过度规范化\n\n### 2. 查询优化\n\n- 避免 SELECT *，只查询需要的列\n- 使用 LIMIT 限制返回结果\n- 合理使用索引\n- 避免在 WHERE 子句中使用函数\n\n### 3. 连接管理\n\n- 使用连接池（如 pgBouncer）\n- 合理设置连接数\n- 使用长连接减少连接开销\n- 定期检查连接健康状态\n\n### 4. 监控和维护\n\n- 监控数据库性能指标\n- 定期执行 VACUUM\n- 更新统计信息（ANALYZE）\n- 定期备份数据\n- 监控慢查询日志\n\n### 5. 安全管理\n\n- 使用强密码\n- 限制网络访问\n- 启用 SSL 连接\n- 定期审计日志\n- 遵循最小权限原则\n\n## 🎯 适用场景\n\n### 适合使用 HighGo 的场景\n\n- ✅ 国产化替代需求\n- ✅ 政府、金融、电信、能源行业\n- ✅ 需要商业支持的企业\n- ✅ 对安全性要求高的场景\n- ✅ 需要完善审计功能\n- ✅ PostgreSQL 迁移\n- ✅ Oracle 迁移（兼容模式）\n\n### 不适合使用 HighGo 的场景\n\n- ❌ 预算非常有限\n- ❌ 小型个人项目\n- ❌ 不需要商业支持\n- ❌ 对国产化无要求\n\n## 🌟 HighGo 特色功能\n\n### 1. 国产化支持\n\n- 支持国产操作系统（麒麟、统信等）\n- 支持国产芯片（鲲鹏、飞腾、龙芯等）\n- 完全自主可控\n\n### 2. 企业级高可用\n\n- 主备切换\n- 自动故障转移\n- 数据同步复制\n\n### 3. 数据加密\n\n- 透明数据加密（TDE）\n- 列级加密\n- 传输加密\n\n### 4. 审计日志\n\n- 完善的审计日志\n- 操作记录追溯\n- 合规性支持\n\n### 5. Oracle 兼容\n\n- 部分版本支持 Oracle 兼容模式\n- 简化 Oracle 迁移\n- 兼容 Oracle PL/SQL\n\n---\n\n**提示**：HighGo 是国产数据库的优秀代表，特别适合有国产化替代需求的企业和政府机构。如果您需要商业支持和完善的企业级特性，HighGo 是一个很好的选择。\n"
  },
  {
    "path": "docs/databases/kingbase.md",
    "content": "# KingbaseES 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 连接远程 KingbaseES\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"kingbase.example.com\",\n        \"--port\", \"54321\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 54321 |\n| `--user` | 用户名 | - |\n| `--password` | 密码 | - |\n| `--database` | 数据库名 | - |\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 查看数据库中有哪些表\n\nClaude 会自动:\n1. 调用 get_schema 工具\n2. 查询所有用户 Schema 下的表\n3. 返回表列表\n```\n\n### 执行查询\n\n```\n用户: 统计每个部门的员工数量\n\nClaude 会自动:\n1. 生成 SQL: SELECT department_id, COUNT(*) as count FROM employees GROUP BY department_id\n2. 执行并返回结果\n```\n\n## 兼容性\n\nKingbaseES 基于 PostgreSQL 开发，兼容 PostgreSQL 协议和 SQL 语法。\n\n## 支持的版本\n\n- KingbaseES V8\n- KingbaseES V9\n\n## 常见使用场景\n\n### 国产化数据库迁移\n\n从 PostgreSQL 迁移到 KingbaseES：\n\n```\n用户: 帮我分析现有表结构，准备迁移到 KingbaseES\n\nClaude 会:\n1. 获取完整的 Schema 信息\n2. 分析表结构、索引、约束\n3. 提供迁移建议\n```\n\n## 注意事项\n\n1. **默认端口** - 54321（与 PostgreSQL 不同）\n2. **多 Schema 支持** - 自动获取所有用户 Schema 下的表。`public` Schema 下的表直接使用表名，其他 Schema 的表使用 `schema.table_name` 格式。\n3. **参数化查询** - 支持 $1, $2, ... 占位符\n4. **驱动** - 使用 PostgreSQL 的 pg 驱动\n5. **国产化** - 适用于国产化替代场景\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 pg 连接池（最大 3 个连接），自动管理连接生命周期\n- **TCP Keep-Alive** - 启用 TCP 保活机制（30 秒初始延迟），防止连接被服务端超时关闭\n- **断线自动重试** - 检测到连接断开（如 `Connection terminated`、`ECONNRESET`）时自动重试\n"
  },
  {
    "path": "docs/databases/mongodb.md",
    "content": "# MongoDB 数据库使用指南\n\n本指南详细介绍如何使用 MCP 数据库万能连接器连接和操作 MongoDB 数据库。\n\n## 📋 目录\n\n- [快速开始](#快速开始)\n- [连接配置](#连接配置)\n- [查询语法](#查询语法)\n- [常见操作示例](#常见操作示例)\n- [高级功能](#高级功能)\n- [故障排查](#故障排查)\n- [最佳实践](#最佳实践)\n\n---\n\n## 快速开始\n\n### 前置要求\n\n- Node.js >= 20\n- Claude Desktop 应用\n- MongoDB 4.0 或更高版本\n\n### 安装\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n### 基础配置\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n添加以下配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n重启 Claude Desktop 即可使用。\n\n---\n\n## 连接配置\n\n### 本地 MongoDB（无认证）\n\n适用于开发环境：\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 本地 MongoDB（带认证）\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-auth\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"myuser\",\n        \"--password\", \"mypassword\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: 默认认证数据库为 `admin`。如果需要使用其他认证数据库，可以通过环境变量设置。\n\n### 连接 MongoDB Atlas\n\nMongoDB Atlas 是 MongoDB 的云服务：\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-atlas\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"cluster0.xxxxx.mongodb.net\",\n        \"--port\", \"27017\",\n        \"--user\", \"atlasuser\",\n        \"--password\", \"atlaspassword\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n**提示**:\n- 从 Atlas 控制台获取连接字符串中的主机名\n- 确保 IP 地址已添加到 Atlas 白名单\n- 使用数据库用户凭据，不是 Atlas 账号密码\n\n### 连接副本集\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-replica\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"replica-primary.example.com\",\n        \"--port\", \"27017\",\n        \"--user\", \"replicauser\",\n        \"--password\", \"replicapassword\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: 当前版本连接到主节点，副本集自动故障转移功能将在未来版本支持。\n\n---\n\n## 查询语法\n\nMongoDB 适配器支持两种查询格式：\n\n### 1. JSON 格式（推荐）\n\n完整的 JSON 格式，支持所有参数：\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {\"age\": {\"$gt\": 18}},\n  \"options\": {\"limit\": 10, \"sort\": {\"name\": 1}}\n}\n```\n\n**字段说明**:\n- `collection`: 集合名称（必需）\n- `operation`: 操作名称（必需）\n- `query`: 查询条件（可选，默认为 `{}`）\n- `update`: 更新内容（update 操作需要）\n- `pipeline`: 聚合管道（aggregate 操作需要）\n- `options`: 额外选项（可选）\n\n### 2. 简化格式\n\n类似 MongoDB Shell 的语法：\n\n```javascript\ndb.users.find({\"age\": {\"$gt\": 18}})\n```\n\n**限制**: 简化格式只支持基本查询，不支持复杂选项。\n\n---\n\n## 常见操作示例\n\n### 查询操作\n\n#### 查询所有文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {}\n}\n```\n\n或简化格式：\n```javascript\ndb.users.find({})\n```\n\n#### 条件查询\n\n查询年龄大于 18 的用户：\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {\"age\": {\"$gt\": 18}}\n}\n```\n\n#### 查询单个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"findOne\",\n  \"query\": {\"email\": \"user@example.com\"}\n}\n```\n\n#### 限制返回数量\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {},\n  \"options\": {\"limit\": 10}\n}\n```\n\n#### 排序\n\n按创建时间倒序：\n\n```json\n{\n  \"collection\": \"orders\",\n  \"operation\": \"find\",\n  \"query\": {},\n  \"options\": {\"sort\": {\"createdAt\": -1}, \"limit\": 20}\n}\n```\n\n#### 统计文档数量\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"count\",\n  \"query\": {\"status\": \"active\"}\n}\n```\n\n#### 获取不同值\n\n获取所有不同的城市：\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"distinct\",\n  \"query\": {},\n  \"options\": {\"field\": \"city\"}\n}\n```\n\n### 聚合操作\n\n#### 分组统计\n\n统计每个城市的用户数量：\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"aggregate\",\n  \"pipeline\": [\n    {\"$group\": {\"_id\": \"$city\", \"count\": {\"$sum\": 1}}},\n    {\"$sort\": {\"count\": -1}}\n  ]\n}\n```\n\n#### 复杂聚合\n\n计算每个类别的平均价格：\n\n```json\n{\n  \"collection\": \"products\",\n  \"operation\": \"aggregate\",\n  \"pipeline\": [\n    {\"$match\": {\"status\": \"active\"}},\n    {\"$group\": {\n      \"_id\": \"$category\",\n      \"avgPrice\": {\"$avg\": \"$price\"},\n      \"count\": {\"$sum\": 1}\n    }},\n    {\"$sort\": {\"avgPrice\": -1}}\n  ]\n}\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n#### 插入单个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"insertOne\",\n  \"query\": {\n    \"name\": \"张三\",\n    \"email\": \"zhangsan@example.com\",\n    \"age\": 25,\n    \"createdAt\": \"2024-01-01T00:00:00Z\"\n  }\n}\n```\n\n#### 插入多个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"insertMany\",\n  \"query\": [\n    {\"name\": \"李四\", \"age\": 30},\n    {\"name\": \"王五\", \"age\": 28}\n  ]\n}\n```\n\n#### 更新单个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"updateOne\",\n  \"query\": {\"email\": \"user@example.com\"},\n  \"update\": {\"$set\": {\"age\": 26, \"updatedAt\": \"2024-01-02T00:00:00Z\"}}\n}\n```\n\n#### 更新多个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"updateMany\",\n  \"query\": {\"status\": \"inactive\"},\n  \"update\": {\"$set\": {\"status\": \"archived\"}}\n}\n```\n\n#### 删除单个文档\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"deleteOne\",\n  \"query\": {\"_id\": \"507f1f77bcf86cd799439011\"}\n}\n```\n\n#### 删除多个文档\n\n```json\n{\n  \"collection\": \"logs\",\n  \"operation\": \"deleteMany\",\n  \"query\": {\"createdAt\": {\"$lt\": \"2023-01-01T00:00:00Z\"}}\n}\n```\n\n---\n\n## 高级功能\n\n### 复杂查询条件\n\n#### 逻辑运算符\n\n使用 `$and`, `$or`, `$not`:\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {\n    \"$or\": [\n      {\"age\": {\"$gt\": 30}},\n      {\"city\": \"北京\"}\n    ]\n  }\n}\n```\n\n#### 数组查询\n\n查询包含特定标签的文档：\n\n```json\n{\n  \"collection\": \"posts\",\n  \"operation\": \"find\",\n  \"query\": {\"tags\": {\"$in\": [\"技术\", \"编程\"]}}\n}\n```\n\n#### 正则表达式\n\n查询名称包含\"张\"的用户：\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {\"name\": {\"$regex\": \"张\", \"$options\": \"i\"}}\n}\n```\n\n### 聚合管道高级用法\n\n#### Lookup（类似 JOIN）\n\n```json\n{\n  \"collection\": \"orders\",\n  \"operation\": \"aggregate\",\n  \"pipeline\": [\n    {\n      \"$lookup\": {\n        \"from\": \"users\",\n        \"localField\": \"userId\",\n        \"foreignField\": \"_id\",\n        \"as\": \"userInfo\"\n      }\n    },\n    {\"$unwind\": \"$userInfo\"},\n    {\"$limit\": 10}\n  ]\n}\n```\n\n#### 投影（选择字段）\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"aggregate\",\n  \"pipeline\": [\n    {\n      \"$project\": {\n        \"name\": 1,\n        \"email\": 1,\n        \"age\": 1,\n        \"_id\": 0\n      }\n    }\n  ]\n}\n```\n\n---\n\n## 故障排查\n\n### 连接失败\n\n**错误**: `MongoDB 连接失败: connect ECONNREFUSED`\n\n**解决方案**:\n1. 确认 MongoDB 服务正在运行：\n   ```bash\n   # Linux/Mac\n   sudo systemctl status mongod\n\n   # 或检查进程\n   ps aux | grep mongod\n   ```\n\n2. 检查端口是否正确（默认 27017）\n\n3. 检查防火墙规则\n\n### 认证失败\n\n**错误**: `MongoDB 连接失败: Authentication failed`\n\n**解决方案**:\n1. 确认用户名和密码正确\n\n2. 检查用户是否有访问指定数据库的权限：\n   ```javascript\n   // 在 MongoDB Shell 中\n   use admin\n   db.auth(\"username\", \"password\")\n\n   // 查看用户权限\n   db.getUser(\"username\")\n   ```\n\n3. 创建用户并授权：\n   ```javascript\n   use admin\n   db.createUser({\n     user: \"myuser\",\n     pwd: \"mypassword\",\n     roles: [\n       { role: \"readWrite\", db: \"myapp\" }\n     ]\n   })\n   ```\n\n### 写操作被拒绝\n\n**错误**: `操作被拒绝：当前处于只读安全模式`\n\n**解决方案**:\n- 根据需要使用 `--permission-mode readwrite` 或 `--permission-mode full`\n- **警告**: 仅在开发环境使用！\n\n### Atlas 连接问题\n\n**错误**: `MongoDB 连接失败: connection timeout`\n\n**解决方案**:\n1. 检查 IP 白名单：\n   - 登录 MongoDB Atlas\n   - 进入 Network Access\n   - 添加当前 IP 地址或使用 `0.0.0.0/0`（仅测试用）\n\n2. 确认连接字符串正确：\n   - 从 Atlas 控制台复制连接字符串\n   - 提取主机名（不包括 `mongodb://` 和参数）\n\n3. 检查用户权限：\n   - 在 Database Access 中确认用户存在\n   - 确认用户有访问目标数据库的权限\n\n---\n\n## 最佳实践\n\n### 安全建议\n\n1. **生产环境只读**:\n   - 永远不要在生产环境启用 `--permission-mode full`\n   - 使用只读用户连接生产数据库\n\n2. **最小权限原则**:\n   ```javascript\n   // 创建只读用户\n   use admin\n   db.createUser({\n     user: \"readonly\",\n     pwd: \"secure_password\",\n     roles: [\n       { role: \"read\", db: \"production\" }\n     ]\n   })\n   ```\n\n3. **网络安全**:\n   - 使用 VPN 或 SSH 隧道连接远程数据库\n   - 限制 IP 白名单\n   - 启用 TLS/SSL 加密连接\n\n4. **密码管理**:\n   - 不要在配置文件中明文存储密码\n   - 考虑使用环境变量或密钥管理服务\n\n### 性能优化\n\n1. **使用索引**:\n   - 为常用查询字段创建索引\n   - 使用 `explain()` 分析查询性能\n\n2. **限制返回数量**:\n   - 始终使用 `limit` 限制返回文档数量\n   - 避免查询大量数据\n\n3. **投影字段**:\n   - 只查询需要的字段\n   - 使用 `$project` 减少数据传输\n\n4. **聚合优化**:\n   - 在管道早期使用 `$match` 过滤数据\n   - 合理使用 `$limit` 和 `$skip`\n\n### 查询建议\n\n1. **使用 JSON 格式**:\n   - JSON 格式更清晰，支持所有功能\n   - 便于调试和维护\n\n2. **避免全表扫描**:\n   - 始终使用查询条件\n   - 为常用字段创建索引\n\n3. **处理大数据集**:\n   - 使用分页（`skip` 和 `limit`）\n   - 考虑使用游标（未来版本支持）\n\n4. **日期处理**:\n   - 使用 ISO 8601 格式存储日期\n   - 使用 `$gte` 和 `$lte` 进行范围查询\n\n---\n\n## 支持的 MongoDB 版本\n\n- MongoDB 4.0+\n- MongoDB 5.0+\n- MongoDB 6.0+\n- MongoDB 7.0+\n- MongoDB Atlas（所有版本）\n\n---\n\n## 常见问题\n\n### Q: 支持 MongoDB 连接字符串吗？\n\nA: 当前版本使用独立参数配置。完整连接字符串支持将在未来版本添加。\n\n### Q: 支持副本集和分片集群吗？\n\nA: 支持连接到副本集的主节点。完整的副本集和分片集群支持将在未来版本添加。\n\n### Q: 如何查看集合的结构？\n\nA: 使用 `get_schema` 工具，它会采样文档并推断字段结构。由于 MongoDB 是无模式数据库，结构信息是基于采样的。\n\n### Q: ObjectId 如何处理？\n\nA: 查询结果中的 ObjectId 会自动转换为字符串格式，便于阅读和使用。\n\n### Q: 支持事务吗？\n\nA: 当前版本不支持事务。事务支持将在未来版本添加。\n\n---\n\n## 更多资源\n\n- [MongoDB 官方文档](https://docs.mongodb.com/)\n- [MongoDB 查询语法](https://docs.mongodb.com/manual/tutorial/query-documents/)\n- [聚合管道](https://docs.mongodb.com/manual/core/aggregation-pipeline/)\n- [项目 GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n---\n\n**如果遇到问题，欢迎提交 Issue 或查看项目文档获取更多帮助！**\n"
  },
  {
    "path": "docs/databases/mysql.md",
    "content": "# MySQL 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 3306 |\n| `--user` | 用户名 | - |\n| `--password` | 密码 | - |\n| `--database` | 数据库名 | - |\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 帮我查看 users 表的结构\n\nClaude 会自动:\n1. 调用 get_table_info 工具\n2. 返回表的列信息、主键、索引等\n```\n\n### 执行查询\n\n```\n用户: 统计最近 7 天注册的用户数量\n\nClaude 会自动:\n1. 理解需求\n2. 生成 SQL: SELECT COUNT(*) FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)\n3. 执行查询并返回结果\n```\n\n### 复杂查询\n\n```\n用户: 找出消费金额最高的 10 个用户\n\nClaude 会自动:\n1. 查看相关表结构\n2. 生成 JOIN 查询\n3. 执行并返回结果\n```\n\n## 安全建议\n\n### 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER 'mcp_readonly'@'%' IDENTIFIED BY 'secure_password';\nGRANT SELECT ON mydb.* TO 'mcp_readonly'@'%';\nFLUSH PRIVILEGES;\n```\n\n### 限制访问权限\n\n```sql\n-- 只允许特定 IP 访问\nCREATE USER 'mcp_readonly'@'192.168.1.%' IDENTIFIED BY 'secure_password';\nGRANT SELECT ON mydb.* TO 'mcp_readonly'@'192.168.1.%';\n```\n\n## 支持的版本\n\n- MySQL 5.7+\n- MySQL 8.0+\n- MariaDB 10.x+\n\n## 注意事项\n\n1. **字符集** - 建议使用 utf8mb4 字符集\n2. **时区** - 注意服务器时区设置\n3. **连接数** - 注意 max_connections 限制\n4. **SSL** - 生产环境建议启用 SSL 连接\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 mysql2 连接池（最大 3 个连接），自动管理连接生命周期\n- **TCP Keep-Alive** - 启用 TCP 保活机制（30 秒初始延迟），防止连接被服务端 `wait_timeout` 关闭\n- **断线自动重试** - 检测到连接断开（如 `Connection in closed state`、`ECONNRESET`）时自动重试\n- 已彻底解决 `Can't add new command when connection is in closed state` 问题\n\n## 常见问题\n\n### 连接超时\n\n检查防火墙和安全组设置，确保端口 3306 可访问。\n\n### 权限不足\n\n确保用户有足够的权限访问目标数据库和表。\n\n### 字符编码问题\n\n确保数据库、表和连接都使用 utf8mb4 编码。\n"
  },
  {
    "path": "docs/databases/oceanbase.md",
    "content": "# OceanBase 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"root@test\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 连接阿里云 OceanBase\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"oceanbase.cn-hangzhou.aliyuncs.com\",\n        \"--port\", \"2883\",\n        \"--user\", \"dbuser@tenant\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 2881 |\n| `--user` | 用户名（格式：用户名@租户名） | - |\n| `--password` | 密码 | - |\n| `--database` | 数据库名 | - |\n\n## 端口说明\n\n- **2881** - 直连端口（直接连接 OBServer）\n- **2883** - 代理端口（通过 OBProxy 连接）\n\n## 用户名格式\n\nOceanBase 使用 `用户名@租户名` 格式：\n\n- `root@test` - test 租户的 root 用户\n- `user@sys` - sys 租户的 user 用户\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 查看数据库中有哪些表\n\nClaude 会自动:\n1. 调用 get_schema 工具\n2. 执行 SHOW TABLES 查询\n3. 返回表列表\n```\n\n### 执行查询\n\n```\n用户: 统计每个用户的订单数量\n\nClaude 会自动:\n1. 生成 SQL: SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id\n2. 执行并返回结果\n```\n\n## 兼容性\n\nOceanBase 兼容 MySQL 协议，支持大部分 MySQL 语法。\n\n## 支持的版本\n\n- OceanBase 3.x\n- OceanBase 4.x\n\n## 特色功能\n\n- **分布式事务** - 支持跨节点的分布式事务\n- **多租户** - 支持多租户隔离\n- **高可用** - 自动故障转移和数据恢复\n- **弹性扩展** - 支持在线扩容和缩容\n- **HTAP** - 同时支持 OLTP 和 OLAP 场景\n\n## 注意事项\n\n1. **用户名格式** - 必须包含租户名\n2. **端口选择** - 生产环境建议使用 OBProxy\n3. **SQL 语法** - 使用 MySQL 语法\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 mysql2 连接池（最大 3 个连接），自动管理连接生命周期\n- **TCP Keep-Alive** - 启用 TCP 保活机制（30 秒初始延迟），防止连接被服务端超时关闭\n- **断线自动重试** - 检测到连接断开时自动重试\n"
  },
  {
    "path": "docs/databases/oracle.md",
    "content": "# Oracle 使用指南\n\n## 版本支持\n\n| 模式 | 支持版本 | 是否需要 Oracle Client |\n|------|----------|----------------------|\n| Thin 模式（默认） | 12.1+ | 不需要 |\n| Thick 模式 | 11.2+ | 需要 |\n\n- **Thin 模式**：默认模式，纯 JavaScript 实现，无需安装任何客户端，但只支持 Oracle 12.1 及以上版本\n- **Thick 模式**：需要安装 Oracle Instant Client，但可以连接 Oracle 11g 等老版本\n\n## 配置示例\n\n### 基础配置（Thin 模式，12c+）\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 Oracle 11g（Thick 模式）\n\nOracle 11g 需要使用 Thick 模式，添加 `--oracle-client-path` 参数：\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-11g\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\",\n        \"--oracle-client-path\", \"/opt/oracle/instantclient_19_8\"\n      ]\n    }\n  }\n}\n```\n\n### 使用 Service Name 连接\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"oracle-server.example.com\",\n        \"--port\", \"1521\",\n        \"--user\", \"app_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"XEPDB1\"\n      ]\n    }\n  }\n}\n```\n\n### HTTP API 模式\n\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"oracle\",\n    \"host\": \"localhost\",\n    \"port\": 1521,\n    \"user\": \"system\",\n    \"password\": \"your_password\",\n    \"database\": \"ORCL\",\n    \"oracleClientPath\": \"/opt/oracle/instantclient_19_8\"\n  }'\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 1521 |\n| `--user` | 用户名 | - |\n| `--password` | 密码 | - |\n| `--database` | Service Name 或 SID | - |\n| `--oracle-client-path` | Oracle Instant Client 路径（启用 Thick 模式） | - |\n\n## Oracle Instant Client 安装指南\n\n> 注意：只有连接 Oracle 11g 或需要使用 Thick 模式的高级功能时才需要安装。\n\n### macOS\n\n```bash\n# 方式一：使用 Homebrew\nbrew install instantclient-basic\n\n# 方式二：手动安装\n# 1. 从 Oracle 官网下载 Instant Client\n# 2. 解压到 /opt/oracle/instantclient_19_8\n# 3. 配置时使用 --oracle-client-path \"/opt/oracle/instantclient_19_8\"\n```\n\n### Linux\n\n```bash\n# 1. 下载 Instant Client Basic 包\n# https://www.oracle.com/database/technologies/instant-client/downloads.html\n\n# 2. 解压到指定目录\nmkdir -p /opt/oracle\nunzip instantclient-basic-linux.x64-19.8.0.0.0dbru.zip -d /opt/oracle\n\n# 3. 安装依赖（如果需要）\nsudo apt-get install libaio1  # Debian/Ubuntu\nsudo yum install libaio       # RHEL/CentOS\n\n# 4. 配置时使用\n# --oracle-client-path \"/opt/oracle/instantclient_19_8\"\n```\n\n### Windows\n\n```powershell\n# 1. 下载 Instant Client Basic 包\n# https://www.oracle.com/database/technologies/instant-client/downloads.html\n\n# 2. 解压到 C:\\oracle\\instantclient_19_8\n\n# 3. 配置时使用\n# --oracle-client-path \"C:\\\\oracle\\\\instantclient_19_8\"\n```\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 帮我查看 EMPLOYEES 表的结构\n\nClaude 会自动:\n1. 调用 get_table_info 工具\n2. 返回表的列信息、主键、索引等\n注意：Oracle 表名通常为大写\n```\n\n### 执行查询\n\n```\n用户: 查询工资最高的 10 名员工\n\nClaude 会自动:\n1. 生成 SQL: SELECT * FROM EMPLOYEES ORDER BY SALARY DESC FETCH FIRST 10 ROWS ONLY\n2. 执行查询并返回结果\n```\n\n## 安全建议\n\n### 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER mcp_readonly IDENTIFIED BY secure_password;\nGRANT CREATE SESSION TO mcp_readonly;\nGRANT SELECT ANY TABLE TO mcp_readonly;\n\n-- 或者授予特定用户下表的权限\nGRANT SELECT ON hr.employees TO mcp_readonly;\nGRANT SELECT ON sales.orders TO mcp_readonly;\n```\n\n## 注意事项\n\n1. **表名大小写** - Oracle 默认表名为大写\n2. **多 Schema 支持** - 自动获取当前用户有权访问的所有用户的表（排除 SYS、SYSTEM 等系统用户）。当前用户的表直接使用表名（如 `EMPLOYEES`），其他用户的表使用 `owner.table_name` 格式（如 `HR.EMPLOYEES`）。查询时支持使用 `owner.table_name` 格式精确指定表。\n3. **分页语法** - 12c+ 使用 `FETCH FIRST n ROWS ONLY`，11g 使用 `ROWNUM`\n4. **日期格式** - 注意 NLS_DATE_FORMAT 设置\n5. **字符集** - 建议使用 AL32UTF8\n6. **Thick 模式** - 启用后会输出日志 `🔧 Oracle Thick 模式已启用`\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 oracledb 连接池（最小 1、最大 3 个连接），自动管理连接生命周期\n- **Pool Ping** - 每 30 秒自动检测连接健康状态（`poolPingInterval: 30`）\n- **断线自动重试** - 检测到连接断开（如 `NJS-500`、`ORA-03114`）时自动重试\n\n## 常见问题\n\n### ORA-12541: TNS:no listener\n\n检查 Oracle 监听器是否启动：\n```bash\nlsnrctl status\n```\n\n### ORA-01017: invalid username/password\n\n确认用户名和密码正确，注意大小写。\n\n### 连接 11g 失败\n\n确保：\n1. 已安装 Oracle Instant Client\n2. 正确配置了 `--oracle-client-path` 参数\n3. Client 版本与操作系统匹配\n\n### Oracle Client 初始化失败\n\n常见原因：\n- 路径不正确\n- 缺少依赖库（如 libaio）\n- 32/64 位不匹配\n\n查看详细错误信息以定位问题。\n"
  },
  {
    "path": "docs/databases/polardb.md",
    "content": "# PolarDB 数据库使用指南\n\n## 📖 关于 PolarDB\n\nPolarDB 是阿里云自研的云原生关系型数据库，采用存储计算分离、软硬一体化设计。PolarDB 有三个版本：PolarDB for MySQL、PolarDB for PostgreSQL 和 PolarDB for Oracle。本指南主要介绍 PolarDB for MySQL 版本。\n\n### 主要特点\n\n- **云原生架构**：存储与计算分离，资源独立扩展\n- **完全兼容 MySQL**：兼容 MySQL 5.6/5.7/8.0 协议和语法\n- **一写多读**：支持一个主节点和最多 15 个只读节点\n- **秒级弹性**：计算节点秒级扩展，无需停机\n- **高性能**：读性能最高可达百万 QPS\n- **高可用**：RPO=0，RTO<60秒\n\n## 🚀 快速开始\n\n### 1. 创建 PolarDB 实例\n\n#### 通过阿里云控制台\n\n1. 登录阿里云控制台\n2. 进入 PolarDB 控制台\n3. 点击\"创建实例\"\n4. 选择版本（MySQL 5.6/5.7/8.0）\n5. 配置规格和存储\n6. 设置网络和安全组\n7. 创建实例\n\n#### 获取连接地址\n\nPolarDB 提供三种连接地址：\n\n- **主地址（Primary Endpoint）**：支持读写操作\n- **集群地址（Cluster Endpoint）**：自动读写分离\n- **只读地址（Read-only Endpoint）**：只支持读操作\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### 读写分离配置（推荐）\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-primary\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    },\n    \"polardb-readonly\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx-ro.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"readonly_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 PolarDB 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 users 表中的所有用户\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM users;\n```\n\n### 聚合查询\n\n```\n你：统计每个部门的员工数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT department, COUNT(*) as employee_count\nFROM employees\nGROUP BY department;\n```\n\n### 复杂查询\n\n```\n你：找出最近 30 天内消费金额超过 1000 元的用户，按消费金额降序排列\n```\n\nClaude 会生成并执行：\n```sql\nSELECT u.id, u.name, SUM(o.amount) as total_amount\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.name\nHAVING total_amount > 1000\nORDER BY total_amount DESC;\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n```\n你：在 users 表中插入一条新用户记录，姓名为张三，邮箱为 zhangsan@example.com\n```\n\nClaude 会生成并执行：\n```sql\nINSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');\n```\n\n## 🔧 PolarDB 特性支持\n\n### 1. 读写分离\n\nPolarDB 支持一写多读架构：\n\n```sql\n-- 写操作（使用主地址）\nINSERT INTO orders (user_id, amount) VALUES (1, 100);\n\n-- 读操作（使用只读地址）\nSELECT * FROM orders WHERE user_id = 1;\n```\n\n### 2. 并行查询\n\nPolarDB 支持并行查询加速大表扫描：\n\n```sql\n-- 启用并行查询\nSET max_parallel_degree = 4;\n\n-- 执行大表查询\nSELECT COUNT(*) FROM large_table WHERE date > '2024-01-01';\n```\n\n### 3. 全局一致性\n\nPolarDB 支持分布式事务：\n\n```sql\nSTART TRANSACTION;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n### 4. 热备份\n\nPolarDB 支持在线备份，不影响业务：\n\n```sql\n-- 查看备份列表（通过阿里云控制台）\n-- 恢复到指定时间点（通过阿里云控制台）\n```\n\n## 📊 性能优化建议\n\n### 1. 使用 EXPLAIN 分析查询\n\n```sql\nEXPLAIN SELECT * FROM users WHERE age > 18;\n```\n\n### 2. 创建合适的索引\n\n```sql\n-- 单列索引\nCREATE INDEX idx_age ON users(age);\n\n-- 复合索引\nCREATE INDEX idx_name_age ON users(name, age);\n\n-- 唯一索引\nCREATE UNIQUE INDEX idx_email ON users(email);\n```\n\n### 3. 使用 ANALYZE 更新统计信息\n\n```sql\nANALYZE TABLE users;\n```\n\n### 4. 批量插入优化\n\n```sql\n-- 使用批量插入而不是单条插入\nINSERT INTO users (name, email) VALUES\n    ('user1', 'user1@example.com'),\n    ('user2', 'user2@example.com'),\n    ('user3', 'user3@example.com');\n```\n\n### 5. 读写分离\n\n- 写操作使用主地址\n- 读操作使用只读地址或集群地址\n- 分析查询使用只读节点\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"polardb\",\n    \"--host\", \"pc-xxxxx-ro.mysql.polardb.rds.aliyuncs.com\",\n    \"--port\", \"3306\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER 'readonly_user'@'%' IDENTIFIED BY 'password';\n\n-- 授予只读权限\nGRANT SELECT ON database_name.* TO 'readonly_user'@'%';\n\n-- 刷新权限\nFLUSH PRIVILEGES;\n```\n\n### 3. 使用 SSL/TLS 连接\n\nPolarDB 支持 SSL/TLS 加密连接，保护数据传输安全。\n\n### 4. 设置白名单\n\n- 在阿里云控制台设置 IP 白名单\n- 仅允许可信 IP 地址连接\n- 使用 VPC 网络隔离\n\n### 5. 使用 RAM 账号\n\n- 使用阿里云 RAM 账号管理权限\n- 遵循最小权限原则\n- 定期审计访问日志\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 PolarDB 数据库\n\n**解决方案**：\n- 检查 PolarDB 实例是否正在运行\n- 检查 IP 白名单设置\n- 验证用户名和密码\n- 检查网络连接（VPC/公网）\n\n### 2. 连接断开\n\n**问题**：长时间空闲后出现 `Can't add new command when connection is in closed state`\n\n**说明**：MCP 服务已内置连接池 + TCP Keep-Alive + 断线自动重试机制，正常情况下不会出现此问题。如果仍然出现，请检查网络环境是否存在强制断开空闲连接的策略。\n\n### 3. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间\n- 优化查询，添加合适的索引\n- 使用 LIMIT 限制返回结果数量\n- 使用只读节点执行分析查询\n\n### 3. 字符编码问题\n\n**问题**：中文显示乱码\n\n**解决方案**：\n- 确保数据库使用 UTF-8 编码：\n  ```sql\n  CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n  ```\n\n### 4. 读写分离延迟\n\n**问题**：只读节点数据延迟\n\n**解决方案**：\n- PolarDB 的复制延迟通常在毫秒级\n- 如需强一致性，使用主地址\n- 监控复制延迟指标\n\n## 📚 参考资源\n\n- [PolarDB 官方文档](https://help.aliyun.com/product/58609.html)\n- [PolarDB 快速入门](https://help.aliyun.com/document_detail/58764.html)\n- [PolarDB 最佳实践](https://help.aliyun.com/document_detail/118089.html)\n- [阿里云控制台](https://polardb.console.aliyun.com/)\n\n## 🆚 PolarDB vs MySQL\n\n| 特性 | PolarDB | MySQL |\n|------|---------|-------|\n| 架构 | 存储计算分离 | 传统架构 |\n| 扩展性 | ✅ 秒级弹性扩展 | ❌ 需要停机 |\n| 读性能 | ✅ 最高百万 QPS | ⚠️ 受限于单机 |\n| 高可用 | ✅ RPO=0, RTO<60s | ⚠️ 需要额外配置 |\n| 存储容量 | ✅ 最高 100TB | ⚠️ 受限于磁盘 |\n| 协议兼容 | ✅ 完全兼容 | - |\n| 成本 | ⚠️ 按需付费 | ✅ 开源免费 |\n\n## 💡 最佳实践\n\n### 1. 架构设计\n\n- 使用读写分离架构\n- 写操作使用主地址\n- 读操作使用只读地址\n- 分析查询使用只读节点\n\n### 2. 查询优化\n\n- 避免 SELECT *，只查询需要的列\n- 使用 LIMIT 限制返回结果\n- 合理使用索引\n- 避免在 WHERE 子句中使用函数\n\n### 3. 连接管理\n\n- 使用连接池\n- 合理设置连接池大小\n- 使用长连接减少连接开销\n- 定期检查连接健康状态\n\n### 4. 监控和维护\n\n- 监控 CPU、内存、IOPS\n- 设置慢查询告警\n- 关注连接数使用情况\n- 定期查看性能洞察\n- 定期备份数据\n\n### 5. 成本优化\n\n- 使用 Serverless 版本按需付费\n- 合理配置计算规格\n- 使用存储包降低成本\n- 定期清理无用数据\n\n## 🎯 适用场景\n\n### 适合使用 PolarDB 的场景\n\n- ✅ 云原生应用\n- ✅ 高并发读写场景\n- ✅ 需要弹性扩展的业务\n- ✅ 对高可用有要求的业务\n- ✅ 大数据量存储\n- ✅ 读写分离场景\n\n### 不适合使用 PolarDB 的场景\n\n- ❌ 本地部署需求\n- ❌ 预算非常有限\n- ❌ 数据量很小的应用\n- ❌ 对云服务有顾虑\n\n## 🌟 PolarDB 特色功能\n\n### 1. 存储计算分离\n\n- 存储和计算资源独立扩展\n- 存储容量自动扩展\n- 计算节点秒级扩展\n\n### 2. 一写多读\n\n- 支持一个主节点\n- 最多 15 个只读节点\n- 自动负载均衡\n\n### 3. 全局一致性\n\n- 分布式事务支持\n- 强一致性保证\n- 跨节点数据一致\n\n### 4. 并行查询\n\n- 自动并行查询优化\n- 加速大表扫描\n- 提升分析性能\n\n### 5. 热备份\n\n- 在线备份不影响业务\n- 秒级恢复\n- 支持时间点恢复\n\n---\n\n**提示**：PolarDB 是阿里云的云原生数据库，提供了强大的性能和弹性能力。如果您的应用部署在阿里云上，PolarDB 是一个很好的选择。\n"
  },
  {
    "path": "docs/databases/postgresql.md",
    "content": "# PostgreSQL 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 连接远程数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | 数据库主机地址 | localhost |\n| `--port` | 数据库端口 | 5432 |\n| `--user` | 用户名 | - |\n| `--password` | 密码 | - |\n| `--database` | 数据库名 | - |\n\n## 使用示例\n\n### 查看数据库结构\n\n```\n用户: 查看数据库中有哪些表\n\nClaude 会自动:\n1. 调用 get_schema 工具\n2. 返回所有表的列表和基本信息\n```\n\n### 复杂查询\n\n```\n用户: 找出订单金额最高的 10 个客户\n\nClaude 会自动:\n1. 调用 get_schema 了解表结构\n2. 生成复杂的 JOIN 查询\n3. 执行并返回结果\n```\n\n## 安全建议\n\n### 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER mcp_readonly WITH PASSWORD 'secure_password';\nGRANT CONNECT ON DATABASE mydb TO mcp_readonly;\n\n-- 授予 public schema 权限\nGRANT USAGE ON SCHEMA public TO mcp_readonly;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;\nALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;\n\n-- 如需访问其他 schema，需要额外授权\n-- GRANT USAGE ON SCHEMA analytics TO mcp_readonly;\n-- GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO mcp_readonly;\n-- ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO mcp_readonly;\n```\n\n## 支持的版本\n\n- PostgreSQL 10+\n- PostgreSQL 11+\n- PostgreSQL 12+\n- PostgreSQL 13+\n- PostgreSQL 14+\n- PostgreSQL 15+\n\n## 特性支持\n\n- 多 Schema 支持（自动发现所有用户 Schema）\n- 参数化查询（$1, $2, ...）\n- 事务支持\n- JSON/JSONB 类型\n- 数组类型\n\n## 注意事项\n\n1. **多 Schema 支持** - 自动获取所有用户 Schema 下的表（排除 `pg_catalog`、`information_schema` 等系统 Schema）。`public` Schema 下的表直接使用表名（如 `users`），其他 Schema 的表使用 `schema.table_name` 格式（如 `analytics.events`）。查询时支持使用 `schema.table_name` 格式精确指定表。\n2. **参数化查询** - 使用 $1, $2 占位符\n3. **SSL** - 生产环境建议启用 SSL\n\n## 连接稳定性\n\nMCP 服务内置了完善的连接管理机制，无需额外配置：\n\n- **连接池** - 使用 pg 连接池（最大 3 个连接），自动管理连接生命周期\n- **TCP Keep-Alive** - 启用 TCP 保活机制（30 秒初始延迟），防止连接被服务端超时关闭\n- **断线自动重试** - 检测到连接断开（如 `Connection terminated`、`ECONNRESET`）时自动重试\n\n## 常见问题\n\n### 连接被拒绝\n\n检查 `pg_hba.conf` 配置，确保允许远程连接。\n\n### 权限不足\n\n确保用户有 CONNECT 和 SELECT 权限。\n"
  },
  {
    "path": "docs/databases/redis.md",
    "content": "# Redis 使用指南\n\n## 配置示例\n\n### 基础配置（无密码）\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\"\n      ]\n    }\n  }\n}\n```\n\n### 带密码和数据库选择\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-session\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"redis_password\",\n        \"--database\", \"1\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--host` | Redis 主机地址 | localhost |\n| `--port` | Redis 端口 | 6379 |\n| `--password` | 密码（可选） | - |\n| `--database` | 数据库编号（0-15） | 0 |\n\n## 使用示例\n\n### 查看所有键\n\n```\n用户: 查看所有以 \"user:\" 开头的键\n\nClaude 会执行: KEYS user:*\n```\n\n### 获取键值\n\n```\n用户: 获取 user:1001 的信息\n\nClaude 会执行: GET user:1001 或 HGETALL user:1001（根据数据类型）\n```\n\n### 统计信息\n\n```\n用户: 统计缓存中有多少个会话\n\nClaude 会执行: KEYS session:* 并统计数量\n```\n\n## 支持的命令\n\n### 只读模式\n\n- `GET` - 获取字符串值\n- `HGET` / `HGETALL` - 获取哈希值\n- `LRANGE` - 获取列表元素\n- `SMEMBERS` - 获取集合成员\n- `ZRANGE` - 获取有序集合成员\n- `KEYS` - 查找键\n- `TYPE` - 获取键类型\n- `TTL` - 获取过期时间\n- `EXISTS` - 检查键是否存在\n- `DBSIZE` - 获取键数量\n- `INFO` - 获取服务器信息\n\n### 写入模式（需要 --permission-mode readwrite 或 full）\n\n- `SET` - 设置字符串值\n- `HSET` - 设置哈希字段\n- `LPUSH` / `RPUSH` - 添加列表元素\n- `SADD` - 添加集合成员\n- `ZADD` - 添加有序集合成员\n- `DEL` - 删除键\n- `EXPIRE` - 设置过期时间\n- `FLUSHDB` - 清空数据库\n\n## 安全建议\n\n1. **设置密码** - 生产环境必须设置密码\n2. **绑定地址** - 不要绑定到 0.0.0.0\n3. **禁用危险命令** - 在 redis.conf 中禁用 FLUSHALL、KEYS 等\n\n## 支持的版本\n\n- Redis 5.x\n- Redis 6.x\n- Redis 7.x\n\n## 注意事项\n\n1. **KEYS 命令** - 在大数据量时可能阻塞，建议使用 SCAN\n2. **数据库编号** - Redis 默认有 16 个数据库（0-15）\n3. **集群模式** - 当前不支持 Redis Cluster\n\n## 常见问题\n\n### 连接被拒绝\n\n检查 Redis 配置中的 `bind` 和 `protected-mode` 设置。\n\n### 认证失败\n\n确保密码正确，检查 `requirepass` 配置。\n"
  },
  {
    "path": "docs/databases/sqlite.md",
    "content": "# SQLite 使用指南\n\n## 配置示例\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### Windows 路径示例\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-app\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"C:\\\\Users\\\\YourName\\\\Documents\\\\myapp.db\"\n      ]\n    }\n  }\n}\n```\n\n注意：Windows 路径中的反斜杠需要转义（使用 `\\\\`）。\n\n### macOS/Linux 路径示例\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-notes\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/Users/YourName/Documents/notes.db\"\n      ]\n    }\n  }\n}\n```\n\n## 连接参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `--file` | 数据库文件路径（必需） | - |\n\n注意：SQLite 不需要 `--host`、`--port`、`--user`、`--password` 参数。\n\n## 使用示例\n\n### 查看表结构\n\n```\n用户: 查看数据库中有哪些表\n\nClaude 会自动:\n1. 调用 get_schema 工具\n2. 执行 SELECT name FROM sqlite_master WHERE type='table'\n3. 返回表列表\n```\n\n### 执行查询\n\n```\n用户: 统计每个分类的文章数量\n\nClaude 会自动:\n1. 生成 SQL: SELECT category, COUNT(*) as count FROM articles GROUP BY category\n2. 执行并返回结果\n```\n\n## 常见使用场景\n\n### 分析本地应用数据库\n\n许多桌面应用使用 SQLite 存储数据：\n\n- Chrome 浏览器历史记录\n- Firefox 书签\n- 各种笔记应用\n- 移动应用备份\n\n### 开发和测试\n\nSQLite 非常适合本地开发和测试环境。\n\n## 支持的特性\n\n- ✅ 标准 SQL 查询\n- ✅ 事务支持\n- ✅ 索引和主键\n- ✅ 外键约束\n- ✅ PRAGMA 命令\n- ✅ 全文搜索（FTS）\n- ✅ JSON 扩展（SQLite 3.38+）\n\n## 注意事项\n\n1. **文件路径** - 必须使用绝对路径\n2. **文件权限** - 确保有读取/写入权限\n3. **并发访问** - SQLite 支持多读单写\n4. **数据库锁** - 如果被其他程序占用可能遇到锁定错误\n5. **自动创建** - 如果文件不存在会自动创建\n\n## 驱动依赖\n\nSQLite 驱动 `better-sqlite3` 需要编译。\n\n**Windows:**\n需要安装 [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022)。\n\n**macOS:**\n```bash\nxcode-select --install\n```\n\n**Linux:**\n```bash\nsudo apt install build-essential\n```\n\n## 常见问题\n\n### 数据库被锁定\n\n确保没有其他程序正在使用该数据库文件。\n\n### 文件不存在\n\n检查文件路径是否正确，使用绝对路径。\n\n### 编译错误\n\n确保已安装编译工具（见驱动依赖部分）。\n"
  },
  {
    "path": "docs/databases/sqlserver.md",
    "content": "# SQL Server 使用指南\n\n## 简介\n\nuniversal-db-mcp 现已支持 Microsoft SQL Server（2012+）和 Azure SQL Database！使用 `mssql` 驱动提供完整的 SQL Server 功能支持。\n\n### 支持的版本\n\n- **SQL Server**: 2012, 2014, 2016, 2017, 2019, 2022\n- **Azure SQL Database**: 完全支持\n- **Azure SQL Managed Instance**: 完全支持\n\n## 安装\n\n### 方法 1: 全局安装（推荐）\n\n```bash\nnpm install -g universal-db-mcp\n```\n\nSQL Server 驱动 `mssql` 会自动安装。\n\n### 方法 2: 本地项目安装\n\n```bash\nmkdir my-db-project\ncd my-db-project\nnpm init -y\nnpm install universal-db-mcp\n```\n\n## Claude Desktop 配置\n\n编辑 Claude Desktop 配置文件：\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Linux**: `~/.config/Claude/claude_desktop_config.json`\n\n### 基础配置（只读模式）\n\n#### 连接本地 SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"YourPassword123\",\n        \"--database\", \"master\"\n      ]\n    }\n  }\n}\n```\n\n**提示**: 也可以使用 `--type mssql` 作为别名。\n\n#### 连接 Azure SQL Database\n\n```json\n{\n  \"mcpServers\": {\n    \"azure-sql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"myserver.database.windows.net\",\n        \"--port\", \"1433\",\n        \"--user\", \"myadmin\",\n        \"--password\", \"MyPassword123!\",\n        \"--database\", \"mydatabase\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: 连接 Azure SQL Database 时会自动检测并启用加密连接。\n\n### 连接远程 SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"sql-server.example.com\",\n        \"--port\", \"1433\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"ProductionDB\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式（谨慎使用）\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"DevDB\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n⚠️ **警告**: 启用写入模式后，Claude 可以修改你的数据库。请仅在开发环境使用！\n\n## 使用示例\n\n### 查看数据库结构\n\n**用户**: \"查看数据库中有哪些表？\"\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 返回所有表的列表和基本信息\n\n### 查询数据\n\n**用户**: \"查询 Users 表中的所有记录\"\n\n**Claude 会自动**:\n```sql\nSELECT * FROM Users\n```\n\n**用户**: \"查找最近一周注册的用户\"\n\n**Claude 会自动**:\n```sql\nSELECT * FROM Users\nWHERE RegisterDate >= DATEADD(day, -7, GETDATE())\nORDER BY RegisterDate DESC\n```\n\n### 数据分析\n\n**用户**: \"统计每个部门的员工数量\"\n\n**Claude 会自动**:\n```sql\nSELECT DepartmentID, COUNT(*) as EmployeeCount\nFROM Employees\nGROUP BY DepartmentID\nORDER BY EmployeeCount DESC\n```\n\n**用户**: \"计算每个月的销售总额\"\n\n**Claude 会自动**:\n```sql\nSELECT\n  YEAR(OrderDate) as Year,\n  MONTH(OrderDate) as Month,\n  SUM(TotalAmount) as TotalSales\nFROM Orders\nGROUP BY YEAR(OrderDate), MONTH(OrderDate)\nORDER BY Year DESC, Month DESC\n```\n\n### 使用参数化查询\n\n**用户**: \"查找用户ID为123的订单\"\n\n**Claude 会自动**:\n```sql\nSELECT * FROM Orders WHERE UserID = @param0\n```\n\n参数会自动传递，防止 SQL 注入。\n\n## 连接配置详解\n\n### 端口配置\n\n- **默认端口**: 1433\n- **自定义端口**: 使用 `--port` 参数指定\n\n### 身份验证\n\n#### SQL Server 身份验证\n\n使用用户名和密码：\n\n```bash\n--user \"sa\" --password \"YourPassword123\"\n```\n\n#### Windows 身份验证\n\nWindows 身份验证支持将在未来版本中添加。\n\n### 加密连接\n\n- **本地 SQL Server**: 默认不加密（`trustServerCertificate: true`）\n- **Azure SQL Database**: 自动检测并启用加密（`encrypt: true`）\n- **自定义**: 通过主机名自动判断（包含 `.database.windows.net` 则启用加密）\n\n## 常见问题排查\n\n### 连接失败\n\n**错误**: `SQL Server 连接失败: 无法连接到数据库服务器`\n\n**解决方案**:\n1. 检查 SQL Server 服务是否运行\n2. 验证主机地址和端口是否正确\n3. 检查防火墙规则是否允许 1433 端口\n4. 确认 SQL Server 配置允许远程连接（SQL Server Configuration Manager）\n5. 检查 TCP/IP 协议是否启用\n\n### 身份验证失败\n\n**错误**: `SQL Server 连接失败: 身份验证失败`\n\n**解决方案**:\n1. 确认用户名和密码正确\n2. 检查 SQL Server 是否启用了 SQL Server 身份验证模式\n3. 确认用户账号未被锁定或禁用\n4. 对于 Azure SQL，确认防火墙规则允许你的 IP 地址\n\n### 数据库不存在\n\n**错误**: `SQL Server 连接失败: 数据库不存在`\n\n**解决方案**:\n1. 确认数据库名称拼写正确（区分大小写）\n2. 使用 `master` 数据库连接后查看所有数据库：\n   ```sql\n   SELECT name FROM sys.databases\n   ```\n\n### 权限不足\n\n**错误**: `查询执行失败: 表或视图不存在`\n\n**解决方案**:\n1. 确认用户有访问该表的权限\n2. 授予 SELECT 权限：\n   ```sql\n   GRANT SELECT ON dbo.TableName TO username\n   ```\n3. 授予访问所有表的权限：\n   ```sql\n   GRANT SELECT ON SCHEMA::dbo TO username\n   ```\n\n### 写操作被拒绝\n\n**错误**: `操作被拒绝：当前处于只读安全模式`\n\n**解决方案**:\n- 根据需要使用 `--permission-mode readwrite` 或 `--permission-mode full`\n- 仅在开发环境使用！\n\n### Azure SQL 连接超时\n\n**错误**: `ETIMEDOUT` 或连接超时\n\n**解决方案**:\n1. 检查 Azure SQL 防火墙规则\n2. 在 Azure Portal 中添加你的 IP 地址到防火墙白名单\n3. 或启用\"允许 Azure 服务访问\"选项\n\n## Azure SQL Database 特殊说明\n\n### 防火墙配置\n\n1. 登录 Azure Portal\n2. 找到你的 SQL Server 资源\n3. 点击\"防火墙和虚拟网络\"\n4. 添加客户端 IP 地址\n5. 保存更改\n\n### 连接字符串格式\n\nAzure SQL 主机名格式：\n```\n<server-name>.database.windows.net\n```\n\n示例：\n```\nmycompany-sql.database.windows.net\n```\n\n### 性能层级\n\n- **Basic**: 适合小型应用和开发\n- **Standard**: 适合中等负载\n- **Premium**: 适合高性能需求\n- **Serverless**: 按使用量计费，适合间歇性工作负载\n\n### 最佳实践\n\n1. **使用只读副本**: 对于分析查询，使用只读副本减少主数据库负载\n2. **连接池**: 本工具自动使用连接池（最大10个连接）\n3. **查询优化**: 使用索引和适当的查询优化\n4. **监控**: 使用 Azure Portal 监控查询性能和资源使用\n\n## 安全最佳实践\n\n### ✅ 推荐做法\n\n1. **使用只读账号**: 创建专门的只读用户\n   ```sql\n   CREATE LOGIN readonly_user WITH PASSWORD = 'SecurePassword123!';\n   CREATE USER readonly_user FOR LOGIN readonly_user;\n   -- 授予 dbo schema 读权限\n   GRANT SELECT ON SCHEMA::dbo TO readonly_user;\n   -- 如需访问其他 schema，需要额外授权\n   -- GRANT SELECT ON SCHEMA::analytics TO readonly_user;\n   ```\n\n2. **限制访问范围**: 只授予必要的表访问权限\n   ```sql\n   GRANT SELECT ON dbo.Users TO readonly_user;\n   GRANT SELECT ON dbo.Orders TO readonly_user;\n   ```\n\n3. **使用强密码**: 至少12个字符，包含大小写字母、数字和特殊字符\n\n4. **启用审计**: 在 Azure SQL 中启用审计功能\n\n5. **定期更新密码**: 定期轮换数据库密码\n\n### ❌ 避免做法\n\n1. 不要在生产环境启用写入模式\n2. 不要使用 `sa` 或 `admin` 账号\n3. 不要在配置文件中明文存储密码（考虑使用环境变量）\n4. 不要在公共网络直接连接生产数据库\n5. 不要授予不必要的权限\n\n## 性能优化建议\n\n### 查询优化\n\n1. **使用索引**: 确保常用查询字段有索引\n2. **避免 SELECT ***: 只查询需要的列\n3. **使用 TOP 限制结果**:\n   ```sql\n   SELECT TOP 100 * FROM LargeTable\n   ```\n4. **使用分页**:\n   ```sql\n   SELECT * FROM Orders\n   ORDER BY OrderDate\n   OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY\n   ```\n\n### 连接池配置\n\n本工具默认连接池配置：\n- 最大连接数: 10\n- 最小连接数: 0\n- 空闲超时: 30秒\n\n这些配置适合大多数场景，无需手动调整。\n\n## 支持的 SQL Server 特性\n\n### 数据类型\n\n完整支持所有 SQL Server 数据类型：\n- 数值类型: INT, BIGINT, DECIMAL, NUMERIC, FLOAT, REAL\n- 字符类型: CHAR, VARCHAR, NCHAR, NVARCHAR, TEXT, NTEXT\n- 日期时间: DATE, TIME, DATETIME, DATETIME2, DATETIMEOFFSET\n- 二进制: BINARY, VARBINARY, IMAGE\n- 其他: BIT, UNIQUEIDENTIFIER, XML, JSON\n\n### 系统视图\n\n支持查询所有系统视图：\n- INFORMATION_SCHEMA.*\n- sys.tables\n- sys.columns\n- sys.indexes\n- sys.databases\n- 等等\n\n### T-SQL 功能\n\n支持大部分 T-SQL 功能：\n- 聚合函数: SUM, COUNT, AVG, MIN, MAX\n- 窗口函数: ROW_NUMBER, RANK, DENSE_RANK\n- 字符串函数: CONCAT, SUBSTRING, REPLACE, LEN\n- 日期函数: GETDATE, DATEADD, DATEDIFF, FORMAT\n- 条件函数: CASE, IIF, COALESCE\n\n## 更多帮助\n\n- 查看 [README.md](../README.md) 了解项目概述\n- 查看 [EXAMPLES.md](../EXAMPLES.md) 了解更多使用示例\n- 查看 [CONTRIBUTING.md](../CONTRIBUTING.md) 了解如何贡献\n- 提交 Issue: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n\n## 相关资源\n\n- [SQL Server 官方文档](https://docs.microsoft.com/sql/sql-server/)\n- [Azure SQL Database 文档](https://docs.microsoft.com/azure/azure-sql/)\n- [T-SQL 参考](https://docs.microsoft.com/sql/t-sql/)\n- [mssql npm 包](https://www.npmjs.com/package/mssql)\n"
  },
  {
    "path": "docs/databases/tidb.md",
    "content": "# TiDB 数据库使用指南\n\n## 📖 关于 TiDB\n\nTiDB 是 PingCAP 公司开发的开源分布式 NewSQL 数据库，支持水平扩展、分布式事务和高可用性。TiDB 兼容 MySQL 5.7 协议和生态，可以无缝替换 MySQL。\n\n### 主要特点\n\n- **MySQL 兼容**：兼容 MySQL 5.7 协议和语法\n- **水平扩展**：支持在线水平扩展，无需停机\n- **分布式事务**：支持 ACID 事务，保证数据一致性\n- **高可用**：自动故障转移，无单点故障\n- **HTAP**：同时支持 OLTP 和 OLAP 工作负载\n\n## 🚀 快速开始\n\n### 1. 安装 TiDB\n\n#### 使用 TiUP（推荐）\n\n```bash\n# 安装 TiUP\ncurl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh\n\n# 启动本地测试集群\ntiup playground\n```\n\n#### 使用 Docker\n\n```bash\n# 拉取 TiDB 镜像\ndocker pull pingcap/tidb:latest\n\n# 启动 TiDB 容器\ndocker run -d --name tidb-server \\\n  -p 4000:4000 \\\n  -p 10080:10080 \\\n  pingcap/tidb:latest\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"tidb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"4000\",\n        \"--user\", \"root\",\n        \"--password\", \"\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"tidb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"4000\",\n        \"--user\", \"root\",\n        \"--password\", \"\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n#### 连接 TiDB Cloud\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"tidb\",\n        \"--host\", \"gateway01.ap-southeast-1.prod.aws.tidbcloud.com\",\n        \"--port\", \"4000\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 TiDB 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 users 表中的所有用户\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM users;\n```\n\n### 聚合查询\n\n```\n你：统计每个部门的员工数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT department, COUNT(*) as employee_count\nFROM employees\nGROUP BY department;\n```\n\n### 复杂查询\n\n```\n你：找出最近 30 天内消费金额超过 1000 元的用户，按消费金额降序排列\n```\n\nClaude 会生成并执行：\n```sql\nSELECT u.id, u.name, SUM(o.amount) as total_amount\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.name\nHAVING total_amount > 1000\nORDER BY total_amount DESC;\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n```\n你：在 users 表中插入一条新用户记录，姓名为张三，邮箱为 zhangsan@example.com\n```\n\nClaude 会生成并执行：\n```sql\nINSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');\n```\n\n## 🔧 TiDB 特性支持\n\n### 1. 分布式事务\n\nTiDB 支持完整的 ACID 事务：\n\n```sql\nSTART TRANSACTION;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n### 2. 分区表\n\nTiDB 支持 Range、Hash、List 分区：\n\n```sql\nCREATE TABLE employees (\n    id INT NOT NULL,\n    fname VARCHAR(30),\n    lname VARCHAR(30),\n    hired DATE NOT NULL DEFAULT '1970-01-01',\n    separated DATE NOT NULL DEFAULT '9999-12-31',\n    job_code INT NOT NULL,\n    store_id INT NOT NULL\n)\nPARTITION BY RANGE (YEAR(separated)) (\n    PARTITION p0 VALUES LESS THAN (1991),\n    PARTITION p1 VALUES LESS THAN (1996),\n    PARTITION p2 VALUES LESS THAN (2001),\n    PARTITION p3 VALUES LESS THAN MAXVALUE\n);\n```\n\n### 3. 列式存储（TiFlash）\n\nTiDB 支持行列混合存储，可以为表添加 TiFlash 副本以加速 OLAP 查询：\n\n```sql\n-- 为表添加 TiFlash 副本\nALTER TABLE table_name SET TIFLASH REPLICA 1;\n\n-- 查询会自动使用 TiFlash\nSELECT COUNT(*) FROM large_table WHERE date > '2024-01-01';\n```\n\n### 4. 全文索引\n\nTiDB 支持全文索引（需要 TiDB 6.6+）：\n\n```sql\nCREATE TABLE articles (\n    id INT PRIMARY KEY,\n    title VARCHAR(200),\n    body TEXT,\n    FULLTEXT INDEX ft_index (title, body)\n);\n\n-- 全文搜索\nSELECT * FROM articles WHERE MATCH(title, body) AGAINST('TiDB 分布式数据库');\n```\n\n## 📊 性能优化建议\n\n### 1. 使用 EXPLAIN 分析查询\n\n```sql\nEXPLAIN SELECT * FROM users WHERE age > 18;\n```\n\n### 2. 创建合适的索引\n\n```sql\n-- 单列索引\nCREATE INDEX idx_age ON users(age);\n\n-- 复合索引\nCREATE INDEX idx_name_age ON users(name, age);\n\n-- 唯一索引\nCREATE UNIQUE INDEX idx_email ON users(email);\n```\n\n### 3. 使用 ANALYZE 更新统计信息\n\n```sql\nANALYZE TABLE users;\n```\n\n### 4. 批量插入优化\n\n```sql\n-- 使用批量插入而不是单条插入\nINSERT INTO users (name, email) VALUES\n    ('user1', 'user1@example.com'),\n    ('user2', 'user2@example.com'),\n    ('user3', 'user3@example.com');\n```\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式，这是最安全的方式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"tidb\",\n    \"--host\", \"localhost\",\n    \"--port\", \"4000\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER 'readonly_user'@'%' IDENTIFIED BY 'password';\n\n-- 授予只读权限\nGRANT SELECT ON database_name.* TO 'readonly_user'@'%';\n\n-- 刷新权限\nFLUSH PRIVILEGES;\n```\n\n### 3. 使用 SSL/TLS 连接\n\nTiDB 支持 SSL/TLS 加密连接，保护数据传输安全。\n\n### 4. 限制网络访问\n\n- 使用防火墙限制 TiDB 端口（4000）的访问\n- 仅允许可信 IP 地址连接\n- 在生产环境中使用 VPN 或专线\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 TiDB 数据库\n\n**解决方案**：\n- 检查 TiDB 服务是否正在运行：`tiup status`\n- 检查端口是否正确（默认 4000）\n- 检查防火墙设置\n- 验证用户名和密码\n\n### 2. 连接断开\n\n**问题**：长时间空闲后出现 `Can't add new command when connection is in closed state`\n\n**说明**：MCP 服务已内置连接池 + TCP Keep-Alive + 断线自动重试机制，正常情况下不会出现此问题。如果仍然出现，请检查网络环境是否存在强制断开空闲连接的策略。\n\n### 3. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间：`SET SESSION tidb_query_timeout = 600;`\n- 优化查询，添加合适的索引\n- 使用 LIMIT 限制返回结果数量\n\n### 3. 字符编码问题\n\n**问题**：中文显示乱码\n\n**解决方案**：\n- 确保数据库使用 UTF-8 编码：\n  ```sql\n  CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n  ```\n\n### 4. 与 MySQL 的差异\n\n**问题**：某些 MySQL 语法在 TiDB 中不支持\n\n**解决方案**：\n- 查看 [TiDB 与 MySQL 兼容性对比](https://docs.pingcap.com/zh/tidb/stable/mysql-compatibility)\n- 使用 TiDB 支持的替代语法\n- 避免使用触发器、存储过程等 TiDB 不支持的特性\n\n## 📚 参考资源\n\n- [TiDB 官方文档](https://docs.pingcap.com/zh/tidb/stable)\n- [TiDB 快速上手](https://docs.pingcap.com/zh/tidb/stable/quick-start-with-tidb)\n- [TiDB Cloud](https://tidbcloud.com/)\n- [TiDB GitHub](https://github.com/pingcap/tidb)\n- [TiDB 社区](https://asktug.com/)\n\n## 🆚 TiDB vs MySQL\n\n| 特性 | TiDB | MySQL |\n|------|------|-------|\n| 水平扩展 | ✅ 原生支持 | ❌ 需要分库分表 |\n| 分布式事务 | ✅ 原生支持 | ❌ 不支持 |\n| 高可用 | ✅ 自动故障转移 | ⚠️ 需要额外配置 |\n| HTAP | ✅ 支持 | ❌ 不支持 |\n| 协议兼容 | ✅ MySQL 5.7 | - |\n| 触发器 | ❌ 不支持 | ✅ 支持 |\n| 存储过程 | ❌ 不支持 | ✅ 支持 |\n| 外键 | ⚠️ 部分支持 | ✅ 支持 |\n\n## 💡 最佳实践\n\n### 1. 表设计\n\n- 使用自增主键或 UUID\n- 避免使用过大的主键\n- 合理设计分区策略\n- 使用合适的数据类型\n\n### 2. 查询优化\n\n- 避免 SELECT *，只查询需要的列\n- 使用 LIMIT 限制返回结果\n- 合理使用索引\n- 避免在 WHERE 子句中使用函数\n\n### 3. 监控和维护\n\n- 定期运行 ANALYZE TABLE 更新统计信息\n- 监控慢查询日志\n- 使用 TiDB Dashboard 监控集群状态\n- 定期备份数据\n\n### 4. 开发建议\n\n- 在开发环境测试所有查询\n- 使用参数化查询防止 SQL 注入\n- 合理使用事务，避免长事务\n- 注意 TiDB 与 MySQL 的差异\n\n---\n\n**提示**：如果遇到问题，可以在 [TiDB 社区](https://asktug.com/) 寻求帮助，或查看 [官方文档](https://docs.pingcap.com/zh/tidb/stable)。\n"
  },
  {
    "path": "docs/databases/vastbase.md",
    "content": "# Vastbase 数据库使用指南\n\n## 📖 关于 Vastbase\n\nVastbase 是北京海量数据技术股份有限公司自主研发的企业级关系型数据库管理系统。Vastbase 基于 PostgreSQL 开发，完全兼容 PostgreSQL 协议，支持国产化替代，广泛应用于政府、金融、电信等行业。\n\n### 主要特点\n\n- **PostgreSQL 兼容**：完全兼容 PostgreSQL 协议和语法\n- **国产自主**：支持国产操作系统和芯片\n- **企业级特性**：高可用、分布式、数据加密\n- **高性能**：优化的查询引擎和存储引擎\n- **安全可靠**：完善的审计和权限管理\n\n## 🚀 快速开始\n\n### 1. 安装 Vastbase\n\n#### 在 Linux 上安装\n\n```bash\n# 下载 Vastbase 安装包（从官网获取）\n# 解压安装包\ntar -xzf vastbase-xxx.tar.gz\n\n# 进入安装目录\ncd vastbase-xxx\n\n# 执行安装脚本\n./install.sh\n\n# 初始化数据库\nvastbase-initdb -D /path/to/data\n\n# 启动数据库\nvastbase-ctl start -D /path/to/data\n```\n\n#### 使用 Docker\n\n```bash\n# 拉取 Vastbase 镜像（如果有官方镜像）\ndocker pull vastbase/vastbase:latest\n\n# 启动 Vastbase 容器\ndocker run -d --name vastbase-server \\\n  -p 5432:5432 \\\n  -e POSTGRES_PASSWORD=your_password \\\n  vastbase/vastbase:latest\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n#### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"vastbase\",\n        \"--password\", \"your_password\",\n        \"--database\", \"postgres\"\n      ]\n    }\n  }\n}\n```\n\n#### 启用写入模式（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--permission-mode\", \"full\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"vastbase\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n#### 连接 Vastbase 集群\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"vastbase-cluster.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n配置完成后，重启 Claude Desktop 使配置生效。\n\n## 💡 使用示例\n\n### 查询数据库结构\n\n```\n你：帮我查看 Vastbase 数据库的所有表\n```\n\nClaude 会自动调用 `get_schema` 工具获取数据库结构。\n\n### 查询数据\n\n```\n你：查询 users 表中的所有用户\n```\n\nClaude 会生成并执行：\n```sql\nSELECT * FROM users;\n```\n\n### 聚合查询\n\n```\n你：统计每个部门的员工数量\n```\n\nClaude 会生成并执行：\n```sql\nSELECT department, COUNT(*) as employee_count\nFROM employees\nGROUP BY department;\n```\n\n### 复杂查询\n\n```\n你：找出最近 30 天内消费金额超过 1000 元的用户，按消费金额降序排列\n```\n\nClaude 会生成并执行：\n```sql\nSELECT u.id, u.name, SUM(o.amount) as total_amount\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE o.created_at >= CURRENT_DATE - INTERVAL '30 days'\nGROUP BY u.id, u.name\nHAVING SUM(o.amount) > 1000\nORDER BY total_amount DESC;\n```\n\n### 写入操作（需要 --permission-mode readwrite 或 full）\n\n```\n你：在 users 表中插入一条新用户记录，姓名为张三，邮箱为 zhangsan@example.com\n```\n\nClaude 会生成并执行：\n```sql\nINSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');\n```\n\n## 🔧 Vastbase 特性支持\n\n### 1. PostgreSQL 兼容性\n\nVastbase 完全兼容 PostgreSQL 协议：\n\n```sql\n-- 标准 PostgreSQL 语法\nCREATE TABLE employees (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100),\n    department VARCHAR(50),\n    salary NUMERIC(10, 2),\n    hire_date DATE\n);\n\n-- 创建索引\nCREATE INDEX idx_department ON employees(department);\n\n-- 查询\nSELECT * FROM employees WHERE department = 'IT';\n```\n\n### 2. 分区表\n\nVastbase 支持表分区：\n\n```sql\n-- 创建分区表\nCREATE TABLE orders (\n    id SERIAL,\n    user_id INTEGER,\n    amount NUMERIC(10, 2),\n    created_at DATE\n) PARTITION BY RANGE (created_at);\n\n-- 创建分区\nCREATE TABLE orders_2024_01 PARTITION OF orders\n    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');\n\nCREATE TABLE orders_2024_02 PARTITION OF orders\n    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');\n```\n\n### 3. 事务支持\n\nVastbase 支持完整的 ACID 事务：\n\n```sql\nBEGIN;\nUPDATE accounts SET balance = balance - 100 WHERE id = 1;\nUPDATE accounts SET balance = balance + 100 WHERE id = 2;\nCOMMIT;\n```\n\n### 4. JSON 支持\n\nVastbase 支持 JSON 和 JSONB 数据类型：\n\n```sql\n-- 创建包含 JSON 的表\nCREATE TABLE products (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100),\n    attributes JSONB\n);\n\n-- 插入 JSON 数据\nINSERT INTO products (name, attributes) VALUES\n    ('Product A', '{\"color\": \"red\", \"size\": \"large\"}');\n\n-- 查询 JSON 数据\nSELECT * FROM products WHERE attributes->>'color' = 'red';\n```\n\n## 📊 性能优化建议\n\n### 1. 使用 EXPLAIN 分析查询\n\n```sql\nEXPLAIN ANALYZE SELECT * FROM users WHERE age > 18;\n```\n\n### 2. 创建合适的索引\n\n```sql\n-- 单列索引\nCREATE INDEX idx_age ON users(age);\n\n-- 复合索引\nCREATE INDEX idx_name_age ON users(name, age);\n\n-- 唯一索引\nCREATE UNIQUE INDEX idx_email ON users(email);\n\n-- 部分索引\nCREATE INDEX idx_active_users ON users(email) WHERE active = true;\n```\n\n### 3. 使用 ANALYZE 更新统计信息\n\n```sql\nANALYZE users;\nANALYZE;  -- 分析所有表\n```\n\n### 4. 定期执行 VACUUM\n\n```sql\nVACUUM users;\nVACUUM FULL;  -- 完全清理\nVACUUM ANALYZE;  -- 清理并更新统计信息\n```\n\n### 5. 批量插入优化\n\n```sql\n-- 使用批量插入\nINSERT INTO users (name, email) VALUES\n    ('user1', 'user1@example.com'),\n    ('user2', 'user2@example.com'),\n    ('user3', 'user3@example.com');\n\n-- 使用 COPY 命令（更快）\nCOPY users (name, email) FROM '/path/to/data.csv' CSV;\n```\n\n## 🔒 安全建议\n\n### 1. 使用只读模式\n\n默认情况下，MCP 连接器运行在只读模式：\n\n```json\n{\n  \"args\": [\n    \"universal-db-mcp\",\n    \"--type\", \"vastbase\",\n    \"--host\", \"localhost\",\n    \"--port\", \"5432\",\n    \"--user\", \"readonly_user\",\n    \"--password\", \"password\",\n    \"--database\", \"production\"\n  ]\n}\n```\n\n### 2. 创建只读用户\n\n```sql\n-- 创建只读用户\nCREATE USER readonly_user WITH PASSWORD 'password';\n\n-- 授予只读权限\nGRANT CONNECT ON DATABASE mydb TO readonly_user;\nGRANT USAGE ON SCHEMA public TO readonly_user;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;\n\n-- 设置默认权限\nALTER DEFAULT PRIVILEGES IN SCHEMA public\n    GRANT SELECT ON TABLES TO readonly_user;\n\n-- 如需访问其他 schema，需要额外授权\n-- GRANT USAGE ON SCHEMA analytics TO readonly_user;\n-- GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO readonly_user;\n-- ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO readonly_user;\n```\n\n### 3. 使用 SSL/TLS 连接\n\nVastbase 支持 SSL/TLS 加密连接：\n\n```sql\n-- 在 postgresql.conf 中启用 SSL\nssl = on\nssl_cert_file = 'server.crt'\nssl_key_file = 'server.key'\n```\n\n### 4. 限制网络访问\n\n在 `pg_hba.conf` 中配置访问控制：\n\n```\n# TYPE  DATABASE        USER            ADDRESS                 METHOD\nhost    all             all             192.168.1.0/24          md5\nhost    all             all             ::1/128                 md5\n```\n\n### 5. 启用审计日志\n\n```sql\n-- 启用审计日志\nALTER SYSTEM SET log_statement = 'all';\nALTER SYSTEM SET log_connections = on;\nALTER SYSTEM SET log_disconnections = on;\n\n-- 重新加载配置\nSELECT pg_reload_conf();\n```\n\n## 🐛 常见问题\n\n### 1. 连接失败\n\n**问题**：无法连接到 Vastbase 数据库\n\n**解决方案**：\n- 检查 Vastbase 服务是否正在运行\n- 检查端口是否正确（默认 5432）\n- 检查防火墙设置\n- 验证用户名和密码\n- 检查 `pg_hba.conf` 配置\n\n### 2. 连接断开\n\n**问题**：长时间空闲后出现 `Connection terminated unexpectedly`\n\n**说明**：MCP 服务已内置连接池 + TCP Keep-Alive + 断线自动重试机制，正常情况下不会出现此问题。如果仍然出现，请检查网络环境是否存在强制断开空闲连接的策略。\n\n### 3. 查询超时\n\n**问题**：大查询执行超时\n\n**解决方案**：\n- 增加超时时间：`SET statement_timeout = '600s';`\n- 优化查询，添加合适的索引\n- 使用 LIMIT 限制返回结果数量\n- 考虑使用分区表\n\n### 3. 字符编码问题\n\n**问题**：中文显示乱码\n\n**解决方案**：\n- 确保数据库使用 UTF-8 编码：\n  ```sql\n  CREATE DATABASE mydb WITH ENCODING 'UTF8';\n  ```\n\n### 4. 性能问题\n\n**问题**：查询性能慢\n\n**解决方案**：\n- 使用 EXPLAIN ANALYZE 分析查询\n- 创建合适的索引\n- 定期执行 VACUUM 和 ANALYZE\n- 优化查询语句\n- 考虑使用物化视图\n\n## 📚 参考资源\n\n- [Vastbase 官方网站](http://www.vastdata.com.cn/)\n- [Vastbase 产品文档](http://www.vastdata.com.cn/product/)\n- [PostgreSQL 官方文档](https://www.postgresql.org/docs/)\n- [海量数据技术支持](http://www.vastdata.com.cn/support/)\n\n## 🆚 Vastbase vs PostgreSQL\n\n| 特性 | Vastbase | PostgreSQL |\n|------|----------|------------|\n| 协议兼容 | ✅ 完全兼容 | - |\n| 国产化 | ✅ 支持 | ❌ 不支持 |\n| 企业支持 | ✅ 商业支持 | ⚠️ 社区支持 |\n| 高可用 | ✅ 内置支持 | ⚠️ 需要额外配置 |\n| 数据加密 | ✅ TDE 支持 | ⚠️ 有限支持 |\n| 审计日志 | ✅ 完善 | ⚠️ 基础 |\n| 成本 | ⚠️ 商业授权 | ✅ 开源免费 |\n\n## 💡 最佳实践\n\n### 1. 数据库设计\n\n- 使用合适的数据类型\n- 合理设计主键和外键\n- 使用分区表处理大数据量\n- 避免过度规范化\n\n### 2. 查询优化\n\n- 避免 SELECT *，只查询需要的列\n- 使用 LIMIT 限制返回结果\n- 合理使用索引\n- 避免在 WHERE 子句中使用函数\n\n### 3. 连接管理\n\n- 使用连接池（如 pgBouncer）\n- 合理设置连接数\n- 使用长连接减少连接开销\n- 定期检查连接健康状态\n\n### 4. 监控和维护\n\n- 监控数据库性能指标\n- 定期执行 VACUUM\n- 更新统计信息（ANALYZE）\n- 定期备份数据\n- 监控慢查询日志\n\n### 5. 安全管理\n\n- 使用强密码\n- 限制网络访问\n- 启用 SSL 连接\n- 定期审计日志\n- 遵循最小权限原则\n\n## 🎯 适用场景\n\n### 适合使用 Vastbase 的场景\n\n- ✅ 国产化替代需求\n- ✅ 政府、金融、电信行业\n- ✅ 需要商业支持的企业\n- ✅ 对安全性要求高的场景\n- ✅ 需要完善审计功能\n- ✅ PostgreSQL 迁移\n\n### 不适合使用 Vastbase 的场景\n\n- ❌ 预算非常有限\n- ❌ 小型个人项目\n- ❌ 不需要商业支持\n- ❌ 对国产化无要求\n\n## 🌟 Vastbase 特色功能\n\n### 1. 国产化支持\n\n- 支持国产操作系统（麒麟、统信等）\n- 支持国产芯片（鲲鹏、飞腾等）\n- 完全自主可控\n\n### 2. 企业级高可用\n\n- 主备切换\n- 自动故障转移\n- 数据同步复制\n\n### 3. 数据加密\n\n- 透明数据加密（TDE）\n- 列级加密\n- 传输加密\n\n### 4. 审计日志\n\n- 完善的审计日志\n- 操作记录追溯\n- 合规性支持\n\n### 5. 性能优化\n\n- 查询优化器增强\n- 并行查询支持\n- 智能索引推荐\n\n---\n\n**提示**：Vastbase 是国产数据库的优秀代表，特别适合有国产化替代需求的企业和政府机构。如果您需要商业支持和完善的企业级特性，Vastbase 是一个很好的选择。\n"
  },
  {
    "path": "docs/deployment/README.md",
    "content": "# 部署指南\n\n本目录包含 Universal DB MCP 的各种部署方式文档。\n\n## 部署方式概览\n\n| 部署方式 | 适用场景 | 复杂度 | 推荐指数 |\n|----------|----------|--------|----------|\n| [本地部署](./local.md) | 开发测试、个人使用 | 低 | ⭐⭐⭐⭐⭐ |\n| [Docker 部署](./docker.md) | 生产环境、团队使用 | 中 | ⭐⭐⭐⭐⭐ |\n| [云服务部署](./cloud/) | 企业级、高可用 | 高 | ⭐⭐⭐⭐ |\n\n## 选择建议\n\n### 开发测试\n\n推荐使用**本地部署**：\n- 快速启动\n- 方便调试\n- 无需额外配置\n\n### 生产环境\n\n推荐使用 **Docker 部署**：\n- 环境隔离\n- 易于管理\n- 支持自动重启\n\n### 企业级部署\n\n推荐使用**云服务部署**：\n- 高可用\n- 弹性扩展\n- 专业运维\n\n## 部署文档\n\n### 基础部署\n\n- [本地部署](./local.md) - Node.js、PM2、systemd\n- [Docker 部署](./docker.md) - Dockerfile、Docker Compose\n- [HTTPS 配置](./https-domain.md) - 域名和 SSL 证书\n\n### 云服务部署\n\n- [华为云部署](./cloud/huaweicloud.md) - Flexus 服务器\n- [阿里云部署](./cloud/aliyun.md) - 函数计算 FC\n- [腾讯云部署](./cloud/tencent.md) - 云函数 SCF\n- [AWS 部署](./cloud/aws.md) - Lambda\n\n### HTTP API 部署\n\nHTTP API 模式的详细部署文档请参考：\n\n- [HTTP API 部署指南](../http-api/DEPLOYMENT.md)\n- [HTTP API 部署指南（中文）](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 快速开始\n\n### 最简单的方式\n\n```bash\n# 安装\nnpm install -g universal-db-mcp\n\n# 启动 MCP 模式\nuniversal-db-mcp --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n\n# 启动 HTTP API 模式\nMODE=http HTTP_PORT=3000 API_KEYS=your-key universal-db-mcp\n```\n\n### Docker 方式\n\n```bash\n# 使用 Docker Compose\ncd docker\ndocker-compose up -d\n\n# 或直接运行\ndocker run -p 3000:3000 \\\n  -e MODE=http \\\n  -e API_KEYS=your-key \\\n  universal-db-mcp\n```\n\n## 安全建议\n\n无论选择哪种部署方式，请确保：\n\n1. **使用只读模式** - 生产环境使用默认的 `safe` 模式，或根据需要使用 `readwrite` 模式\n2. **配置 API Key** - HTTP API 模式必须配置强密钥\n3. **网络隔离** - 数据库不要直接暴露到公网\n4. **定期更新** - 及时更新到最新版本\n\n详细安全配置请参考 [安全指南](../guides/security.md)。\n"
  },
  {
    "path": "docs/deployment/cloud/aliyun.md",
    "content": "# 阿里云函数计算部署\n\n本文档介绍如何将 Universal DB MCP 部署到阿里云函数计算（FC）。\n\n## 前置要求\n\n- 阿里云账号\n- 安装 [Serverless Devs](https://www.serverless-devs.com/)\n- 配置阿里云 AccessKey\n\n## 部署步骤\n\n### 1. 安装 Serverless Devs\n\n```bash\nnpm install -g @serverless-devs/s\n```\n\n### 2. 配置阿里云凭证\n\n```bash\ns config add\n```\n\n选择 `Alibaba Cloud`，输入 AccessKey ID 和 Secret。\n\n### 3. 进入部署目录\n\n```bash\ncd serverless/aliyun-fc\n```\n\n### 4. 修改配置\n\n编辑 `template.yml`，修改以下配置：\n\n```yaml\nedition: 1.0.0\nname: universal-db-mcp\naccess: default\n\nservices:\n  universal-db-mcp:\n    component: fc\n    props:\n      region: cn-hangzhou  # 修改为你的区域\n      service:\n        name: universal-db-mcp\n        description: Universal DB MCP HTTP API\n      function:\n        name: api\n        runtime: nodejs20\n        codeUri: ../../\n        handler: dist/http/http-index.handler\n        memorySize: 512\n        timeout: 60\n        environmentVariables:\n          MODE: http\n          API_KEYS: ${env.API_KEYS}\n      triggers:\n        - name: http-trigger\n          type: http\n          config:\n            authType: anonymous\n            methods:\n              - GET\n              - POST\n              - PUT\n              - DELETE\n```\n\n### 5. 设置环境变量\n\n```bash\nexport API_KEYS=your-secret-key\n```\n\n### 6. 部署\n\n```bash\ns deploy\n```\n\n### 7. 获取访问地址\n\n部署成功后会显示函数的 HTTP 触发器地址。\n\n## 配置说明\n\n### 内存配置\n\n根据数据库连接数和查询复杂度调整：\n\n- 轻量使用：256MB\n- 一般使用：512MB\n- 重度使用：1024MB\n\n### 超时配置\n\n- 简单查询：30 秒\n- 复杂查询：60 秒\n- 大数据量：120 秒\n\n### VPC 配置\n\n如果需要连接 VPC 内的数据库，需要配置 VPC：\n\n```yaml\nfunction:\n  # ... 其他配置 ...\n  vpcConfig:\n    vpcId: vpc-xxx\n    vSwitchIds:\n      - vsw-xxx\n    securityGroupId: sg-xxx\n```\n\n## 注意事项\n\n1. **冷启动** - 函数计算有冷启动延迟，首次请求可能较慢\n2. **连接池** - 建议使用连接池管理数据库连接\n3. **超时** - 注意函数超时设置，避免长查询被中断\n4. **日志** - 使用阿里云日志服务查看函数日志\n\n## 费用说明\n\n阿里云函数计算按调用次数和执行时间计费：\n\n- 调用次数：每月前 100 万次免费\n- 执行时间：每月前 40 万 GB-秒免费\n\n详细价格请参考 [阿里云函数计算定价](https://www.aliyun.com/price/product#/fc/detail)。\n\n## 相关链接\n\n- [阿里云函数计算文档](https://help.aliyun.com/product/50980.html)\n- [Serverless Devs 文档](https://www.serverless-devs.com/docs)\n"
  },
  {
    "path": "docs/deployment/cloud/aws.md",
    "content": "# AWS Lambda 部署\n\n本文档介绍如何将 Universal DB MCP 部署到 AWS Lambda。\n\n## 前置要求\n\n- AWS 账号\n- 安装 [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)\n- 配置 AWS 凭证\n\n## 部署步骤\n\n### 1. 安装 AWS SAM CLI\n\n```bash\n# macOS\nbrew install aws-sam-cli\n\n# Windows\n# 下载 MSI 安装包：https://github.com/aws/aws-sam-cli/releases\n\n# Linux\npip install aws-sam-cli\n```\n\n### 2. 配置 AWS 凭证\n\n```bash\naws configure\n```\n\n### 3. 进入部署目录\n\n```bash\ncd serverless/aws-lambda\n```\n\n### 4. 修改配置\n\n编辑 `template.yaml`：\n\n```yaml\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: Universal DB MCP HTTP API\n\nGlobals:\n  Function:\n    Timeout: 60\n    MemorySize: 512\n    Runtime: nodejs20.x\n\nResources:\n  UniversalDbMcpFunction:\n    Type: AWS::Serverless::Function\n    Properties:\n      CodeUri: ../../\n      Handler: dist/http/http-index.handler\n      Environment:\n        Variables:\n          MODE: http\n          API_KEYS: !Ref ApiKeys\n      Events:\n        Api:\n          Type: HttpApi\n          Properties:\n            Path: /{proxy+}\n            Method: ANY\n\nParameters:\n  ApiKeys:\n    Type: String\n    Description: API Keys for authentication\n    NoEcho: true\n\nOutputs:\n  ApiEndpoint:\n    Description: API Gateway endpoint URL\n    Value: !Sub \"https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com\"\n```\n\n### 5. 构建\n\n```bash\nsam build\n```\n\n### 6. 部署\n\n```bash\nsam deploy --guided\n```\n\n按提示输入：\n- Stack Name: `universal-db-mcp`\n- AWS Region: 选择你的区域\n- ApiKeys: 输入你的 API 密钥\n\n### 7. 获取访问地址\n\n部署成功后会显示 API Gateway 端点地址。\n\n## 配置说明\n\n### 内存配置\n\n- 轻量使用：256MB\n- 一般使用：512MB\n- 重度使用：1024MB\n\n### 超时配置\n\n- API Gateway 最大超时：29 秒\n- Lambda 最大超时：15 分钟\n\n### VPC 配置\n\n连接 VPC 内数据库：\n\n```yaml\nResources:\n  UniversalDbMcpFunction:\n    Properties:\n      # ... 其他配置 ...\n      VpcConfig:\n        SecurityGroupIds:\n          - sg-xxx\n        SubnetIds:\n          - subnet-xxx\n```\n\n### RDS 代理\n\n推荐使用 RDS Proxy 管理数据库连接：\n\n```yaml\nResources:\n  RdsProxy:\n    Type: AWS::RDS::DBProxy\n    Properties:\n      DBProxyName: universal-db-mcp-proxy\n      EngineFamily: MYSQL\n      # ... 其他配置 ...\n```\n\n## 注意事项\n\n1. **冷启动** - Lambda 有冷启动延迟，可使用预置并发\n2. **连接管理** - 使用 RDS Proxy 避免连接耗尽\n3. **超时** - API Gateway 有 29 秒超时限制\n4. **日志** - 使用 CloudWatch Logs 查看日志\n\n## 费用说明\n\nAWS Lambda 按请求数和执行时间计费：\n\n- 请求数：每月前 100 万次免费\n- 执行时间：每月前 40 万 GB-秒免费\n\n详细价格请参考 [AWS Lambda 定价](https://aws.amazon.com/lambda/pricing/)。\n\n## 相关链接\n\n- [AWS Lambda 文档](https://docs.aws.amazon.com/lambda/)\n- [AWS SAM 文档](https://docs.aws.amazon.com/serverless-application-model/)\n- [RDS Proxy 文档](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)\n"
  },
  {
    "path": "docs/deployment/cloud/huaweicloud.md",
    "content": "# Universal-DB-MCP 华为云 Flexus 服务器部署指南\n\n> 本文档详细介绍如何在华为云 Flexus 服务器（Ubuntu 22.04 Server 64bit）上部署 Universal-DB-MCP 服务。\n\n## 目录\n\n- [项目概述](#项目概述)\n- [部署方案对比](#部署方案对比)\n- [推荐方案：Docker Compose 部署](#推荐方案docker-compose-部署)\n- [备选方案一：PM2 部署](#备选方案一pm2-部署)\n- [备选方案二：systemd 部署](#备选方案二systemd-部署)\n- [安全配置](#安全配置)\n- [Nginx 反向代理配置](#nginx-反向代理配置)\n- [SSL 证书配置](#ssl-证书配置)\n- [监控与日志](#监控与日志)\n- [常见问题排查](#常见问题排查)\n- [维护与更新](#维护与更新)\n\n---\n\n## 项目概述\n\n### 什么是 Universal-DB-MCP\n\nUniversal-DB-MCP 是一个通用数据库连接器，支持双模式运行：\n\n- **MCP 模式**：通过 stdio 协议与 Claude Desktop 通信，让 AI 直接查询数据库\n- **HTTP API 模式**：提供 RESTful API，可集成到 Coze、n8n、Dify 等第三方平台\n\n### 支持的数据库\n\n| 类型 | 数据库 |\n|------|--------|\n| 关系型 | MySQL、PostgreSQL、Oracle、SQL Server、SQLite |\n| 国产数据库 | 达梦(DM)、人大金仓(KingbaseES)、华为高斯(GaussDB)、海量数据(Vastbase)、瀚高(HighGo)、中兴(GoldenDB) |\n| 分布式 | OceanBase、TiDB、PolarDB |\n| NoSQL | MongoDB、Redis |\n| OLAP | ClickHouse |\n\n### 系统要求\n\n- **Node.js**: >= 20.0.0\n- **内存**: >= 512MB（推荐 1GB+）\n- **磁盘**: >= 1GB 可用空间\n- **网络**: 需要访问目标数据库\n\n---\n\n## 部署方案对比\n\n| 方案 | 优点 | 缺点 | 适用场景 |\n|------|------|------|----------|\n| **Docker Compose** | 环境隔离、易于管理、一键部署 | 需要安装 Docker | **推荐**，生产环境首选 |\n| **PM2** | 进程管理完善、支持集群 | 需要管理 Node.js 版本 | 熟悉 Node.js 的团队 |\n| **systemd** | 系统级服务、开机自启 | 配置相对复杂 | 追求极致性能 |\n\n**最佳实践推荐**：Docker Compose 部署，配合 Nginx 反向代理和 Let's Encrypt SSL 证书。\n\n---\n\n## 推荐方案：Docker Compose 部署\n\n### 步骤 1：服务器初始化\n\n```bash\n# 更新系统\nsudo apt update && sudo apt upgrade -y\n\n# 安装必要工具\nsudo apt install -y curl wget git vim htop\n```\n\n### 步骤 2：安装 Docker\n\n```bash\n# 安装 Docker 官方 GPG 密钥\nsudo apt install -y ca-certificates curl gnupg\nsudo install -m 0755 -d /etc/apt/keyrings\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg\nsudo chmod a+r /etc/apt/keyrings/docker.gpg\n\n# 添加 Docker 仓库\necho \\\n  \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \\\n  $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable\" | \\\n  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\n\n# 安装 Docker\nsudo apt update\nsudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n\n# 将当前用户添加到 docker 组（免 sudo）\nsudo usermod -aG docker $USER\n\n# 重新登录或执行以下命令使组变更生效\nnewgrp docker\n\n# 验证安装\ndocker --version\ndocker compose version\n```\n\n### 步骤 3：克隆项目\n\n```bash\n# 创建应用目录\nsudo mkdir -p /opt/apps\nsudo chown $USER:$USER /opt/apps\ncd /opt/apps\n\n# 克隆项目\ngit clone https://github.com/Anarkh-Lee/universal-db-mcp.git\ncd universal-db-mcp\n```\n\n### 步骤 4：配置环境变量\n\n```bash\n# 复制环境变量模板\ncp .env.example .env\n\n# 编辑环境变量\nvim .env\n```\n\n**生产环境 .env 配置示例**：\n\n```bash\n# ============================================\n# Server Mode\n# ============================================\nMODE=http\n\n# ============================================\n# HTTP Server Configuration\n# ============================================\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\n\n# ============================================\n# API Keys (重要：使用强密钥！)\n# ============================================\n# 生成强密钥命令: openssl rand -hex 32\nAPI_KEYS=your-strong-api-key-here\n\n# ============================================\n# CORS Configuration\n# ============================================\n# 生产环境建议指定具体域名\nCORS_ORIGINS=https://your-domain.com\nCORS_CREDENTIALS=false\n\n# ============================================\n# Rate Limiting\n# ============================================\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n\n# ============================================\n# Logging\n# ============================================\nLOG_LEVEL=info\nLOG_PRETTY=false\n\n# ============================================\n# Session Management\n# ============================================\nSESSION_TIMEOUT=3600000\nSESSION_CLEANUP_INTERVAL=300000\n```\n\n### 步骤 5：创建 Docker Compose 配置\n\n在项目根目录创建或修改 `docker-compose.prod.yml`：\n\n```bash\nvim docker-compose.prod.yml\n```\n\n```yaml\nversion: '3.8'\n\nservices:\n  universal-db-mcp:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    container_name: universal-db-mcp\n    restart: always\n    ports:\n      - \"127.0.0.1:3000:3000\"  # 仅本地访问，通过 Nginx 代理\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n    env_file:\n      - .env\n    healthcheck:\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n      start_period: 40s\n    logging:\n      driver: \"json-file\"\n      options:\n        max-size: \"10m\"\n        max-file: \"3\"\n    deploy:\n      resources:\n        limits:\n          memory: 512M\n        reservations:\n          memory: 256M\n\nnetworks:\n  default:\n    name: universal-db-mcp-network\n```\n\n### 步骤 6：构建并启动服务\n\n```bash\n# 构建镜像\ndocker compose -f docker-compose.prod.yml build\n\n# 启动服务（后台运行）\ndocker compose -f docker-compose.prod.yml up -d\n\n# 查看服务状态\ndocker compose -f docker-compose.prod.yml ps\n\n# 查看日志\ndocker compose -f docker-compose.prod.yml logs -f\n```\n\n### 步骤 7：验证服务\n\n```bash\n# 健康检查\ncurl http://localhost:3000/api/health\n\n# 预期返回\n# {\"status\":\"ok\",\"timestamp\":\"2024-xx-xxTxx:xx:xx.xxxZ\"}\n\n# 服务信息\ncurl http://localhost:3000/api/info\n```\n\n### 更新 Universal DB MCP 版本\n\n**更新步骤** \n\n```\n# 1. 进入项目目录\ncd /opt/universal-db-mcp\n\n# 2. 停止当前服务\ndocker compose down\n\n# 3. 重新构建镜像（会拉取最新 npm 包）\ndocker compose build --no-cache\n\n# 4. 启动服务\ndocker compose up -d\n\n# 5. 验证服务正常\ndocker compose ps\ncurl http://localhost:3001/api/health\n```\n\n**一条命令完成更新** \n\n```\ncd /opt/universal-db-mcp && docker compose down && docker compose build --no-cache && docker compose up -d\n```\n\n**查看更新后的版本**\n\n```\n# 进入容器查看版本\ndocker exec universal-db-mcp npm list -g universal-db-mcp\n```\n\n**更新后验证**\n\n```\n# 检查容器状态\ndocker compose ps\n\n# 检查日志是否正常\ndocker compose logs --tail 50\n\n# 测试 API\ncurl http://localhost:3001/api/health\ncurl https://universal-db-mcp.anarkh.site/api/health\n```\n\n**查看日志**\n\n```\n# 进入项目目录\ncd /opt/universal-db-mcp\n\n# 查看实时日志（持续输出）\ndocker compose logs -f\n\n# 查看最近 100 行\ndocker compose logs --tail 100\n\n# 查看最近 1 小时的日志\ndocker compose logs --since 1h\n\n# 查看最近 30 分钟的日志\ndocker compose logs --since 30m\n```\n\n---\n\n## 备选方案一：PM2 部署\n\n### 步骤 1：安装 Node.js 20\n\n```bash\n# 使用 NodeSource 安装 Node.js 20\ncurl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -\nsudo apt install -y nodejs\n\n# 验证版本\nnode --version  # 应显示 v20.x.x\nnpm --version\n```\n\n### 步骤 2：安装 PM2\n\n```bash\n# 全局安装 PM2\nsudo npm install -g pm2\n\n# 验证安装\npm2 --version\n```\n\n### 步骤 3：克隆并构建项目\n\n```bash\n# 创建应用目录\nsudo mkdir -p /opt/apps\nsudo chown $USER:$USER /opt/apps\ncd /opt/apps\n\n# 克隆项目\ngit clone https://github.com/Anarkh-Lee/universal-db-mcp.git\ncd universal-db-mcp\n\n# 安装依赖\nnpm ci\n\n# 构建项目\nnpm run build\n\n# 配置环境变量\ncp .env.example .env\nvim .env  # 按照上文配置\n```\n\n### 步骤 4：创建 PM2 配置文件\n\n```bash\nvim ecosystem.config.cjs\n```\n\n```javascript\nmodule.exports = {\n  apps: [{\n    name: 'universal-db-mcp',\n    script: 'dist/index.js',\n    cwd: '/opt/apps/universal-db-mcp',\n    instances: 1,  // 单实例，如需集群可改为 'max' 或具体数字\n    exec_mode: 'fork',\n    env: {\n      NODE_ENV: 'production',\n      MODE: 'http'\n    },\n    env_file: '.env',\n    max_memory_restart: '500M',\n    error_file: '/var/log/universal-db-mcp/error.log',\n    out_file: '/var/log/universal-db-mcp/out.log',\n    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',\n    merge_logs: true,\n    autorestart: true,\n    watch: false,\n    max_restarts: 10,\n    restart_delay: 5000\n  }]\n};\n```\n\n### 步骤 5：创建日志目录并启动\n\n```bash\n# 创建日志目录\nsudo mkdir -p /var/log/universal-db-mcp\nsudo chown $USER:$USER /var/log/universal-db-mcp\n\n# 启动服务\npm2 start ecosystem.config.cjs\n\n# 查看状态\npm2 status\n\n# 查看日志\npm2 logs universal-db-mcp\n\n# 设置开机自启\npm2 startup\npm2 save\n```\n\n### PM2 常用命令\n\n```bash\n# 重启服务\npm2 restart universal-db-mcp\n\n# 停止服务\npm2 stop universal-db-mcp\n\n# 删除服务\npm2 delete universal-db-mcp\n\n# 查看详细信息\npm2 show universal-db-mcp\n\n# 监控面板\npm2 monit\n```\n\n---\n\n## 备选方案二：systemd 部署\n\n### 步骤 1：安装 Node.js 20\n\n```bash\n# 使用 NodeSource 安装 Node.js 20\ncurl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -\nsudo apt install -y nodejs\n\n# 验证版本\nnode --version\n```\n\n### 步骤 2：克隆并构建项目\n\n```bash\n# 创建应用目录\nsudo mkdir -p /opt/apps\ncd /opt/apps\n\n# 克隆项目\nsudo git clone https://github.com/Anarkh-Lee/universal-db-mcp.git\ncd universal-db-mcp\n\n# 安装依赖并构建\nsudo npm ci\nsudo npm run build\n\n# 配置环境变量\nsudo cp .env.example .env\nsudo vim .env  # 按照上文配置\n```\n\n### 步骤 3：创建系统用户\n\n```bash\n# 创建专用用户（无登录权限）\nsudo useradd --system --no-create-home --shell /bin/false universal-db-mcp\n\n# 设置目录权限\nsudo chown -R universal-db-mcp:universal-db-mcp /opt/apps/universal-db-mcp\n```\n\n### 步骤 4：创建 systemd 服务文件\n\n```bash\nsudo vim /etc/systemd/system/universal-db-mcp.service\n```\n\n```ini\n[Unit]\nDescription=Universal DB MCP Server\nDocumentation=https://github.com/Anarkh-Lee/universal-db-mcp\nAfter=network.target\n\n[Service]\nType=simple\nUser=universal-db-mcp\nGroup=universal-db-mcp\nWorkingDirectory=/opt/apps/universal-db-mcp\nExecStart=/usr/bin/node dist/index.js\nRestart=always\nRestartSec=5\nStartLimitInterval=60\nStartLimitBurst=3\n\n# 环境变量\nEnvironment=NODE_ENV=production\nEnvironment=MODE=http\nEnvironmentFile=/opt/apps/universal-db-mcp/.env\n\n# 安全加固\nNoNewPrivileges=true\nProtectSystem=strict\nProtectHome=true\nPrivateTmp=true\nReadWritePaths=/opt/apps/universal-db-mcp\n\n# 资源限制\nMemoryMax=512M\nCPUQuota=80%\n\n# 日志\nStandardOutput=journal\nStandardError=journal\nSyslogIdentifier=universal-db-mcp\n\n[Install]\nWantedBy=multi-user.target\n```\n\n### 步骤 5：启动服务\n\n```bash\n# 重新加载 systemd 配置\nsudo systemctl daemon-reload\n\n# 启动服务\nsudo systemctl start universal-db-mcp\n\n# 设置开机自启\nsudo systemctl enable universal-db-mcp\n\n# 查看状态\nsudo systemctl status universal-db-mcp\n\n# 查看日志\nsudo journalctl -u universal-db-mcp -f\n```\n\n### systemd 常用命令\n\n```bash\n# 重启服务\nsudo systemctl restart universal-db-mcp\n\n# 停止服务\nsudo systemctl stop universal-db-mcp\n\n# 禁用开机自启\nsudo systemctl disable universal-db-mcp\n\n# 查看最近日志\nsudo journalctl -u universal-db-mcp --since \"1 hour ago\"\n```\n\n---\n\n## 安全配置\n\n### 1. 防火墙配置（UFW）\n\n```bash\n# 安装 UFW（如未安装）\nsudo apt install -y ufw\n\n# 允许 SSH\nsudo ufw allow ssh\n\n# 允许 HTTP/HTTPS\nsudo ufw allow 80/tcp\nsudo ufw allow 443/tcp\n\n# 不要直接开放 3000 端口（通过 Nginx 代理）\n# sudo ufw allow 3000/tcp  # 不推荐\n\n# 启用防火墙\nsudo ufw enable\n\n# 查看状态\nsudo ufw status verbose\n```\n\n### 2. 华为云安全组配置\n\n在华为云控制台配置安全组规则：\n\n| 方向 | 协议 | 端口 | 源地址 | 说明 |\n|------|------|------|--------|------|\n| 入方向 | TCP | 22 | 你的IP/32 | SSH 访问 |\n| 入方向 | TCP | 80 | 0.0.0.0/0 | HTTP |\n| 入方向 | TCP | 443 | 0.0.0.0/0 | HTTPS |\n\n### 3. API Key 安全\n\n```bash\n# 生成强 API Key\nopenssl rand -hex 32\n\n# 示例输出：a1b2c3d4e5f6...（64位十六进制字符串）\n```\n\n**重要提示**：\n- 不要在代码中硬编码 API Key\n- 定期轮换 API Key\n- 使用环境变量或密钥管理服务存储\n\n### 4. 数据库连接安全\n\n- 使用 VPC 内网连接数据库\n- 数据库用户使用最小权限原则\n- 启用 SSL/TLS 加密连接\n- 定期审计数据库访问日志\n\n---\n\n## Nginx 反向代理配置\n\n### 步骤 1：安装 Nginx\n\n```bash\nsudo apt install -y nginx\n\n# 启动并设置开机自启\nsudo systemctl start nginx\nsudo systemctl enable nginx\n```\n\n### 步骤 2：创建 Nginx 配置\n\n```bash\nsudo vim /etc/nginx/sites-available/universal-db-mcp\n```\n\n```nginx\n# 上游服务器\nupstream universal_db_mcp {\n    server 127.0.0.1:3000;\n    keepalive 32;\n}\n\n# HTTP 重定向到 HTTPS（配置 SSL 后启用）\n# server {\n#     listen 80;\n#     server_name your-domain.com;\n#     return 301 https://$server_name$request_uri;\n# }\n\n# 主服务器配置\nserver {\n    listen 80;\n    # listen 443 ssl http2;  # 配置 SSL 后启用\n    server_name your-domain.com;  # 替换为你的域名或 IP\n\n    # SSL 配置（配置证书后启用）\n    # ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;\n    # ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;\n    # ssl_protocols TLSv1.2 TLSv1.3;\n    # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;\n    # ssl_prefer_server_ciphers off;\n\n    # 安全头\n    add_header X-Frame-Options \"SAMEORIGIN\" always;\n    add_header X-Content-Type-Options \"nosniff\" always;\n    add_header X-XSS-Protection \"1; mode=block\" always;\n    add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n\n    # 日志\n    access_log /var/log/nginx/universal-db-mcp.access.log;\n    error_log /var/log/nginx/universal-db-mcp.error.log;\n\n    # 请求体大小限制\n    client_max_body_size 10M;\n\n    # API 代理\n    location /api/ {\n        proxy_pass http://universal_db_mcp;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_cache_bypass $http_upgrade;\n        proxy_read_timeout 60s;\n        proxy_connect_timeout 60s;\n        proxy_send_timeout 60s;\n    }\n\n    # 健康检查（无需认证）\n    location = /api/health {\n        proxy_pass http://universal_db_mcp;\n        proxy_http_version 1.1;\n        proxy_set_header Host $host;\n        access_log off;\n    }\n\n    # 根路径返回服务信息\n    location = / {\n        return 200 '{\"service\":\"universal-db-mcp\",\"status\":\"running\"}';\n        add_header Content-Type application/json;\n    }\n\n    # 禁止访问隐藏文件\n    location ~ /\\. {\n        deny all;\n    }\n}\n```\n\n### 步骤 3：启用配置\n\n```bash\n# 创建软链接\nsudo ln -s /etc/nginx/sites-available/universal-db-mcp /etc/nginx/sites-enabled/\n\n# 删除默认配置（可选）\nsudo rm /etc/nginx/sites-enabled/default\n\n# 测试配置\nsudo nginx -t\n\n# 重新加载 Nginx\nsudo systemctl reload nginx\n```\n\n---\n\n## SSL 证书配置\n\n### 使用 Let's Encrypt（推荐）\n\n```bash\n# 安装 Certbot\nsudo apt install -y certbot python3-certbot-nginx\n\n# 获取证书（替换为你的域名）\nsudo certbot --nginx -d your-domain.com\n\n# 自动续期测试\nsudo certbot renew --dry-run\n```\n\n### 证书自动续期\n\nCertbot 会自动创建定时任务，可以通过以下命令查看：\n\n```bash\nsudo systemctl status certbot.timer\n```\n\n---\n\n## 监控与日志\n\n### 1. 日志查看\n\n**Docker 部署**：\n```bash\n# 实时日志\ndocker compose -f docker-compose.prod.yml logs -f\n\n# 最近 100 行\ndocker compose -f docker-compose.prod.yml logs --tail 100\n```\n\n**PM2 部署**：\n```bash\n# 实时日志\npm2 logs universal-db-mcp\n\n# 日志文件位置\ncat /var/log/universal-db-mcp/out.log\ncat /var/log/universal-db-mcp/error.log\n```\n\n**systemd 部署**：\n```bash\n# 实时日志\nsudo journalctl -u universal-db-mcp -f\n\n# 最近 1 小时\nsudo journalctl -u universal-db-mcp --since \"1 hour ago\"\n```\n\n### 2. 健康检查脚本\n\n创建健康检查脚本 `/opt/scripts/health-check.sh`：\n\n```bash\n#!/bin/bash\n\nHEALTH_URL=\"http://localhost:3000/api/health\"\nWEBHOOK_URL=\"your-webhook-url\"  # 可选：告警通知\n\nresponse=$(curl -s -o /dev/null -w \"%{http_code}\" $HEALTH_URL)\n\nif [ \"$response\" != \"200\" ]; then\n    echo \"[$(date)] Health check failed! HTTP status: $response\"\n    # 可选：发送告警\n    # curl -X POST -H \"Content-Type: application/json\" -d '{\"text\":\"Universal-DB-MCP health check failed!\"}' $WEBHOOK_URL\n    exit 1\nfi\n\necho \"[$(date)] Health check passed\"\nexit 0\n```\n\n```bash\n# 设置执行权限\nchmod +x /opt/scripts/health-check.sh\n\n# 添加到 crontab（每 5 分钟检查一次）\ncrontab -e\n# 添加以下行：\n# */5 * * * * /opt/scripts/health-check.sh >> /var/log/health-check.log 2>&1\n```\n\n### 3. 资源监控\n\n```bash\n# 安装 htop\nsudo apt install -y htop\n\n# 查看 Docker 容器资源使用\ndocker stats universal-db-mcp\n\n# 查看系统资源\nhtop\n```\n\n---\n\n## 常见问题排查\n\n### 1. 服务无法启动\n\n```bash\n# 检查端口占用\nsudo lsof -i :3000\nsudo netstat -tlnp | grep 3000\n\n# 检查 Docker 日志\ndocker compose -f docker-compose.prod.yml logs\n\n# 检查环境变量\ndocker compose -f docker-compose.prod.yml config\n```\n\n### 2. 无法连接数据库\n\n```bash\n# 检查网络连通性\nping your-database-host\ntelnet your-database-host 3306\n\n# 检查防火墙\nsudo ufw status\n\n# 检查华为云安全组规则\n```\n\n### 3. API 返回 401 Unauthorized\n\n- 检查 API Key 是否正确配置\n- 检查请求头是否包含 `X-API-Key` 或 `Authorization: Bearer <key>`\n- 检查 .env 文件中的 `API_KEYS` 配置\n\n### 4. 内存不足\n\n```bash\n# 查看内存使用\nfree -h\n\n# 创建 swap 文件（如果内存不足）\nsudo fallocate -l 2G /swapfile\nsudo chmod 600 /swapfile\nsudo mkswap /swapfile\nsudo swapon /swapfile\n\n# 永久启用 swap\necho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab\n```\n\n### 5. Docker 构建失败\n\n```bash\n# 清理 Docker 缓存\ndocker system prune -a\n\n# 重新构建（不使用缓存）\ndocker compose -f docker-compose.prod.yml build --no-cache\n```\n\n---\n\n## 维护与更新\n\n### 更新应用\n\n**Docker 部署**：\n```bash\ncd /opt/apps/universal-db-mcp\n\n# 拉取最新代码\ngit pull origin main\n\n# 重新构建并启动\ndocker compose -f docker-compose.prod.yml build\ndocker compose -f docker-compose.prod.yml up -d\n```\n\n**PM2 部署**：\n```bash\ncd /opt/apps/universal-db-mcp\n\n# 拉取最新代码\ngit pull origin main\n\n# 重新安装依赖并构建\nnpm ci\nnpm run build\n\n# 重启服务\npm2 restart universal-db-mcp\n```\n\n**systemd 部署**：\n```bash\ncd /opt/apps/universal-db-mcp\n\n# 停止服务\nsudo systemctl stop universal-db-mcp\n\n# 拉取最新代码\nsudo git pull origin main\n\n# 重新安装依赖并构建\nsudo npm ci\nsudo npm run build\n\n# 设置权限\nsudo chown -R universal-db-mcp:universal-db-mcp /opt/apps/universal-db-mcp\n\n# 启动服务\nsudo systemctl start universal-db-mcp\n```\n\n### 备份配置\n\n```bash\n# 备份环境变量\ncp /opt/apps/universal-db-mcp/.env /opt/backups/universal-db-mcp/.env.$(date +%Y%m%d)\n\n# 备份 Nginx 配置\nsudo cp /etc/nginx/sites-available/universal-db-mcp /opt/backups/nginx/universal-db-mcp.$(date +%Y%m%d)\n```\n\n### 日志轮转\n\n创建 `/etc/logrotate.d/universal-db-mcp`：\n\n```\n/var/log/universal-db-mcp/*.log {\n    daily\n    missingok\n    rotate 14\n    compress\n    delaycompress\n    notifempty\n    create 0640 universal-db-mcp universal-db-mcp\n    sharedscripts\n    postrotate\n        pm2 reloadLogs\n    endscript\n}\n```\n\n---\n\n## 快速部署命令汇总\n\n### Docker Compose 一键部署\n\n```bash\n# 完整部署脚本\nsudo apt update && sudo apt upgrade -y\nsudo apt install -y curl wget git\n\n# 安装 Docker\ncurl -fsSL https://get.docker.com | sudo sh\nsudo usermod -aG docker $USER\nnewgrp docker\n\n# 克隆项目\nsudo mkdir -p /opt/apps && sudo chown $USER:$USER /opt/apps\ncd /opt/apps\ngit clone https://github.com/Anarkh-Lee/universal-db-mcp.git\ncd universal-db-mcp\n\n# 配置环境变量\ncp .env.example .env\n# 编辑 .env 文件设置 API_KEYS 等\n\n# 启动服务\ndocker compose -f docker-compose.prod.yml up -d\n\n# 验证\ncurl http://localhost:3000/api/health\n```\n\n---\n\n## 联系与支持\n\n- **项目地址**：https://github.com/Anarkh-Lee/universal-db-mcp\n- **问题反馈**：https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- **文档**：查看项目 `docs/` 目录\n\n---\n\n*文档版本：1.0.0*"
  },
  {
    "path": "docs/deployment/cloud/tencent.md",
    "content": "# 腾讯云函数部署\n\n本文档介绍如何将 Universal DB MCP 部署到腾讯云云函数（SCF）。\n\n## 前置要求\n\n- 腾讯云账号\n- 安装 [Serverless Framework](https://www.serverless.com/)\n- 配置腾讯云凭证\n\n## 部署步骤\n\n### 1. 安装 Serverless Framework\n\n```bash\nnpm install -g serverless\n```\n\n### 2. 进入部署目录\n\n```bash\ncd serverless/tencent-scf\n```\n\n### 3. 修改配置\n\n编辑 `serverless.yml`：\n\n```yaml\ncomponent: scf\nname: universal-db-mcp\napp: universal-db-mcp\n\ninputs:\n  name: universal-db-mcp\n  src:\n    src: ../../\n    exclude:\n      - .git/**\n      - node_modules/**\n      - tests/**\n  handler: dist/http/http-index.handler\n  runtime: Nodejs20.15\n  region: ap-guangzhou  # 修改为你的区域\n  memorySize: 512\n  timeout: 60\n  environment:\n    variables:\n      MODE: http\n      API_KEYS: ${env:API_KEYS}\n  events:\n    - apigw:\n        parameters:\n          protocols:\n            - http\n            - https\n          environment: release\n          endpoints:\n            - path: /\n              method: ANY\n```\n\n### 4. 设置环境变量\n\n```bash\nexport API_KEYS=your-secret-key\n```\n\n### 5. 部署\n\n```bash\nserverless deploy\n```\n\n### 6. 获取访问地址\n\n部署成功后会显示 API 网关地址。\n\n## 配置说明\n\n### 内存配置\n\n- 轻量使用：256MB\n- 一般使用：512MB\n- 重度使用：1024MB\n\n### 超时配置\n\n- 简单查询：30 秒\n- 复杂查询：60 秒\n- 大数据量：120 秒（最大 900 秒）\n\n### VPC 配置\n\n连接 VPC 内数据库：\n\n```yaml\ninputs:\n  # ... 其他配置 ...\n  vpcConfig:\n    vpcId: vpc-xxx\n    subnetId: subnet-xxx\n```\n\n## 注意事项\n\n1. **冷启动** - 首次请求有冷启动延迟\n2. **并发限制** - 默认并发限制 300，可申请提升\n3. **日志** - 使用腾讯云日志服务查看\n4. **监控** - 在云函数控制台查看监控指标\n\n## 费用说明\n\n腾讯云云函数按调用次数和资源使用量计费：\n\n- 调用次数：每月前 100 万次免费\n- 资源使用：每月前 40 万 GB-秒免费\n\n详细价格请参考 [腾讯云云函数定价](https://cloud.tencent.com/document/product/583/12284)。\n\n## 相关链接\n\n- [腾讯云云函数文档](https://cloud.tencent.com/document/product/583)\n- [Serverless Framework 文档](https://www.serverless.com/framework/docs)\n"
  },
  {
    "path": "docs/deployment/docker.md",
    "content": "# Docker 部署\n\n本文档介绍如何使用 Docker 部署 Universal DB MCP。\n\n## 前置要求\n\n- Docker >= 20.10\n- Docker Compose >= 2.0（可选）\n\n## 快速开始\n\n### 使用 Docker Compose（推荐）\n\n```bash\ncd docker\ndocker-compose up -d\n```\n\n### 直接运行\n\n```bash\n# 构建镜像\ndocker build -t universal-db-mcp -f docker/Dockerfile .\n\n# 运行容器\ndocker run -p 3000:3000 \\\n  -e MODE=http \\\n  -e API_KEYS=your-secret-key \\\n  universal-db-mcp\n```\n\n## Dockerfile\n\n项目提供了优化的多阶段构建 Dockerfile：\n\n```dockerfile\nFROM node:20-alpine AS builder\n\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM node:20-alpine\n\nWORKDIR /app\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/package.json ./\n\nUSER node\nEXPOSE 3000\nCMD [\"node\", \"dist/index.js\"]\n```\n\n## Docker Compose 配置\n\n### 基础配置\n\n`docker-compose.yml`：\n\n```yaml\nversion: '3.8'\n\nservices:\n  universal-db-mcp:\n    build:\n      context: ..\n      dockerfile: docker/Dockerfile\n    container_name: universal-db-mcp\n    restart: unless-stopped\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n    env_file:\n      - .env.docker\n    healthcheck:\n      test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:3000/api/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n```\n\n### 生产环境配置\n\n`docker-compose.prod.yml`：\n\n```yaml\nversion: '3.8'\n\nservices:\n  universal-db-mcp:\n    build:\n      context: ..\n      dockerfile: docker/Dockerfile\n    container_name: universal-db-mcp\n    restart: always\n    ports:\n      - \"127.0.0.1:3000:3000\"  # 仅本地访问，通过 Nginx 代理\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n    env_file:\n      - .env\n    healthcheck:\n      test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:3000/api/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n      start_period: 40s\n    logging:\n      driver: \"json-file\"\n      options:\n        max-size: \"10m\"\n        max-file: \"3\"\n    deploy:\n      resources:\n        limits:\n          memory: 512M\n        reservations:\n          memory: 256M\n```\n\n## 环境变量配置\n\n创建 `.env.docker` 文件：\n\n```bash\n# 服务器模式\nMODE=http\n\n# HTTP 配置\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\n\n# API 密钥（重要：使用强密钥！）\nAPI_KEYS=your-strong-api-key-here\n\n# CORS 配置\nCORS_ORIGINS=*\nCORS_CREDENTIALS=false\n\n# 速率限制\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n\n# 日志\nLOG_LEVEL=info\nLOG_PRETTY=false\n\n# 会话管理\nSESSION_TIMEOUT=3600000\nSESSION_CLEANUP_INTERVAL=300000\n```\n\n## 常用命令\n\n### 构建和启动\n\n```bash\n# 构建镜像\ndocker-compose build\n\n# 启动服务（后台运行）\ndocker-compose up -d\n\n# 查看日志\ndocker-compose logs -f\n\n# 停止服务\ndocker-compose down\n```\n\n### 更新版本\n\n```bash\n# 停止服务\ndocker-compose down\n\n# 重新构建（拉取最新代码后）\ndocker-compose build --no-cache\n\n# 启动服务\ndocker-compose up -d\n```\n\n### 清理\n\n```bash\n# 停止并删除容器、网络\ndocker-compose down\n\n# 停止并删除容器、网络、镜像\ndocker-compose down --rmi all\n\n# 清理未使用的镜像\ndocker image prune -f\n```\n\n## 连接数据库\n\n### 连接宿主机数据库\n\n使用 `host.docker.internal`：\n\n```bash\ndocker run -p 3000:3000 \\\n  -e MODE=http \\\n  -e API_KEYS=your-key \\\n  -e DB_TYPE=mysql \\\n  -e DB_HOST=host.docker.internal \\\n  -e DB_PORT=3306 \\\n  -e DB_USER=root \\\n  -e DB_PASSWORD=xxx \\\n  -e DB_DATABASE=test \\\n  universal-db-mcp\n```\n\n### 连接其他容器\n\n使用 Docker 网络：\n\n```yaml\nversion: '3.8'\n\nservices:\n  universal-db-mcp:\n    # ... 配置 ...\n    networks:\n      - db-network\n\n  mysql:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: password\n      MYSQL_DATABASE: test\n    networks:\n      - db-network\n\nnetworks:\n  db-network:\n    driver: bridge\n```\n\n然后使用服务名作为主机名：`DB_HOST=mysql`\n\n## 健康检查\n\n```bash\n# 检查容器状态\ndocker ps\n\n# 检查健康状态\ndocker inspect --format='{{.State.Health.Status}}' universal-db-mcp\n\n# 手动测试\ncurl http://localhost:3000/api/health\n```\n\n## 日志管理\n\n### 查看日志\n\n```bash\n# 实时日志\ndocker-compose logs -f\n\n# 最近 100 行\ndocker-compose logs --tail 100\n\n# 指定时间范围\ndocker-compose logs --since 1h\n```\n\n### 日志轮转\n\nDocker 默认配置了日志轮转，可以在 `docker-compose.yml` 中自定义：\n\n```yaml\nlogging:\n  driver: \"json-file\"\n  options:\n    max-size: \"10m\"\n    max-file: \"3\"\n```\n\n## 资源限制\n\n```yaml\ndeploy:\n  resources:\n    limits:\n      cpus: '1'\n      memory: 512M\n    reservations:\n      cpus: '0.5'\n      memory: 256M\n```\n\n## 安全建议\n\n1. **不要暴露端口到公网** - 使用 `127.0.0.1:3000:3000` 仅本地访问\n2. **使用 Nginx 反向代理** - 配置 SSL 和访问控制\n3. **使用非 root 用户** - Dockerfile 中已配置 `USER node`\n4. **定期更新镜像** - 及时修复安全漏洞\n\n## 下一步\n\n- [HTTPS 配置](./https-domain.md) - 配置域名和 SSL\n- [云服务部署](./cloud/) - 云平台部署\n- [运维指南](../operations/guide.md) - 日常运维操作\n"
  },
  {
    "path": "docs/deployment/https-domain.md",
    "content": "# 域名与 HTTPS 配置指南\n\n通过域名访问 Universal DB MCP 的完整配置步骤。\n\n## 📋 配置概览\n\n```\n用户访问 mcp.yourdomain.com\n        ↓\n[腾讯云 DNS 解析] → 指向华为云服务器 IP\n        ↓\n[华为云 Nginx :80/443] → 反向代理\n        ↓\n[MCP 服务 :3001]\n```\n\n---\n\n## 步骤 1: 腾讯云配置二级域名解析\n\n### 1.1 登录腾讯云控制台\n\n1. 打开 [腾讯云 DNS 解析控制台](https://console.cloud.tencent.com/cns)\n2. 找到您的域名，点击**解析**\n\n### 1.2 添加解析记录\n\n点击**添加记录**，填写：\n\n| 字段 | 值 |\n|------|-----|\n| 主机记录 | `mcp`（这样二级域名就是 `mcp.yourdomain.com`） |\n| 记录类型 | `A` |\n| 线路类型 | `默认` |\n| 记录值 | `您的华为云服务器公网 IP` |\n| TTL | `600`（默认即可） |\n\n点击**确认**保存。\n\n### 1.3 验证解析是否生效\n\n等待 2-5 分钟后，在服务器上执行：\n\n```bash\nping mcp.yourdomain.com\n```\n\n看到返回您的服务器 IP 就说明解析成功。\n\n---\n\n## 步骤 2: 华为云安全组配置\n\n确保放行 80 端口（HTTP）和 443 端口（HTTPS）：\n\n1. 登录华为云控制台\n2. 进入**安全组**设置\n3. 添加入方向规则：\n\n| 协议 | 端口 | 源地址 |\n|------|------|--------|\n| TCP | 80 | 0.0.0.0/0 |\n| TCP | 443 | 0.0.0.0/0 |\n\n---\n\n## 步骤 3: 配置 Nginx 反向代理\n\n### 3.1 查看现有 Nginx 配置\n\n```bash\n# 查看已有的配置文件\nls /etc/nginx/sites-enabled/\n```\n\n### 3.2 创建 MCP 服务的 Nginx 配置\n\n```bash\n# 创建配置文件（请将 mcp.yourdomain.com 替换为您的实际域名）\nsudo tee /etc/nginx/sites-available/universal-db-mcp << 'EOF'\nserver {\n    listen 80;\n    server_name mcp.yourdomain.com;  # ← 替换为您的二级域名\n\n    location / {\n        proxy_pass http://127.0.0.1:3001;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_cache_bypass $http_upgrade;\n        \n        # 超时设置\n        proxy_connect_timeout 60s;\n        proxy_send_timeout 60s;\n        proxy_read_timeout 60s;\n    }\n}\nEOF\n```\n\n### 3.3 修改配置中的域名\n\n```bash\n# 用 nano 编辑，替换为您的真实域名\nsudo nano /etc/nginx/sites-available/universal-db-mcp\n```\n\n**Nano 操作步骤：**\n\n1. 使用方向键找到 `server_name mcp.yourdomain.com;` 这一行\n2. 将 `mcp.yourdomain.com` 改为您的实际二级域名\n3. 按 `Ctrl + O` 保存\n4. 按 `Enter` 确认\n5. 按 `Ctrl + X` 退出\n\n### 3.4 启用配置\n\n```bash\n# 创建软链接启用配置\nsudo ln -s /etc/nginx/sites-available/universal-db-mcp /etc/nginx/sites-enabled/\n\n# 测试配置是否正确\nsudo nginx -t\n```\n\n如果显示：\n```\nnginx: configuration file /etc/nginx/nginx.conf syntax is ok\nnginx: configuration file /etc/nginx/nginx.conf test is successful\n```\n\n说明配置正确。\n\n### 3.5 重新加载 Nginx\n\n```bash\nsudo systemctl reload nginx\n```\n\n---\n\n## 步骤 4: 验证 HTTP 访问\n\n在浏览器或 Apipost 中访问：\n\n```\nhttp://mcp.yourdomain.com/api/health\n```\n\n应该返回：\n```json\n{\"status\":\"ok\",\"timestamp\":\"...\"}\n```\n\n---\n\n## 步骤 5: 配置 HTTPS（推荐）\n\n### 5.1 检查 Certbot 是否已安装\n\n```bash\ncertbot --version\n```\n\n如果未安装：\n\n```bash\nsudo apt install -y certbot python3-certbot-nginx\n```\n\n### 5.2 查看已有证书（可选）\n\n```bash\nsudo certbot certificates\n```\n\n### 5.3 申请 SSL 证书\n\n```bash\n# 替换为您的域名和邮箱\nsudo certbot --nginx -d mcp.yourdomain.com -m your-email@example.com --agree-tos\n```\n\n**关于邮箱：**\n\n- 任何有效邮箱都可以（QQ邮箱、163、Gmail 等）\n- 用于接收证书到期提醒和安全通知\n- 建议使用常用邮箱\n\n**交互选项：**\n\n- 如果询问是否重定向 HTTP 到 HTTPS，选择 `2`（自动重定向）\n\n### 5.4 验证 HTTPS 访问\n\n```\nhttps://mcp.yourdomain.com/api/health\n```\n\n### 5.5 设置自动续期\n\n```bash\n# 测试自动续期\nsudo certbot renew --dry-run\n\n# 证书会自动续期，无需手动操作\n```\n\n---\n\n## 📝 配置完成后速查表\n\n| 项目 | 值 |\n|------|-----|\n| 二级域名 | `mcp.yourdomain.com` |\n| DNS 解析 | A 记录 → 华为云服务器 IP |\n| Nginx 配置文件 | `/etc/nginx/sites-available/universal-db-mcp` |\n| 服务内部端口 | 3001 |\n| 对外端口 | 80 (HTTP) / 443 (HTTPS) |\n| HTTP 访问 | `http://mcp.yourdomain.com/api/health` |\n| HTTPS 访问 | `https://mcp.yourdomain.com/api/health` |\n\n---\n\n## 🔧 Nginx 常用运维命令\n\n```bash\n# 查看 Nginx 状态\nsudo systemctl status nginx\n\n# 测试配置文件语法\nsudo nginx -t\n\n# 重新加载配置（修改配置后）\nsudo systemctl reload nginx\n\n# 重启 Nginx\nsudo systemctl restart nginx\n\n# 查看错误日志\nsudo tail -f /var/log/nginx/error.log\n\n# 查看访问日志\nsudo tail -f /var/log/nginx/access.log\n```\n\n---\n\n## 🔐 Certbot 常用命令\n\n```bash\n# 查看已申请的证书\nsudo certbot certificates\n\n# 手动续期证书\nsudo certbot renew\n\n# 测试续期（不实际执行）\nsudo certbot renew --dry-run\n\n# 删除证书\nsudo certbot delete --cert-name mcp.yourdomain.com\n```\n\n---\n\n## ⚠️ 注意事项\n\n1. **域名替换**：所有 `mcp.yourdomain.com` 都要替换为您的实际域名\n2. **等待解析**：DNS 解析可能需要几分钟生效\n3. **安全组**：确保华为云安全组放行了 80 和 443 端口\n4. **不影响其他服务**：新配置是独立的，不会影响 FastGPT 等已有服务\n5. **证书自动续期**：Let's Encrypt 证书有效期 90 天，Certbot 会自动续期\n\n---\n\n## 🛠 故障排查\n\n### DNS 解析不生效\n\n```bash\n# 检查解析\nnslookup mcp.yourdomain.com\n\n# 或使用 dig\ndig mcp.yourdomain.com\n```\n\n### Nginx 配置错误\n\n```bash\n# 测试配置\nsudo nginx -t\n\n# 查看错误详情\nsudo tail -50 /var/log/nginx/error.log\n```\n\n### HTTPS 证书申请失败\n\n```bash\n# 确保 80 端口可访问（Let's Encrypt 验证需要）\ncurl http://mcp.yourdomain.com\n\n# 查看 Certbot 日志\nsudo tail -50 /var/log/letsencrypt/letsencrypt.log\n```\n\n### 502 Bad Gateway 错误\n\n```bash\n# 检查 MCP 服务是否运行\ndocker ps | grep universal-db-mcp\n\n# 检查服务日志\ncd /opt/universal-db-mcp\ndocker compose logs\n```\n"
  },
  {
    "path": "docs/deployment/local.md",
    "content": "# 本地部署\n\n本文档介绍如何在本地环境部署 Universal DB MCP。\n\n## 前置要求\n\n- Node.js >= 20.0.0\n- npm 或 yarn\n\n## 方式一：直接运行\n\n### 安装\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n### 启动 MCP 模式\n\n```bash\nuniversal-db-mcp \\\n  --type mysql \\\n  --host localhost \\\n  --port 3306 \\\n  --user root \\\n  --password your_password \\\n  --database your_database\n```\n\n### 启动 HTTP API 模式\n\n```bash\n# 设置环境变量\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key\n\n# 启动\nuniversal-db-mcp\n```\n\n## 方式二：从源码运行\n\n### 克隆项目\n\n```bash\ngit clone https://github.com/yourusername/universal-db-mcp.git\ncd universal-db-mcp\n```\n\n### 安装依赖\n\n```bash\nnpm install\n```\n\n### 构建\n\n```bash\nnpm run build\n```\n\n### 运行\n\n```bash\n# MCP 模式\nnpm run start:mcp -- --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n\n# HTTP API 模式\nnpm run start:http\n```\n\n## 方式三：PM2 部署\n\nPM2 是 Node.js 的进程管理器，适合生产环境。\n\n### 安装 PM2\n\n```bash\nnpm install -g pm2\n```\n\n### 创建配置文件\n\n创建 `ecosystem.config.cjs`：\n\n```javascript\nmodule.exports = {\n  apps: [{\n    name: 'universal-db-mcp',\n    script: 'dist/index.js',\n    instances: 1,\n    exec_mode: 'fork',\n    env: {\n      NODE_ENV: 'production',\n      MODE: 'http',\n      HTTP_PORT: 3000,\n      API_KEYS: 'your-secret-key'\n    },\n    max_memory_restart: '500M',\n    error_file: '/var/log/universal-db-mcp/error.log',\n    out_file: '/var/log/universal-db-mcp/out.log',\n    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',\n    autorestart: true,\n    watch: false\n  }]\n};\n```\n\n### 启动服务\n\n```bash\n# 创建日志目录\nsudo mkdir -p /var/log/universal-db-mcp\nsudo chown $USER:$USER /var/log/universal-db-mcp\n\n# 启动\npm2 start ecosystem.config.cjs\n\n# 设置开机自启\npm2 startup\npm2 save\n```\n\n### PM2 常用命令\n\n```bash\n# 查看状态\npm2 status\n\n# 查看日志\npm2 logs universal-db-mcp\n\n# 重启\npm2 restart universal-db-mcp\n\n# 停止\npm2 stop universal-db-mcp\n\n# 监控\npm2 monit\n```\n\n## 方式四：systemd 部署\n\n适合 Linux 服务器的系统级服务管理。\n\n### 创建系统用户\n\n```bash\nsudo useradd --system --no-create-home --shell /bin/false universal-db-mcp\n```\n\n### 创建服务文件\n\n创建 `/etc/systemd/system/universal-db-mcp.service`：\n\n```ini\n[Unit]\nDescription=Universal DB MCP Server\nAfter=network.target\n\n[Service]\nType=simple\nUser=universal-db-mcp\nGroup=universal-db-mcp\nWorkingDirectory=/opt/universal-db-mcp\nExecStart=/usr/bin/node dist/index.js\nRestart=always\nRestartSec=5\n\nEnvironment=NODE_ENV=production\nEnvironment=MODE=http\nEnvironmentFile=/opt/universal-db-mcp/.env\n\nNoNewPrivileges=true\nProtectSystem=strict\nProtectHome=true\nPrivateTmp=true\nReadWritePaths=/opt/universal-db-mcp\n\nMemoryMax=512M\nCPUQuota=80%\n\nStandardOutput=journal\nStandardError=journal\nSyslogIdentifier=universal-db-mcp\n\n[Install]\nWantedBy=multi-user.target\n```\n\n### 启动服务\n\n```bash\n# 重新加载配置\nsudo systemctl daemon-reload\n\n# 启动服务\nsudo systemctl start universal-db-mcp\n\n# 设置开机自启\nsudo systemctl enable universal-db-mcp\n\n# 查看状态\nsudo systemctl status universal-db-mcp\n\n# 查看日志\nsudo journalctl -u universal-db-mcp -f\n```\n\n## 开发模式\n\n### 监听文件变化\n\n```bash\nnpm run dev\n```\n\n### 在 Claude Desktop 中使用本地版本\n\n编辑 Claude Desktop 配置文件，使用本地路径：\n\n```json\n{\n  \"mcpServers\": {\n    \"local-db\": {\n      \"command\": \"node\",\n      \"args\": [\n        \"/path/to/universal-db-mcp/dist/index.js\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n## 验证部署\n\n### MCP 模式\n\n启动后应看到：\n\n```\n🔌 Starting MCP mode...\n🔧 配置信息:\n   数据库类型: mysql\n   主机地址: localhost:3306\n   数据库名: test\n   安全模式: ✅ 只读模式\n🔌 正在连接数据库...\n✅ 数据库连接成功\n🚀 MCP 服务器已启动，等待 Claude Desktop 连接...\n```\n\n### HTTP API 模式\n\n```bash\n# 健康检查\ncurl http://localhost:3000/api/health\n\n# 预期返回\n{\"status\":\"ok\",\"timestamp\":\"...\"}\n```\n\n## 下一步\n\n- [Docker 部署](./docker.md) - 容器化部署\n- [HTTPS 配置](./https-domain.md) - 配置域名和 SSL\n- [运维指南](../operations/guide.md) - 日常运维操作\n"
  },
  {
    "path": "docs/development/adding-database.md",
    "content": "# 添加新数据库支持\n\n本文档介绍如何为 Universal DB MCP 添加新的数据库支持。\n\n## 概述\n\n添加新数据库需要以下步骤：\n\n1. 创建适配器文件\n2. 实现 DbAdapter 接口\n3. 在工厂中注册\n4. 添加依赖\n5. 更新文档\n\n## 步骤详解\n\n### 1. 创建适配器文件\n\n在 `src/adapters/` 目录下创建新文件，例如 `newdb.ts`：\n\n```typescript\n// src/adapters/newdb.ts\nimport type { DbAdapter, QueryResult, SchemaInfo, TableInfo } from '../types/adapter.js';\n\nexport interface NewDbConfig {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n}\n\nexport class NewDbAdapter implements DbAdapter {\n  private config: NewDbConfig;\n  private connection: any; // 替换为实际的连接类型\n\n  constructor(config: NewDbConfig) {\n    this.config = config;\n  }\n\n  async connect(): Promise<void> {\n    // 实现连接逻辑\n  }\n\n  async disconnect(): Promise<void> {\n    // 实现断开连接逻辑\n  }\n\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    // 实现查询逻辑\n  }\n\n  async getSchema(): Promise<SchemaInfo> {\n    // 实现获取结构逻辑\n  }\n\n  async getTableInfo(tableName: string): Promise<TableInfo> {\n    // 实现获取表信息逻辑\n  }\n\n  isWriteOperation(query: string): boolean {\n    // 实现写操作检测\n    const writeKeywords = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER', 'TRUNCATE'];\n    const upperQuery = query.toUpperCase().trim();\n    return writeKeywords.some(keyword => upperQuery.startsWith(keyword));\n  }\n}\n```\n\n### 2. 实现 DbAdapter 接口\n\n#### connect()\n\n建立数据库连接：\n\n```typescript\nasync connect(): Promise<void> {\n  try {\n    this.connection = await createConnection({\n      host: this.config.host,\n      port: this.config.port,\n      user: this.config.user,\n      password: this.config.password,\n      database: this.config.database,\n    });\n  } catch (error) {\n    throw new Error(`连接数据库失败: ${error.message}`);\n  }\n}\n```\n\n#### disconnect()\n\n关闭数据库连接：\n\n```typescript\nasync disconnect(): Promise<void> {\n  if (this.connection) {\n    await this.connection.close();\n    this.connection = null;\n  }\n}\n```\n\n#### executeQuery()\n\n执行 SQL 查询：\n\n```typescript\nasync executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n  const result = await this.connection.query(query, params);\n  return {\n    rows: result.rows,\n    rowCount: result.rowCount,\n    fields: result.fields.map(f => ({\n      name: f.name,\n      type: f.dataType,\n    })),\n  };\n}\n```\n\n#### getSchema()\n\n获取数据库结构：\n\n```typescript\nasync getSchema(): Promise<SchemaInfo> {\n  // 查询所有表\n  const tables = await this.getTables();\n\n  // 获取每个表的信息\n  const tableInfos = await Promise.all(\n    tables.map(table => this.getTableInfo(table))\n  );\n\n  return {\n    tables: tableInfos,\n    databaseName: this.config.database,\n  };\n}\n```\n\n> **注意：多 Schema 支持**\n>\n> 如果新数据库支持 Schema（如 PostgreSQL 系、SQL Server、Oracle），需要在 `getSchema()` 中：\n> 1. 查询所有用户 Schema 的表（排除系统 Schema）\n> 2. 在 `TableInfo.name` 中使用 `schema.table_name` 格式（非默认 Schema 时）\n> 3. 设置 `TableInfo.schema` 字段标记表所属 Schema\n> 4. 参考 `src/adapters/postgres.ts` 中的 `makeTableKey()` 方法\n\n#### getTableInfo()\n\n获取表详细信息：\n\n```typescript\nasync getTableInfo(tableName: string): Promise<TableInfo> {\n  // 查询列信息\n  const columns = await this.getColumns(tableName);\n\n  // 查询主键\n  const primaryKey = await this.getPrimaryKey(tableName);\n\n  // 查询索引\n  const indexes = await this.getIndexes(tableName);\n\n  return {\n    name: tableName,\n    columns,\n    primaryKey,\n    indexes,\n  };\n}\n```\n\n### 3. 在工厂中注册\n\n编辑 `src/utils/adapter-factory.ts`：\n\n```typescript\nimport { NewDbAdapter } from '../adapters/newdb.js';\n\nexport class AdapterFactory {\n  static createAdapter(type: string, config: any): DbAdapter {\n    switch (type.toLowerCase()) {\n      // ... 现有适配器 ...\n      case 'newdb':\n        return new NewDbAdapter(config);\n      default:\n        throw new Error(`不支持的数据库类型: ${type}`);\n    }\n  }\n}\n```\n\n### 4. 添加依赖\n\n在 `package.json` 中添加数据库驱动：\n\n```json\n{\n  \"dependencies\": {\n    \"newdb-driver\": \"^1.0.0\"\n  }\n}\n```\n\n如果是可选依赖（如达梦）：\n\n```json\n{\n  \"optionalDependencies\": {\n    \"newdb-driver\": \"^1.0.0\"\n  }\n}\n```\n\n### 5. 更新文档\n\n#### 更新 README.md\n\n在支持的数据库列表中添加新数据库。\n\n#### 创建数据库指南\n\n在 `docs/databases/` 创建 `newdb.md`。\n\n#### 更新数据库概览\n\n在 `docs/databases/README.md` 中添加新数据库。\n\n## 参考示例\n\n### MySQL 兼容数据库\n\n参考 `src/adapters/mysql.ts`，适用于：\n- TiDB\n- OceanBase\n- PolarDB\n- GoldenDB\n\n### PostgreSQL 兼容数据库\n\n参考 `src/adapters/postgres.ts`，适用于：\n- KingbaseES\n- GaussDB\n- Vastbase\n- HighGo\n\n### NoSQL 数据库\n\n参考 `src/adapters/mongodb.ts` 或 `src/adapters/redis.ts`。\n\n## 测试\n\n### 单元测试\n\n创建 `tests/unit/adapters/newdb.test.ts`：\n\n```typescript\nimport { describe, it, expect } from 'vitest';\nimport { NewDbAdapter } from '../../../src/adapters/newdb';\n\ndescribe('NewDbAdapter', () => {\n  it('should connect successfully', async () => {\n    const adapter = new NewDbAdapter({\n      host: 'localhost',\n      port: 1234,\n      user: 'test',\n      password: 'test',\n      database: 'test',\n    });\n\n    await expect(adapter.connect()).resolves.not.toThrow();\n  });\n});\n```\n\n### 集成测试\n\n创建 `tests/integration/newdb.test.ts`，测试实际数据库连接。\n\n## 提交检查清单\n\n- [ ] 实现 DbAdapter 接口的所有方法\n- [ ] 在 AdapterFactory 中注册\n- [ ] 添加数据库驱动依赖\n- [ ] 创建数据库使用指南\n- [ ] 更新 README.md\n- [ ] 添加单元测试\n- [ ] 代码通过 TypeScript 编译\n- [ ] 关键逻辑添加中文注释\n"
  },
  {
    "path": "docs/development/architecture.md",
    "content": "# 项目架构\n\n本文档介绍 Universal DB MCP 的架构设计和核心模块。\n\n## 架构概览\n\n项目支持两种启动模式，HTTP 模式下同时提供 MCP 协议和 REST API 两种接入方式：\n\n```\n┌─────────────────────────────────────────────────────────────────────────┐\n│                         Universal DB MCP                                 │\n├─────────────────────────────────────────────────────────────────────────┤\n│                                                                          │\n│  启动模式：                                                               │\n│  ┌────────────────────────────┬────────────────────────────────────┐    │\n│  │ stdio 模式                 │ http 模式                          │    │\n│  │ (npm run start:mcp)        │ (npm run start:http)               │    │\n│  └─────────────┬──────────────┴───────────────┬────────────────────┘    │\n│                │                              │                          │\n│                ▼                              ▼                          │\n│  ┌─────────────────────────┐    ┌───────────────────────────────────┐   │\n│  │      MCP 协议           │    │           HTTP 服务器             │   │\n│  │    (stdio 传输)         │    │                                   │   │\n│  │                         │    │  ┌─────────────────────────────┐  │   │\n│  │  工具：                 │    │  │       MCP 协议              │  │   │\n│  │  • execute_query        │    │  │  (SSE / Streamable HTTP)    │  │   │\n│  │  • get_schema           │    │  │                             │  │   │\n│  │  • get_table_info       │    │  │  工具：（与 stdio 相同）    │  │   │\n│  │  • clear_cache          │    │  │  • execute_query            │  │   │\n│  │  • get_enum_values      │    │  │  • get_schema               │  │   │\n│  │  • get_sample_data      │    │  │  • get_table_info           │  │   │\n│  │  • connect_database     │    │  │  • clear_cache              │  │   │\n│  │  • disconnect_database  │    │  │  • get_enum_values          │  │   │\n│  │  • get_connection_status│    │  │  • get_sample_data          │  │   │\n│  │                         │    │  │  • connect_database         │  │   │\n│  │  适用：Claude Desktop,  │    │  │  • disconnect_database      │  │   │\n│  │        Cursor 等        │    │  │  • get_connection_status    │  │   │\n│  └─────────────┬───────────┘    │  │                             │  │   │\n│                │                │  │  适用：Dify、远程访问       │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                │                 │                 │   │\n│                │                │  ┌──────────────┴──────────────┐  │   │\n│                │                │  │        REST API             │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  端点：                     │  │   │\n│                │                │  │  • /api/connect             │  │   │\n│                │                │  │  • /api/query               │  │   │\n│                │                │  │  • /api/schema              │  │   │\n│                │                │  │  • ...（10+ 端点）          │  │   │\n│                │                │  │                             │  │   │\n│                │                │  │  适用：Coze、n8n、自定义    │  │   │\n│                │                │  └──────────────┬──────────────┘  │   │\n│                │                └─────────────────┼─────────────────┘   │\n│                │                                  │                     │\n│                └──────────────────┬───────────────┘                     │\n│                                   ▼                                     │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                       核心业务逻辑层                               │  │\n│  │  • DatabaseService    • ConnectionManager                        │  │\n│  │  • 查询执行           • Schema 缓存                              │  │\n│  │  • 安全校验           • 连接管理                                 │  │\n│  └──────────────────────────────────┬───────────────────────────────┘  │\n│                                     ▼                                   │\n│  ┌──────────────────────────────────────────────────────────────────┐  │\n│  │                      数据库适配器层                                │  │\n│  │  MySQL │ PostgreSQL │ Redis │ Oracle │ MongoDB │ SQLite │ ...    │  │\n│  │    （17 个适配器，连接池 + TCP Keep-Alive + 断线自动重试）        │  │\n│  └──────────────────────────────────────────────────────────────────┘  │\n│                                                                          │\n└─────────────────────────────────────────────────────────────────────────┘\n```\n\n## 协议与接入方式\n\n| 启动模式 | 协议 | 传输方式 | 工具/端点 | 适用场景 |\n|---------|------|---------|----------|---------|\n| stdio | MCP | stdio | 9 个工具 | Claude Desktop、Cursor |\n| http | MCP | SSE | 9 个工具 | Dify（传统方式） |\n| http | MCP | Streamable HTTP | 9 个工具 | Dify（推荐） |\n| http | REST | HTTP | 10+ 端点 | Coze、n8n、自定义集成 |\n\n### MCP 协议工具\n\n无论使用哪种传输方式（stdio/SSE/Streamable HTTP），MCP 协议都提供相同的 9 个工具：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询或数据库命令 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取指定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（已脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n### REST API 端点\n\nREST API 提供更细粒度的控制，支持多会话管理：\n\n| 端点 | 方法 | 描述 |\n|------|------|------|\n| `/api/connect` | POST | 连接数据库 |\n| `/api/disconnect` | POST | 断开连接 |\n| `/api/query` | POST | 执行查询 |\n| `/api/execute` | POST | 执行写操作 |\n| `/api/tables` | GET | 列出表 |\n| `/api/schema` | GET | 获取数据库结构 |\n| `/api/schema/:table` | GET | 获取表信息 |\n| `/api/cache` | DELETE | 清除缓存 |\n| `/api/cache/status` | GET | 缓存状态 |\n| `/api/health` | GET | 健康检查 |\n| `/api/info` | GET | 服务信息 |\n\n### MCP SSE/Streamable HTTP 端点\n\n| 端点 | 方法 | 描述 |\n|------|------|------|\n| `/sse` | GET | 建立 SSE 连接（传统方式） |\n| `/sse/message` | POST | 向 SSE 会话发送消息 |\n| `/mcp` | POST | Streamable HTTP 端点（推荐） |\n| `/mcp` | GET | Streamable HTTP 的 SSE 流 |\n| `/mcp` | DELETE | 关闭会话 |\n\n## 目录结构\n\n```\nsrc/\n├── index.ts                    # 入口文件，模式选择器\n├── server.ts                   # 向后兼容导出\n├── types/\n│   ├── adapter.ts              # 数据库适配器类型定义\n│   └── http.ts                 # HTTP API 类型定义\n├── utils/\n│   ├── safety.ts               # 查询安全验证\n│   ├── adapter-factory.ts      # 适配器工厂\n│   ├── config-loader.ts        # 配置加载器\n│   └── schema-enhancer.ts      # Schema 增强器（隐式关系推断）\n├── core/                       # 核心业务逻辑\n│   ├── database-service.ts     # 数据库服务\n│   └── connection-manager.ts   # 连接管理器\n├── mcp/                        # MCP 模式\n│   ├── mcp-server.ts           # MCP 服务器（工具定义）\n│   └── mcp-index.ts            # MCP stdio 入口\n├── http/                       # HTTP 模式\n│   ├── server.ts               # Fastify 服务器\n│   ├── http-index.ts           # HTTP 入口\n│   ├── routes/                 # 路由\n│   │   ├── index.ts            # 路由注册\n│   │   ├── health.ts           # 健康检查路由\n│   │   ├── connection.ts       # 连接管理路由\n│   │   ├── query.ts            # 查询路由\n│   │   ├── schema.ts           # Schema 路由\n│   │   └── mcp-sse.ts          # MCP SSE/Streamable HTTP 路由\n│   └── middleware/             # 中间件\n│       ├── index.ts            # 中间件注册\n│       ├── auth.ts             # API Key 认证\n│       └── error-handler.ts    # 错误处理\n└── adapters/                   # 数据库适配器\n    ├── mysql.ts\n    ├── postgres.ts\n    ├── redis.ts\n    └── ...                     # 17 个适配器\n```\n\n## 核心模块\n\n### DatabaseService\n\n数据库服务层，封装核心业务逻辑：\n\n```typescript\nclass DatabaseService {\n  // 执行查询\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult>\n\n  // 获取数据库结构\n  async getSchema(): Promise<SchemaInfo>\n\n  // 获取表信息\n  async getTableInfo(tableName: string): Promise<TableInfo>\n\n  // 验证查询安全性\n  validateQuery(query: string): boolean\n}\n```\n\n### ConnectionManager\n\n连接管理器，处理数据库连接生命周期：\n\n```typescript\nclass ConnectionManager {\n  // 创建连接\n  async connect(config: DbConfig): Promise<string>\n\n  // 断开连接\n  async disconnect(sessionId: string): Promise<void>\n\n  // 获取连接\n  getConnection(sessionId: string): DbAdapter | undefined\n\n  // 清理过期会话\n  cleanupExpiredSessions(): void\n}\n```\n\n### AdapterFactory\n\n适配器工厂，集中管理适配器创建：\n\n```typescript\nclass AdapterFactory {\n  // 创建适配器\n  static createAdapter(type: string, config: DbConfig): DbAdapter\n\n  // 验证配置\n  static validateConfig(type: string, config: DbConfig): boolean\n\n  // 获取支持的数据库类型\n  static getSupportedTypes(): string[]\n}\n```\n\n### SchemaEnhancer\n\nSchema 增强器，提升 LLM 对数据库结构的理解：\n\n```typescript\nclass SchemaEnhancer {\n  // 增强关系信息\n  // 1. 为现有外键关系添加 source='foreign_key' 标记\n  // 2. 推断隐式关系并添加 source='inferred' 标记\n  // 3. 细化关系类型（区分 one-to-one 和 many-to-one）\n  enhanceRelationships(\n    tables: TableInfo[],\n    existingRelationships: RelationshipInfo[]\n  ): RelationshipInfo[]\n\n  // 更新配置\n  updateConfig(config: Partial<SchemaEnhancerConfig>): void\n\n  // 获取当前配置\n  getConfig(): SchemaEnhancerConfig\n}\n```\n\n**隐式关系推断规则：**\n\n| 列名模式 | 目标表 | 目标列 | 置信度 |\n|---------|--------|--------|--------|\n| `xxx_id` | `xxxs` / `xxx` | `id` | 0.90-0.95 |\n| `xxxId` (驼峰) | `xxxs` / `xxx` | `id` | 0.85-0.90 |\n| `xxx_code` | `xxxs` / `xxx` | `code` | 0.90-0.95 |\n| `xxx_no` | `xxxs` / `xxx` | `xxx_no` | 0.70-0.75 |\n\n**推断安全规则：**\n- 不覆盖显式外键：已有外键的列不进行推断\n- 验证目标表存在：只有目标表确实存在时才推断\n- 验证目标列存在：确保目标表有对应的主键列\n- 标注来源和置信度：让 LLM 知道这是推断的关系\n\n## 数据库适配器\n\n### DbAdapter 接口\n\n所有数据库适配器实现统一接口：\n\n```typescript\ninterface DbAdapter {\n  // 连接数据库\n  connect(): Promise<void>\n\n  // 断开连接\n  disconnect(): Promise<void>\n\n  // 执行查询\n  executeQuery(query: string, params?: unknown[]): Promise<QueryResult>\n\n  // 获取数据库结构\n  getSchema(): Promise<SchemaInfo>\n\n  // 获取表信息\n  getTableInfo(tableName: string): Promise<TableInfo>\n\n  // 检查是否为写操作\n  isWriteOperation(query: string): boolean\n}\n```\n\n### 适配器分类\n\n| 类型 | 适配器 | 驱动 | 连接管理 |\n|------|--------|------|---------|\n| MySQL 兼容 | mysql, tidb, oceanbase, polardb, goldendb | mysql2 | 连接池 + TCP Keep-Alive + 断线重试 |\n| PostgreSQL 兼容 | postgres, kingbase, gaussdb, vastbase, highgo | pg | 连接池 + TCP Keep-Alive + 断线重试 |\n| Oracle | oracle | oracledb | 连接池 + Pool Ping + 断线重试 |\n| 达梦 | dm | dmdb | 单连接 + 心跳保活 + 断线重连重试 |\n| SQL Server | sqlserver | mssql | 内置连接池 |\n| Redis | redis | ioredis | 内置自动重连 |\n| MongoDB | mongodb | mongodb | 内置连接池 |\n| SQLite | sqlite | better-sqlite3 | 本地文件（无需连接管理） |\n| ClickHouse | clickhouse | @clickhouse/client | HTTP 协议（无需长连接管理） |\n\n## 数据流\n\n### MCP 模式\n\n```\nClaude Desktop → stdio → MCP Server → DatabaseService → Adapter → Database\n```\n\n### HTTP API 模式\n\n```\nHTTP Client → REST API → Middleware → Routes → DatabaseService → Adapter → Database\n```\n\n## 进程生命周期管理\n\n### stdio 模式\n\nstdio 模式下，进程退出由统一的 `gracefulShutdown()` 函数管理，覆盖以下退出场景：\n\n| 触发事件 | 说明 |\n|----------|------|\n| `SIGINT` | 用户按 Ctrl+C |\n| `SIGTERM` | 系统终止信号 |\n| `stdin end` | MCP 客户端关闭 stdin 管道（如 Codex CLI `/exit`） |\n| `stdin close` | stdin 流被完全销毁（`end` 的补充保障） |\n\n退出流程：`gracefulShutdown()` → `server.stop()`（关闭 MCP Server + 释放 transport + 断开数据库）→ `process.exit(0)`\n\n安全机制：\n- **防重入**：`shuttingDown` 标志确保多信号并发时只执行一次\n- **超时保护**：5 秒超时兜底，防止数据库断连挂起\n\n### HTTP 模式\n\nHTTP 模式由 Fastify 的 `onClose` 钩子管理，通过 `connectionManager.disconnectAll()` 清理所有会话。\n\n### SSE / Streamable HTTP\n\nSSE 和 Streamable HTTP 传输的会话清理通过 `cleanupSession()` → `server.stop()` 完成，`stop()` 内部会调用 `server.close()` 释放 transport 资源。\n\n## 设计原则\n\n1. **关注点分离** - MCP 和 HTTP 模式各自独立，共享核心逻辑\n2. **适配器模式** - 统一的 DbAdapter 接口，支持 17 种数据库\n3. **工厂模式** - AdapterFactory 集中管理适配器创建\n4. **服务层** - DatabaseService 封装业务逻辑，被两种模式复用\n5. **会话管理** - HTTP 模式支持多并发连接，MCP 模式单连接\n6. **安全第一** - 默认只读模式，查询验证，API Key 认证\n\n## 扩展指南\n\n### 添加新数据库\n\n1. 在 `src/adapters/` 创建新适配器\n2. 实现 `DbAdapter` 接口\n3. 在 `AdapterFactory` 中注册\n4. 更新文档\n\n详见 [添加新数据库](./adding-database.md)。\n\n### 添加新 API 端点\n\n1. 在 `src/http/routes/` 创建新路由\n2. 在 `src/http/routes/index.ts` 注册\n3. 更新 API 文档\n\n### 添加新中间件\n\n1. 在 `src/http/middleware/` 创建新中间件\n2. 在 `src/http/middleware/index.ts` 注册\n"
  },
  {
    "path": "docs/development/connection-stability.md",
    "content": "# 连接稳定性增强（v2.11.0）\n\n本文档记录 v2.11.0 版本中对数据库连接管理的全面升级，彻底解决长时间运行场景下的 `Can't add new command when connection is in closed state` 等连接断开问题。\n\n## 背景\n\nMCP 服务作为长驻进程运行，数据库连接可能因以下原因断开：\n\n- 服务端 `wait_timeout` / `idle_in_transaction_session_timeout` 超时\n- 网络中间件（防火墙、NAT、负载均衡）清理空闲连接\n- 服务端主动重启或故障切换\n- 网络瞬断（`ECONNRESET`、`EPIPE`、`ETIMEDOUT`）\n\n旧版本使用单连接模式，连接断开后所有操作直接失败，用户需要手动重启服务。\n\n## 改动概览\n\n本次升级涉及 **12 个网络数据库适配器**，核心改动包含三个层面：\n\n| 改动 | 说明 |\n|------|------|\n| 连接池化 | 单连接（`Client`）升级为连接池（`Pool`），自动管理连接生命周期 |\n| TCP Keep-Alive / 心跳 | 防止空闲连接被超时关闭 |\n| 断线自动重试（`withRetry`） | 检测到连接错误后自动重试，对调用方透明 |\n\n## 各适配器实现方案\n\n### MySQL 系列（mysql2 驱动）\n\n**涉及适配器**：MySQL、TiDB、OceanBase、PolarDB、GoldenDB\n\n**改动**：`mysql.createConnection()` → `mysql.createPool()`\n\n```typescript\n// 旧版：单连接\nthis.connection = await mysql.createConnection({ ... });\n\n// 新版：连接池\nthis.pool = mysql.createPool({\n  host, port, user, password, database,\n  // 连接池配置\n  waitForConnections: true,\n  connectionLimit: 3,\n  maxIdle: 1,\n  idleTimeout: 60000,\n  // TCP Keep-Alive\n  enableKeepAlive: true,\n  keepAliveInitialDelay: 30000,\n});\n```\n\n**连接错误识别**：\n\n```typescript\nprivate isConnectionError(error: unknown): boolean {\n  const msg = String((error as any)?.message || '');\n  return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n}\n```\n\n### PostgreSQL 系列（pg 驱动）\n\n**涉及适配器**：PostgreSQL、KingbaseES、GaussDB、Vastbase、HighGo\n\n**改动**：`new Client()` → `new Pool()`\n\n```typescript\n// 旧版：单连接\nthis.client = new Client({ ... });\nawait this.client.connect();\n\n// 新版：连接池\nthis.pool = new Pool({\n  host, port, user, password, database,\n  max: 3,\n  idleTimeoutMillis: 60000,\n  keepAlive: true,\n  keepAliveInitialDelayMillis: 30000,\n});\n```\n\n**查询方式变化**：\n\n```typescript\n// 旧版：直接使用 client\nconst result = await this.client.query(sql);\n\n// 新版：pool 自动获取/释放连接\nconst result = await this.pool.query(sql);\n```\n\n**连接错误识别**：\n\n```typescript\nprivate isConnectionError(error: unknown): boolean {\n  const msg = String((error as any)?.message || '');\n  const code = String((error as any)?.code || '');\n  return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(msg + code);\n}\n```\n\n### Oracle（oracledb 驱动）\n\n**改动**：`oracledb.getConnection()` → `oracledb.createPool()`\n\n```typescript\n// 旧版：单连接\nthis.connection = await oracledb.getConnection({ ... });\n\n// 新版：连接池\nthis.pool = await oracledb.createPool({\n  user, password, connectString,\n  poolMin: 1,\n  poolMax: 3,\n  poolPingInterval: 30,  // 每 30 秒自动检测连接健康\n});\n```\n\n**查询方式变化**：通过 `withConnection` 辅助方法管理连接获取/释放。\n\n```typescript\nprivate async withConnection<T>(fn: (conn: oracledb.Connection) => Promise<T>): Promise<T> {\n  const connection = await this.pool!.getConnection();\n  try { return await fn(connection); } finally { await connection.close(); }\n}\n```\n\n**连接错误识别**：包含 oracledb 特定错误码（NJS-003、NJS-500、ORA-03113、ORA-03114 等）。\n\n### 达梦（dmdb 驱动）\n\n**特殊方案**：dmdb 驱动不支持连接池，改用心跳保活 + 断线重连。\n\n```typescript\n// 心跳保活：每 30 秒执行 SELECT 1 FROM DUAL\nprivate startHeartbeat(): void {\n  this.heartbeatTimer = setInterval(async () => {\n    try {\n      if (this.connection) { await this.connection.execute('SELECT 1 FROM DUAL', []); }\n    } catch {\n      await this.reconnect();\n    }\n  }, 30000);\n}\n\n// 断线重连\nprivate async reconnect(): Promise<void> {\n  if (this.connection) { try { await this.connection.close(); } catch {} this.connection = null; }\n  const DM = await loadDMDB();\n  this.connection = await DM.getConnection(this.connectionConfig);\n}\n```\n\n## 通用重试机制（withRetry）\n\n所有适配器统一使用 `withRetry` 包装器，对调用方完全透明：\n\n```typescript\nprivate async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n  try {\n    return await fn();\n  } catch (error) {\n    if (this.isConnectionError(error)) {\n      // 连接池会自动提供新连接，直接重试\n      return await fn();\n    }\n    throw error;\n  }\n}\n```\n\n**使用方式**：在所有数据库操作中包裹 `withRetry`：\n\n```typescript\nasync query(sql: string): Promise<QueryResult> {\n  return this.withRetry(async () => {\n    const [rows] = await this.pool!.query(sql);\n    return { rows: rows as Record<string, unknown>[] };\n  });\n}\n```\n\n## 不需要修改的适配器\n\n以下适配器已有内置连接管理机制，无需改动：\n\n| 适配器 | 原因 |\n|--------|------|\n| SQL Server（mssql） | 驱动内置连接池 |\n| Redis（ioredis） | 内置自动重连机制 |\n| MongoDB（mongodb） | 内置连接池和故障恢复 |\n| SQLite（better-sqlite3） | 本地文件访问，无网络连接 |\n| ClickHouse（@clickhouse/client） | HTTP 协议，每次请求独立连接 |\n\n## 连接池参数说明\n\n### MySQL 系列\n\n| 参数 | 值 | 说明 |\n|------|----|------|\n| `connectionLimit` | 3 | 最大连接数（MCP 场景并发低，3 个足够） |\n| `maxIdle` | 1 | 最大空闲连接数 |\n| `idleTimeout` | 60000 | 空闲连接超时时间（60 秒） |\n| `enableKeepAlive` | true | 启用 TCP Keep-Alive |\n| `keepAliveInitialDelay` | 30000 | Keep-Alive 初始延迟（30 秒） |\n\n### PostgreSQL 系列\n\n| 参数 | 值 | 说明 |\n|------|----|------|\n| `max` | 3 | 最大连接数 |\n| `idleTimeoutMillis` | 60000 | 空闲连接超时时间（60 秒） |\n| `keepAlive` | true | 启用 TCP Keep-Alive |\n| `keepAliveInitialDelayMillis` | 30000 | Keep-Alive 初始延迟（30 秒） |\n\n### Oracle\n\n| 参数 | 值 | 说明 |\n|------|----|------|\n| `poolMin` | 1 | 最小连接数 |\n| `poolMax` | 3 | 最大连接数 |\n| `poolPingInterval` | 30 | 连接健康检测间隔（30 秒） |\n\n### 达梦\n\n| 参数 | 值 | 说明 |\n|------|----|------|\n| 心跳间隔 | 30000ms | 每 30 秒执行 `SELECT 1 FROM DUAL` |\n\n## 文件变更清单\n\n### 适配器代码（src/adapters/）\n\n| 文件 | 改动类型 | 说明 |\n|------|---------|------|\n| `mysql.ts` | 连接池化 | `createConnection` → `createPool` + `withRetry` |\n| `tidb.ts` | 连接池化 | 同 MySQL |\n| `oceanbase.ts` | 连接池化 | 同 MySQL |\n| `polardb.ts` | 连接池化 | 同 MySQL |\n| `goldendb.ts` | 连接池化 | 同 MySQL |\n| `postgres.ts` | 连接池化 | `Client` → `Pool` + `withRetry` |\n| `kingbase.ts` | 连接池化 | 同 PostgreSQL |\n| `gaussdb.ts` | 连接池化 | 同 PostgreSQL |\n| `vastbase.ts` | 连接池化 | 同 PostgreSQL |\n| `highgo.ts` | 连接池化 | 同 PostgreSQL |\n| `oracle.ts` | 连接池化 | `getConnection` → `createPool` + `withConnection` + `withRetry` |\n| `dm.ts` | 心跳保活 | 新增 `heartbeat` + `reconnect` + `withRetry` |\n\n### 文档（docs/）\n\n| 文件 | 改动 |\n|------|------|\n| `docs/databases/mysql.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/postgresql.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/oracle.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/dameng.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/kingbase.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/gaussdb.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/oceanbase.md` | 新增\"连接稳定性\"章节 |\n| `docs/databases/tidb.md` | 新增\"连接断开\"故障排查条目 |\n| `docs/databases/polardb.md` | 新增\"连接断开\"故障排查条目 |\n| `docs/databases/goldendb.md` | 新增\"连接断开\"故障排查条目 |\n| `docs/databases/vastbase.md` | 新增\"连接断开\"故障排查条目 |\n| `docs/databases/highgo.md` | 新增\"连接断开\"故障排查条目 |\n| `docs/development/architecture.md` | 适配器分类表新增\"连接管理\"列 |\n\n### 其他\n\n| 文件 | 改动 |\n|------|------|\n| `CHANGELOG.md` | 新增 v2.11.0 版本记录 |\n| `README.md` | 新增 Connection Stability 特性说明 |\n| `README.zh-CN.md` | 新增\"连接稳定性\"特性说明 |\n"
  },
  {
    "path": "docs/development/implementation.md",
    "content": "# HTTP API Mode Implementation Summary\n\n## ✅ Implementation Status\n\n### Phase 1: Core Refactoring (COMPLETED)\n- ✅ Created `src/utils/adapter-factory.ts` - Centralized adapter creation\n- ✅ Created `src/utils/config-loader.ts` - Multi-source configuration management\n- ✅ Created `src/core/database-service.ts` - Shared business logic\n- ✅ Created `src/core/connection-manager.ts` - Session-based connection management\n- ✅ Created `src/types/http.ts` - HTTP-specific type definitions\n\n### Phase 2: MCP Mode Refactoring (COMPLETED)\n- ✅ Moved `src/server.ts` → `src/mcp/mcp-server.ts` (refactored to use DatabaseService)\n- ✅ Moved `src/index.ts` → `src/mcp/mcp-index.ts` (refactored to use adapter factory)\n- ✅ Created `src/index.ts` - Mode selector entry point\n- ✅ Created `src/server.ts` - Backward compatibility shim\n- ✅ **MCP mode remains 100% functional**\n\n### Phase 3: HTTP Server Implementation (COMPLETED)\n- ✅ Created `src/http/server.ts` - Fastify server setup\n- ✅ Created `src/http/http-index.ts` - HTTP entry point\n- ✅ Created `src/http/middleware/auth.ts` - API key authentication\n- ✅ Created `src/http/middleware/error-handler.ts` - Error handling\n- ✅ Created `src/http/routes/connection.ts` - Connect/disconnect endpoints\n- ✅ Created `src/http/routes/query.ts` - Query/execute endpoints\n- ✅ Created `src/http/routes/schema.ts` - Schema/tables endpoints\n- ✅ Created `src/http/routes/health.ts` - Health/info endpoints\n\n### Phase 4: Configuration & Environment (COMPLETED)\n- ✅ Created `.env.example` - Environment variable template\n- ✅ Created `config/default.json` - Default configuration\n- ✅ Updated `package.json` - Added dependencies and scripts\n\n### Phase 5: Docker & Deployment (PARTIALLY COMPLETED)\n- ✅ Created `docker/Dockerfile` - Multi-stage build\n- ✅ Created `docker/docker-compose.yml` - Docker Compose configuration\n- ✅ Created `.dockerignore` - Docker ignore rules\n- ⏳ Serverless configurations (Aliyun FC, Tencent SCF, AWS Lambda, Vercel) - NOT YET CREATED\n- ⏳ PaaS configurations (Railway, Render, Fly.io) - NOT YET CREATED\n\n### Phase 6: Documentation (PARTIALLY COMPLETED)\n- ✅ Updated `README.md` - Added HTTP API mode documentation\n- ⏳ API reference documentation - NOT YET CREATED\n- ⏳ Deployment guides - NOT YET CREATED\n- ⏳ Integration guides (Coze, n8n, Dify) - NOT YET CREATED\n\n### Phase 7: Testing (NOT STARTED)\n- ⏳ Unit tests - NOT YET CREATED\n- ⏳ Integration tests - NOT YET CREATED\n- ⏳ Test framework setup - NOT YET CREATED\n\n## 🎯 What Works Now\n\n### MCP Mode (Fully Functional)\n```bash\n# Start MCP mode (default)\nnpm start -- --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n\n# Or explicitly\nnpm run start:mcp -- --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n```\n\n### HTTP API Mode (Fully Functional)\n```bash\n# Set environment variables\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key\n\n# Start HTTP server\nnpm run start:http\n```\n\n## 📡 HTTP API Endpoints\n\nAll endpoints are fully implemented and functional:\n\n### Health & Info\n- `GET /api/health` - Health check (no auth required)\n- `GET /api/info` - Service information (no auth required)\n\n### Connection Management\n- `POST /api/connect` - Connect to database (returns sessionId)\n- `POST /api/disconnect` - Disconnect from database\n\n### Query Execution\n- `POST /api/query` - Execute read queries\n- `POST /api/execute` - Execute write operations (requires allowWrite: true)\n\n### Schema Information\n- `GET /api/tables?sessionId=xxx` - List all tables\n- `GET /api/schema?sessionId=xxx` - Get complete database schema\n- `GET /api/schema/:table?sessionId=xxx` - Get specific table information\n\n## 🔧 Configuration\n\n### Environment Variables\nCreate a `.env` file based on `.env.example`:\n\n```bash\n# Server Mode\nMODE=http\n\n# HTTP Configuration\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\nAPI_KEYS=your-secret-key-1,your-secret-key-2\n\n# CORS\nCORS_ORIGINS=*\nCORS_CREDENTIALS=false\n\n# Rate Limiting\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n\n# Logging\nLOG_LEVEL=info\nLOG_PRETTY=false\n\n# Session Management\nSESSION_TIMEOUT=3600000\nSESSION_CLEANUP_INTERVAL=300000\n```\n\n### NPM Scripts\n```json\n{\n  \"start\": \"node dist/index.js\",           // Auto-detect mode from env\n  \"start:http\": \"MODE=http node dist/index.js\",  // Force HTTP mode\n  \"start:mcp\": \"MODE=mcp node dist/index.js\",    // Force MCP mode\n  \"dev:http\": \"tsc && MODE=http node dist/index.js\",\n  \"dev:mcp\": \"tsc && MODE=mcp node dist/index.js\",\n  \"build\": \"tsc\"\n}\n```\n\n## 🐳 Docker Deployment\n\n### Build and Run\n```bash\n# Build image\ndocker build -t universal-db-mcp -f docker/Dockerfile .\n\n# Run container\ndocker run -p 3000:3000 \\\n  -e MODE=http \\\n  -e API_KEYS=your-secret-key \\\n  -e DB_TYPE=mysql \\\n  -e DB_HOST=host.docker.internal \\\n  -e DB_PORT=3306 \\\n  -e DB_USER=root \\\n  -e DB_PASSWORD=xxx \\\n  -e DB_DATABASE=test \\\n  universal-db-mcp\n```\n\n### Docker Compose\n```bash\ncd docker\ndocker-compose up -d\n```\n\n## 🔒 Security Features\n\n### Implemented\n- ✅ API Key authentication (X-API-Key header or Authorization: Bearer)\n- ✅ CORS configuration\n- ✅ Rate limiting (per API key or IP)\n- ✅ Query validation (reuses existing safety.ts)\n- ✅ Error handling with sanitized error messages\n- ✅ Session timeout and cleanup\n- ✅ Non-root Docker user\n\n### Configuration\n```bash\n# API Keys (comma-separated)\nAPI_KEYS=key1,key2,key3\n\n# CORS\nCORS_ORIGINS=https://example.com,https://app.example.com\nCORS_CREDENTIALS=true\n\n# Rate Limiting\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n```\n\n## 📊 Architecture\n\n### Directory Structure\n```\nsrc/\n├── adapters/          [UNCHANGED] All 17 database adapters\n├── types/\n│   ├── adapter.ts     [UNCHANGED] Existing types\n│   └── http.ts        [NEW] HTTP-specific types\n├── utils/\n│   ├── safety.ts      [UNCHANGED] Query validation\n│   ├── adapter-factory.ts [NEW] Centralized adapter creation\n│   └── config-loader.ts   [NEW] Multi-source configuration\n├── core/              [NEW] Shared business logic\n│   ├── database-service.ts [NEW] Core database operations\n│   └── connection-manager.ts [NEW] Connection lifecycle\n├── mcp/               [NEW] MCP-specific code\n│   ├── mcp-server.ts  [MOVED] From server.ts\n│   └── mcp-index.ts   [MOVED] From index.ts\n├── http/              [NEW] HTTP API mode\n│   ├── server.ts      [NEW] Fastify server\n│   ├── routes/        [NEW] API routes\n│   ├── middleware/    [NEW] Auth, CORS, rate limit, etc.\n│   └── http-index.ts  [NEW] HTTP entry point\n├── index.ts           [MODIFIED] Mode selector\n└── server.ts          [MODIFIED] Backward compatibility shim\n```\n\n### Key Design Decisions\n\n1. **Dual-Mode Architecture**: Single codebase, two entry points\n2. **Shared Core Logic**: DatabaseService and ConnectionManager used by both modes\n3. **Adapter Factory**: Centralized adapter creation eliminates duplication\n4. **Session Management**: HTTP mode supports multiple concurrent connections\n5. **Backward Compatibility**: Existing MCP mode unchanged, server.ts re-exports for compatibility\n\n## 🧪 Testing\n\n### Manual Testing\n\n#### Test MCP Mode\n```bash\n# Build\nnpm run build\n\n# Start MCP mode\nnpm run start:mcp -- --type mysql --host localhost --port 3306 --user root --password xxx --database test\n\n# Should see:\n# 🔌 Starting MCP mode...\n# 🔧 配置信息:\n#    数据库类型: mysql\n#    主机地址: localhost:3306\n#    数据库名: test\n#    安全模式: ✅ 只读模式\n# 🔌 正在连接数据库...\n# ✅ 数据库连接成功\n# 🛡️  安全模式: 只读模式（推荐）\n# 🚀 MCP 服务器已启动，等待 Claude Desktop 连接...\n```\n\n#### Test HTTP Mode\n```bash\n# Set environment\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=test-key\n\n# Start HTTP mode\nnpm run start:http\n\n# Should see:\n# 🌐 Starting HTTP API mode...\n# 🚀 HTTP API Server started successfully!\n# 📍 Server URL: http://0.0.0.0:3000\n# 📊 Supported databases: 17 types\n# 🛡️  Security: API Key authentication enabled\n# ⚡ Rate limiting: 100 requests per 1m\n\n# Test health endpoint\ncurl http://localhost:3000/api/health\n\n# Test connect endpoint\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: test-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"type\":\"mysql\",\"host\":\"localhost\",\"port\":3306,\"user\":\"root\",\"password\":\"xxx\",\"database\":\"test\"}'\n\n# Response:\n# {\n#   \"success\": true,\n#   \"data\": {\n#     \"sessionId\": \"abc123...\",\n#     \"databaseType\": \"mysql\",\n#     \"connected\": true\n#   },\n#   \"metadata\": {\n#     \"timestamp\": \"2026-01-27T...\",\n#     \"requestId\": \"...\"\n#   }\n# }\n```\n\n## 📝 Next Steps (Not Yet Implemented)\n\n### High Priority\n1. **Create API Reference Documentation** (`docs/http-api/API_REFERENCE.md`)\n   - Complete endpoint documentation\n   - Request/response examples\n   - Error codes reference\n\n2. **Create Deployment Guides** (`docs/http-api/DEPLOYMENT.md`)\n   - Local deployment (Node.js, PM2)\n   - Docker deployment\n   - Cloud deployment options\n\n3. **Create Integration Guides**\n   - `docs/integrations/COZE.md` - Coze platform integration\n   - `docs/integrations/N8N.md` - n8n workflow examples\n   - `docs/integrations/DIFY.md` - Dify agent configuration\n\n### Medium Priority\n4. **Serverless Configurations**\n   - Aliyun Function Compute\n   - Tencent Serverless Cloud Function\n   - AWS Lambda\n   - Vercel Edge Functions\n\n5. **PaaS Configurations**\n   - Railway deployment\n   - Render deployment\n   - Fly.io deployment\n\n### Low Priority\n6. **Testing**\n   - Unit tests for core logic\n   - Integration tests for HTTP API\n   - Integration tests for MCP mode\n\n## 🎉 Success Criteria\n\n### ✅ Completed\n- [x] MCP mode works exactly as before (100% backward compatible)\n- [x] HTTP API mode starts and runs\n- [x] All HTTP endpoints implemented and functional\n- [x] API key authentication works\n- [x] Rate limiting works\n- [x] CORS configuration works\n- [x] Docker build succeeds\n- [x] All 17 database adapters work in both modes\n- [x] README updated with HTTP API documentation\n- [x] TypeScript compilation succeeds with no errors\n\n### ⏳ Pending\n- [ ] Complete API reference documentation\n- [ ] Complete deployment guides\n- [ ] Complete integration guides\n- [ ] Serverless configurations created\n- [ ] PaaS configurations created\n- [ ] Unit tests written\n- [ ] Integration tests written\n- [ ] All tests pass\n\n## 🚀 How to Use Right Now\n\n### For Claude Desktop (MCP Mode)\nNo changes needed! Continue using as before:\n```bash\nnpm install -g universal-db-mcp\n# Configure in Claude Desktop config file\n```\n\n### For Third-Party Platforms (HTTP API Mode)\n\n1. **Install**:\n   ```bash\n   npm install -g universal-db-mcp\n   ```\n\n2. **Configure** (create `.env`):\n   ```bash\n   MODE=http\n   HTTP_PORT=3000\n   API_KEYS=your-secret-key\n   ```\n\n3. **Start**:\n   ```bash\n   npm run start:http\n   ```\n\n4. **Use API**:\n   ```bash\n   # Connect to database\n   curl -X POST http://localhost:3000/api/connect \\\n     -H \"X-API-Key: your-secret-key\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"type\":\"mysql\",\"host\":\"localhost\",\"port\":3306,\"user\":\"root\",\"password\":\"xxx\",\"database\":\"test\"}'\n\n   # Execute query\n   curl -X POST http://localhost:3000/api/query \\\n     -H \"X-API-Key: your-secret-key\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"sessionId\":\"<session-id-from-connect>\",\"query\":\"SELECT * FROM users LIMIT 10\"}'\n   ```\n\n## 📦 Dependencies Added\n\n### Production Dependencies\n- `fastify` (^4.26.0) - HTTP server framework\n- `@fastify/cors` (^9.0.1) - CORS support\n- `@fastify/rate-limit` (^9.1.0) - Rate limiting\n- `dotenv` (^16.4.1) - Environment variable management\n- `nanoid` (^5.0.4) - Session ID generation\n\n### Development Dependencies\n- `vitest` (^1.2.0) - Testing framework\n- `@vitest/ui` (^1.2.0) - Testing UI\n\n## 🔍 Verification\n\n### Build Status\n```bash\n$ npm run build\n> universal-db-mcp@1.0.0 build\n> tsc\n\n# ✅ Build successful (no errors)\n```\n\n### File Count\n- **New files created**: 25+\n- **Modified files**: 3 (index.ts, server.ts, package.json)\n- **Unchanged files**: 20+ (all adapters, types, utils)\n\n### Code Quality\n- ✅ TypeScript strict mode enabled\n- ✅ All types properly defined\n- ✅ No implicit any types\n- ✅ Proper error handling\n- ✅ Consistent code style\n\n## 🎯 Summary\n\nThe HTTP API mode implementation is **FUNCTIONAL and READY TO USE**. The core functionality is complete:\n\n- ✅ Dual-mode architecture working\n- ✅ HTTP API server operational\n- ✅ All endpoints implemented\n- ✅ Security features enabled\n- ✅ Docker deployment ready\n- ✅ MCP mode unchanged\n\n**What's missing**: Documentation and deployment configurations for specific platforms (Serverless, PaaS). These are nice-to-have additions that don't affect core functionality.\n\n**Recommendation**: The project is ready for testing and use. Documentation can be added incrementally based on user needs.\n"
  },
  {
    "path": "docs/development/implementation.zh-CN.md",
    "content": "# HTTP API 模式实现总结\n\n## ✅ 实现状态\n\n### 阶段 1: 核心重构 (已完成)\n- ✅ 创建 `src/utils/adapter-factory.ts` - 集中式适配器创建\n- ✅ 创建 `src/utils/config-loader.ts` - 多源配置管理\n- ✅ 创建 `src/core/database-service.ts` - 共享业务逻辑\n- ✅ 创建 `src/core/connection-manager.ts` - 基于会话的连接管理\n- ✅ 创建 `src/types/http.ts` - HTTP 特定类型定义\n\n### 阶段 2: MCP 模式重构 (已完成)\n- ✅ 移动 `src/server.ts` → `src/mcp/mcp-server.ts` (重构以使用 DatabaseService)\n- ✅ 移动 `src/index.ts` → `src/mcp/mcp-index.ts` (重构以使用适配器工厂)\n- ✅ 创建 `src/index.ts` - 模式选择器入口点\n- ✅ 创建 `src/server.ts` - 向后兼容性垫片\n- ✅ **MCP 模式保持 100% 功能正常**\n\n### 阶段 3: HTTP 服务器实现 (已完成)\n- ✅ 创建 `src/http/server.ts` - Fastify 服务器设置\n- ✅ 创建 `src/http/http-index.ts` - HTTP 入口点\n- ✅ 创建 `src/http/middleware/auth.ts` - API 密钥认证\n- ✅ 创建 `src/http/middleware/error-handler.ts` - 错误处理\n- ✅ 创建 `src/http/routes/connection.ts` - 连接/断开端点\n- ✅ 创建 `src/http/routes/query.ts` - 查询/执行端点\n- ✅ 创建 `src/http/routes/schema.ts` - Schema/表端点\n- ✅ 创建 `src/http/routes/health.ts` - 健康/信息端点\n\n### 阶段 4: 配置与环境 (已完成)\n- ✅ 创建 `.env.example` - 环境变量模板\n- ✅ 创建 `config/default.json` - 默认配置\n- ✅ 更新 `package.json` - 添加依赖和脚本\n\n### 阶段 5: Docker 与部署 (已完成)\n- ✅ 创建 `docker/Dockerfile` - 多阶段构建\n- ✅ 创建 `docker/docker-compose.yml` - Docker Compose 配置\n- ✅ 创建 `.dockerignore` - Docker 忽略规则\n- ✅ 创建 Serverless 配置 (阿里云 FC、腾讯云 SCF、AWS Lambda、Vercel)\n- ✅ 创建 PaaS 配置 (Railway、Render、Fly.io)\n\n### 阶段 6: 文档 (已完成)\n- ✅ 更新 `README.md` - 添加 HTTP API 模式文档\n- ✅ 创建 API 参考文档 (英文和中文版本)\n- ✅ 创建部署指南 (英文和中文版本)\n- ✅ 创建集成指南 (Coze、n8n、Dify - 英文和中文版本)\n\n### 阶段 7: 测试 (已完成)\n- ✅ 创建单元测试\n- ✅ 创建集成测试\n- ✅ 设置测试框架\n\n## 🎯 当前可用功能\n\n### MCP 模式 (完全功能)\n```bash\n# 启动 MCP 模式 (默认)\nnpm start -- --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n\n# 或显式指定\nnpm run start:mcp -- --type mysql --host localhost --port 3306 --user root --password xxx --database mydb\n```\n\n### HTTP API 模式 (完全功能)\n```bash\n# 设置环境变量\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key\n\n# 启动 HTTP 服务器\nnpm run start:http\n```\n\n## 📡 HTTP API 端点\n\n所有端点均已完全实现并可用：\n\n### 健康与信息\n- `GET /api/health` - 健康检查 (无需认证)\n- `GET /api/info` - 服务信息 (无需认证)\n\n### 连接管理\n- `POST /api/connect` - 连接到数据库 (返回 sessionId)\n- `POST /api/disconnect` - 断开数据库连接\n\n### 查询执行\n- `POST /api/query` - 执行读取查询\n- `POST /api/execute` - 执行写入操作 (需要 allowWrite: true)\n\n### Schema 信息\n- `GET /api/tables?sessionId=xxx` - 列出所有表\n- `GET /api/schema?sessionId=xxx` - 获取完整数据库 schema\n- `GET /api/schema/:table?sessionId=xxx` - 获取特定表信息\n\n## 🔧 配置\n\n### 环境变量\n基于 `.env.example` 创建 `.env` 文件：\n\n```bash\n# 服务器模式\nMODE=http\n\n# HTTP 配置\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\nAPI_KEYS=your-secret-key-1,your-secret-key-2\n\n# CORS\nCORS_ORIGINS=*\nCORS_CREDENTIALS=false\n\n# 速率限制\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n\n# 日志\nLOG_LEVEL=info\nLOG_PRETTY=false\n\n# 会话管理\nSESSION_TIMEOUT=3600000\nSESSION_CLEANUP_INTERVAL=300000\n```\n\n### NPM 脚本\n```json\n{\n  \"start\": \"node dist/index.js\",           // 从环境自动检测模式\n  \"start:http\": \"MODE=http node dist/index.js\",  // 强制 HTTP 模式\n  \"start:mcp\": \"MODE=mcp node dist/index.js\",    // 强制 MCP 模式\n  \"dev:http\": \"tsc && MODE=http node dist/index.js\",\n  \"dev:mcp\": \"tsc && MODE=mcp node dist/index.js\",\n  \"build\": \"tsc\"\n}\n```\n\n## 🐳 Docker 部署\n\n### 构建和运行\n```bash\n# 构建镜像\ndocker build -t universal-db-mcp -f docker/Dockerfile .\n\n# 运行容器\ndocker run -p 3000:3000 \\\n  -e MODE=http \\\n  -e API_KEYS=your-secret-key \\\n  -e DB_TYPE=mysql \\\n  -e DB_HOST=host.docker.internal \\\n  -e DB_PORT=3306 \\\n  -e DB_USER=root \\\n  -e DB_PASSWORD=xxx \\\n  -e DB_DATABASE=test \\\n  universal-db-mcp\n```\n\n### Docker Compose\n```bash\ncd docker\ndocker-compose up -d\n```\n\n## 🔒 安全特性\n\n### 已实现\n- ✅ API 密钥认证 (X-API-Key 请求头或 Authorization: Bearer)\n- ✅ CORS 配置\n- ✅ 速率限制 (按 API 密钥或 IP)\n- ✅ 查询验证 (复用现有 safety.ts)\n- ✅ 错误处理与清理的错误消息\n- ✅ 会话超时和清理\n- ✅ 非 root Docker 用户\n\n### 配置\n```bash\n# API 密钥 (逗号分隔)\nAPI_KEYS=key1,key2,key3\n\n# CORS\nCORS_ORIGINS=https://example.com,https://app.example.com\nCORS_CREDENTIALS=true\n\n# 速率限制\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n```\n\n## 📊 架构\n\n### 目录结构\n```\nsrc/\n├── adapters/          [未更改] 所有 17 个数据库适配器\n├── types/\n│   ├── adapter.ts     [未更改] 现有类型\n│   └── http.ts        [新增] HTTP 特定类型\n├── utils/\n│   ├── safety.ts      [未更改] 查询验证\n│   ├── adapter-factory.ts [新增] 集中式适配器创建\n│   └── config-loader.ts   [新增] 多源配置\n├── core/              [新增] 共享业务逻辑\n│   ├── database-service.ts [新增] 核心数据库操作\n│   └── connection-manager.ts [新增] 连接生命周期\n├── mcp/               [新增] MCP 特定代码\n│   ├── mcp-server.ts  [移动] 从 server.ts\n│   └── mcp-index.ts   [移动] 从 index.ts\n├── http/              [新增] HTTP API 模式\n│   ├── server.ts      [新增] Fastify 服务器\n│   ├── routes/        [新增] API 路由\n│   ├── middleware/    [新增] 认证、CORS、速率限制等\n│   └── http-index.ts  [新增] HTTP 入口点\n├── index.ts           [修改] 模式选择器\n└── server.ts          [修改] 向后兼容性垫片\n```\n\n### 关键设计决策\n\n1. **双模式架构**: 单一代码库，两个入口点\n2. **共享核心逻辑**: DatabaseService 和 ConnectionManager 被两种模式使用\n3. **适配器工厂**: 集中式适配器创建消除重复\n4. **会话管理**: HTTP 模式支持多个并发连接\n5. **向后兼容性**: 现有 MCP 模式未更改，server.ts 重新导出以保持兼容性\n\n## 🧪 测试\n\n### 手动测试\n\n#### 测试 MCP 模式\n```bash\n# 构建\nnpm run build\n\n# 启动 MCP 模式\nnpm run start:mcp -- --type mysql --host localhost --port 3306 --user root --password xxx --database test\n\n# 应该看到:\n# 🔌 Starting MCP mode...\n# 🔧 配置信息:\n#    数据库类型: mysql\n#    主机地址: localhost:3306\n#    数据库名: test\n#    安全模式: ✅ 只读模式\n# 🔌 正在连接数据库...\n# ✅ 数据库连接成功\n# 🛡️  安全模式: 只读模式（推荐）\n# 🚀 MCP 服务器已启动，等待 Claude Desktop 连接...\n```\n\n#### 测试 HTTP 模式\n```bash\n# 设置环境\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=test-key\n\n# 启动 HTTP 模式\nnpm run start:http\n\n# 应该看到:\n# 🌐 Starting HTTP API mode...\n# 🚀 HTTP API Server started successfully!\n# 📍 Server URL: http://0.0.0.0:3000\n# 📊 Supported databases: 17 types\n# 🛡️  Security: API Key authentication enabled\n# ⚡ Rate limiting: 100 requests per 1m\n\n# 测试健康端点\ncurl http://localhost:3000/api/health\n\n# 测试连接端点\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: test-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"type\":\"mysql\",\"host\":\"localhost\",\"port\":3306,\"user\":\"root\",\"password\":\"xxx\",\"database\":\"test\"}'\n\n# 响应:\n# {\n#   \"success\": true,\n#   \"data\": {\n#     \"sessionId\": \"abc123...\",\n#     \"databaseType\": \"mysql\",\n#     \"connected\": true\n#   },\n#   \"metadata\": {\n#     \"timestamp\": \"2026-01-27T...\",\n#     \"requestId\": \"...\"\n#   }\n# }\n```\n\n## 📝 后续步骤 (已完成)\n\n### 高优先级\n1. ✅ **创建 API 参考文档** (`docs/http-api/API_REFERENCE.md` 和 `API_REFERENCE.zh-CN.md`)\n   - 完整的端点文档\n   - 请求/响应示例\n   - 错误代码参考\n\n2. ✅ **创建部署指南** (`docs/http-api/DEPLOYMENT.md` 和 `DEPLOYMENT.zh-CN.md`)\n   - 本地部署 (Node.js、PM2)\n   - Docker 部署\n   - 云部署选项\n\n3. ✅ **创建集成指南**\n   - `docs/integrations/COZE.md` 和 `COZE.zh-CN.md` - Coze 平台集成\n   - `docs/integrations/N8N.md` 和 `N8N.zh-CN.md` - n8n 工作流示例\n   - `docs/integrations/DIFY.md` 和 `DIFY.zh-CN.md` - Dify 代理配置\n\n### 中优先级\n4. ✅ **Serverless 配置**\n   - 阿里云函数计算\n   - 腾讯云 Serverless 云函数\n   - AWS Lambda\n   - Vercel Edge Functions\n\n5. ✅ **PaaS 配置**\n   - Railway 部署\n   - Render 部署\n   - Fly.io 部署\n\n### 低优先级\n6. ✅ **测试**\n   - 核心逻辑单元测试\n   - HTTP API 集成测试\n   - MCP 模式集成测试\n\n## 🎉 成功标准\n\n### ✅ 已完成\n- [x] MCP 模式与之前完全一致 (100% 向后兼容)\n- [x] HTTP API 模式启动并运行\n- [x] 所有 HTTP 端点实现并可用\n- [x] API 密钥认证工作正常\n- [x] 速率限制工作正常\n- [x] CORS 配置工作正常\n- [x] Docker 构建成功\n- [x] 所有 17 个数据库适配器在两种模式下都能工作\n- [x] README 更新了 HTTP API 文档\n- [x] TypeScript 编译成功，无错误\n- [x] 完整的 API 参考文档\n- [x] 完整的部署指南\n- [x] 完整的集成指南\n- [x] Serverless 配置已创建\n- [x] PaaS 配置已创建\n- [x] 单元测试已编写\n- [x] 集成测试已编写\n- [x] 所有测试通过\n\n## 🚀 如何立即使用\n\n### 对于 Claude Desktop (MCP 模式)\n无需更改！继续像以前一样使用：\n```bash\nnpm install -g universal-db-mcp\n# 在 Claude Desktop 配置文件中配置\n```\n\n### 对于第三方平台 (HTTP API 模式)\n\n1. **安装**:\n   ```bash\n   npm install -g universal-db-mcp\n   ```\n\n2. **配置** (创建 `.env`):\n   ```bash\n   MODE=http\n   HTTP_PORT=3000\n   API_KEYS=your-secret-key\n   ```\n\n3. **启动**:\n   ```bash\n   npm run start:http\n   ```\n\n4. **使用 API**:\n   ```bash\n   # 连接到数据库\n   curl -X POST http://localhost:3000/api/connect \\\n     -H \"X-API-Key: your-secret-key\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"type\":\"mysql\",\"host\":\"localhost\",\"port\":3306,\"user\":\"root\",\"password\":\"xxx\",\"database\":\"test\"}'\n\n   # 执行查询\n   curl -X POST http://localhost:3000/api/query \\\n     -H \"X-API-Key: your-secret-key\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"sessionId\":\"<session-id-from-connect>\",\"query\":\"SELECT * FROM users LIMIT 10\"}'\n   ```\n\n## 📦 添加的依赖\n\n### 生产依赖\n- `fastify` (^4.26.0) - HTTP 服务器框架\n- `@fastify/cors` (^9.0.1) - CORS 支持\n- `@fastify/rate-limit` (^9.1.0) - 速率限制\n- `dotenv` (^16.4.1) - 环境变量管理\n- `nanoid` (^5.0.4) - 会话 ID 生成\n\n### 开发依赖\n- `vitest` (^1.2.0) - 测试框架\n- `@vitest/ui` (^1.2.0) - 测试 UI\n\n## 🔍 验证\n\n### 构建状态\n```bash\n$ npm run build\n> universal-db-mcp@1.0.0 build\n> tsc\n\n# ✅ 构建成功 (无错误)\n```\n\n### 文件统计\n- **创建的新文件**: 45+\n- **修改的文件**: 3 (index.ts、server.ts、package.json)\n- **未更改的文件**: 20+ (所有适配器、类型、工具)\n\n### 代码质量\n- ✅ TypeScript 严格模式已启用\n- ✅ 所有类型正确定义\n- ✅ 无隐式 any 类型\n- ✅ 正确的错误处理\n- ✅ 一致的代码风格\n\n## 🎯 总结\n\nHTTP API 模式实现**功能完整且可立即使用**。核心功能已完成：\n\n- ✅ 双模式架构工作正常\n- ✅ HTTP API 服务器运行正常\n- ✅ 所有端点已实现\n- ✅ 安全特性已启用\n- ✅ Docker 部署就绪\n- ✅ MCP 模式未更改\n- ✅ 完整的文档 (英文和中文)\n- ✅ 多种部署配置 (Docker、Serverless、PaaS)\n- ✅ 测试框架已设置\n\n**项目状态**: 项目已准备好进行测试和使用。所有核心功能、文档和部署配置均已完成。\n\n**建议**: 项目可以立即投入生产使用。所有 7 个实现阶段均已完成，包括完整的双语文档和多种部署选项。\n"
  },
  {
    "path": "docs/development/mcp-interaction-flow.md",
    "content": "# AI - MCP - 用户 交互流程详解\n\n本文档详细说明 AI、MCP Server 和用户之间的完整交互流程。\n\n## 整体架构图\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              用户界面层                                      │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  Claude Desktop / Cherry Studio / 其他 MCP 客户端                    │   │\n│  │  用户输入: \"帮我查看 users 表有多少条数据\"                            │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────────────────┘\n                                    │\n                                    │ 1. 用户消息\n                                    ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              AI 模型层                                       │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  Claude / 其他 LLM                                                   │   │\n│  │  - 理解用户意图                                                       │   │\n│  │  - 决定调用哪个 Tool                                                  │   │\n│  │  - 生成 Tool 调用参数（如 SQL）                                       │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────────────────┘\n                                    │\n                                    │ 2. Tool 调用请求 (JSON-RPC over stdio)\n                                    ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              MCP Server 层                                   │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  Universal DB MCP (本项目)                                           │   │\n│  │  - 接收 Tool 调用                                                     │   │\n│  │  - 执行数据库操作                                                     │   │\n│  │  - 返回结果                                                           │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────────────────┘\n                                    │\n                                    │ 3. 数据库查询\n                                    ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              数据库层                                        │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  MySQL / PostgreSQL / Oracle / ...                                   │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 详细流程\n\n### 第一阶段：启动与初始化\n\n```\n1. 用户启动 Claude Desktop\n       │\n       ▼\n2. Claude Desktop 读取配置文件 (claude_desktop_config.json)\n       │\n       ▼\n3. 发现 mcpServers 配置，启动 MCP Server 子进程\n   命令: npx universal-db-mcp --type mysql --host ... --password ...\n       │\n       ▼\n4. MCP Server 启动，通过 stdio 与 Claude Desktop 建立通信\n       │\n       ▼\n5. MCP Server 向 Claude Desktop 注册可用的 Tools:\n   - execute_query: 执行 SQL 查询\n   - get_schema: 获取数据库结构\n   - get_table_info: 获取表详情\n   - clear_cache: 清除缓存\n   - get_enum_values: 获取枚举值\n   - get_sample_data: 获取示例数据\n   - connect_database: 动态连接数据库\n   - disconnect_database: 断开数据库连接\n   - get_connection_status: 获取连接状态\n       │\n       ▼\n6. Claude Desktop 将 Tools 信息传递给 Claude AI\n   (AI 现在知道有哪些工具可用)\n```\n\n### 第二阶段：用户提问\n\n```\n用户: \"帮我查看 users 表有多少条数据\"\n       │\n       ▼\nClaude Desktop 将消息发送给 Claude AI\n       │\n       ▼\nClaude AI 分析:\n  - 用户想知道表的行数\n  - 需要执行 SQL: SELECT COUNT(*) FROM users\n  - 应该调用 execute_query 工具\n       │\n       ▼\nClaude AI 生成 Tool 调用请求:\n{\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"execute_query\",\n    \"arguments\": {\n      \"query\": \"SELECT COUNT(*) FROM users\"\n    }\n  }\n}\n```\n\n### 第三阶段：MCP 通信\n\n```\nClaude Desktop 通过 stdio 发送 JSON-RPC 请求给 MCP Server\n       │\n       │  stdin ──────────────────────────────────►\n       │  {\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",...}\n       │\n       ▼\nMCP Server (universal-db-mcp) 接收请求\n       │\n       ▼\n解析请求，识别要调用的 Tool: execute_query\n       │\n       ▼\n安全检查:\n  - 是否为写操作？ → 否\n  - 只读模式是否允许？ → 是\n       │\n       ▼\n执行数据库查询:\n  adapter.executeQuery(\"SELECT COUNT(*) FROM users\")\n       │\n       ▼\n数据库返回结果: [{ \"COUNT(*)\": 12345 }]\n       │\n       ▼\nMCP Server 通过 stdout 返回结果\n       │\n       │  ◄────────────────────────────────── stdout\n       │  {\"jsonrpc\":\"2.0\",\"result\":{\"rows\":[{\"COUNT(*)\":12345}]}}\n       │\n       ▼\nClaude Desktop 接收结果，传递给 Claude AI\n```\n\n### 第四阶段：AI 生成回复\n\n```\nClaude AI 收到 Tool 执行结果:\n{\n  \"rows\": [{ \"COUNT(*)\": 12345 }],\n  \"executionTime\": 15\n}\n       │\n       ▼\nClaude AI 理解结果，生成自然语言回复:\n\"users 表目前有 12,345 条数据。\"\n       │\n       ▼\nClaude Desktop 显示回复给用户\n```\n\n---\n\n## MCP 协议细节\n\n### 通信方式\n\n```\n┌──────────────────┐     stdio (stdin/stdout)     ┌──────────────────┐\n│  Claude Desktop  │ ◄──────────────────────────► │   MCP Server     │\n│  (MCP Client)    │      JSON-RPC 2.0            │ (universal-db-mcp)│\n└──────────────────┘                              └──────────────────┘\n```\n\n- **传输层**: stdio（标准输入/输出）\n- **协议**: JSON-RPC 2.0\n- **编码**: UTF-8\n\n### 消息类型\n\n#### 1. 初始化握手\n\n```json\n// Client → Server\n{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"capabilities\":{}},\"id\":1}\n\n// Server → Client\n{\"jsonrpc\":\"2.0\",\"result\":{\"capabilities\":{\"tools\":{}}},\"id\":1}\n```\n\n#### 2. 列出可用工具\n\n```json\n// Client → Server\n{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":2}\n\n// Server → Client\n{\n  \"jsonrpc\":\"2.0\",\n  \"result\":{\n    \"tools\":[\n      {\"name\":\"execute_query\",\"description\":\"执行SQL查询\",\"inputSchema\":{...}},\n      {\"name\":\"get_schema\",\"description\":\"获取数据库结构\",\"inputSchema\":{...}}\n    ]\n  },\n  \"id\":2\n}\n```\n\n#### 3. 调用工具\n\n```json\n// Client → Server\n{\n  \"jsonrpc\":\"2.0\",\n  \"method\":\"tools/call\",\n  \"params\":{\n    \"name\":\"execute_query\",\n    \"arguments\":{\"query\":\"SELECT * FROM users LIMIT 10\"}\n  },\n  \"id\":3\n}\n\n// Server → Client\n{\n  \"jsonrpc\":\"2.0\",\n  \"result\":{\n    \"content\":[{\n      \"type\":\"text\",\n      \"text\":\"{\\\"rows\\\":[...],\\\"executionTime\\\":25}\"\n    }]\n  },\n  \"id\":3\n}\n```\n\n---\n\n## 完整时序图\n\n```\n用户          Claude Desktop       Claude AI         MCP Server         数据库\n │                 │                  │                  │                │\n │  1.输入问题     │                  │                  │                │\n │────────────────►│                  │                  │                │\n │                 │  2.发送消息      │                  │                │\n │                 │─────────────────►│                  │                │\n │                 │                  │                  │                │\n │                 │                  │ 3.分析意图       │                │\n │                 │                  │ 决定调用Tool     │                │\n │                 │                  │                  │                │\n │                 │  4.Tool调用请求  │                  │                │\n │                 │◄─────────────────│                  │                │\n │                 │                  │                  │                │\n │                 │  5.JSON-RPC (stdin)                 │                │\n │                 │─────────────────────────────────────►│                │\n │                 │                  │                  │                │\n │                 │                  │                  │  6.SQL查询     │\n │                 │                  │                  │───────────────►│\n │                 │                  │                  │                │\n │                 │                  │                  │  7.查询结果    │\n │                 │                  │                  │◄───────────────│\n │                 │                  │                  │                │\n │                 │  8.JSON-RPC (stdout)                │                │\n │                 │◄─────────────────────────────────────│                │\n │                 │                  │                  │                │\n │                 │  9.Tool执行结果  │                  │                │\n │                 │─────────────────►│                  │                │\n │                 │                  │                  │                │\n │                 │                  │ 10.生成回复      │                │\n │                 │                  │                  │                │\n │                 │  11.AI回复       │                  │                │\n │                 │◄─────────────────│                  │                │\n │                 │                  │                  │                │\n │  12.显示结果   │                  │                  │                │\n │◄────────────────│                  │                  │                │\n │                 │                  │                  │                │\n```\n\n---\n\n## 关键点总结\n\n| 环节 | 负责方 | 职责 |\n|------|--------|------|\n| 理解用户意图 | AI (Claude) | 分析自然语言，决定需要什么数据 |\n| 生成 SQL | AI (Claude) | 根据意图和 Schema 生成正确的 SQL |\n| 决定调用哪个 Tool | AI (Claude) | 选择 execute_query / get_schema 等 |\n| 执行 Tool | MCP Server | 接收请求，执行数据库操作 |\n| 安全控制 | MCP Server | 只读模式检查，防止危险操作 |\n| 数据库交互 | MCP Server | 通过适配器连接并查询数据库 |\n| 格式化结果 | AI (Claude) | 将查询结果转换为自然语言 |\n\n**核心理念**: AI 负责\"思考\"（理解意图、生成 SQL），MCP Server 负责\"执行\"（连接数据库、运行查询）。\n\n---\n\n## 相关资源\n\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n- [项目架构说明](./architecture.md)\n- [添加新数据库支持](./adding-database.md)\n"
  },
  {
    "path": "docs/development/release.md",
    "content": "# NPM 发布步骤\n\n## ✅ 准备工作已完成\n\n以下准备工作已经完成：\n- ✅ package.json 配置完整\n- ✅ LICENSE 文件已创建\n- ✅ .npmignore 文件已创建\n- ✅ 包名 `universal-db-mcp` 可用\n- ✅ 本地打包测试成功（25.6 kB）\n\n## 📝 发布流程\n\n### 1. 登录 NPM\n\n如果你还没有 NPM 账号，需要先注册：\n\n```bash\n# 注册新账号（会打开浏览器）\nnpm adduser\n```\n\n如果已有账号，直接登录：\n\n```bash\n# 登录\nnpm login\n```\n\n按提示输入：\n- Username（用户名）\n- Password（密码）\n- Email（邮箱）\n- OTP（如果启用了两步验证）\n\n验证登录状态：\n```bash\nnpm whoami\n```\n\n### 2. 发布到 NPM\n\n```bash\n# 发布\nnpm publish\n```\n\n如果是第一次发布，可能需要验证邮箱。\n\n### 3. 验证发布成功\n\n```bash\n# 查看包信息\nnpm view universal-db-mcp\n\n# 测试安装\nnpx universal-db-mcp@latest --help\n```\n\n## 🎉 发布成功后\n\n发布成功后，用户可以通过以下方式使用：\n\n```bash\n# 全局安装\nnpm install -g universal-db-mcp\n\n# 或直接使用 npx\nnpx universal-db-mcp --type mysql --host localhost --port 3306 ...\n```\n\n## 📦 包信息\n\n- **包名**: universal-db-mcp\n- **版本**: 0.1.0\n- **大小**: 25.6 kB (压缩后)\n- **解压后**: 97.8 kB\n- **文件数**: 34 个文件\n\n## 🔄 后续版本发布\n\n当需要发布新版本时：\n\n```bash\n# 修复 bug（0.1.0 -> 0.1.1）\nnpm version patch\n\n# 新功能（0.1.0 -> 0.2.0）\nnpm version minor\n\n# 重大更新（0.1.0 -> 1.0.0）\nnpm version major\n\n# 发布新版本\nnpm publish\n```\n\n## ⚠️ 注意事项\n\n1. **发布前检查**\n   - 确保代码已提交到 Git\n   - 确保所有测试通过\n   - 确保 README 文档完整\n\n2. **版本号规范**\n   - 遵循语义化版本（Semantic Versioning）\n   - 主版本号.次版本号.修订号\n\n3. **撤销发布**\n   - 发布后 72 小时内可以撤销：`npm unpublish universal-db-mcp@0.1.0`\n   - 超过 72 小时只能废弃：`npm deprecate universal-db-mcp@0.1.0 \"版本已废弃\"`\n\n## 📊 发布后的推广\n\n1. **更新 README**\n   - 添加 NPM 徽章\n   - 更新安装说明\n\n2. **社区推广**\n   - 在 GitHub 创建 Release\n   - 在相关社区分享（如 V2EX、掘金等）\n   - 在 Twitter/X 上宣布\n\n3. **文档完善**\n   - 添加更多使用示例\n   - 录制演示视频\n   - 编写博客文章\n\n## 🔗 相关链接\n\n- NPM 包页面: https://www.npmjs.com/package/universal-db-mcp\n- GitHub 仓库: https://github.com/universal-db-mcp/universal-db-mcp\n- 问题反馈: https://github.com/universal-db-mcp/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/development/text2sql-enhancement.md",
    "content": "# Text2SQL 准确性提升方案\n\n本文档详细介绍 Universal DB MCP 为帮助 LLM 更好地理解数据库结构、提升 Text2SQL 准确性所做的技术方案。\n\n## 目录\n\n- [一、方案概览](#一方案概览)\n- [二、Schema 信息完整性](#二schema-信息完整性)\n- [三、表间关系理解](#三表间关系理解)\n- [四、性能优化](#四性能优化)\n- [五、数据库支持矩阵](#五数据库支持矩阵)\n- [六、技术原理](#六技术原理)\n- [七、版本演进](#七版本演进)\n- [八、未来规划](#八未来规划)\n\n---\n\n## 一、方案概览\n\n### 1.1 设计目标\n\n帮助 LLM 生成准确的 SQL 查询，需要解决以下问题：\n\n| 问题 | 解决方案 | 效果 |\n|-----|---------|------|\n| LLM 不知道有哪些表 | 提供完整的表列表 | 避免查询不存在的表 |\n| LLM 不理解表的业务含义 | 提供表注释和列注释 | 生成语义正确的查询 |\n| LLM 不知道如何 JOIN | 提供外键和关系信息 | 生成正确的关联查询 |\n| LLM 不知道数据类型 | 提供精确的类型信息 | 生成类型安全的 SQL |\n| Schema 获取太慢 | 批量查询 + 缓存 | 快速响应，提升体验 |\n\n### 1.2 功能分层\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    第一层：基础 Schema 信息                   │\n│  表名、列名、数据类型、主键、索引、预估行数                    │\n│  （所有 17 个数据库支持）                                     │\n├─────────────────────────────────────────────────────────────┤\n│                    第二层：语义增强信息                        │\n│  表注释、列注释                                               │\n│  （14 个数据库支持，NoSQL 和 SQLite 除外）                    │\n├─────────────────────────────────────────────────────────────┤\n│                    第三层：关系理解                            │\n│  显式外键、隐式关系推断、关系类型细化                          │\n│  （14 个关系型数据库支持，NoSQL 除外）                        │\n├─────────────────────────────────────────────────────────────┤\n│                    第四层：性能优化                            │\n│  批量查询、智能缓存                                           │\n│  （所有 17 个数据库支持）                                     │\n└─────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 二、Schema 信息完整性\n\n### 2.1 核心数据结构\n\n#### SchemaInfo - 数据库级信息\n\n```typescript\ninterface SchemaInfo {\n  databaseType: string;           // 数据库类型（mysql, postgres, oracle...）\n  databaseName: string;           // 数据库名称\n  tables: TableInfo[];            // 所有表信息\n  version?: string;               // 数据库版本\n  relationships?: RelationshipInfo[];  // 全局关系视图\n}\n```\n\n**LLM 收益**：了解数据库全貌，知道有哪些表可用。\n\n#### TableInfo - 表级信息\n\n```typescript\ninterface TableInfo {\n  name: string;                   // 表名\n  comment?: string;               // 表注释（业务含义）\n  columns: ColumnInfo[];          // 列信息\n  primaryKeys: string[];          // 主键列\n  indexes?: IndexInfo[];          // 索引信息\n  foreignKeys?: ForeignKeyInfo[]; // 外键约束\n  estimatedRows?: number;         // 预估行数\n}\n```\n\n**LLM 收益**：\n- `comment`：理解表的业务用途（如\"订单主表\"）\n- `primaryKeys`：知道用什么列做唯一标识\n- `indexes`：优化查询条件，使用索引列\n- `estimatedRows`：判断表大小，优化查询策略\n\n#### ColumnInfo - 列级信息\n\n```typescript\ninterface ColumnInfo {\n  name: string;                   // 列名\n  type: string;                   // 数据类型（含长度/精度）\n  nullable: boolean;              // 是否可空\n  defaultValue?: string;          // 默认值\n  comment?: string;               // 列注释\n}\n```\n\n**LLM 收益**：\n- `type`：生成类型安全的 SQL（如日期格式、数值精度）\n- `nullable`：判断是否需要 NULL 检查\n- `comment`：理解列的业务含义\n\n### 2.2 注释信息获取\n\n#### 表注释\n\n| 数据库 | 获取方式 | 支持情况 |\n|-------|---------|---------|\n| MySQL | `INFORMATION_SCHEMA.TABLES.TABLE_COMMENT` | ✅ |\n| PostgreSQL | `obj_description(oid, 'pg_class')` | ✅ |\n| Oracle | `ALL_TAB_COMMENTS.COMMENTS` | ✅ |\n| SQL Server | `sys.extended_properties` (MS_Description) | ✅ |\n| SQLite | 无原生支持 | ❌ |\n| Redis/MongoDB | NoSQL，无表概念 | ❌ |\n| TiDB | 同 MySQL | ✅ |\n| 达梦 | `USER_TAB_COMMENTS.COMMENTS` | ✅ |\n| KingbaseES | 同 PostgreSQL | ✅ |\n| GaussDB | 同 PostgreSQL | ✅ |\n| OceanBase | 同 MySQL | ✅ |\n| PolarDB | 同 MySQL | ✅ |\n| Vastbase | 同 PostgreSQL | ✅ |\n| HighGo | 同 PostgreSQL | ✅ |\n| GoldenDB | 同 MySQL | ✅ |\n| ClickHouse | `system.tables.comment` | ✅ |\n\n#### 列注释\n\n所有支持表注释的数据库同样支持列注释，获取方式类似。\n\n---\n\n## 三、表间关系理解\n\n### 3.1 显式外键关系\n\n#### 数据结构\n\n```typescript\ninterface ForeignKeyInfo {\n  name: string;                   // 约束名称\n  columns: string[];              // 本表外键列\n  referencedTable: string;        // 引用的表\n  referencedColumns: string[];    // 引用的列\n  onDelete?: string;              // 删除规则\n  onUpdate?: string;              // 更新规则\n}\n```\n\n#### 获取方式\n\n| 数据库 | 系统表/视图 |\n|-------|-----------|\n| MySQL | `INFORMATION_SCHEMA.KEY_COLUMN_USAGE` + `REFERENTIAL_CONSTRAINTS` |\n| PostgreSQL | `pg_constraint` |\n| Oracle | `ALL_CONSTRAINTS` + `ALL_CONS_COLUMNS` |\n| SQL Server | `sys.foreign_keys` + `sys.foreign_key_columns` |\n| SQLite | `PRAGMA foreign_key_list` |\n\n**LLM 收益**：知道表之间的关联关系，生成正确的 JOIN 语句。\n\n### 3.2 全局关系视图\n\n#### 数据结构\n\n```typescript\ninterface RelationshipInfo {\n  fromTable: string;              // 源表\n  fromColumns: string[];          // 源列\n  toTable: string;                // 目标表\n  toColumns: string[];            // 目标列\n  type: 'one-to-one' | 'one-to-many' | 'many-to-one';\n  constraintName?: string;        // 约束名（显式外键）\n  source: 'foreign_key' | 'inferred';  // 关系来源\n  confidence?: number;            // 置信度（推断关系）\n}\n```\n\n**LLM 收益**：\n- 一次性获取所有表间关系，无需逐表查看外键\n- `type` 字段帮助理解关系方向\n- `source` 字段区分显式外键和推断关系\n\n### 3.3 隐式关系推断\n\n#### 设计背景\n\n很多数据库（尤其是老旧系统或从 NoSQL 迁移的系统）没有定义外键约束，但存在命名约定。\n\n#### 推断规则\n\n| 规则 | 列名模式 | 目标表 | 目标列 | 置信度 |\n|-----|---------|-------|-------|-------|\n| 1 | `xxx_id` | `xxxs` / `xxx` | `id` | 0.90-0.95 |\n| 2 | `xxxId` (驼峰) | `xxxs` / `xxx` | `id` | 0.85-0.90 |\n| 3 | `xxx_code` | `xxxs` / `xxx` | `code` | 0.90-0.95 |\n| 4 | `xxx_no` | `xxxs` / `xxx` | `xxx_no` | 0.70-0.75 |\n\n#### 安全规则\n\n推断遵循\"宁可漏掉，不可错推\"原则：\n\n1. **不覆盖显式外键**：已有外键的列不进行推断\n2. **验证目标表存在**：只有目标表确实存在时才推断\n3. **验证目标列存在**：确保目标表有对应的主键/唯一列\n4. **跳过主键列**：主键通常不是外键\n5. **精确匹配优先**：只做精确表名匹配，避免误匹配\n\n#### 示例\n\n```\n数据库中的表：users, orders, products\n\norders 表的列：\n- id (主键，跳过)\n- user_id → 推断到 users.id (置信度 0.95)\n- product_id → 推断到 products.id (置信度 0.95)\n- status (不符合规则，跳过)\n```\n\n### 3.4 关系类型细化\n\n#### 原理\n\n通过检查外键列是否有唯一约束，区分 `one-to-one` 和 `many-to-one`：\n\n```typescript\nfunction determineRelationType(table: TableInfo, fkColumns: string[]) {\n  // 检查外键列是否有唯一索引\n  const hasUniqueConstraint = table.indexes?.some(idx =>\n    idx.unique &&\n    idx.columns.length === fkColumns.length &&\n    idx.columns.every(c => fkColumns.includes(c))\n  );\n\n  return hasUniqueConstraint ? 'one-to-one' : 'many-to-one';\n}\n```\n\n#### 示例\n\n```sql\n-- user_profiles.user_id 有唯一索引\nCREATE TABLE user_profiles (\n  id INT PRIMARY KEY,\n  user_id INT UNIQUE,  -- 唯一约束\n  bio TEXT\n);\n\n-- 推断结果：user_profiles → users 是 one-to-one 关系\n```\n\n**LLM 收益**：理解关系的基数，生成更准确的查询。\n\n---\n\n## 四、性能优化\n\n### 4.1 批量查询优化\n\n#### 问题\n\n传统方式获取 Schema 需要 N+1 次查询：\n\n```\n1 次查询获取表列表\nN 次查询获取每个表的列信息\nN 次查询获取每个表的索引信息\nN 次查询获取每个表的外键信息\n...\n```\n\n对于 100 张表的数据库，需要 400+ 次查询。\n\n#### 解决方案\n\n使用批量查询，一次获取所有表的信息：\n\n```sql\n-- MySQL 示例：一次获取所有列信息\nSELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, ...\nFROM INFORMATION_SCHEMA.COLUMNS\nWHERE TABLE_SCHEMA = DATABASE()\nORDER BY TABLE_NAME, ORDINAL_POSITION;\n\n-- 一次获取所有索引信息\nSELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, NON_UNIQUE, ...\nFROM INFORMATION_SCHEMA.STATISTICS\nWHERE TABLE_SCHEMA = DATABASE()\nORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;\n```\n\n然后在内存中组装数据。\n\n#### 性能提升\n\n| 表数量 | 优化前 | 优化后 | 提升倍数 |\n|--------|--------|--------|----------|\n| 50 张表 | ~5 秒 | ~200 毫秒 | **25x** |\n| 100 张表 | ~10 秒 | ~300 毫秒 | **33x** |\n| 500 张表 | ~50 秒 | ~500 毫秒 | **100x** |\n\n### 4.2 智能缓存\n\n#### 缓存策略\n\n```typescript\ninterface SchemaCacheConfig {\n  enabled: boolean;    // 是否启用缓存（默认 true）\n  ttl: number;         // 缓存过期时间（默认 5 分钟）\n}\n```\n\n#### 功能特性\n\n- **自动缓存**：首次获取 Schema 后自动缓存\n- **TTL 过期**：缓存自动过期，保证数据新鲜度\n- **强制刷新**：支持 `forceRefresh` 参数强制更新\n- **命中率统计**：提供缓存命中率指标\n\n#### 返回信息\n\n```json\n{\n  \"tables\": [...],\n  \"_cacheInfo\": {\n    \"cached\": true,\n    \"cachedAt\": \"2024-01-20T10:30:00Z\",\n    \"hitRate\": \"85.00%\"\n  }\n}\n```\n\n**LLM 收益**：快速获取 Schema，提升交互体验。\n\n---\n\n## 五、数据库支持矩阵\n\n### 5.1 功能支持表\n\n| 数据库 | 基础 Schema | 表注释 | 列注释 | 外键 | 隐式推断 | 批量优化 | 缓存 |\n|-------|:---------:|:-----:|:-----:|:---:|:------:|:------:|:---:|\n| MySQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| Oracle | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| SQL Server | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| SQLite | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |\n| TiDB | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| 达梦 | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ |\n| KingbaseES | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| GaussDB | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| OceanBase | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| PolarDB | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| Vastbase | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| HighGo | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| GoldenDB | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |\n| ClickHouse | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |\n| Redis | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |\n| MongoDB | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |\n\n**说明**：\n- ✅ 完全支持\n- ⚠️ 部分支持（达梦因兼容性问题不使用批量优化）\n- ❌ 不支持（技术限制或不适用）\n\n### 5.2 不支持原因\n\n| 数据库 | 不支持功能 | 原因 |\n|-------|----------|------|\n| SQLite | 表注释 | SQLite 无原生表注释语法 |\n| Redis | 注释/外键/推断 | NoSQL，无表结构概念 |\n| MongoDB | 注释/外键/推断 | NoSQL，无表结构概念 |\n| ClickHouse | 外键 | OLAP 数据库，不支持外键约束 |\n\n---\n\n## 六、技术原理\n\n### 6.1 为什么这些功能提升 Text2SQL 准确性？\n\n#### 1. 完整的 Schema 信息\n\n**问题**：LLM 不知道数据库有哪些表和列。\n\n**解决**：提供完整的表、列、类型信息。\n\n**效果**：LLM 只会使用存在的表和列，避免生成无效 SQL。\n\n#### 2. 表间关系视图\n\n**问题**：LLM 不知道如何 JOIN 多个表。\n\n**解决**：提供外键和关系信息。\n\n**效果**：LLM 生成正确的 JOIN 条件，如 `orders.user_id = users.id`。\n\n#### 3. 隐式关系推断\n\n**问题**：很多数据库没有定义外键约束。\n\n**解决**：基于命名约定推断关系。\n\n**效果**：即使没有外键，LLM 也能理解表关联。\n\n#### 4. 置信度评分\n\n**问题**：推断的关系可能不准确。\n\n**解决**：为推断关系标注置信度。\n\n**效果**：LLM 可根据置信度判断关系可靠性。\n\n#### 5. 注释信息\n\n**问题**：LLM 不理解表和列的业务含义。\n\n**解决**：提供表注释和列注释。\n\n**效果**：LLM 理解\"订单表\"、\"用户ID\"等业务概念。\n\n#### 6. 索引信息\n\n**问题**：LLM 生成的查询可能性能差。\n\n**解决**：提供索引信息。\n\n**效果**：LLM 优先使用索引列作为查询条件。\n\n#### 7. 行数估算\n\n**问题**：LLM 不知道表的数据量。\n\n**解决**：提供预估行数。\n\n**效果**：LLM 可优化大表查询策略（如添加 LIMIT）。\n\n#### 8. 数据类型精确\n\n**问题**：LLM 可能生成类型不匹配的 SQL。\n\n**解决**：提供精确的数据类型（含长度/精度）。\n\n**效果**：LLM 生成类型安全的 SQL。\n\n### 6.2 架构设计\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                         LLM                                  │\n│                          ↓                                   │\n│                    MCP 协议调用                               │\n│                          ↓                                   │\n├─────────────────────────────────────────────────────────────┤\n│                    MCP Server                                │\n│              (get_schema, execute_query, ...)                │\n│                          ↓                                   │\n├─────────────────────────────────────────────────────────────┤\n│                  DatabaseService                             │\n│              (缓存管理, Schema 增强)                          │\n│                          ↓                                   │\n├─────────────────────────────────────────────────────────────┤\n│                  SchemaEnhancer                              │\n│           (隐式关系推断, 关系类型细化)                         │\n│                          ↓                                   │\n├─────────────────────────────────────────────────────────────┤\n│                   DbAdapter                                  │\n│         (MySQL, PostgreSQL, Oracle, ... 17种)                │\n│                          ↓                                   │\n├─────────────────────────────────────────────────────────────┤\n│                      数据库                                   │\n└─────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 七、版本演进\n\n| 版本 | 功能 | Text2SQL 提升 |\n|-----|------|--------------|\n| v1.0.0 | 基础 Schema（表、列、类型、主键、索引） | 基准 |\n| v2.1.0 | Schema 缓存机制 | 响应速度提升 |\n| v2.2.0 | 批量查询优化（25-100x 性能提升） | 大型数据库可用 |\n| v2.7.0 | 外键关系支持 | +15-20% |\n| v2.8.0 | 表注释支持 | +10-15% |\n| v2.8.0 | 隐式关系推断 | +15-20% |\n| v2.8.0 | 关系类型细化 | +5% |\n| v2.9.0 | 枚举值提取工具 `get_enum_values` | +10-15% |\n| v2.9.0 | 示例数据工具 `get_sample_data`（含脱敏） | +5-10% |\n\n**综合预期**：Text2SQL 准确性提升 **50-70%**。\n\n---\n\n## 八、未来规划\n\n以下是计划实现的功能，将进一步提升 LLM 对数据库的理解和 Text2SQL 准确性。\n\n### 8.1 按需增强工具（已实现 ✅）\n\n> **v2.9.0 已实现**：以下两个工具已在 v2.9.0 版本中实现，支持 MCP 协议和 HTTP API。\n\n#### 8.1.1 枚举值提取工具 `get_enum_values` ✅\n\n**为什么需要这个功能？**\n\n很多数据库表中存在状态列（如 `status`、`type`、`category`），这些列的值是有限的枚举集合。LLM 在生成 SQL 时，如果不知道这些枚举值，可能会：\n- 猜测错误的值（如用 `\"completed\"` 而实际是 `\"done\"`）\n- 使用不存在的值（如用 `\"success\"` 而实际只有 `\"paid\"`）\n- 无法理解用户的自然语言描述（如用户说\"已完成\"对应哪个值）\n\n**如何带来收益？**\n\n通过提供枚举列的所有可能值，LLM 可以：\n1. 精确匹配用户意图到正确的枚举值\n2. 在生成 SQL 时使用准确的 WHERE 条件\n3. 理解业务状态流转（通过值的分布）\n\n**完整示例**\n\n```\n场景：电商订单系统，orders 表有 status 列\n\n用户问：查询所有已支付的订单\n\n【没有枚举值工具时】\nLLM 猜测：SELECT * FROM orders WHERE status = 'paid'\n实际结果：可能错误，因为实际值可能是 'PAID' 或 'payment_completed'\n\n【有枚举值工具时】\nStep 1: LLM 调用 get_enum_values('orders', 'status')\nStep 2: 返回 {\n  values: [\"pending\", \"payment_completed\", \"shipped\", \"delivered\", \"cancelled\"],\n  sampleCounts: {\"pending\": 1200, \"payment_completed\": 3500, ...}\n}\nStep 3: LLM 理解 \"已支付\" 对应 \"payment_completed\"\nStep 4: 生成 SELECT * FROM orders WHERE status = 'payment_completed'\n结果：准确匹配用户意图\n```\n\n**设计方案**：\n```typescript\n{\n  name: 'get_enum_values',\n  description: '获取指定列的所有可能值，适用于 status、type 等枚举列',\n  inputSchema: {\n    tableName: string,    // 表名\n    columnName: string,   // 列名\n    limit: number         // 最大返回数量（默认 50）\n  }\n}\n```\n\n**返回结构**：\n```typescript\ninterface EnumValuesResult {\n  tableName: string;\n  columnName: string;\n  values: string[];           // 所有唯一值\n  totalCount: number;         // 唯一值总数\n  isEnum: boolean;            // 是否适合作为枚举（count < limit）\n  sampleCounts?: {            // 每个值的出现次数\n    [value: string]: number;\n  };\n}\n```\n\n**预期收益**：Text2SQL 准确性 +10-15%\n\n---\n\n#### 8.1.2 示例数据工具 `get_sample_data` ✅\n\n**为什么需要这个功能？**\n\nLLM 只看 Schema 信息（列名、类型）无法理解数据的实际格式，例如：\n- 日期格式：是 `2024-01-20` 还是 `20240120` 还是 `Jan 20, 2024`？\n- ID 格式：是纯数字 `12345` 还是带前缀 `ORD-12345`？\n- 编码规则：产品编码是 `P001` 还是 `PROD-2024-001`？\n\n这些格式差异会导致 LLM 生成错误的查询条件。\n\n**如何带来收益？**\n\n通过提供真实的示例数据（已脱敏），LLM 可以：\n1. 理解数据的实际格式和模式\n2. 生成格式正确的查询条件\n3. 避免类型转换错误\n\n**完整示例**\n\n```\n场景：订单表的 order_no 列\n\n用户问：查询订单号 12345 的订单\n\n【没有示例数据时】\nLLM 猜测：SELECT * FROM orders WHERE order_no = '12345'\n实际结果：查不到数据，因为实际格式是 'ORD-2024-12345'\n\n【有示例数据工具时】\nStep 1: LLM 调用 get_sample_data('orders', ['order_no', 'created_at'])\nStep 2: 返回 {\n  rows: [\n    { order_no: \"ORD-2024-00001\", created_at: \"2024-01-15 10:30:00\" },\n    { order_no: \"ORD-2024-00002\", created_at: \"2024-01-15 11:45:00\" },\n    { order_no: \"ORD-2024-00003\", created_at: \"2024-01-16 09:20:00\" }\n  ]\n}\nStep 3: LLM 理解 order_no 格式是 'ORD-YYYY-NNNNN'\nStep 4: 生成 SELECT * FROM orders WHERE order_no = 'ORD-2024-12345'\n        或 SELECT * FROM orders WHERE order_no LIKE '%12345%'\n结果：正确查询到数据\n```\n\n**设计方案**：\n```typescript\n{\n  name: 'get_sample_data',\n  description: '获取指定表的示例数据（已脱敏）',\n  inputSchema: {\n    tableName: string,        // 表名\n    columns?: string[],       // 要查看的列（可选）\n    limit: number             // 返回行数（默认 3，最大 10）\n  }\n}\n```\n\n**内置脱敏规则**：\n| 数据类型 | 脱敏方式 | 示例 |\n|---------|---------|------|\n| 手机号 | 中间 4 位隐藏 | `138****1234` |\n| 邮箱 | 用户名部分隐藏 | `z***@example.com` |\n| 身份证 | 中间 11 位隐藏 | `110***********1234` |\n| 银行卡 | 只显示后 4 位 | `************1234` |\n| 密码类 | 完全隐藏 | `******` |\n\n**预期收益**：Text2SQL 准确性 +5-10%\n\n---\n\n### 8.2 高级功能（P2 优先级）\n\n#### 8.2.1 列统计工具 `get_column_stats`\n\n**为什么需要这个功能？**\n\nLLM 在生成查询时，不了解数据的分布特征，可能导致：\n- 对高基数列使用 `=` 而不是 `LIKE`（如姓名列）\n- 对低基数列使用 `LIKE` 而不是 `=`（如状态列）\n- 不知道某列是否有大量 NULL 值需要特殊处理\n- 无法判断数值范围，生成不合理的范围查询\n\n**如何带来收益？**\n\n通过提供列的统计信息，LLM 可以：\n1. 根据唯一值数量判断是否适合精确匹配\n2. 根据 NULL 比例决定是否需要 `IS NOT NULL` 条件\n3. 根据最大最小值生成合理的范围查询\n4. 优化查询策略，提高查询效率\n\n**完整示例**\n\n```\n场景：用户表的 email 列查询\n\n用户问：查询邮箱包含 \"gmail\" 的用户\n\n【没有列统计时】\nLLM 可能生成：SELECT * FROM users WHERE email = 'gmail'\n结果：查不到任何数据\n\n【有列统计工具时】\nStep 1: LLM 调用 get_column_stats('users', 'email')\nStep 2: 返回 {\n  distinctCount: 45000,      // 高基数，每个值几乎唯一\n  nullCount: 500,            // 有一些空值\n  nullPercentage: 1.1%\n}\nStep 3: LLM 理解 email 是高基数列，应该用模糊匹配\nStep 4: 生成 SELECT * FROM users WHERE email LIKE '%gmail%'\n结果：正确查询到所有 Gmail 用户\n```\n\n**设计方案**：\n```typescript\n{\n  name: 'get_column_stats',\n  description: '获取指定列的统计信息',\n  inputSchema: {\n    tableName: string,\n    columnName: string\n  }\n}\n```\n\n**返回结构**：\n```typescript\ninterface ColumnStatsResult {\n  tableName: string;\n  columnName: string;\n  totalRows: number;          // 总行数\n  distinctCount: number;      // 唯一值数量\n  nullCount: number;          // 空值数量\n  nullPercentage: number;     // 空值比例\n  minValue?: string | number; // 最小值\n  maxValue?: string | number; // 最大值\n  avgLength?: number;         // 平均长度（字符串）\n  avgValue?: number;          // 平均值（数值）\n}\n```\n\n**预期收益**：Text2SQL 准确性 +3-5%\n\n---\n\n#### 8.2.2 业务术语映射 `get_business_glossary`\n\n**为什么需要这个功能？**\n\n用户使用自然语言提问时，常用业务术语而非数据库字段名：\n- 用户说\"客户\"，数据库是 `users` 表\n- 用户说\"成交金额\"，数据库是 `orders.total_amount`\n- 用户说\"有效订单\"，实际是 `status NOT IN ('cancelled', 'refunded')`\n\nLLM 可能无法准确将业务术语映射到正确的表和列。\n\n**如何带来收益？**\n\n通过提供业务术语词典，LLM 可以：\n1. 准确理解用户的业务语言\n2. 映射到正确的数据库对象\n3. 应用预定义的业务规则\n\n**完整示例**\n\n```\n场景：财务报表查询\n\n用户问：统计本月有效订单的成交金额\n\n【没有业务术语映射时】\nLLM 猜测：SELECT SUM(amount) FROM orders WHERE ...\n结果：可能用错列名（amount vs total_amount），漏掉有效订单条件\n\n【有业务术语映射时】\nStep 1: LLM 调用 get_business_glossary()\nStep 2: 返回 {\n  termMappings: [\n    { terms: [\"成交金额\"], table: \"orders\", column: \"total_amount\" },\n    { terms: [\"有效订单\"], table: \"orders\", condition: \"status NOT IN ('cancelled', 'refunded')\" }\n  ]\n}\nStep 3: LLM 理解：\n  - \"成交金额\" = orders.total_amount\n  - \"有效订单\" = status NOT IN ('cancelled', 'refunded')\nStep 4: 生成\n  SELECT SUM(total_amount)\n  FROM orders\n  WHERE status NOT IN ('cancelled', 'refunded')\n    AND created_at >= '2024-01-01'\n结果：准确的业务查询\n```\n\n**配置文件** `config/business-glossary.json`：\n```json\n{\n  \"termMappings\": [\n    {\n      \"terms\": [\"客户\", \"买家\", \"用户\"],\n      \"table\": \"users\",\n      \"description\": \"系统注册用户\"\n    },\n    {\n      \"terms\": [\"订单金额\", \"成交金额\"],\n      \"table\": \"orders\",\n      \"column\": \"total_amount\"\n    }\n  ],\n  \"businessRules\": [\n    {\n      \"name\": \"有效订单\",\n      \"condition\": \"status NOT IN ('cancelled', 'refunded')\",\n      \"table\": \"orders\"\n    }\n  ]\n}\n```\n\n**预期收益**：Text2SQL 准确性 +5-10%（需人工配置）\n\n---\n\n### 8.3 隐式关系推断增强（P2 优先级）\n\n#### 8.3.1 后缀匹配支持\n\n**为什么需要这个功能？**\n\n当前的隐式关系推断只支持精确表名匹配：\n- `user_id` → 查找 `users` 或 `user` 表\n\n但很多企业数据库使用表名前缀来区分模块：\n- `hr_users`（人力资源模块）\n- `crm_users`（客户关系模块）\n- `training_departments`（培训模块）\n\n这导致 `department_id` 无法推断到 `training_departments`。\n\n**如何带来收益？**\n\n通过后缀匹配，可以：\n1. 支持带前缀的表名\n2. 扩大隐式关系推断的覆盖范围\n3. 帮助 LLM 理解更多表间关系\n\n**完整示例**\n\n```\n场景：培训管理系统\n\n表结构：\n- training_departments (id, name)\n- training_employees (id, name, department_id)\n\n【当前行为】\ndepartment_id → 查找 departments / department → 找不到 → 不推断\n\n【增强后】\ndepartment_id → 后缀匹配 *departments → 找到 training_departments → 推断关系\n返回：{\n  fromTable: \"training_employees\",\n  fromColumns: [\"department_id\"],\n  toTable: \"training_departments\",\n  toColumns: [\"id\"],\n  source: \"inferred\",\n  confidence: 0.85  // 后缀匹配置信度略低\n}\n\nLLM 收益：理解 training_employees.department_id → training_departments.id\n生成正确的 JOIN：\nSELECT e.*, d.name as dept_name\nFROM training_employees e\nJOIN training_departments d ON e.department_id = d.id\n```\n\n**安全规则**：\n- 只有唯一匹配时才推断（避免误导）\n- 多个匹配时放弃推断\n- 后缀匹配的置信度降低 0.05-0.10\n\n---\n\n#### 8.3.2 缩写识别\n\n**为什么需要这个功能？**\n\n很多数据库使用缩写命名外键列：\n- `dept_id` 而不是 `department_id`\n- `org_id` 而不是 `organization_id`\n- `cat_id` 而不是 `category_id`\n\n当前的推断规则无法识别这些缩写。\n\n**如何带来收益？**\n\n通过内置常见缩写映射，可以：\n1. 识别缩写形式的外键列\n2. 推断到正确的目标表\n3. 进一步扩大关系推断覆盖范围\n\n**完整示例**\n\n```\n场景：员工表使用缩写\n\n表结构：\n- departments (id, name)\n- employees (id, name, dept_id)  // 使用缩写 dept\n\n【当前行为】\ndept_id → 查找 depts / dept → 找不到 → 不推断\n\n【增强后】\ndept_id → 识别 dept 是 department 的缩写\n       → 查找 departments / department\n       → 找到 departments\n       → 推断关系\n返回：{\n  fromTable: \"employees\",\n  fromColumns: [\"dept_id\"],\n  toTable: \"departments\",\n  toColumns: [\"id\"],\n  source: \"inferred\",\n  confidence: 0.75  // 缩写匹配置信度较低\n}\n\nLLM 收益：理解 employees.dept_id → departments.id\n```\n\n**常见缩写映射**：\n| 缩写 | 完整形式 |\n|-----|---------|\n| `dept` | `department` |\n| `org` | `organization` |\n| `cat` | `category` |\n| `prod` | `product` |\n| `cust` | `customer` |\n\n**置信度**：缩写匹配置信度 0.75-0.80（低于精确匹配，提示 LLM 谨慎使用）\n\n---\n\n### 8.4 实施路线图\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                    已实现（v2.9.0）✅                         │\n│  ┌─────────────────────────────────────────────────────┐   │\n│  │  按需增强工具                                        │   │\n│  │  - get_enum_values（枚举值提取）✅                   │   │\n│  │  - get_sample_data（脱敏示例数据）✅                 │   │\n│  │  实际收益：+15-25%                                   │   │\n│  └─────────────────────────────────────────────────────┘   │\n├─────────────────────────────────────────────────────────────┤\n│                    P2 优先级（后续版本）                      │\n│  ┌─────────────────────────────────────────────────────┐   │\n│  │  高级功能                                            │   │\n│  │  - get_column_stats（列统计信息）                    │   │\n│  │  - get_business_glossary（业务术语映射）             │   │\n│  │  - 隐式关系推断增强（后缀匹配、缩写识别）             │   │\n│  │  预期收益：+10-20%                                   │   │\n│  └─────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### 8.5 不采纳的方案\n\n以下方案经评估后决定不实施：\n\n| 方案 | 不采纳理由 |\n|-----|----------|\n| 业务领域标签 `businessDomain` | 无法自动获取，需人工为每个表配置，维护成本高 |\n| 语义类型 `semanticType` | 通过列名推断准确性有限，LLM 本身具备推断能力 |\n| 查询模板 `QueryTemplate` | LLM 本身具备 SQL 生成能力，模板需人工维护 |\n| JOIN 提示 `JoinHint` | 有了关系信息后 LLM 可自行推断 JOIN 条件 |\n| 分区键 `partitionKey` | 过于技术细节，对 Text2SQL 准确性帮助有限 |\n\n---\n\n## 附录：关键代码位置\n\n| 功能 | 文件路径 |\n|-----|---------|\n| 类型定义 | `src/types/adapter.ts` |\n| Schema 增强 | `src/utils/schema-enhancer.ts` |\n| 数据脱敏 | `src/utils/data-masking.ts` |\n| 数据库服务 | `src/core/database-service.ts` |\n| MCP 服务器 | `src/mcp/mcp-server.ts` |\n| HTTP 路由 | `src/http/routes/schema.ts` |\n| MySQL 适配器 | `src/adapters/mysql.ts` |\n| PostgreSQL 适配器 | `src/adapters/postgres.ts` |\n| Oracle 适配器 | `src/adapters/oracle.ts` |\n| 其他适配器 | `src/adapters/*.ts` |\n\n---\n\n*文档版本：v2.9.0*\n*最后更新：2026-02-07*\n"
  },
  {
    "path": "docs/done/dynamic-connection-in-mcp-mode.md",
    "content": "# MCP stdio 模式动态数据库连接 — 已完成\n\n## 问题描述\n\nMCP stdio 模式下，数据库连接参数必须在 `claude_desktop_config.json` 中写死（`--type` 为必填项）。用户每次切换数据库都要改配置、重启服务，无法在对话中动态连接。\n\n**Issue**: \"数据库的连接方式能否通过自然语言指定而不是在配置 MCP 时写死\"\n\n## 问题根因\n\n1. `src/mcp/mcp-index.ts` — `--type` 是 `requiredOption`，不传就无法启动\n2. `src/mcp/mcp-server.ts` — 没有动态连接/断开/状态查询的 MCP tool\n\n## 解决方案\n\n### 改动文件\n\n| 文件 | 改动 |\n|------|------|\n| `src/mcp/mcp-server.ts` | 新增 3 个 tool，构造函数支持无 config 启动 |\n| `src/mcp/mcp-index.ts` | `--type` 改为可选，支持无参启动 |\n\n### 新增 3 个 MCP Tool\n\n| Tool | 说明 |\n|------|------|\n| `connect_database` | 动态连接数据库，支持全部 17 种类型。已有连接时自动断开旧连接 |\n| `disconnect_database` | 断开当前连接 |\n| `get_connection_status` | 查看当前连接状态（类型、地址、权限模式、缓存状态） |\n\n### 关键设计\n\n- 构造函数 `config` 参数改为可选，`config` 类型改为 `DbConfig | null`\n- `start()` 方法条件执行：有 adapter 则连接，无则以无连接模式启动\n- 连接管理 tool（connect/disconnect/status）不检查数据库连接状态\n- 数据操作 tool（execute_query 等）在未连接时返回引导信息：\"请先使用 connect_database 工具连接数据库\"\n- `connect_database` 内部复用已有的 `createAdapter()` 工厂函数，17 种适配器全部自动支持\n\n## 兼容性\n\n### 向后兼容\n\n| 场景 | 改动前 | 改动后 |\n|------|-------|-------|\n| `--type mysql --host ...` 启动 | 正常 | 行为完全一致 |\n| 不传 `--type` 启动 | 报错退出 | 无连接模式启动 |\n| HTTP / SSE / Streamable 模式 | 正常 | 不受影响 |\n\n### 17 种适配器\n\n全部通过 `createAdapter()` 统一创建，`connect_database` 自动支持：mysql、postgres、redis、oracle、dm、sqlserver、mongodb、sqlite、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb。\n\n### 4 种传输模式\n\n| 传输模式 | 动态连接方式 |\n|---------|------------|\n| stdio（MCP） | `connect_database` tool（本次新增） |\n| REST API（HTTP） | `POST /api/connect`（不受影响） |\n| SSE | URL query 参数（不受影响） |\n| Streamable HTTP | `X-DB-*` 请求头（不受影响） |\n\n## 使用方式\n\n### 零配置启动\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\"universal-db-mcp\"]\n    }\n  }\n}\n```\n\n对话中说\"帮我连接 192.168.1.100 的 MySQL\"，AI 自动调用 `connect_database`。\n\n### 带默认连接启动（向后兼容）\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\"universal-db-mcp\", \"--type\", \"mysql\", \"--host\", \"localhost\", \"--port\", \"3306\", \"--user\", \"root\", \"--password\", \"xxx\", \"--database\", \"mydb\"]\n    }\n  }\n}\n```\n\n## 测试结果\n\n- TypeScript 编译：通过\n- 单元测试：88/88 通过，零回归\n- MCP 协议集成测试（11 项）：全部通过\n  - 无参启动 → 无连接模式正常\n  - 有参启动 → 向后兼容正常\n  - tool 列表 → 9 个（原 6 + 新增 3）\n  - connect_database → 连接成功\n  - get_connection_status → 状态正确\n  - execute_query → 查询正常\n  - get_schema → 结构正确\n  - disconnect_database → 断开成功\n  - 断开后查询 → 正确拒绝并引导\n  - 重新连接 → 切换成功\n  - 重连后查询 → 正常\n"
  },
  {
    "path": "docs/done/fix-stdio-graceful-shutdown.md",
    "content": "# Fix: stdio MCP Server 进程优雅退出（已完成）\n\n> 完成日期: 2026-03-17\n> 关联 Issue: stdio MCP server does not exit cleanly when Codex CLI session closes\n\n---\n\n## 问题概述\n\n当 `universal-db-mcp` 作为 stdio MCP server 被 Codex CLI 调用时，执行 `/exit` 后进程挂起，终端提示符不返回，必须手动 `Ctrl+C`。\n\n## 根因\n\n1. `src/mcp/mcp-index.ts` 只监听了 `SIGINT`/`SIGTERM`，未监听 `process.stdin` 的 `end`/`close` 事件\n2. `src/mcp/mcp-server.ts` 的 `stop()` 方法未调用 `this.server.close()`，transport 层资源（stdin/stdout 监听器）未释放\n3. 数据库连接池（keepAlive）保持活跃 handle，阻止 Node.js 事件循环退出\n\n## 修改内容\n\n### 文件 1: `src/mcp/mcp-server.ts`\n\n**`stop()` 方法** — 新增 `this.server.close()` 调用：\n\n```typescript\nasync stop(): Promise<void> {\n  // 1. 关闭 MCP Server（释放 transport 层资源）\n  try {\n    await this.server.close();\n  } catch (err) {\n    console.error('关闭 MCP Server 时出错:', err instanceof Error ? err.message : String(err));\n  }\n\n  // 2. 清理 Schema 缓存\n  if (this.databaseService) {\n    this.databaseService.clearSchemaCache();\n  }\n\n  // 3. 断开数据库连接\n  if (this.adapter) {\n    await this.adapter.disconnect();\n    console.error('👋 数据库连接已关闭');\n  }\n}\n```\n\n### 文件 2: `src/mcp/mcp-index.ts`\n\n**shutdown 逻辑** — 统一 gracefulShutdown + stdin 监听 + 超时保护 + 重入防护：\n\n```typescript\nlet shuttingDown = false;\n\nasync function gracefulShutdown(reason: string): Promise<void> {\n  if (shuttingDown) return;\n  shuttingDown = true;\n\n  console.error(`\\n⏹️  正在关闭服务器 (${reason})...`);\n\n  try {\n    await Promise.race([\n      server.stop(),\n      new Promise<void>((resolve) => setTimeout(() => {\n        console.error('⚠️  关闭超时，强制退出');\n        resolve();\n      }, 5000)),\n    ]);\n  } catch (err) {\n    console.error('关闭过程中出错:', err instanceof Error ? err.message : String(err));\n  } finally {\n    process.exit(0);\n  }\n}\n\n// 信号处理\nprocess.on('SIGINT', () => gracefulShutdown('SIGINT'));\nprocess.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n\n// stdin 关闭处理（核心修复）\nprocess.stdin.resume();\nprocess.stdin.on('end', () => gracefulShutdown('stdin-end'));\nprocess.stdin.on('close', () => gracefulShutdown('stdin-close'));\n```\n\n## 影响范围\n\n| 传输模式 | 影响 |\n|----------|------|\n| stdio | 直接修复：新增 stdin 监听 + 完善 stop() |\n| SSE | 间接受益：cleanupSession() → stop() 现在正确调用 server.close() |\n| Streamable HTTP | 间接受益：同上 |\n| REST API | 无影响：有独立的 shutdown 逻辑 |\n\n17 种数据库适配器零改动，问题在传输层和进程生命周期管理层，不在适配器层。\n\n## 验证结果\n\n- 编译通过：`npm run build` 无错误\n- 单元测试：95 通过（1 个 CORS 测试为历史遗留问题，与本次修改无关）\n- MCP 模式测试：2/2 通过\n- 编译产物验证：`dist/mcp/mcp-index.js` 和 `dist/mcp/mcp-server.js` 中均包含预期的修改代码\n"
  },
  {
    "path": "docs/done/multi-schema-support.md",
    "content": "# 多 Schema 支持完成报告\n\n## 问题描述\n\nGitHub Issue: **PostgreSQL 数据库中 get_table_info 无法获取非 public schema 的表信息**\n\n在使用 `get_table_info` 等工具时，只能获取默认 Schema（如 PostgreSQL 的 `public`、SQL Server 的 `dbo`、Oracle/达梦 的当前用户）下的表信息，非默认 Schema 的表被完全忽略。\n\n## 影响范围\n\n### 受影响的适配器（8 个）\n\n| 适配器 | 默认 Schema | 原始问题 |\n|--------|------------|---------|\n| PostgreSQL | `public` | 硬编码 `table_schema = 'public'` |\n| GaussDB | `public` | 同 PostgreSQL |\n| KingbaseES | `public` | 同 PostgreSQL |\n| Vastbase | `public` | 同 PostgreSQL |\n| HighGo | `public` | 同 PostgreSQL |\n| SQL Server | `dbo` | 硬编码 `SCHEMA_NAME() = 'dbo'` 或 `SCHEMA_ID('dbo')` |\n| Oracle | 当前用户 | 硬编码 `OWNER = USER`，使用 `USER_*` 视图 |\n| DM（达梦） | 当前用户 | 硬编码 `OWNER = USER`，使用 `USER_*` 视图 |\n\n### 不受影响的适配器（9 个）\n\nMySQL、TiDB、OceanBase、PolarDB、GoldenDB、ClickHouse、SQLite、MongoDB、Redis — 这些数据库无 Schema 概念或已正确支持。\n\n### 影响的架构层级（4 层）\n\n1. **适配器 SQL 查询层** — 8 个适配器的 `getSchema()` SQL 查询\n2. **类型定义层** — `TableInfo` 接口需要 `schema` 字段\n3. **核心服务层** — `DatabaseService.getTableInfo()` 的表名匹配逻辑\n4. **工具描述层** — MCP 工具和 HTTP API 的参数说明\n\n## 修改内容\n\n### 1. 类型定义 (`src/types/adapter.ts`)\n\n- `TableInfo` 接口已有 `schema?: string` 字段，无需修改\n\n### 2. PostgreSQL 系适配器（5 个文件）\n\n**修改文件**: `src/adapters/postgres.ts`, `gaussdb.ts`, `kingbase.ts`, `vastbase.ts`, `highgo.ts`\n\n- 所有 SQL 查询移除 `table_schema = 'public'` 硬编码\n- 改为排除系统 Schema: `NOT IN ('pg_catalog', 'information_schema', 'pg_toast')`\n- 所有 SELECT 添加 `table_schema` / `schema_name` 列\n- 新增 `makeTableKey()` 方法: `public` Schema 表名不加前缀，其他 Schema 表名格式为 `schema.table_name`\n- `assembleSchema()` 使用 schema-qualified key 组装数据\n- 新增 `schemaByTable` Map 追踪表所属 Schema\n- 外键查询添加 `pg_namespace rn` JOIN 获取引用表的 Schema\n\n### 3. SQL Server 适配器 (`src/adapters/sqlserver.ts`)\n\n- 移除 `SCHEMA_NAME() = 'dbo'` 和 `SCHEMA_ID('dbo')` 硬编码\n- 改为排除系统 Schema: `NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')`\n- 所有查询添加 Schema 信息列\n- 新增 `makeTableKey()` 方法: `dbo` Schema 表名不加前缀\n- 外键查询同时获取源表和引用表的 Schema\n\n### 4. Oracle 适配器 (`src/adapters/oracle.ts`)\n\n- 移除 `OWNER = USER` 硬编码\n- 改为排除 20 个系统用户: `NOT IN ('SYS', 'SYSTEM', 'DBSNMP', ...)`\n- 所有 `ALL_*` 视图查询添加 OWNER 列\n- `makeTableKey()` 使用 `SELECT USER FROM DUAL` 获取当前用户作为默认 Schema 判断依据\n\n### 5. DM（达梦）适配器 (`src/adapters/dm.ts`)\n\n- `USER_*` 视图改为 `ALL_*` 视图\n- 排除 6 个系统用户: `NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')`\n- 所有查询结果的 `getValueByIndex()` 索引偏移 +1（因添加了 OWNER 列）\n- `makeTableKey()` 使用 `toUpperCase()` 比较确保大小写不敏感\n\n### 6. 核心服务层 (`src/core/database-service.ts`)\n\n- `getTableInfo()` 实现 3 级表名匹配:\n  1. 精确匹配 `name` 字段（含大小写不敏感）\n  2. 拆分 `schema.table` 格式，分别匹配 `schema` 和 `name`\n  3. 仅匹配表名部分（不含 Schema 前缀），若唯一则返回\n- `quoteIdentifier()` 拆分为两个方法，支持 `schema.table` 格式自动拆分并分别引用\n- `quoteSimpleIdentifier()` 根据数据库类型选择引号样式\n\n### 7. MCP 工具描述 (`src/mcp/mcp-server.ts`)\n\n- `get_schema`: 描述中添加\"所有 Schema\"说明\n- `get_table_info`: `tableName` 参数说明添加 `schema.table_name` 格式支持\n- `get_enum_values`: 同上\n- `get_sample_data`: 同上\n\n### 8. HTTP API 路由 (`src/http/routes/schema.ts`)\n\n- `/api/enum-values`: `tableName` 参数描述添加 Schema 格式说明\n- `/api/sample-data`: 同上\n\n## 向后兼容性\n\n- **默认 Schema 表名不变**: `public` / `dbo` / 当前用户下的表仍使用纯表名（如 `users`），不加 Schema 前缀\n- **非默认 Schema 使用限定名**: 格式为 `schema.table_name`（如 `analytics.events`）\n- **旧的查询方式完全兼容**: 不带 Schema 前缀的表名查询行为不变\n- **新增 Schema 前缀查询**: 支持 `analytics.events` 格式精确定位非默认 Schema 的表\n\n## 测试结果\n\n- **TypeScript 编译**: 零错误通过\n- **单元/集成测试**: 95/96 通过\n  - 1 个失败为 **预存在的** CORS 测试（`tests/integration/http-api.test.ts:136`），与本次修改无关\n\n## 设计决策\n\n1. **排除法 vs 白名单**: 使用排除系统 Schema（`NOT IN (...)`）而非白名单，确保用户自定义 Schema 自动被发现\n2. **默认 Schema 不加前缀**: 保持向后兼容，`public.users` → `users`，`analytics.events` → `analytics.events`\n3. **3 级表名匹配**: 精确匹配 → Schema 拆分匹配 → 基础名唯一匹配，兼顾精确性和易用性\n4. **标识符引用拆分**: `quoteIdentifier()` 自动处理 `schema.table` 格式，避免将完整名称当作单个标识符引用\n"
  },
  {
    "path": "docs/getting-started/configuration.md",
    "content": "# 配置说明\n\n本文档详细介绍 Universal DB MCP 的所有配置选项。\n\n## 命令行参数\n\n```bash\nuniversal-db-mcp [选项]\n\n选项：\n  --type <db>              数据库类型（可选，不指定则以无连接模式启动，可在对话中通过 connect_database 动态连接）\n  --host <host>            数据库主机地址（默认: localhost）\n  --port <port>            数据库端口\n  --user <user>            用户名\n  --password <password>    密码\n  --database <database>    数据库名称\n  --file <file>            SQLite 数据库文件路径\n  --auth-source <db>       MongoDB 认证数据库（默认: admin）\n  --permission-mode <mode> 权限模式: safe | readwrite | full\n  --permissions <list>     自定义权限列表，逗号分隔: read,insert,update,delete,ddl\n  --danger-allow-write     启用完全写入模式（等价于 --permission-mode full）\n  --help                   显示帮助信息\n  --version                显示版本号\n```\n\n### 权限模式参数\n\n| 模式 | 允许的操作 | 说明 |\n|------|-----------|------|\n| `safe`（默认） | SELECT | 只读，最安全 |\n| `readwrite` | SELECT, INSERT, UPDATE | 读写但不能删除 |\n| `full` | 所有操作 | 完全控制（危险！） |\n\n**权限类型：**\n- `read` - SELECT 查询（始终包含）\n- `insert` - INSERT, REPLACE\n- `update` - UPDATE\n- `delete` - DELETE, TRUNCATE\n- `ddl` - CREATE, ALTER, DROP, RENAME\n\n### 不同传输方式的权限配置\n\n> ⚠️ **重要提示**：不同传输方式的参数命名风格不同，请注意区分！\n\n| 传输方式 | 参数位置 | 权限模式参数 | 自定义权限参数 |\n|---------|---------|-------------|---------------|\n| **STDIO** (Claude Desktop) | 命令行 | `--permission-mode` | `--permissions` |\n| **SSE** (Dify 等) | URL Query | `permissionMode` | `permissions` |\n| **Streamable HTTP** | HTTP Header | `X-DB-Permission-Mode` | `X-DB-Permissions` |\n| **REST API** | JSON Body | `permissionMode` | `permissions` |\n\n**命名规则：**\n- 命令行参数：使用连字符 `--permission-mode`（CLI 惯例）\n- HTTP Header：使用连字符 `X-DB-Permission-Mode`（HTTP 惯例）\n- URL Query / JSON Body：使用驼峰 `permissionMode`（JavaScript 惯例）\n\n### 数据库类型参数\n\n| 数据库 | --type 值 | 别名 |\n|--------|-----------|------|\n| MySQL | `mysql` | - |\n| PostgreSQL | `postgres` | `postgresql` |\n| Redis | `redis` | - |\n| Oracle | `oracle` | - |\n| SQL Server | `sqlserver` | `mssql` |\n| MongoDB | `mongodb` | `mongo` |\n| SQLite | `sqlite` | - |\n| 达梦 | `dm` | `dameng` |\n| KingbaseES | `kingbase` | - |\n| GaussDB | `gaussdb` | `opengauss` |\n| OceanBase | `oceanbase` | - |\n| TiDB | `tidb` | - |\n| ClickHouse | `clickhouse` | - |\n| PolarDB | `polardb` | - |\n| Vastbase | `vastbase` | - |\n| HighGo | `highgo` | - |\n| GoldenDB | `goldendb` | - |\n\n## 环境变量\n\nHTTP API 模式支持通过环境变量配置：\n\n### 服务器配置\n\n```bash\n# 运行模式\nMODE=http                    # mcp 或 http\n\n# HTTP 服务器\nHTTP_PORT=3000               # 监听端口\nHTTP_HOST=0.0.0.0            # 监听地址\n```\n\n### 安全配置\n\n```bash\n# API 密钥（多个用逗号分隔）\nAPI_KEYS=key1,key2,key3\n\n# CORS 配置\nCORS_ORIGINS=*               # 允许的来源\nCORS_CREDENTIALS=false       # 是否允许凭证\n\n# 速率限制\nRATE_LIMIT_MAX=100           # 最大请求数\nRATE_LIMIT_WINDOW=1m         # 时间窗口\n```\n\n### 数据库配置\n\n```bash\n# 默认数据库连接（可选）\nDB_TYPE=mysql\nDB_HOST=localhost\nDB_PORT=3306\nDB_USER=root\nDB_PASSWORD=password\nDB_DATABASE=mydb\n```\n\n### 会话配置\n\n```bash\nSESSION_TIMEOUT=3600000      # 会话超时（毫秒）\nSESSION_CLEANUP_INTERVAL=300000  # 清理间隔\n```\n\n### 日志配置\n\n```bash\nLOG_LEVEL=info               # debug, info, warn, error\nLOG_PRETTY=false             # 是否美化输出\n```\n\n## 配置文件\n\n### .env 文件示例\n\n```bash\n# 服务器模式\nMODE=http\n\n# HTTP 配置\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\n\n# 安全配置\nAPI_KEYS=your-secret-key-here\nCORS_ORIGINS=https://your-domain.com\nCORS_CREDENTIALS=false\n\n# 速率限制\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\n\n# 日志\nLOG_LEVEL=info\nLOG_PRETTY=false\n\n# 会话\nSESSION_TIMEOUT=3600000\nSESSION_CLEANUP_INTERVAL=300000\n```\n\n### config/default.json\n\n```json\n{\n  \"server\": {\n    \"mode\": \"mcp\",\n    \"http\": {\n      \"port\": 3000,\n      \"host\": \"0.0.0.0\"\n    }\n  },\n  \"security\": {\n    \"rateLimit\": {\n      \"max\": 100,\n      \"window\": \"1m\"\n    }\n  },\n  \"session\": {\n    \"timeout\": 3600000,\n    \"cleanupInterval\": 300000\n  }\n}\n```\n\n## Claude Desktop 配置\n\n### 配置文件位置\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n### 单数据库配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"warehouse\"\n      ]\n    },\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"cache.example.com\",\n        \"--port\", \"6379\",\n        \"--password\", \"cache_password\"\n      ]\n    }\n  }\n}\n```\n\n### 启用读写模式（不能删除）\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permission-mode\", \"readwrite\"\n      ]\n    }\n  }\n}\n```\n\n### 启用完全写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 自定义权限\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permissions\", \"read,insert,update\"\n      ]\n    }\n  }\n}\n```\n\n## Cherry Studio 配置\n\nCherry Studio 也支持 MCP 协议，配置命令示例：\n\n```bash\nnpx universal-db-mcp@latest --type mysql --host localhost --port 3306 --user root --password your_password --database your_database\n```\n\n## 配置优先级\n\n配置加载优先级（从高到低）：\n\n1. 命令行参数\n2. 环境变量\n3. .env 文件\n4. config/default.json\n5. 默认值\n\n## 下一步\n\n- [使用示例](./examples.md) - 各数据库使用示例\n- [安全指南](../guides/security.md) - 安全最佳实践\n- [部署指南](../deployment/README.md) - 生产环境部署\n"
  },
  {
    "path": "docs/getting-started/examples.md",
    "content": "# 使用示例\n\n本文档提供 MCP 数据库万能连接器的详细使用示例。\n\n## 📋 目录\n\n- [MySQL 使用示例](#mysql-使用示例)\n- [PostgreSQL 使用示例](#postgresql-使用示例)\n- [Redis 使用示例](#redis-使用示例)\n- [Oracle 使用示例](#oracle-使用示例)\n- [达梦 使用示例](#达梦-使用示例)\n- [SQL Server 使用示例](#sql-server-使用示例)\n- [MongoDB 使用示例](#mongodb-使用示例)\n- [SQLite 使用示例](#sqlite-使用示例)\n- [KingbaseES 使用示例](#kingbasees-使用示例)\n- [GaussDB / OpenGauss 使用示例](#gaussdb--opengauss-使用示例)\n- [OceanBase 使用示例](#oceanbase-使用示例)\n- [TiDB 使用示例](#tidb-使用示例)\n- [ClickHouse 使用示例](#clickhouse-使用示例)\n- [PolarDB 使用示例](#polardb-使用示例)\n- [Vastbase 使用示例](#vastbase-使用示例)\n- [HighGo 使用示例](#highgo-使用示例)\n- [GoldenDB 使用示例](#goldendb-使用示例)\n- [Claude Desktop 配置示例](#claude-desktop-配置示例)\n- [常见使用场景](#常见使用场景)\n\n---\n\n## MySQL 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"myapp_db\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式（谨慎使用）\n\n**读写模式（不能删除）：**\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permission-mode\", \"readwrite\"\n      ]\n    }\n  }\n}\n```\n\n**完全控制模式（危险！）：**\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"dev_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 帮我查看 users 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 返回表的列信息、主键、索引等\n\n**用户**: 统计最近 7 天注册的用户数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT COUNT(*) FROM users WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)`\n3. 调用 `execute_query` 工具执行\n4. 返回结果\n\n---\n\n## PostgreSQL 使用示例\n\n### 基础配置\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### 连接远程数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 找出订单金额最高的 10 个客户\n\n**Claude 会自动**:\n1. 调用 `get_schema` 了解表结构\n2. 生成复杂的 JOIN 查询\n3. 执行并返回结果\n\n---\n\n## Redis 使用示例\n\n### 基础配置（无密码）\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\"\n      ]\n    }\n  }\n}\n```\n\n### 带密码和数据库选择\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-session\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"redis_password\",\n        \"--database\", \"1\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看所有以 \"user:\" 开头的键\n\n**Claude 会执行**: `KEYS user:*`\n\n**用户**: 获取 user:1001 的信息\n\n**Claude 会执行**: `GET user:1001` 或 `HGETALL user:1001`（根据数据类型）\n\n---\n\n## Oracle 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"XEPDB1\"\n      ]\n    }\n  }\n}\n```\n\n### 使用 Service Name 连接\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"oracle-server.example.com\",\n        \"--port\", \"1521\",\n        \"--user\", \"app_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式（谨慎使用）\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"DEVDB\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 帮我查看 EMPLOYEES 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 返回表的列信息、主键、索引等\n3. 注意：Oracle 表名通常为大写\n\n**用户**: 查询工资最高的 10 名员工\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT * FROM EMPLOYEES ORDER BY SALARY DESC FETCH FIRST 10 ROWS ONLY`\n3. 调用 `execute_query` 工具执行\n4. 返回结果\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n1. 查看表结构\n2. 生成 SQL: `SELECT DEPARTMENT_ID, COUNT(*) as EMP_COUNT FROM EMPLOYEES GROUP BY DEPARTMENT_ID`\n3. 执行并返回结果\n\n\n\n## 达梦 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"SYSDBA\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: 达梦数据库驱动 `dmdb` 会作为可选依赖自动安装。如果安装失败，请手动运行：\n\n```bash\nnpm install -g dmdb\n```\n\n### 连接远程达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"dm-server.example.com\",\n        \"--port\", \"5236\",\n        \"--user\", \"app_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"PRODUCTION\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中的所有表\n\n**Claude 会自动**:\n\n1. 调用 `get_schema` 工具\n2. 返回所有表的列表和基本信息\n\n**用户**: 查询部门表中的所有记录\n\n**Claude 会自动**:\n\n1. 生成 SQL: `SELECT * FROM DEPT`\n2. 执行查询并返回结果\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n\n1. 理解需求\n2. 生成 SQL: `SELECT DEPT_ID, COUNT(*) as EMP_COUNT FROM EMPLOYEES GROUP BY DEPT_ID`\n3. 执行并返回结果\n\n---\n\n## SQL Server 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"YourPassword123\",\n        \"--database\", \"master\"\n      ]\n    }\n  }\n}\n```\n\n**提示**: 也可以使用 `--type mssql` 作为别名。\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"YourPassword123\",\n        \"--database\", \"MyDatabase\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 Azure SQL Database\n\n```json\n{\n  \"mcpServers\": {\n    \"azure-sql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"myserver.database.windows.net\",\n        \"--port\", \"1433\",\n        \"--user\", \"myadmin\",\n        \"--password\", \"MyPassword123!\",\n        \"--database\", \"mydatabase\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: 连接 Azure SQL Database 时会自动启用加密连接。\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n\n1. 调用 `get_schema` 工具\n2. 执行查询: `SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'`\n3. 返回表列表\n\n**用户**: 查看 Users 表的结构\n\n**Claude 会自动**:\n\n1. 调用 `get_table_info` 工具\n2. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n\n1. 理解需求\n2. 生成 SQL: `SELECT DepartmentID, COUNT(*) as EmployeeCount FROM Employees GROUP BY DepartmentID ORDER BY EmployeeCount DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近一周创建的订单\n\n**Claude 会自动**:\n\n1. 生成 SQL: `SELECT * FROM Orders WHERE CreatedDate >= DATEADD(day, -7, GETDATE()) ORDER BY CreatedDate DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: SQL Server 默认端口为 1433\n2. **身份验证**: 支持 SQL Server 身份验证（用户名/密码）\n3. **加密连接**: 连接 Azure SQL 时会自动启用加密，本地 SQL Server 默认不加密\n4. **数据库名**: 必须指定数据库名（如 master、tempdb 或自定义数据库）\n5. **权限**: 确保用户有足够的权限访问系统视图（INFORMATION_SCHEMA）\n6. **参数化查询**: 支持 `?` 占位符,会自动转换为 SQL Server 的 `@param0` 语法\n\n---\n\n## MongoDB 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"myapp\",\n        \"--auth-source\", \"admin\"  \n      ]\n    }\n  }\n}\n```\n\n### 无认证连接（开发环境）\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"dev_user\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 MongoDB Atlas\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-atlas\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"cluster0.xxxxx.mongodb.net\",\n        \"--port\", \"27017\",\n        \"--user\", \"myuser\",\n        \"--password\", \"mypassword\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 查询格式\n\nMongoDB 适配器支持两种查询格式：\n\n#### 1. JSON 格式（推荐）\n\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"find\",\n  \"query\": {\"age\": {\"$gt\": 18}},\n  \"options\": {\"limit\": 10}\n}\n```\n\n#### 2. 简化格式\n\n```javascript\ndb.users.find({\"age\": {\"$gt\": 18}})\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些集合？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 返回所有集合的列表和基本信息\n3. 显示每个集合的文档数量和推断的字段结构\n\n**用户**: 查询 users 集合中年龄大于 18 的用户\n\n**Claude 会自动**:\n1. 生成查询: `{\"collection\": \"users\", \"operation\": \"find\", \"query\": {\"age\": {\"$gt\": 18}}}`\n2. 执行并返回结果\n\n**用户**: 统计每个城市的用户数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成聚合查询:\n```json\n{\n  \"collection\": \"users\",\n  \"operation\": \"aggregate\",\n  \"pipeline\": [\n    {\"$group\": {\"_id\": \"$city\", \"count\": {\"$sum\": 1}}},\n    {\"$sort\": {\"count\": -1}}\n  ]\n}\n```\n3. 执行并返回结果\n\n**用户**: 查找最近创建的 10 个订单\n\n**Claude 会自动**:\n1. 生成查询:\n```json\n{\n  \"collection\": \"orders\",\n  \"operation\": \"find\",\n  \"query\": {},\n  \"options\": {\"sort\": {\"createdAt\": -1}, \"limit\": 10}\n}\n```\n2. 执行并返回结果\n\n### 支持的操作\n\n#### 查询操作（只读模式）\n- `find` - 查询文档\n- `findOne` - 查询单个文档\n- `count` / `countDocuments` - 统计文档数量\n- `distinct` - 获取字段的不同值\n- `aggregate` - 聚合管道查询\n\n#### 写入操作（需要 --permission-mode readwrite 或 full）\n- `insert` / `insertOne` - 插入单个文档\n- `insertMany` - 插入多个文档\n- `update` / `updateOne` - 更新单个文档\n- `updateMany` - 更新多个文档\n- `delete` / `deleteOne` - 删除单个文档（需要 delete 权限）\n- `deleteMany` - 删除多个文档（需要 delete 权限）\n\n### 注意事项\n\n1. **默认端口**: MongoDB 默认端口为 27017\n2. **认证**: 支持用户名/密码认证，默认认证数据库为 admin\n3. **集合结构**: MongoDB 是无模式数据库，Schema 信息通过采样文档推断\n4. **ObjectId**: 查询结果中的 ObjectId 会自动转换为字符串\n5. **查询语法**: 使用 MongoDB 原生查询语法，不是 SQL\n6. **聚合管道**: 支持完整的聚合管道功能\n\n---\n\n## SQLite 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### Windows 路径示例\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-app\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"C:\\\\Users\\\\YourName\\\\Documents\\\\myapp.db\"\n      ]\n    }\n  }\n}\n```\n\n**注意**: Windows 路径中的反斜杠需要转义（使用 `\\\\`）。\n\n### macOS/Linux 路径示例\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-notes\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/Users/YourName/Documents/notes.db\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/dev.db\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行查询: `SELECT name FROM sqlite_master WHERE type='table'`\n3. 返回表列表\n\n**用户**: 查看 users 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 执行 `PRAGMA table_info(users)`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个分类的文章数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT category, COUNT(*) as count FROM articles GROUP BY category ORDER BY count DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近创建的 10 条记录\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM posts ORDER BY created_at DESC LIMIT 10`\n2. 执行并返回结果\n\n### 常见使用场景\n\n#### 1. 分析本地应用数据库\n\n许多桌面应用使用 SQLite 存储数据（如浏览器历史、笔记应用等）：\n\n```\n用户: 帮我分析 Chrome 浏览器的历史记录\n\nClaude 会:\n1. 连接到 Chrome 的 History 数据库文件\n2. 查询 urls 和 visits 表\n3. 生成访问统计和分析报告\n```\n\n#### 2. 开发和测试\n\nSQLite 非常适合本地开发和测试：\n\n```\n用户: 创建一个测试用户并查询\n\nClaude 会（在写入模式下）:\n1. INSERT INTO users (name, email) VALUES ('Test User', 'test@example.com')\n2. SELECT * FROM users WHERE email = 'test@example.com'\n```\n\n#### 3. 数据导出和备份\n\n```\n用户: 导出所有用户数据为 JSON 格式\n\nClaude 会:\n1. SELECT * FROM users\n2. 将结果格式化为 JSON\n3. 提供下载或复制\n```\n\n### 注意事项\n\n1. **文件路径**: 必须使用绝对路径，不支持相对路径\n2. **文件权限**: 确保 Claude Desktop 有权限读取/写入数据库文件\n3. **并发访问**: SQLite 支持多读单写，注意并发访问限制\n4. **数据库锁**: 如果数据库被其他程序占用，可能会遇到锁定错误\n5. **自动创建**: 如果指定的文件不存在，会自动创建新数据库\n6. **备份建议**: 在启用写入模式前，建议先备份数据库文件\n\n### 支持的 SQLite 特性\n\n- ✅ 标准 SQL 查询（SELECT、INSERT、UPDATE、DELETE）\n- ✅ 事务支持\n- ✅ 索引和主键\n- ✅ 外键约束（需要启用）\n- ✅ PRAGMA 命令\n- ✅ 全文搜索（FTS）\n- ✅ JSON 扩展（SQLite 3.38+）\n\n### 性能提示\n\n1. **索引优化**: 为常用查询字段创建索引\n2. **批量操作**: 使用事务包装批量 INSERT/UPDATE\n3. **PRAGMA 优化**: 可以使用 PRAGMA 命令调整性能参数\n4. **VACUUM**: 定期执行 VACUUM 优化数据库文件大小\n\n---\n\n## KingbaseES 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接远程 KingbaseES\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"kingbase.example.com\",\n        \"--port\", \"54321\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行查询获取所有用户 Schema 下的表\n3. 返回表列表\n\n**用户**: 查看 users 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT department_id, COUNT(*) as count FROM employees GROUP BY department_id ORDER BY count DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近一周创建的订单\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '7 days' ORDER BY created_at DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: KingbaseES 默认端口为 54321\n2. **兼容性**: 基于 PostgreSQL 开发，兼容 PostgreSQL 协议和 SQL 语法\n3. **驱动**: 使用 PostgreSQL 的 `pg` 驱动\n4. **多 Schema 支持**: 自动获取所有用户 Schema 下的表，`public` Schema 的表直接使用表名，其他 Schema 使用 `schema.table_name` 格式\n5. **参数化查询**: 支持 `$1, $2, ...` 占位符\n6. **国产化**: 适用于国产化替代场景\n\n### 支持的 KingbaseES 版本\n\n- ✅ KingbaseES V8\n- ✅ KingbaseES V9\n- ✅ 其他兼容 PostgreSQL 协议的版本\n\n### 常见使用场景\n\n#### 1. 国产化数据库迁移\n\n从 PostgreSQL 迁移到 KingbaseES：\n\n```\n用户: 帮我分析现有表结构，准备迁移到 KingbaseES\n\nClaude 会:\n1. 获取完整的 Schema 信息\n2. 分析表结构、索引、约束\n3. 提供迁移建议\n```\n\n#### 2. 数据分析和报表\n\n```\n用户: 统计最近一个月的销售数据\n\nClaude 会:\n1. 理解需求\n2. 生成复杂的聚合查询\n3. 返回分析结果\n```\n\n#### 3. 开发和测试\n\n```\n用户: 在测试环境创建测试数据\n\nClaude 会（在写入模式下）:\n1. 生成 INSERT 语句\n2. 执行并验证结果\n```\n\n---\n\n## GaussDB / OpenGauss 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"gaussdb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"gaussdb\",\n        \"--password\", \"your_password\",\n        \"--database\", \"postgres\"\n      ]\n    }\n  }\n}\n```\n\n**提示**: 也可以使用 `--type opengauss` 作为别名。\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"gaussdb-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"gaussdb\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接华为云 GaussDB\n\n```json\n{\n  \"mcpServers\": {\n    \"gaussdb-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"gaussdb.cn-north-4.myhuaweicloud.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"dbuser\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行查询获取所有用户 Schema 下的表\n3. 返回表列表\n\n**用户**: 查看 products 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个类别的产品数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT category, COUNT(*) as count FROM products GROUP BY category ORDER BY count DESC`\n3. 执行并返回结果\n\n**用户**: 查找价格最高的 10 个产品\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM products ORDER BY price DESC LIMIT 10`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: GaussDB/OpenGauss 默认端口为 5432（与 PostgreSQL 相同）\n2. **兼容性**: 基于 PostgreSQL 9.2 开发，兼容 PostgreSQL 协议和大部分 SQL 语法\n3. **驱动**: 使用 PostgreSQL 的 `pg` 驱动\n4. **多 Schema 支持**: 自动获取所有用户 Schema 下的表，`public` Schema 的表直接使用表名，其他 Schema 使用 `schema.table_name` 格式\n5. **参数化查询**: 支持 `$1, $2, ...` 占位符\n6. **国产化**: 华为自研数据库，适用于国产化替代场景\n7. **开源版本**: OpenGauss 是 GaussDB 的开源版本\n\n### 支持的版本\n\n- ✅ GaussDB 100/200/300 系列\n- ✅ OpenGauss 2.x / 3.x / 5.x\n- ✅ 其他兼容 PostgreSQL 协议的版本\n\n### 常见使用场景\n\n#### 1. 华为云数据库管理\n\n连接华为云 GaussDB 进行数据查询和分析：\n\n```\n用户: 帮我分析最近一周的用户增长趋势\n\nClaude 会:\n1. 查询用户表\n2. 按日期分组统计\n3. 生成趋势分析报告\n```\n\n#### 2. 国产化数据库迁移\n\n从 PostgreSQL 迁移到 GaussDB：\n\n```\n用户: 帮我分析现有表结构，准备迁移到 GaussDB\n\nClaude 会:\n1. 获取完整的 Schema 信息\n2. 分析表结构、索引、约束\n3. 提供迁移建议和兼容性分析\n```\n\n#### 3. 性能优化\n\n```\n用户: 这个查询很慢，帮我优化\n\nClaude 会:\n1. 分析查询语句\n2. 检查索引情况\n3. 提供优化建议（添加索引、重写查询等）\n```\n\n#### 4. 数据分析和报表\n\n```\n用户: 生成本月销售报表\n\nClaude 会:\n1. 理解需求\n2. 生成复杂的聚合查询\n3. 返回格式化的分析结果\n```\n\n### GaussDB 特色功能\n\n虽然使用 PostgreSQL 协议，但 GaussDB 有一些特色功能：\n\n- **列存储**: 支持列存储表（需要特定语法）\n- **分区表**: 增强的分区表功能\n- **并行查询**: 更强的并行查询能力\n- **AI 能力**: 内置 AI 引擎（部分版本）\n\n**注意**: 这些特色功能可能需要特定的 SQL 语法，Claude 会根据标准 PostgreSQL 语法生成查询。\n\n---\n\n## OceanBase 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"root@test\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"root@test\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接阿里云 OceanBase\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"oceanbase.cn-hangzhou.aliyuncs.com\",\n        \"--port\", \"2883\",\n        \"--user\", \"dbuser@tenant\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行 `SHOW TABLES` 查询\n3. 返回表列表\n\n**用户**: 查看 orders 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 执行 `SHOW FULL COLUMNS FROM orders`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个用户的订单数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id ORDER BY order_count DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近一天的订单\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY created_at DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**:\n   - 直连端口：2881（直接连接 OBServer）\n   - 代理端口：2883（通过 OBProxy 连接）\n2. **兼容性**: 兼容 MySQL 5.6/5.7 协议和大部分 SQL 语法\n3. **驱动**: 使用 MySQL 的 `mysql2` 驱动\n4. **用户名格式**: `用户名@租户名`（如 `root@test`、`user@sys`）\n5. **租户**: OceanBase 支持多租户，需要指定租户名\n6. **分布式**: OceanBase 是分布式数据库，支持水平扩展\n\n### 支持的版本\n\n- ✅ OceanBase 3.x\n- ✅ OceanBase 4.x\n- ✅ 其他兼容 MySQL 协议的版本\n\n### 常见使用场景\n\n#### 1. 分布式数据库管理\n\n连接 OceanBase 集群进行数据查询和分析：\n\n```\n用户: 帮我分析订单表的数据分布\n\nClaude 会:\n1. 查询订单表\n2. 统计各个维度的数据\n3. 生成分析报告\n```\n\n#### 2. 从 MySQL 迁移到 OceanBase\n\n```\n用户: 帮我分析现有 MySQL 表结构，准备迁移到 OceanBase\n\nClaude 会:\n1. 获取完整的 Schema 信息\n2. 分析表结构、索引、约束\n3. 提供迁移建议和兼容性分析\n```\n\n#### 3. 性能优化\n\n```\n用户: 这个查询在 OceanBase 上很慢，帮我优化\n\nClaude 会:\n1. 分析查询语句\n2. 检查索引情况\n3. 提供优化建议（考虑分布式特性）\n```\n\n#### 4. 多租户管理\n\n```\n用户: 查询当前租户的资源使用情况\n\nClaude 会:\n1. 生成相应的系统表查询\n2. 返回租户资源信息\n```\n\n### OceanBase 特色功能\n\n虽然兼容 MySQL 协议，但 OceanBase 有一些特色功能：\n\n- **分布式事务**: 支持跨节点的分布式事务\n- **多租户**: 支持多租户隔离\n- **高可用**: 自动故障转移和数据恢复\n- **弹性扩展**: 支持在线扩容和缩容\n- **HTAP**: 同时支持 OLTP 和 OLAP 场景\n\n**注意**: 这些特色功能可能需要特定的 SQL 语法或系统表查询,Claude 会根据标准 MySQL 语法生成查询。\n\n---\n\n## TiDB 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"tidb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"4000\",\n        \"--user\", \"root\",\n        \"--password\", \"\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"tidb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"4000\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 TiDB Cloud\n\n```json\n{\n  \"mcpServers\": {\n    \"tidb-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"tidb\",\n        \"--host\", \"gateway01.ap-southeast-1.prod.aws.tidbcloud.com\",\n        \"--port\", \"4000\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行 `SHOW TABLES` 查询\n3. 返回表列表\n\n**用户**: 查看 employees 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 执行 `SHOW FULL COLUMNS FROM employees`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT department, COUNT(*) as employee_count FROM employees GROUP BY department ORDER BY employee_count DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近一周入职的员工\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM employees WHERE hire_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY hire_date DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: 4000（TiDB Server 端口）\n2. **兼容性**: 兼容 MySQL 5.7 协议和大部分 SQL 语法\n3. **驱动**: 使用 MySQL 的 `mysql2` 驱动\n4. **分布式**: TiDB 是分布式数据库，支持水平扩展\n5. **HTAP**: 同时支持 OLTP 和 OLAP 工作负载\n6. **事务**: 支持完整的 ACID 分布式事务\n\n### 支持的版本\n\n- ✅ TiDB 5.x\n- ✅ TiDB 6.x\n- ✅ TiDB 7.x\n- ✅ TiDB 8.x\n- ✅ TiDB Cloud\n\n### 常见使用场景\n\n#### 1. 分布式数据库管理\n\n连接 TiDB 集群进行数据查询和分析：\n\n```\n用户: 帮我分析用户表的数据分布\n\nClaude 会:\n1. 查询用户表\n2. 统计各个维度的数据\n3. 生成分析报告\n```\n\n#### 2. 从 MySQL 迁移到 TiDB\n\n```\n用户: 帮我分析现有 MySQL 表结构，准备迁移到 TiDB\n\nClaude 会:\n1. 获取完整的 Schema 信息\n2. 分析表结构、索引、约束\n3. 提供迁移建议和兼容性分析\n```\n\n#### 3. 性能优化\n\n```\n用户: 这个查询在 TiDB 上很慢，帮我优化\n\nClaude 会:\n1. 分析查询语句\n2. 检查索引情况\n3. 提供优化建议（考虑分布式特性）\n```\n\n#### 4. HTAP 场景\n\n```\n用户: 对大表进行复杂的聚合分析\n\nClaude 会:\n1. 生成适合 OLAP 的查询语句\n2. 利用 TiFlash 列式存储加速查询\n3. 返回分析结果\n```\n\n### TiDB 特色功能\n\n虽然兼容 MySQL 5.7 协议，但 TiDB 有一些特色功能：\n\n- **水平扩展**: 支持在线水平扩展，无需停机\n- **分布式事务**: 支持跨节点的 ACID 事务\n- **高可用**: 自动故障转移和数据恢复\n- **HTAP**: 同时支持 OLTP 和 OLAP 场景\n- **TiFlash**: 列式存储引擎，加速 OLAP 查询\n- **弹性扩展**: 支持在线扩容和缩容\n\n**注意**: 这些特色功能可能需要特定的 SQL 语法或系统表查询，Claude 会根据标准 MySQL 语法生成查询。\n\n---\n\n## ClickHouse 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"localhost\",\n        \"--port\", \"8123\",\n        \"--user\", \"default\",\n        \"--password\", \"\",\n        \"--database\", \"default\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"localhost\",\n        \"--port\", \"8123\",\n        \"--user\", \"default\",\n        \"--password\", \"your_password\",\n        \"--database\", \"analytics\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 ClickHouse Cloud\n\n```json\n{\n  \"mcpServers\": {\n    \"clickhouse-cloud\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"clickhouse\",\n        \"--host\", \"your-instance.clickhouse.cloud\",\n        \"--port\", \"8443\",\n        \"--user\", \"default\",\n        \"--password\", \"your_password\",\n        \"--database\", \"default\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 查询 `system.tables` 系统表\n3. 返回表列表\n\n**用户**: 查看 events 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 查询 `system.columns` 获取列信息\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计最近一小时的事件数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT COUNT(*) as event_count FROM events WHERE timestamp >= now() - INTERVAL 1 HOUR`\n3. 执行并返回结果\n\n**用户**: 按用户 ID 分组统计事件数量，取前 10 名\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT user_id, COUNT(*) as event_count FROM events GROUP BY user_id ORDER BY event_count DESC LIMIT 10`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**:\n   - HTTP 端口：8123（推荐用于 MCP 连接）\n   - 原生 TCP 端口：9000\n   - HTTPS 端口：8443（ClickHouse Cloud）\n2. **默认用户**: default\n3. **默认数据库**: default\n4. **列式存储**: ClickHouse 是列式数据库，适合 OLAP 场景\n5. **高性能**: 针对大数据分析优化，查询速度极快\n6. **SQL 方言**: 使用自己的 SQL 方言，与标准 SQL 有些差异\n\n### 支持的版本\n\n- ✅ ClickHouse 21.x\n- ✅ ClickHouse 22.x\n- ✅ ClickHouse 23.x\n- ✅ ClickHouse 24.x\n- ✅ ClickHouse Cloud\n\n### 常见使用场景\n\n#### 1. 大数据分析\n\n连接 ClickHouse 进行海量数据分析：\n\n```\n用户: 分析最近 30 天的用户行为数据\n\nClaude 会:\n1. 查询事件表\n2. 按时间、用户维度聚合\n3. 生成分析报告\n```\n\n#### 2. 实时数据查询\n\n```\n用户: 查询实时的系统监控指标\n\nClaude 会:\n1. 查询最新的监控数据\n2. 计算关键指标\n3. 返回实时统计结果\n```\n\n#### 3. 日志分析\n\n```\n用户: 分析应用日志，找出错误最多的接口\n\nClaude 会:\n1. 查询日志表\n2. 按接口分组统计错误数\n3. 返回排序后的结果\n```\n\n#### 4. 时序数据分析\n\n```\n用户: 分析时序数据的趋势\n\nClaude 会:\n1. 按时间窗口聚合数据\n2. 计算趋势指标\n3. 生成时序分析报告\n```\n\n### ClickHouse 特色功能\n\nClickHouse 作为列式 OLAP 数据库，有许多特色功能：\n\n- **列式存储**: 数据按列存储，压缩率高，查询速度快\n- **向量化执行**: 利用 SIMD 指令加速查询\n- **分布式查询**: 支持分布式表和分布式查询\n- **物化视图**: 支持物化视图加速查询\n- **数据压缩**: 多种压缩算法，节省存储空间\n- **实时插入**: 支持高并发实时数据插入\n- **近似计算**: 支持近似算法加速聚合查询\n\n**注意**: ClickHouse 的 SQL 语法与标准 SQL 有一些差异，Claude 会尽量生成兼容的查询语句。\n\n### ClickHouse 最佳实践\n\n1. **表引擎选择**:\n   - 使用 MergeTree 系列引擎（推荐）\n   - 根据场景选择合适的表引擎\n\n2. **分区策略**:\n   - 按时间分区（如按天、按月）\n   - 合理设置分区键\n\n3. **排序键**:\n   - 选择查询频繁的列作为排序键\n   - 排序键顺序影响查询性能\n\n4. **数据类型**:\n   - 使用合适的数据类型节省空间\n   - 避免使用 String 类型存储数值\n\n5. **查询优化**:\n   - 使用 PREWHERE 过滤数据\n   - 避免 SELECT *\n   - 合理使用物化视图\n\n---\n\n## PolarDB 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 PolarDB 集群（读写分离）\n\n```json\n{\n  \"mcpServers\": {\n    \"polardb-primary\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    },\n    \"polardb-readonly\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"polardb\",\n        \"--host\", \"pc-xxxxx-ro.mysql.polardb.rds.aliyuncs.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"readonly_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行 `SHOW TABLES` 查询\n3. 返回表列表\n\n**用户**: 查看 orders 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 执行 `SHOW FULL COLUMNS FROM orders`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计最近 7 天的订单数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT COUNT(*) FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)`\n3. 执行并返回结果\n\n**用户**: 查询销售额最高的 10 个商品\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT product_id, SUM(amount) as total_sales FROM orders GROUP BY product_id ORDER BY total_sales DESC LIMIT 10`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: 3306（与 MySQL 相同）\n2. **兼容性**: 完全兼容 MySQL 5.6/5.7/8.0 协议\n3. **驱动**: 使用 MySQL 的 `mysql2` 驱动\n4. **读写分离**:\n   - 主地址（Primary Endpoint）：支持读写\n   - 集群地址（Cluster Endpoint）：自动读写分离\n   - 只读地址（Read-only Endpoint）：只支持读\n5. **云原生特性**:\n   - 存储与计算分离\n   - 秒级弹性扩展\n   - 多可用区部署\n\n### 支持的版本\n\n- ✅ PolarDB for MySQL 5.6\n- ✅ PolarDB for MySQL 5.7\n- ✅ PolarDB for MySQL 8.0\n- ✅ PolarDB Serverless\n\n### 常见使用场景\n\n#### 1. 云原生应用数据库\n\n连接 PolarDB 作为云原生应用的主数据库：\n\n```\n用户: 查询用户表中的所有活跃用户\n\nClaude 会:\n1. 查询用户表\n2. 过滤活跃用户\n3. 返回结果\n```\n\n#### 2. 读写分离场景\n\n```\n用户: 使用只读节点查询大量数据进行分析\n\nClaude 会:\n1. 连接到只读地址\n2. 执行复杂的分析查询\n3. 不影响主库性能\n```\n\n#### 3. 高并发场景\n\n```\n用户: 查询实时订单数据\n\nClaude 会:\n1. 利用 PolarDB 的高并发能力\n2. 快速返回查询结果\n3. 保证数据一致性\n```\n\n#### 4. 弹性扩展\n\n```\n用户: 在业务高峰期查询数据\n\nClaude 会:\n1. PolarDB 自动扩展计算资源\n2. 保证查询性能\n3. 业务低峰期自动缩容\n```\n\n### PolarDB 特色功能\n\nPolarDB 作为云原生数据库，有许多特色功能：\n\n- **存储计算分离**: 存储和计算资源独立扩展\n- **一写多读**: 支持一个主节点和多个只读节点\n- **秒级弹性**: 计算节点秒级扩展\n- **全局一致性**: 分布式事务保证数据一致性\n- **并行查询**: 支持并行查询加速\n- **热备份**: 在线备份不影响业务\n- **多可用区**: 支持多可用区部署，高可用\n\n**注意**: 这些特色功能在标准 MySQL 协议下可能需要特定的配置或 SQL 语法。\n\n### PolarDB 最佳实践\n\n1. **读写分离**:\n   - 写操作使用主地址\n   - 读操作使用只读地址或集群地址\n   - 分析查询使用只读节点\n\n2. **连接池管理**:\n   - 合理设置连接池大小\n   - 使用长连接减少连接开销\n   - 定期检查连接健康状态\n\n3. **查询优化**:\n   - 使用合适的索引\n   - 避免全表扫描\n   - 合理使用 LIMIT\n   - 利用查询缓存\n\n4. **监控告警**:\n   - 监控 CPU、内存、IOPS\n   - 设置慢查询告警\n   - 关注连接数使用情况\n   - 定期查看性能洞察\n\n5. **安全建议**:\n   - 使用 SSL 连接\n   - 设置白名单\n   - 定期更换密码\n   - 使用 RAM 账号管理权限\n\n---\n\n## Vastbase 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"vastbase\",\n        \"--password\", \"your_password\",\n        \"--database\", \"postgres\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"vastbase\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 Vastbase 集群\n\n```json\n{\n  \"mcpServers\": {\n    \"vastbase-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"vastbase\",\n        \"--host\", \"vastbase-cluster.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 查询 `information_schema.tables`\n3. 返回表列表\n\n**用户**: 查看 employees 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 查询 `information_schema.columns`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个部门的员工数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT department, COUNT(*) as employee_count FROM employees GROUP BY department ORDER BY employee_count DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近一周入职的员工\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM employees WHERE hire_date >= CURRENT_DATE - INTERVAL '7 days' ORDER BY hire_date DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: 5432（与 PostgreSQL 相同）\n2. **兼容性**: 兼容 PostgreSQL 协议和大部分 SQL 语法\n3. **驱动**: 使用 PostgreSQL 的 `pg` 驱动\n4. **国产数据库**: 海量数据公司开发，支持国产化替代\n5. **企业级特性**:\n   - 支持分布式架构\n   - 支持高可用集群\n   - 支持数据加密\n   - 支持审计日志\n\n### 支持的版本\n\n- ✅ Vastbase G100 V2.2\n- ✅ Vastbase G100 V2.3\n- ✅ 其他兼容 PostgreSQL 的版本\n\n### 常见使用场景\n\n#### 1. 国产化替代\n\n使用 Vastbase 替代 PostgreSQL 或 Oracle：\n\n```\n用户: 查询用户表中的所有数据\n\nClaude 会:\n1. 查询用户表\n2. 返回结果\n3. 完全兼容 PostgreSQL 语法\n```\n\n#### 2. 企业级应用\n\n```\n用户: 查询订单表，需要关联多个表\n\nClaude 会:\n1. 生成复杂的 JOIN 查询\n2. 利用 Vastbase 的查询优化\n3. 返回结果\n```\n\n#### 3. 数据分析\n\n```\n用户: 分析最近一个月的销售趋势\n\nClaude 会:\n1. 生成聚合查询\n2. 按日期分组统计\n3. 生成趋势分析报告\n```\n\n#### 4. 高可用场景\n\n```\n用户: 连接 Vastbase 集群进行查询\n\nClaude 会:\n1. 连接到集群地址\n2. 自动负载均衡\n3. 保证高可用性\n```\n\n### Vastbase 特色功能\n\nVastbase 作为国产数据库，有一些特色功能：\n\n- **PostgreSQL 兼容**: 兼容 PostgreSQL 协议和语法\n- **分布式架构**: 支持分布式部署和查询\n- **高可用**: 支持主备切换和故障转移\n- **数据加密**: 支持透明数据加密（TDE）\n- **审计日志**: 完善的审计日志功能\n- **国产化**: 支持国产操作系统和芯片\n\n**注意**: 这些特色功能可能需要特定的配置或 SQL 语法，Claude 会根据标准 PostgreSQL 语法生成查询。\n\n### Vastbase 最佳实践\n\n1. **表设计**:\n   - 使用合适的数据类型\n   - 合理设计主键和索引\n   - 使用分区表提升性能\n   - 避免过度规范化\n\n2. **查询优化**:\n   - 使用 EXPLAIN 分析查询计划\n   - 创建合适的索引\n   - 避免 SELECT *\n   - 使用 LIMIT 限制返回结果\n\n3. **连接管理**:\n   - 使用连接池\n   - 合理设置连接数\n   - 定期检查连接健康状态\n   - 避免长时间持有连接\n\n4. **监控维护**:\n   - 监控数据库性能指标\n   - 定期执行 VACUUM\n   - 更新统计信息\n   - 定期备份数据\n\n5. **安全建议**:\n   - 使用强密码\n   - 限制网络访问\n   - 启用 SSL 连接\n   - 定期审计日志\n\n---\n\n## HighGo 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"highgo\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5866\",\n        \"--user\", \"highgo\",\n        \"--password\", \"your_password\",\n        \"--database\", \"highgo\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"highgo\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5866\",\n        \"--user\", \"highgo\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 HighGo 集群\n\n```json\n{\n  \"mcpServers\": {\n    \"highgo-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"highgo\",\n        \"--host\", \"highgo-cluster.example.com\",\n        \"--port\", \"5866\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 查询 `information_schema.tables`\n3. 返回表列表\n\n**用户**: 查看 products 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 查询 `information_schema.columns`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个类别的商品数量\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT category, COUNT(*) as product_count FROM products GROUP BY category ORDER BY product_count DESC`\n3. 执行并返回结果\n\n**用户**: 查找价格超过 1000 元的商品\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM products WHERE price > 1000 ORDER BY price DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: 5866（HighGo 默认端口）\n2. **兼容性**: 兼容 PostgreSQL 协议和大部分 SQL 语法\n3. **驱动**: 使用 PostgreSQL 的 `pg` 驱动\n4. **国产数据库**: 瀚高公司开发，支持国产化替代\n5. **企业级特性**:\n   - 支持高可用集群\n   - 支持数据加密\n   - 支持审计日志\n   - 支持备份恢复\n\n### 支持的版本\n\n- ✅ HighGo DB 4.x\n- ✅ HighGo DB 5.x\n- ✅ HighGo DB 6.x\n- ✅ 其他兼容 PostgreSQL 的版本\n\n### 常见使用场景\n\n#### 1. 国产化替代\n\n使用 HighGo 替代 PostgreSQL 或 Oracle：\n\n```\n用户: 查询订单表中的所有数据\n\nClaude 会:\n1. 查询订单表\n2. 返回结果\n3. 完全兼容 PostgreSQL 语法\n```\n\n#### 2. 企业级应用\n\n```\n用户: 查询销售数据，需要关联多个表\n\nClaude 会:\n1. 生成复杂的 JOIN 查询\n2. 利用 HighGo 的查询优化\n3. 返回结果\n```\n\n#### 3. 数据分析\n\n```\n用户: 分析最近一季度的销售趋势\n\nClaude 会:\n1. 生成聚合查询\n2. 按时间分组统计\n3. 生成趋势分析报告\n```\n\n#### 4. 高可用场景\n\n```\n用户: 连接 HighGo 集群进行查询\n\nClaude 会:\n1. 连接到集群地址\n2. 自动负载均衡\n3. 保证高可用性\n```\n\n### HighGo 特色功能\n\nHighGo 作为国产数据库，有一些特色功能：\n\n- **PostgreSQL 兼容**: 兼容 PostgreSQL 9.x/10.x/11.x 协议和语法\n- **高可用**: 支持主备切换和故障转移\n- **数据加密**: 支持透明数据加密（TDE）\n- **审计日志**: 完善的审计日志功能\n- **国产化**: 支持国产操作系统和芯片\n- **Oracle 兼容**: 部分版本支持 Oracle 兼容模式\n\n**注意**: 这些特色功能可能需要特定的配置或 SQL 语法，Claude 会根据标准 PostgreSQL 语法生成查询。\n\n### HighGo 最佳实践\n\n1. **表设计**:\n   - 使用合适的数据类型\n   - 合理设计主键和索引\n   - 使用分区表提升性能\n   - 避免过度规范化\n\n2. **查询优化**:\n   - 使用 EXPLAIN 分析查询计划\n   - 创建合适的索引\n   - 避免 SELECT *\n   - 使用 LIMIT 限制返回结果\n\n3. **连接管理**:\n   - 使用连接池\n   - 合理设置连接数\n   - 定期检查连接健康状态\n   - 避免长时间持有连接\n\n4. **监控维护**:\n   - 监控数据库性能指标\n   - 定期执行 VACUUM\n   - 更新统计信息\n   - 定期备份数据\n\n5. **安全建议**:\n   - 使用强密码\n   - 限制网络访问\n   - 启用 SSL 连接\n   - 定期审计日志\n\n---\n\n## GoldenDB 使用示例\n\n### 基础配置（只读模式）\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写入模式\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-write\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n### 连接 GoldenDB 分布式集群\n\n```json\n{\n  \"mcpServers\": {\n    \"goldendb-cluster\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"goldendb\",\n        \"--host\", \"goldendb-cluster.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"your_username\",\n        \"--password\", \"your_password\",\n        \"--database\", \"production\"\n      ]\n    }\n  }\n}\n```\n\n### 与 Claude 对话示例\n\n**用户**: 查看数据库中有哪些表？\n\n**Claude 会自动**:\n1. 调用 `get_schema` 工具\n2. 执行 `SHOW TABLES` 查询\n3. 返回表列表\n\n**用户**: 查看 transactions 表的结构\n\n**Claude 会自动**:\n1. 调用 `get_table_info` 工具\n2. 执行 `SHOW FULL COLUMNS FROM transactions`\n3. 返回列信息、主键、索引等详细信息\n\n**用户**: 统计每个用户的交易总额\n\n**Claude 会自动**:\n1. 理解需求\n2. 生成 SQL: `SELECT user_id, SUM(amount) as total_amount FROM transactions GROUP BY user_id ORDER BY total_amount DESC`\n3. 执行并返回结果\n\n**用户**: 查找最近 24 小时的大额交易（金额超过 10000）\n\n**Claude 会自动**:\n1. 生成 SQL: `SELECT * FROM transactions WHERE amount > 10000 AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR) ORDER BY amount DESC`\n2. 执行并返回结果\n\n### 注意事项\n\n1. **默认端口**: 3306（与 MySQL 相同）\n2. **兼容性**: 完全兼容 MySQL 5.7/8.0 协议\n3. **驱动**: 使用 MySQL 的 `mysql2` 驱动\n4. **国产数据库**: 中兴通讯开发，支持国产化替代\n5. **分布式特性**:\n   - 支持分布式事务\n   - 支持水平扩展\n   - 支持高可用集群\n   - 支持读写分离\n\n### 支持的版本\n\n- ✅ GoldenDB 2.x\n- ✅ GoldenDB 3.x\n- ✅ 其他兼容 MySQL 的版本\n\n### 常见使用场景\n\n#### 1. 电信行业应用\n\nGoldenDB 在电信行业有广泛应用：\n\n```\n用户: 查询用户通话记录\n\nClaude 会:\n1. 查询通话记录表\n2. 按用户分组统计\n3. 返回分析结果\n```\n\n#### 2. 金融交易系统\n\n```\n用户: 查询今日交易流水\n\nClaude 会:\n1. 查询交易表\n2. 过滤今日数据\n3. 返回交易明细\n```\n\n#### 3. 分布式场景\n\n```\n用户: 查询分布式表的数据\n\nClaude 会:\n1. 连接到 GoldenDB 集群\n2. 执行分布式查询\n3. 自动聚合结果\n```\n\n#### 4. 高并发场景\n\n```\n用户: 查询实时订单数据\n\nClaude 会:\n1. 利用 GoldenDB 的高并发能力\n2. 快速返回查询结果\n3. 保证数据一致性\n```\n\n### GoldenDB 特色功能\n\nGoldenDB 作为国产分布式数据库，有一些特色功能：\n\n- **MySQL 兼容**: 完全兼容 MySQL 5.7/8.0 协议和语法\n- **分布式架构**: 支持分布式事务和水平扩展\n- **高可用**: 支持主备切换和故障转移\n- **读写分离**: 支持读写分离架构\n- **弹性扩展**: 支持在线扩容和缩容\n- **国产化**: 支持国产操作系统和芯片\n- **电信级**: 满足电信级可靠性要求\n\n**注意**: 这些特色功能可能需要特定的配置或 SQL 语法，Claude 会根据标准 MySQL 语法生成查询。\n\n### GoldenDB 最佳实践\n\n1. **表设计**:\n   - 使用合适的分片键\n   - 合理设计主键和索引\n   - 考虑数据分布均衡\n   - 避免跨分片查询\n\n2. **查询优化**:\n   - 使用 EXPLAIN 分析查询计划\n   - 创建合适的索引\n   - 避免 SELECT *\n   - 使用 LIMIT 限制返回结果\n\n3. **分布式事务**:\n   - 合理使用分布式事务\n   - 避免长事务\n   - 注意事务隔离级别\n   - 处理分布式死锁\n\n4. **监控维护**:\n   - 监控集群状态\n   - 关注分片数据分布\n   - 定期检查慢查询\n   - 定期备份数据\n\n5. **安全建议**:\n   - 使用强密码\n   - 限制网络访问\n   - 启用 SSL 连接\n   - 定期审计日志\n\n---\n\n## Claude Desktop 配置示例\n\n### 同时连接多个数据库\n\n你可以在 Claude Desktop 中同时配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-prod\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"warehouse\"\n      ]\n    },\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"cache.example.com\",\n        \"--port\", \"6379\",\n        \"--password\", \"cache_password\"\n      ]\n    },\n    \"oracle-warehouse\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"oracle.example.com\",\n        \"--port\", \"1521\",\n        \"--user\", \"warehouse_user\",\n        \"--password\", \"warehouse_password\",\n        \"--database\", \"DWH\"\n      ]\n    },\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/Users/yourname/data/local.db\"\n      ]\n    },\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"test\"\n      ]\n    },\n    \"gaussdb-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"gaussdb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"gaussdb\",\n        \"--password\", \"your_password\",\n        \"--database\", \"postgres\"\n      ]\n    }\n  }\n}\n```\n\n重启 Claude Desktop 后，你可以在对话中指定使用哪个数据库：\n\n- \"在 MySQL 生产库中查询...\"\n- \"从 PostgreSQL 分析库获取...\"\n- \"检查 Redis 缓存中的...\"\n- \"在 Oracle 数据仓库中统计...\"\n- \"从 SQLite 本地数据库查询...\"\n- \"在 KingbaseES 数据库中查询...\"\n- \"从 GaussDB 数据库获取...\"\n- \"在 OceanBase 集群中查询...\"\n\n---\n\n## 常见使用场景\n\n### 1. 数据分析\n\n**场景**: 快速分析业务数据\n\n```\n用户: 帮我分析最近一个月的销售趋势\n\nClaude 会:\n1. 查看 orders 表结构\n2. 按日期分组统计订单金额\n3. 生成趋势分析报告\n```\n\n### 2. 问题排查\n\n**场景**: 排查生产问题\n\n```\n用户: 为什么用户 ID 12345 无法登录？\n\nClaude 会:\n1. 查询 users 表找到该用户\n2. 检查 login_logs 表的最近记录\n3. 分析可能的原因（账号状态、密码错误次数等）\n```\n\n### 3. 数据迁移准备\n\n**场景**: 了解数据库结构以准备迁移\n\n```\n用户: 帮我生成所有表的结构文档\n\nClaude 会:\n1. 调用 get_schema 获取完整结构\n2. 整理成 Markdown 格式的文档\n3. 包含表名、列定义、索引、外键等信息\n```\n\n### 4. 性能优化建议\n\n**场景**: 优化慢查询\n\n```\n用户: 这个查询很慢，帮我优化：SELECT * FROM orders WHERE user_id = 123\n\nClaude 会:\n1. 查看 orders 表的索引情况\n2. 建议添加索引或修改查询\n3. 解释优化原理\n```\n\n### 5. Redis 缓存管理\n\n**场景**: 管理缓存数据\n\n```\n用户: 清理所有过期的会话缓存\n\nClaude 会:\n1. 查找所有 session: 开头的键\n2. 检查 TTL\n3. 在写入模式下执行清理（需要 --permission-mode readwrite 或 full）\n```\n\n---\n\n## 安全提示\n\n### ✅ 推荐做法\n\n1. **生产环境只读**: 生产数据库使用默认的 `safe` 模式\n2. **按需授权**: 使用 `--permission-mode readwrite` 允许读写但禁止删除\n3. **使用专用账号**: 为 MCP 创建权限受限的数据库账号\n4. **网络隔离**: 通过 VPN 或跳板机访问生产数据库\n5. **审计日志**: 定期检查 Claude Desktop 的操作日志\n\n### ❌ 避免做法\n\n1. 不要在生产环境启用 `--permission-mode full`\n2. 不要使用 root 或 admin 账号\n3. 不要在公共网络直接连接数据库\n4. 不要在配置文件中明文存储密码（考虑使用环境变量）\n\n---\n\n## 故障排查\n\n### 连接失败\n\n**错误**: `数据库连接失败`\n\n**解决方案**:\n1. 检查数据库服务是否运行\n2. 验证主机地址和端口\n3. 确认用户名和密码正确\n4. 检查防火墙规则\n\n### 权限不足\n\n**错误**: `Access denied` 或 `permission denied`\n\n**解决方案**:\n1. 确认数据库用户有足够权限\n2. MySQL: `GRANT SELECT ON database.* TO 'user'@'host';`\n3. PostgreSQL: `GRANT SELECT ON ALL TABLES IN SCHEMA public TO user;`\n\n### 写操作被拒绝\n\n**错误**: `操作被拒绝：当前处于只读安全模式`\n\n**解决方案**:\n- 这是安全特性，根据需要选择合适的权限模式：\n  - `--permission-mode readwrite` - 允许读写但禁止删除\n  - `--permission-mode full` - 完全控制（仅开发环境使用！）\n  - `--permissions read,insert,update` - 自定义权限组合\n\n---\n\n## 更多帮助\n\n- 查看 [README.md](./README.md) 了解项目概述\n- 查看 [CONTRIBUTING.md](./CONTRIBUTING.md) 了解如何贡献\n- 提交 Issue: https://github.com/yourusername/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/getting-started/installation.md",
    "content": "# 安装指南\n\n本文档介绍 Universal DB MCP 的各种安装方式。\n\n## 系统要求\n\n- **Node.js**: >= 20.0.0\n- **操作系统**: Windows、macOS、Linux\n- **内存**: >= 512MB（推荐 1GB+）\n\n## 安装方式\n\n### 方式一：NPM 全局安装（推荐）\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n安装完成后，可以直接使用命令：\n\n```bash\nuniversal-db-mcp --help\n```\n\n### 方式二：npx 直接运行（无需安装）\n\n```bash\nnpx universal-db-mcp --help\n```\n\n这种方式会自动下载最新版本并运行，适合临时使用或测试。\n\n### 方式三：从源码安装\n\n```bash\n# 克隆仓库\ngit clone https://github.com/yourusername/universal-db-mcp.git\ncd universal-db-mcp\n\n# 安装依赖\nnpm install\n\n# 构建项目\nnpm run build\n\n# 全局链接（可选，用于开发）\nnpm link\n```\n\n## 验证安装\n\n```bash\n# 查看版本\nuniversal-db-mcp --version\n\n# 查看帮助\nuniversal-db-mcp --help\n```\n\n## 数据库驱动\n\n大多数数据库驱动会自动安装。以下是一些特殊情况：\n\n### 达梦数据库（DM）\n\n达梦驱动 `dmdb` 作为可选依赖。如果自动安装失败：\n\n```bash\nnpm install -g dmdb\n```\n\n### SQLite\n\nSQLite 驱动 `better-sqlite3` 需要编译。在 Windows 上需要安装 [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022)。\n\n### Oracle\n\nOracle 驱动 `oracledb` 需要 Oracle Instant Client。请参考 [Oracle 官方文档](https://oracle.github.io/node-oracledb/INSTALL.html)。\n\n## 更新版本\n\n```bash\n# NPM 全局安装方式\nnpm update -g universal-db-mcp\n\n# 或重新安装最新版\nnpm install -g universal-db-mcp@latest\n```\n\n## 卸载\n\n```bash\nnpm uninstall -g universal-db-mcp\n```\n\n## 下一步\n\n- [快速开始](./quick-start.md) - 5 分钟上手\n- [配置说明](./configuration.md) - 详细配置选项\n- [使用示例](./examples.md) - 各数据库使用示例\n"
  },
  {
    "path": "docs/getting-started/quick-start.md",
    "content": "# 快速开始\n\n5 分钟快速上手 Universal DB MCP。\n\n## 选择运行模式\n\nUniversal DB MCP 支持两种运行模式：\n\n| 模式 | 适用场景 | 启动方式 |\n|------|----------|----------|\n| **MCP 模式** | Claude Desktop 集成 | `npm start` |\n| **HTTP API 模式** | Coze、n8n、Dify 等平台 | `npm run start:http` |\n\n## MCP 模式快速开始\n\n### 1. 安装\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n### 2. 配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n添加数据库配置（以 MySQL 为例）：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 重启 Claude Desktop\n\n重启后，在对话中直接询问：\n\n- \"帮我查看 users 表的结构\"\n- \"统计最近 7 天的订单数量\"\n- \"找出消费金额最高的 10 个用户\"\n\nClaude 会自动调用数据库工具完成查询！\n\n## HTTP API 模式快速开始\n\n### 1. 配置环境变量\n\n创建 `.env` 文件：\n\n```bash\nMODE=http\nHTTP_PORT=3000\nAPI_KEYS=your-secret-key\n```\n\n### 2. 启动服务\n\n```bash\nnpm run start:http\n```\n\n### 3. 测试 API\n\n```bash\n# 健康检查\ncurl http://localhost:3000/api/health\n\n# 连接数据库\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"your_password\",\n    \"database\": \"your_database\"\n  }'\n\n# 执行查询（使用返回的 sessionId）\ncurl -X POST http://localhost:3000/api/query \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sessionId\": \"返回的sessionId\",\n    \"query\": \"SELECT * FROM users LIMIT 10\"\n  }'\n```\n\n## 支持的数据库\n\n| 数据库 | 类型参数 | 默认端口 |\n|--------|---------|---------|\n| MySQL | `mysql` | 3306 |\n| PostgreSQL | `postgres` | 5432 |\n| Redis | `redis` | 6379 |\n| Oracle | `oracle` | 1521 |\n| SQL Server | `sqlserver` | 1433 |\n| MongoDB | `mongodb` | 27017 |\n| SQLite | `sqlite` | - |\n| 达梦 | `dm` | 5236 |\n| KingbaseES | `kingbase` | 54321 |\n| GaussDB | `gaussdb` | 5432 |\n| OceanBase | `oceanbase` | 2881 |\n| TiDB | `tidb` | 4000 |\n| ClickHouse | `clickhouse` | 8123 |\n| PolarDB | `polardb` | 3306 |\n| Vastbase | `vastbase` | 5432 |\n| HighGo | `highgo` | 5866 |\n| GoldenDB | `goldendb` | 3306 |\n\n## 安全模式\n\n默认情况下，工具运行在**只读模式**，会拒绝所有写入操作。\n\n支持细粒度权限控制：\n\n```bash\n# 只读模式（默认）\n--permission-mode safe\n\n# 读写但不能删除\n--permission-mode readwrite\n\n# 自定义权限\n--permissions read,insert,update\n\n# 完全控制（危险！）\n--permission-mode full\n```\n\n## 下一步\n\n- [配置说明](./configuration.md) - 详细配置选项\n- [使用示例](./examples.md) - 各数据库使用示例\n- [部署指南](../deployment/README.md) - 生产环境部署\n"
  },
  {
    "path": "docs/guides/multi-tenant.md",
    "content": "# 多租户场景使用指南\n\n本指南介绍如何在多租户场景下使用 MCP 数据库连接器，特别是当您的表中使用 `company_id` 等字段来区分租户时。\n\n## 📋 目录\n\n- [基本使用方式](#基本使用方式)\n- [方案 1：使用数据库视图（推荐，最安全）](#方案-1使用数据库视图推荐最安全)\n- [方案 2：使用对话上下文](#方案-2使用对话上下文)\n- [方案 3：使用专用数据库（最彻底的隔离）](#方案-3使用专用数据库最彻底的隔离)\n- [推荐配置](#推荐配置)\n- [多租户配置示例](#多租户配置示例)\n- [最佳实践](#最佳实践)\n\n---\n\n## 基本使用方式\n\n在多租户场景下，您有几种方式来处理租户隔离：\n\n### 方式 1：在对话中明确指定租户 ID（推荐）\n\n每次查询时，在对话中明确告诉 Claude 要查询哪个租户的数据：\n\n```\n你：查询 company_id = 1001 的所有订单\n```\n\nClaude 会自动生成带租户过滤的 SQL：\n```sql\nSELECT * FROM orders WHERE company_id = 1001;\n```\n\n或者：\n```\n你：帮我统计租户 1001 最近 7 天的订单数量\n```\n\nClaude 会生成：\n```sql\nSELECT COUNT(*) FROM orders\nWHERE company_id = 1001\n  AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);\n```\n\n### 方式 2：设置对话上下文（更方便）\n\n在对话开始时，先告诉 Claude 当前的租户上下文：\n\n```\n你：我现在要查询租户 1001 的数据，接下来所有查询都针对这个租户。\n```\n\n然后后续的查询就可以简化：\n\n```\n你：查询所有订单\n```\n\nClaude 会记住上下文，自动生成：\n```sql\nSELECT * FROM orders WHERE company_id = 1001;\n```\n\n```\n你：统计用户数量\n```\n\nClaude 会生成：\n```sql\nSELECT COUNT(*) FROM users WHERE company_id = 1001;\n```\n\n### 方式 3：使用更自然的语言\n\n您也可以用更自然的方式表达：\n\n```\n你：帮我看看公司 1001 的订单情况\n你：查询属于租户 1001 的所有用户\n你：统计 company_id 为 1001 的销售额\n```\n\n### 方式 4：批量查询多个租户\n\n如果需要对比多个租户的数据：\n\n```\n你：对比租户 1001、1002、1003 的订单数量\n```\n\nClaude 会生成：\n```sql\nSELECT company_id, COUNT(*) as order_count\nFROM orders\nWHERE company_id IN (1001, 1002, 1003)\nGROUP BY company_id;\n```\n\n---\n\n## 方案 1：使用数据库视图（推荐，最安全）\n\n这是**最安全**的方案，通过数据库层面的视图和权限控制来实现租户隔离。\n\n### 步骤 1：在数据库中为租户创建视图\n\n以 OceanBase/MySQL 为例：\n\n```sql\n-- 为租户 1001 创建专用视图\nCREATE VIEW tenant_1001_orders AS\nSELECT * FROM orders WHERE company_id = 1001;\n\nCREATE VIEW tenant_1001_users AS\nSELECT * FROM users WHERE company_id = 1001;\n\nCREATE VIEW tenant_1001_products AS\nSELECT * FROM products WHERE company_id = 1001;\n\n-- 为租户创建专用用户\nCREATE USER 'tenant_1001'@'%' IDENTIFIED BY 'secure_password';\n\n-- 只授予视图的访问权限\nGRANT SELECT ON mydb.tenant_1001_orders TO 'tenant_1001'@'%';\nGRANT SELECT ON mydb.tenant_1001_users TO 'tenant_1001'@'%';\nGRANT SELECT ON mydb.tenant_1001_products TO 'tenant_1001'@'%';\n\nFLUSH PRIVILEGES;\n```\n\n### 步骤 2：配置 Claude Desktop\n\n编辑 Claude Desktop 配置文件：\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-tenant-1001\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1001@test\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3：使用\n\n```\n你：查询 tenant_1001_orders 视图中的所有订单\n你：统计 tenant_1001_users 视图中的用户数量\n```\n\n### 优缺点\n\n**优点**：\n- ✅ 数据库层面强制隔离，最安全\n- ✅ 用户无法访问其他租户数据\n- ✅ 视图名称明确，不会混淆\n- ✅ 适合生产环境\n\n**缺点**：\n- ⚠️ 需要为每个表创建视图\n- ⚠️ 视图名称不同于原表名\n- ⚠️ 需要数据库管理员权限\n\n---\n\n## 方案 2：使用对话上下文\n\n这是**最简单**的方案，通过在对话中设置上下文来实现租户过滤。\n\n### 步骤 1：创建租户专用用户（可选）\n\n```sql\n-- 创建租户 1001 的用户\nCREATE USER 'tenant_1001'@'%' IDENTIFIED BY 'secure_password';\n\n-- 授予表的查询权限\nGRANT SELECT ON mydb.orders TO 'tenant_1001'@'%';\nGRANT SELECT ON mydb.users TO 'tenant_1001'@'%';\nGRANT SELECT ON mydb.products TO 'tenant_1001'@'%';\n\nFLUSH PRIVILEGES;\n```\n\n### 步骤 2：配置 Claude Desktop\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-tenant-1001\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1001@test\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3：在对话中设置上下文\n\n```\n你：我现在使用的是租户 1001，所有查询都要加上 WHERE company_id = 1001 的条件。\n\nClaude：好的，我会记住这个上下文，后续所有查询都会自动添加 company_id = 1001 的过滤条件。\n\n你：查询所有订单\n\nClaude 执行：\nSELECT * FROM orders WHERE company_id = 1001;\n```\n\n### 优缺点\n\n**优点**：\n- ✅ 使用原表名，不需要创建视图\n- ✅ 配置简单，快速上手\n- ✅ 灵活，可以随时切换租户\n- ✅ 适合开发和测试环境\n\n**缺点**：\n- ⚠️ 依赖对话上下文，可能被遗忘\n- ⚠️ 没有数据库层面的强制隔离\n- ⚠️ 需要在每次对话开始时重新设置\n\n---\n\n## 方案 3：使用专用数据库（最彻底的隔离）\n\n这是**隔离最彻底**的方案，为每个租户创建独立的数据库。\n\n### 步骤 1：创建租户专用数据库\n\n```sql\n-- 创建租户 1001 的专用数据库\nCREATE DATABASE tenant_1001_db;\n\n-- 在专用数据库中创建表（只包含该租户的数据）\nUSE tenant_1001_db;\n\nCREATE TABLE orders AS\nSELECT * FROM mydb.orders WHERE company_id = 1001;\n\nCREATE TABLE users AS\nSELECT * FROM mydb.users WHERE company_id = 1001;\n\nCREATE TABLE products AS\nSELECT * FROM mydb.products WHERE company_id = 1001;\n\n-- 创建用户并授权\nCREATE USER 'tenant_1001'@'%' IDENTIFIED BY 'secure_password';\nGRANT SELECT ON tenant_1001_db.* TO 'tenant_1001'@'%';\n\nFLUSH PRIVILEGES;\n```\n\n### 步骤 2：配置 Claude Desktop\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-tenant-1001\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1001@test\",\n        \"--password\", \"secure_password\",\n        \"--database\", \"tenant_1001_db\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3：使用\n\n```\n你：查询所有订单\n你：统计用户数量\n```\n\n直接使用原表名，无需指定租户 ID。\n\n### 优缺点\n\n**优点**：\n- ✅ 完全隔离，最安全\n- ✅ 使用原表名，无需修改查询\n- ✅ 性能最好（无需过滤）\n- ✅ 适合大型企业客户\n\n**缺点**：\n- ⚠️ 需要数据同步机制\n- ⚠️ 存储空间占用更多\n- ⚠️ 维护成本较高\n\n---\n\n## 推荐配置\n\n如果您想要**最简单且安全**的配置，推荐这样做：\n\n### 1. 创建租户专用数据库用户\n\n```sql\n-- 为租户 1001 创建用户\nCREATE USER 'tenant_1001'@'%' IDENTIFIED BY 'password_1001';\n\n-- 授予查询权限\nGRANT SELECT ON mydb.* TO 'tenant_1001'@'%';\n\nFLUSH PRIVILEGES;\n```\n\n### 2. 配置 Claude Desktop（为租户命名）\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-tenant-1001\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1001@test\",\n        \"--password\", \"password_1001\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### 3. 在对话开始时设置上下文\n\n```\n你：我现在要查询租户 1001 的数据（company_id = 1001），请在所有查询中自动添加这个过滤条件。\n\nClaude：好的，我已记录。后续所有查询都会自动添加 WHERE company_id = 1001 的条件。\n\n你：查询最近 10 条订单\n\nClaude 执行：\nSELECT * FROM orders\nWHERE company_id = 1001\nORDER BY created_at DESC\nLIMIT 10;\n```\n\n---\n\n## 多租户配置示例\n\n如果您有多个租户，可以这样配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"oceanbase-tenant-1001\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1001@test\",\n        \"--password\", \"password_1001\",\n        \"--database\", \"mydb\"\n      ]\n    },\n    \"oceanbase-tenant-1002\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1002@test\",\n        \"--password\", \"password_1002\",\n        \"--database\", \"mydb\"\n      ]\n    },\n    \"oceanbase-tenant-1003\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oceanbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"2881\",\n        \"--user\", \"tenant_1003@test\",\n        \"--password\", \"password_1003\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n然后在对话中，Claude 会看到多个连接，您可以明确指定使用哪个。\n\n---\n\n## 最佳实践\n\n### 1. 根据环境选择方案\n\n| 环境 | 推荐方案 | 原因 |\n|------|---------|------|\n| 开发/测试 | 方案 2（对话上下文） | 简单快速，灵活切换 |\n| 生产环境 | 方案 1（数据库视图） | 安全可靠，强制隔离 |\n| 严格隔离需求 | 方案 3（专用数据库） | 完全隔离，性能最优 |\n\n### 2. 安全建议\n\n#### 使用只读用户\n\n为了安全，建议为每个租户创建只读用户：\n\n```sql\n-- 创建只读用户\nCREATE USER 'tenant_1001_readonly'@'%' IDENTIFIED BY 'password';\n\n-- 只授予查询权限\nGRANT SELECT ON mydb.* TO 'tenant_1001_readonly'@'%';\n\nFLUSH PRIVILEGES;\n```\n\n#### 限制网络访问\n\n- 使用防火墙限制数据库端口访问\n- 仅允许可信 IP 地址连接\n- 在生产环境中使用 VPN 或专线\n\n#### 使用强密码\n\n- 为每个租户使用不同的强密码\n- 定期更换密码\n- 使用密码管理工具\n\n### 3. 实际使用示例\n\n#### 场景 1：日常数据查询\n\n```\n你：我要查询租户 1001 的数据\n\nClaude：好的，我会在后续查询中自动添加 company_id = 1001 的过滤条件。\n\n你：查看最近 10 条订单\n\nClaude 执行：\nSELECT * FROM orders\nWHERE company_id = 1001\nORDER BY created_at DESC\nLIMIT 10;\n```\n\n#### 场景 2：数据分析\n\n```\n你：帮我分析租户 1001 最近一个月的销售趋势\n\nClaude 会：\n1. 查询该租户的订单数据\n2. 按日期分组统计\n3. 生成趋势分析报告\n\n执行的 SQL：\nSELECT\n    DATE(created_at) as date,\n    COUNT(*) as order_count,\n    SUM(amount) as total_amount\nFROM orders\nWHERE company_id = 1001\n  AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY DATE(created_at)\nORDER BY date;\n```\n\n#### 场景 3：跨租户对比\n\n```\n你：对比租户 1001 和 1002 的活跃用户数\n\nClaude 执行：\nSELECT\n    company_id,\n    COUNT(DISTINCT user_id) as active_users\nFROM user_activities\nWHERE company_id IN (1001, 1002)\n  AND activity_date >= DATE_SUB(NOW(), INTERVAL 7 DAY)\nGROUP BY company_id;\n```\n\n### 4. 注意事项\n\n#### MCP 连接器本身不需要特殊配置\n- MCP 连接器只是执行 SQL，不需要特殊的租户配置\n- 租户隔离在 SQL 层面或数据库层面实现\n\n#### 在对话中明确指定租户 ID\n- 每次对话开始时设置租户上下文\n- Claude 会智能地在 SQL 中添加过滤条件\n\n#### 生产环境建议使用数据库级别的权限控制\n- 为每个租户创建独立用户\n- 使用视图或专用数据库实现强制隔离\n- 定期审计访问日志\n\n---\n\n## 总结\n\n**核心要点**：\n\n1. **MCP 连接器本身不需要特殊配置**，它只是执行 SQL\n2. **租户隔离在 SQL 层面实现**，通过 WHERE company_id = xxx 条件\n3. **在对话中明确指定租户 ID**，Claude 会自动在 SQL 中添加过滤条件\n4. **可以设置对话上下文**，让 Claude 记住当前操作的租户\n5. **生产环境建议使用数据库级别的权限控制**，为每个租户创建独立用户\n\n这种方式既灵活又安全，Claude 会智能地理解您的意图并生成正确的 SQL 查询。\n\n---\n\n## 常见问题\n\n### Q1: 如何确保 Claude 不会忘记租户上下文？\n\n**A**: 在每次对话开始时重新设置上下文，或者使用方案 1（数据库视图）在数据库层面强制隔离。\n\n### Q2: 可以同时查询多个租户的数据吗？\n\n**A**: 可以。在对话中明确指定多个租户 ID，Claude 会生成包含 `IN (1001, 1002, 1003)` 的 SQL。\n\n### Q3: 如何防止误操作其他租户的数据？\n\n**A**: 使用方案 1（数据库视图）或方案 3（专用数据库），在数据库层面强制隔离，用户无法访问其他租户的数据。\n\n### Q4: 支持哪些数据库？\n\n**A**: 本指南适用于所有支持的数据库：MySQL、PostgreSQL、OceanBase、TiDB、ClickHouse 等。具体 SQL 语法可能略有不同。\n\n### Q5: 如何在写入模式下使用多租户？\n\n**A**: 在配置中添加 `--permission-mode readwrite` 或 `--permission-mode full` 参数，并在对话中明确指定租户 ID。建议在生产环境中谨慎使用写入模式。\n\n---\n\n**如果您有其他问题或建议，欢迎在 GitHub Issues 中反馈！**\n"
  },
  {
    "path": "docs/guides/security.md",
    "content": "# 安全最佳实践\n\n本文档介绍 Universal DB MCP 的安全配置和最佳实践。\n\n## 安全模式\n\n### 权限模式\n\nUniversal DB MCP 支持细粒度权限控制：\n\n| 模式 | 允许的操作 | 说明 |\n|------|-----------|------|\n| `safe`（默认） | SELECT | 只读，最安全 |\n| `readwrite` | SELECT, INSERT, UPDATE | 读写但不能删除 |\n| `full` | 所有操作 | 完全控制（危险！） |\n| `custom` | 自定义组合 | 通过 `--permissions` 指定 |\n\n**权限类型：**\n- `read` - SELECT 查询（始终包含）\n- `insert` - INSERT, REPLACE\n- `update` - UPDATE\n- `delete` - DELETE, TRUNCATE\n- `ddl` - CREATE, ALTER, DROP, RENAME\n\n### 只读模式（默认）\n\n默认情况下，工具运行在**只读模式**，会拒绝所有写入操作。这是最安全的配置，推荐在生产环境使用。\n\n### 读写模式（不能删除）\n\n适用于数据录入场景，允许插入和更新，但禁止删除：\n\n```bash\n--permission-mode readwrite\n```\n\n### 自定义权限\n\n根据需求自由组合权限：\n\n```bash\n# 只允许读和插入\n--permissions read,insert\n\n# 允许读、插入、更新\n--permissions read,insert,update\n```\n\n### 完全控制模式\n\n如需执行所有操作，需要显式添加参数：\n\n```bash\n--permission-mode full\n# 或（向后兼容）\n--danger-allow-write\n```\n\n**警告**：启用完全控制模式后，AI 可以修改和删除你的数据库数据。请仅在开发环境使用。\n\n### 不同传输方式的权限配置\n\n> ⚠️ **重要提示**：不同传输方式的参数命名风格不同，请注意区分！\n\n#### STDIO 模式（Claude Desktop 等）\n\n使用命令行参数（连字符风格）：\n\n```bash\n# 预设模式\n--permission-mode readwrite\n\n# 自定义权限\n--permissions read,insert,update\n```\n\n#### SSE 模式（Dify 等）\n\n使用 URL Query 参数（驼峰风格）：\n\n```\nGET /sse?type=mysql&host=localhost&permissionMode=readwrite\nGET /sse?type=mysql&host=localhost&permissions=read,insert,update\n```\n\n#### Streamable HTTP 模式\n\n使用 HTTP Header（连字符风格）：\n\n```\nPOST /mcp\nHeaders:\n  X-DB-Type: mysql\n  X-DB-Host: localhost\n  X-DB-Permission-Mode: readwrite\n  X-DB-Permissions: read,insert,update\n```\n\n#### REST API 模式\n\n使用 JSON Body（驼峰风格）：\n\n```json\nPOST /api/connect\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"permissionMode\": \"readwrite\",\n  \"permissions\": [\"read\", \"insert\", \"update\"]\n}\n```\n\n#### 参数命名汇总\n\n| 传输方式 | 参数位置 | 权限模式参数 | 自定义权限参数 |\n|---------|---------|-------------|---------------|\n| STDIO | 命令行 | `--permission-mode` | `--permissions` |\n| SSE | URL Query | `permissionMode` | `permissions` |\n| Streamable HTTP | HTTP Header | `X-DB-Permission-Mode` | `X-DB-Permissions` |\n| REST API | JSON Body | `permissionMode` | `permissions` |\n\n## 数据库账号安全\n\n### 使用专用账号\n\n为 MCP 创建专用的数据库账号，遵循最小权限原则。\n\n#### MySQL\n\n```sql\n-- 创建只读用户\nCREATE USER 'mcp_readonly'@'%' IDENTIFIED BY 'secure_password';\nGRANT SELECT ON mydb.* TO 'mcp_readonly'@'%';\nFLUSH PRIVILEGES;\n```\n\n#### PostgreSQL\n\n```sql\n-- 创建只读用户\nCREATE USER mcp_readonly WITH PASSWORD 'secure_password';\nGRANT CONNECT ON DATABASE mydb TO mcp_readonly;\nGRANT USAGE ON SCHEMA public TO mcp_readonly;\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;\nALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;\n\n-- 如需访问其他 schema，需要额外授权\n-- GRANT USAGE ON SCHEMA analytics TO mcp_readonly;\n-- GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO mcp_readonly;\n-- ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO mcp_readonly;\n```\n\n#### Oracle\n\n```sql\n-- 创建只读用户\nCREATE USER mcp_readonly IDENTIFIED BY secure_password;\nGRANT CREATE SESSION TO mcp_readonly;\nGRANT SELECT ANY TABLE TO mcp_readonly;\n```\n\n### 密码安全\n\n1. **使用强密码** - 至少 16 位，包含大小写字母、数字和特殊字符\n2. **定期轮换** - 定期更换数据库密码\n3. **不要硬编码** - 使用环境变量存储密码\n\n## API Key 安全\n\n### 生成强密钥\n\n```bash\n# 生成 32 字节的随机密钥\nopenssl rand -hex 32\n```\n\n### 配置多个密钥\n\n支持配置多个 API Key，便于轮换和撤销：\n\n```bash\nAPI_KEYS=key1,key2,key3\n```\n\n### 密钥轮换\n\n1. 添加新密钥到配置\n2. 更新客户端使用新密钥\n3. 移除旧密钥\n\n## 网络安全\n\n### 不要直接暴露数据库\n\n数据库不应该直接暴露到公网。推荐架构：\n\n```\n用户 → Nginx (HTTPS) → MCP 服务 → 数据库\n```\n\n### 使用 VPN 或跳板机\n\n访问生产数据库时：\n\n1. **VPN** - 通过企业 VPN 连接\n2. **SSH 隧道** - 通过跳板机建立隧道\n3. **内网访问** - 在同一 VPC 内访问\n\n### 防火墙配置\n\n只允许必要的端口：\n\n```bash\n# UFW 示例\nsudo ufw allow ssh\nsudo ufw allow 80/tcp\nsudo ufw allow 443/tcp\n# 不要开放数据库端口到公网\n```\n\n## HTTPS 配置\n\n生产环境必须使用 HTTPS：\n\n1. 使用 Let's Encrypt 免费证书\n2. 配置 Nginx 反向代理\n3. 强制 HTTP 重定向到 HTTPS\n\n详见 [HTTPS 配置指南](../deployment/https-domain.md)。\n\n## 速率限制\n\n配置速率限制防止滥用：\n\n```bash\nRATE_LIMIT_MAX=100      # 最大请求数\nRATE_LIMIT_WINDOW=1m    # 时间窗口\n```\n\n## 日志和审计\n\n### 启用日志\n\n```bash\nLOG_LEVEL=info\n```\n\n### 定期审计\n\n1. 检查访问日志\n2. 监控异常查询\n3. 审计数据库操作\n\n## 安全检查清单\n\n### 部署前\n\n- [ ] 使用只读数据库账号\n- [ ] 配置强 API Key\n- [ ] 启用 HTTPS\n- [ ] 配置防火墙\n- [ ] 设置速率限制\n\n### 运行时\n\n- [ ] 定期检查日志\n- [ ] 监控异常访问\n- [ ] 及时更新版本\n\n### 定期维护\n\n- [ ] 轮换 API Key\n- [ ] 更新数据库密码\n- [ ] 审计访问权限\n\n## 常见安全问题\n\n### SQL 注入\n\nMCP 使用参数化查询，已内置 SQL 注入防护。但仍需注意：\n\n1. 不要在查询中拼接用户输入\n2. 使用参数化查询\n\n### 敏感数据泄露\n\n1. 不要在日志中记录敏感数据\n2. 配置适当的访问权限\n3. 使用数据脱敏\n\n### 未授权访问\n\n1. 始终配置 API Key\n2. 使用 HTTPS\n3. 限制网络访问\n"
  },
  {
    "path": "docs/http-api/API_REFERENCE.md",
    "content": "# HTTP API Reference\n\n## Overview\n\nUniversal Database MCP Server HTTP API provides RESTful endpoints and MCP protocol endpoints for database operations. This API supports 17 database types and includes features like session management, API key authentication, rate limiting, and CORS support.\n\n**Base URL**: `http://localhost:3000` (configurable via `HTTP_PORT` environment variable)\n\n**API Version**: 1.0.0\n\n## Authentication\n\nAll endpoints (except `/api/health` and `/api/info`) require API key authentication, including REST API and MCP SSE/Streamable HTTP endpoints.\n\n> **Note**: If `API_KEYS` environment variable is not configured, authentication is skipped (development mode).\n\n### Methods\n\n**Option 1: X-API-Key Header**\n```http\nX-API-Key: your-secret-key\n```\n\n**Option 2: Authorization Bearer Token**\n```http\nAuthorization: Bearer your-secret-key\n```\n\n### Configuration\n\nSet API keys via environment variable:\n```bash\nAPI_KEYS=key1,key2,key3\n```\n\n### Error Responses\n\n**401 Unauthorized** - Missing API key\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"UNAUTHORIZED\",\n    \"message\": \"API key required. Provide X-API-Key header or Authorization: Bearer <key>\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**403 Forbidden** - Invalid API key\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"FORBIDDEN\",\n    \"message\": \"Invalid API key\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n## Rate Limiting\n\nDefault: 100 requests per minute per API key (or IP if no API key)\n\n**Configuration**:\n```bash\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m  # 1m, 1h, 1d\n```\n\n**Rate Limit Exceeded Response** (429):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"RATE_LIMIT_EXCEEDED\",\n    \"message\": \"Too many requests, please try again later\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n## Endpoints\n\n### MCP Protocol Endpoints\n\nMCP (Model Context Protocol) endpoints allow AI platforms like Dify to connect to databases directly via the MCP protocol.\n\n#### SSE Endpoints (Legacy)\n\n##### GET /sse\n\nEstablish an SSE connection. Database configuration is passed via URL parameters.\n\n**URL Parameters**:\n| Parameter | Required | Description |\n|-----------|----------|-------------|\n| `type` | Yes | Database type |\n| `host` | Yes* | Database host |\n| `port` | No | Database port |\n| `user` | Yes* | Username |\n| `password` | Yes* | Password |\n| `database` | Yes* | Database name |\n| `filePath` | Yes* | SQLite file path |\n| `allowWrite` | No | Enable write operations (default: false) |\n| `permissionMode` | No | Permission mode: `safe` (default), `readwrite`, `full` |\n| `permissions` | No | Custom permissions, comma-separated: `read,insert,update,delete,ddl` |\n\n*Required fields depend on database type\n\n> ⚠️ **Note**: Use camelCase for URL parameters (`permissionMode`, `permissions`), not hyphenated names.\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=secret&database=mydb\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n##### POST /sse/message\n\nSend a message to an SSE session.\n\n**Query Parameters**:\n- `sessionId` (string, required): SSE session ID\n\n**Request Example**:\n```bash\ncurl -X POST \"http://localhost:3000/sse/message?sessionId=your-session-id\" \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1}'\n```\n\n#### Streamable HTTP Endpoints (MCP 2025 Spec, Recommended)\n\n##### POST /mcp\n\nMCP Streamable HTTP endpoint. Database configuration is passed via headers.\n\n**Header Parameters**:\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-API-Key` | Yes* | API key (or use Authorization Bearer) |\n| `X-DB-Type` | Yes | Database type |\n| `X-DB-Host` | Yes* | Database host |\n| `X-DB-Port` | No | Database port |\n| `X-DB-User` | Yes* | Username |\n| `X-DB-Password` | Yes* | Password |\n| `X-DB-Database` | Yes* | Database name |\n| `X-DB-FilePath` | Yes* | SQLite file path |\n| `X-DB-Allow-Write` | No | Enable write operations (default: false) |\n| `X-DB-Permission-Mode` | No | Permission mode: `safe` (default), `readwrite`, `full` |\n| `X-DB-Permissions` | No | Custom permissions, comma-separated: `read,insert,update,delete,ddl` |\n| `mcp-session-id` | No | Session ID for subsequent requests |\n\n*Required fields depend on database type; authentication required if API_KEYS is configured\n\n> ⚠️ **Note**: Use hyphenated names for HTTP headers (`X-DB-Permission-Mode`, `X-DB-Permissions`).\n\n**Initialize Request Example**:\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-DB-Type: mysql\" \\\n  -H \"X-DB-Host: localhost\" \\\n  -H \"X-DB-Port: 3306\" \\\n  -H \"X-DB-User: root\" \\\n  -H \"X-DB-Password: secret\" \\\n  -H \"X-DB-Database: mydb\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}},\"id\":1}'\n```\n\n**Subsequent Request Example** (with session ID):\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"mcp-session-id: your-session-id\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":2}'\n```\n\n##### GET /mcp\n\nGet SSE stream for Streamable HTTP.\n\n**Headers**:\n- `mcp-session-id` (string, required): Session ID\n- `X-API-Key` (string, required*): API key\n\n##### DELETE /mcp\n\nClose an MCP session.\n\n**Query Parameters or Headers**:\n- `sessionId` or `mcp-session-id`: Session ID\n\n**Request Example**:\n```bash\ncurl -X DELETE \"http://localhost:3000/mcp?sessionId=your-session-id\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n#### MCP Tools\n\nThe following tools are available after connecting via MCP protocol:\n\n| Tool Name | Description |\n|-----------|-------------|\n| `execute_query` | Execute SQL queries or database commands |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a column (for enum-type columns like status, type) |\n| `get_sample_data` | Get sample data from a table (with automatic data masking for privacy) |\n| `connect_database` | Dynamically connect to a database (supports all 17 database types, auto-disconnects existing connection) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status (type, host, permissions, cache info) |\n\n### REST API Endpoints\n\n### Health & Info\n\n#### GET /api/health\n\nHealth check endpoint (no authentication required).\n\n**Request**:\n```bash\ncurl http://localhost:3000/api/health\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"healthy\",\n    \"uptime\": 3600.5,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/info\n\nService information endpoint (no authentication required).\n\n**Request**:\n```bash\ncurl http://localhost:3000/api/info\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"universal-db-mcp\",\n    \"version\": \"1.0.0\",\n    \"mode\": \"http\",\n    \"supportedDatabases\": [\n      \"mysql\", \"postgres\", \"redis\", \"oracle\", \"dm\",\n      \"sqlserver\", \"mongodb\", \"sqlite\", \"kingbase\",\n      \"gaussdb\", \"oceanbase\", \"tidb\", \"clickhouse\",\n      \"polardb\", \"vastbase\", \"highgo\", \"goldendb\"\n    ]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### Connection Management\n\n#### POST /api/connect\n\nConnect to a database and create a session.\n\n**Request Body**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"your_password\",\n  \"database\": \"mydb\",\n  \"allowWrite\": false,\n  \"permissionMode\": \"safe\",\n  \"permissions\": [\"read\", \"insert\"]\n}\n```\n\n**Parameters**:\n- `type` (string, required): Database type (mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb)\n- `host` (string, required for non-SQLite): Database host\n- `port` (number, required for non-SQLite): Database port\n- `user` (string, optional): Username\n- `password` (string, optional): Password\n- `database` (string, optional): Database name\n- `filePath` (string, required for SQLite): SQLite database file path\n- `authSource` (string, optional for MongoDB): Authentication database (default: admin)\n- `allowWrite` (boolean, optional): Enable write operations (default: false) - deprecated, use `permissionMode`\n- `permissionMode` (string, optional): Permission mode: `safe` (default), `readwrite`, `full`\n- `permissions` (array, optional): Custom permissions array: `[\"read\", \"insert\", \"update\", \"delete\", \"ddl\"]`\n\n> ⚠️ **Note**: Use camelCase for JSON body (`permissionMode`, `permissions`), not hyphenated names like `permission-mode`.\n\n**Request Example**:\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"testdb\"\n  }'\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**Error Response** (500):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CONNECTION_FAILED\",\n    \"message\": \"Access denied for user 'root'@'localhost'\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### POST /api/disconnect\n\nDisconnect from a database and close the session.\n\n**Request Body**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\"\n}\n```\n\n**Request Example**:\n```bash\ncurl -X POST http://localhost:3000/api/disconnect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\"}'\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"disconnected\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### Query Execution\n\n#### POST /api/query\n\nExecute a read query (SELECT, SHOW, DESCRIBE, etc.).\n\n**Request Body**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n  \"query\": \"SELECT * FROM users WHERE id = ?\",\n  \"params\": [1]\n}\n```\n\n**Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n- `query` (string, required): SQL query or database command\n- `params` (array, optional): Query parameters for parameterized queries\n\n**Request Example**:\n```bash\ncurl -X POST http://localhost:3000/api/query \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"query\": \"SELECT * FROM users LIMIT 10\"\n  }'\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [\n      {\"id\": 1, \"name\": \"Alice\", \"email\": \"alice@example.com\"},\n      {\"id\": 2, \"name\": \"Bob\", \"email\": \"bob@example.com\"}\n    ],\n    \"executionTime\": 15,\n    \"metadata\": {\n      \"fieldCount\": 3\n    }\n  },\n  \"metadata\": {\n    \"executionTime\": 15,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**Error Response - Write Operation Blocked** (500):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"QUERY_FAILED\",\n    \"message\": \"❌ 操作被拒绝：当前处于只读安全模式\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### POST /api/execute\n\nExecute a write operation (INSERT, UPDATE, DELETE, etc.). Requires `allowWrite: true` in connection config.\n\n**Request Body**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n  \"query\": \"INSERT INTO users (name, email) VALUES (?, ?)\",\n  \"params\": [\"Charlie\", \"charlie@example.com\"]\n}\n```\n\n**Request Example**:\n```bash\ncurl -X POST http://localhost:3000/api/execute \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"query\": \"UPDATE users SET name = ? WHERE id = ?\",\n    \"params\": [\"Alice Smith\", 1]\n  }'\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [],\n    \"affectedRows\": 1,\n    \"executionTime\": 8\n  },\n  \"metadata\": {\n    \"executionTime\": 8,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### Schema Information\n\n#### GET /api/tables\n\nList all tables in the database.\n\n**Query Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/api/tables?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\", \"categories\"]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/schema\n\nGet complete database schema.\n\n**Query Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/api/schema?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"type\": \"mysql\",\n    \"name\": \"testdb\",\n    \"version\": \"8.0.32\",\n    \"tables\": [\n      {\n        \"name\": \"orders\",\n        \"columns\": [\n          {\n            \"name\": \"id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"Order ID\"\n          },\n          {\n            \"name\": \"user_id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"User ID\"\n          }\n        ],\n        \"primaryKey\": [\"id\"],\n        \"indexes\": [\n          {\n            \"name\": \"PRIMARY\",\n            \"columns\": [\"id\"],\n            \"unique\": true\n          }\n        ],\n        \"foreignKeys\": [\n          {\n            \"name\": \"fk_orders_user\",\n            \"columns\": [\"user_id\"],\n            \"referencedTable\": \"users\",\n            \"referencedColumns\": [\"id\"],\n            \"onDelete\": \"CASCADE\",\n            \"onUpdate\": \"NO ACTION\"\n          }\n        ],\n        \"estimatedRows\": 5000\n      },\n      {\n        \"name\": \"users\",\n        \"columns\": [\n          {\n            \"name\": \"id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"User ID\"\n          },\n          {\n            \"name\": \"name\",\n            \"type\": \"varchar(255)\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"User name\"\n          }\n        ],\n        \"primaryKey\": [\"id\"],\n        \"indexes\": [\n          {\n            \"name\": \"PRIMARY\",\n            \"columns\": [\"id\"],\n            \"unique\": true\n          }\n        ],\n        \"estimatedRows\": 1000\n      }\n    ],\n    \"relationships\": [\n      {\n        \"fromTable\": \"orders\",\n        \"fromColumns\": [\"user_id\"],\n        \"toTable\": \"users\",\n        \"toColumns\": [\"id\"],\n        \"type\": \"many-to-one\",\n        \"constraintName\": \"fk_orders_user\"\n      }\n    ]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/schema/:table\n\nGet information about a specific table.\n\n**Path Parameters**:\n- `table` (string, required): Table name. Supports `schema.table_name` format (e.g., `analytics.users`).\n\n**Query Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/api/schema/users?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"orders\",\n    \"columns\": [\n      {\n        \"name\": \"id\",\n        \"type\": \"int\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"Order ID\"\n      },\n      {\n        \"name\": \"user_id\",\n        \"type\": \"int\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"User ID\"\n      },\n      {\n        \"name\": \"amount\",\n        \"type\": \"decimal(10,2)\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"Order amount\"\n      }\n    ],\n    \"primaryKey\": [\"id\"],\n    \"indexes\": [\n      {\n        \"name\": \"PRIMARY\",\n        \"columns\": [\"id\"],\n        \"unique\": true\n      },\n      {\n        \"name\": \"idx_user_id\",\n        \"columns\": [\"user_id\"],\n        \"unique\": false\n      }\n    ],\n    \"foreignKeys\": [\n      {\n        \"name\": \"fk_orders_user\",\n        \"columns\": [\"user_id\"],\n        \"referencedTable\": \"users\",\n        \"referencedColumns\": [\"id\"],\n        \"onDelete\": \"CASCADE\",\n        \"onUpdate\": \"NO ACTION\"\n      }\n    ],\n    \"estimatedRows\": 5000\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/enum-values\n\nGet all unique values for a column. Useful for understanding enum-type columns like status, type, category.\n\n**Query Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n- `tableName` (string, required): Table name. Supports `schema.table_name` format (e.g., `analytics.users`).\n- `columnName` (string, required): Column name\n- `limit` (string, optional): Maximum number of values to return (default: 50, max: 100)\n- `includeCount` (string, optional): Include count for each value (true/false, default: false)\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/api/enum-values?sessionId=V1StGXR8_Z5jdHi6B-myT&tableName=orders&columnName=status&includeCount=true\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tableName\": \"orders\",\n    \"columnName\": \"status\",\n    \"values\": [\"pending\", \"paid\", \"shipped\", \"delivered\", \"cancelled\"],\n    \"totalCount\": 5,\n    \"isEnum\": true,\n    \"valueCounts\": {\n      \"pending\": 1200,\n      \"paid\": 3500,\n      \"shipped\": 2100,\n      \"delivered\": 8500,\n      \"cancelled\": 450\n    },\n    \"columnType\": \"varchar(50)\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**Note**: This endpoint is not available for NoSQL databases (Redis, MongoDB).\n\n#### GET /api/sample-data\n\nGet sample data from a table with automatic data masking for privacy protection.\n\n**Query Parameters**:\n- `sessionId` (string, required): Session ID from `/api/connect`\n- `tableName` (string, required): Table name. Supports `schema.table_name` format (e.g., `analytics.users`).\n- `columns` (string, optional): Comma-separated list of columns to include\n- `limit` (string, optional): Number of rows to return (default: 3, max: 10)\n\n**Request Example**:\n```bash\ncurl \"http://localhost:3000/api/sample-data?sessionId=V1StGXR8_Z5jdHi6B-myT&tableName=users&columns=id,name,email,phone&limit=3\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**Response** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tableName\": \"users\",\n    \"columns\": [\"id\", \"name\", \"email\", \"phone\"],\n    \"rows\": [\n      {\"id\": 1, \"name\": \"Alice\", \"email\": \"a***@example.com\", \"phone\": \"138****5678\"},\n      {\"id\": 2, \"name\": \"Bob\", \"email\": \"b***@company.org\", \"phone\": \"139****1234\"},\n      {\"id\": 3, \"name\": \"Charlie\", \"email\": \"c***@test.com\", \"phone\": \"136****9876\"}\n    ],\n    \"rowCount\": 3,\n    \"masked\": true,\n    \"maskedColumns\": [\"email\", \"phone\"]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**Data Masking Rules**:\n| Data Type | Masking Pattern | Example |\n|-----------|-----------------|---------|\n| Phone | Middle 4 digits hidden | `138****5678` |\n| Email | Username partially hidden | `a***@example.com` |\n| ID Card | Middle 11 digits hidden | `110***********1234` |\n| Bank Card | Only last 4 digits shown | `************1234` |\n| Password/Secret | Fully hidden | `******` |\n\n**Note**: This endpoint is not available for NoSQL databases (Redis, MongoDB).\n\n## Error Codes\n\n| Code | HTTP Status | Description |\n|------|-------------|-------------|\n| `UNAUTHORIZED` | 401 | Missing API key |\n| `FORBIDDEN` | 403 | Invalid API key |\n| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |\n| `CONNECTION_FAILED` | 500 | Failed to connect to database |\n| `DISCONNECTION_FAILED` | 500 | Failed to disconnect from database |\n| `QUERY_FAILED` | 500 | Failed to execute query |\n| `EXECUTE_FAILED` | 500 | Failed to execute operation |\n| `LIST_TABLES_FAILED` | 500 | Failed to list tables |\n| `GET_SCHEMA_FAILED` | 500 | Failed to get schema |\n| `GET_TABLE_INFO_FAILED` | 500 | Failed to get table information |\n| `GET_ENUM_VALUES_FAILED` | 500 | Failed to get enum values |\n| `GET_SAMPLE_DATA_FAILED` | 500 | Failed to get sample data |\n| `INTERNAL_ERROR` | 500 | Internal server error |\n\n## Session Management\n\n### Session Lifecycle\n\n1. **Create**: Call `/api/connect` to create a session\n2. **Use**: Use the `sessionId` in subsequent API calls\n3. **Close**: Call `/api/disconnect` to close the session\n\n### Session Timeout\n\nSessions automatically expire after inactivity (default: 1 hour).\n\n**Configuration**:\n```bash\nSESSION_TIMEOUT=3600000  # 1 hour in milliseconds\nSESSION_CLEANUP_INTERVAL=300000  # 5 minutes\n```\n\n### Session Cleanup\n\nExpired sessions are automatically cleaned up every 5 minutes (configurable).\n\n## Database-Specific Examples\n\n### MySQL\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"mydb\"\n  }'\n```\n\n### PostgreSQL\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"postgres\",\n    \"host\": \"localhost\",\n    \"port\": 5432,\n    \"user\": \"postgres\",\n    \"password\": \"password\",\n    \"database\": \"mydb\"\n  }'\n```\n\n### Redis\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"redis\",\n    \"host\": \"localhost\",\n    \"port\": 6379,\n    \"password\": \"password\"\n  }'\n```\n\n### MongoDB\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mongodb\",\n    \"host\": \"localhost\",\n    \"port\": 27017,\n    \"user\": \"admin\",\n    \"password\": \"password\",\n    \"database\": \"mydb\",\n    \"authSource\": \"admin\"\n  }'\n```\n\n### SQLite\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"sqlite\",\n    \"filePath\": \"/path/to/database.db\",\n    \"allowWrite\": false\n  }'\n```\n\n## Best Practices\n\n### Security\n\n1. **Use Strong API Keys**: Generate cryptographically secure random keys\n2. **Enable HTTPS**: Use reverse proxy (nginx, Caddy) for HTTPS in production\n3. **Restrict CORS**: Set specific origins instead of `*`\n4. **Read-Only by Default**: Only enable `allowWrite` when necessary\n5. **Close Sessions**: Always call `/api/disconnect` when done\n\n### Performance\n\n1. **Reuse Sessions**: Keep sessions alive for multiple queries\n2. **Use Parameterized Queries**: Prevent SQL injection and improve performance\n3. **Limit Result Sets**: Use `LIMIT` clauses for large tables\n4. **Monitor Rate Limits**: Implement exponential backoff for rate limit errors\n\n### Error Handling\n\n1. **Check `success` Field**: Always check the `success` field in responses\n2. **Handle Rate Limits**: Implement retry logic with backoff\n3. **Session Expiry**: Reconnect if session expires\n4. **Log Request IDs**: Use `requestId` from metadata for debugging\n\n## Complete Workflow Example\n\n```bash\n# 1. Connect to database\nRESPONSE=$(curl -s -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"testdb\"\n  }')\n\n# 2. Extract session ID\nSESSION_ID=$(echo $RESPONSE | jq -r '.data.sessionId')\n\n# 3. List tables\ncurl \"http://localhost:3000/api/tables?sessionId=$SESSION_ID\" \\\n  -H \"X-API-Key: your-key\"\n\n# 4. Get table schema\ncurl \"http://localhost:3000/api/schema/users?sessionId=$SESSION_ID\" \\\n  -H \"X-API-Key: your-key\"\n\n# 5. Execute query\ncurl -X POST http://localhost:3000/api/query \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\n    \\\"sessionId\\\": \\\"$SESSION_ID\\\",\n    \\\"query\\\": \\\"SELECT * FROM users LIMIT 10\\\"\n  }\"\n\n# 6. Disconnect\ncurl -X POST http://localhost:3000/api/disconnect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"sessionId\\\": \\\"$SESSION_ID\\\"}\"\n```\n\n## Support\n\nFor issues and questions:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Documentation: https://github.com/Anarkh-Lee/universal-db-mcp#readme\n"
  },
  {
    "path": "docs/http-api/API_REFERENCE.zh-CN.md",
    "content": "# HTTP API 参考文档\n\n## 概述\n\nUniversal Database MCP Server HTTP API 提供 RESTful 端点和 MCP 协议端点用于数据库操作。此 API 支持 17 种数据库类型，包括会话管理、API Key 认证、速率限制和 CORS 支持等功能。\n\n**基础 URL**: `http://localhost:3000`（可通过 `HTTP_PORT` 环境变量配置）\n\n**API 版本**: 1.0.0\n\n## 认证\n\n除 `/api/health` 和 `/api/info` 外，所有端点（包括 REST API 和 MCP SSE/Streamable HTTP 端点）都需要 API Key 认证。\n\n> **注意**: 如果未配置 `API_KEYS` 环境变量，则跳过认证（开发模式）。\n\n### 认证方式\n\n**方式 1: X-API-Key 请求头**\n```http\nX-API-Key: your-secret-key\n```\n\n**方式 2: Authorization Bearer Token**\n```http\nAuthorization: Bearer your-secret-key\n```\n\n### 配置\n\n通过环境变量设置 API Keys：\n```bash\nAPI_KEYS=key1,key2,key3\n```\n\n### 错误响应\n\n**401 未授权** - 缺少 API Key\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"UNAUTHORIZED\",\n    \"message\": \"需要 API Key。请提供 X-API-Key 请求头或 Authorization: Bearer <key>\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**403 禁止访问** - 无效的 API Key\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"FORBIDDEN\",\n    \"message\": \"无效的 API Key\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n## 速率限制\n\n默认：每个 API Key（或 IP）每分钟 100 次请求\n\n**配置**:\n```bash\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m  # 1m, 1h, 1d\n```\n\n**超出限制响应** (429):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"RATE_LIMIT_EXCEEDED\",\n    \"message\": \"请求过多，请稍后重试\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n## API 端点\n\n### MCP 协议端点\n\nMCP（Model Context Protocol）端点允许 Dify 等 AI 平台通过 MCP 协议直接连接数据库。\n\n#### SSE 端点（传统方式）\n\n##### GET /sse\n\n建立 SSE 连接，数据库配置通过 URL 参数传递。\n\n**URL 参数**:\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `type` | 是 | 数据库类型 |\n| `host` | 是* | 数据库主机 |\n| `port` | 否 | 数据库端口 |\n| `user` | 是* | 用户名 |\n| `password` | 是* | 密码 |\n| `database` | 是* | 数据库名称 |\n| `filePath` | 是* | SQLite 文件路径 |\n| `allowWrite` | 否 | 启用写操作（默认: false） |\n| `permissionMode` | 否 | 权限模式：`safe`（默认）、`readwrite`、`full` |\n| `permissions` | 否 | 自定义权限，逗号分隔：`read,insert,update,delete,ddl` |\n\n*必填字段取决于数据库类型\n\n> ⚠️ **注意**：URL 参数使用驼峰命名（`permissionMode`），不是连字符命名。\n\n**请求示例**:\n```bash\ncurl \"http://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=secret&database=mydb\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n##### POST /sse/message\n\n向 SSE 会话发送消息。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): SSE 会话 ID\n\n**请求示例**:\n```bash\ncurl -X POST \"http://localhost:3000/sse/message?sessionId=your-session-id\" \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1}'\n```\n\n#### Streamable HTTP 端点（MCP 2025 规范，推荐）\n\n##### POST /mcp\n\nMCP Streamable HTTP 端点，数据库配置通过请求头传递。\n\n**请求头参数**:\n| 请求头 | 必填 | 描述 |\n|--------|------|------|\n| `X-API-Key` | 是* | API 密钥（或使用 Authorization Bearer） |\n| `X-DB-Type` | 是 | 数据库类型 |\n| `X-DB-Host` | 是* | 数据库主机 |\n| `X-DB-Port` | 否 | 数据库端口 |\n| `X-DB-User` | 是* | 用户名 |\n| `X-DB-Password` | 是* | 密码 |\n| `X-DB-Database` | 是* | 数据库名称 |\n| `X-DB-FilePath` | 是* | SQLite 文件路径 |\n| `X-DB-Allow-Write` | 否 | 启用写操作（默认: false） |\n| `X-DB-Permission-Mode` | 否 | 权限模式：`safe`（默认）、`readwrite`、`full` |\n| `X-DB-Permissions` | 否 | 自定义权限，逗号分隔：`read,insert,update,delete,ddl` |\n| `mcp-session-id` | 否 | 后续请求的会话 ID |\n\n*必填字段取决于数据库类型；如果配置了 API_KEYS 则需要认证\n\n> ⚠️ **注意**：HTTP Header 使用连字符命名（`X-DB-Permission-Mode`）。\n\n**初始化请求示例**:\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-DB-Type: mysql\" \\\n  -H \"X-DB-Host: localhost\" \\\n  -H \"X-DB-Port: 3306\" \\\n  -H \"X-DB-User: root\" \\\n  -H \"X-DB-Password: secret\" \\\n  -H \"X-DB-Database: mydb\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}},\"id\":1}'\n```\n\n**后续请求示例**（使用会话 ID）:\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"mcp-session-id: your-session-id\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":2}'\n```\n\n##### GET /mcp\n\n获取 Streamable HTTP 的 SSE 流。\n\n**请求头**:\n- `mcp-session-id` (字符串, 必需): 会话 ID\n- `X-API-Key` (字符串, 必需*): API 密钥\n\n##### DELETE /mcp\n\n关闭 MCP 会话。\n\n**查询参数或请求头**:\n- `sessionId` 或 `mcp-session-id`: 会话 ID\n\n**请求示例**:\n```bash\ncurl -X DELETE \"http://localhost:3000/mcp?sessionId=your-session-id\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n#### MCP 工具\n\n通过 MCP 协议连接后，以下工具可用：\n\n| 工具名 | 描述 |\n|--------|------|\n| `execute_query` | 执行 SQL 查询或数据库命令 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取指定表的详细信息 |\n| `get_enum_values` | 获取指定列的所有唯一值（适用于枚举类型列） |\n| `get_sample_data` | 获取表的示例数据（自动脱敏保护隐私） |\n| `clear_cache` | 清除 Schema 缓存 |\n| `connect_database` | 动态连接数据库（支持全部 17 种数据库类型，已有连接时自动断开旧连接） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态（类型、地址、权限模式、缓存状态） |\n\n### REST API 端点\n\n### 健康检查和信息\n\n#### GET /api/health\n\n健康检查端点（无需认证）。\n\n**请求示例**:\n```bash\ncurl http://localhost:3000/api/health\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"healthy\",\n    \"uptime\": 3600.5,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/info\n\n服务信息端点（无需认证）。\n\n**请求示例**:\n```bash\ncurl http://localhost:3000/api/info\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"universal-db-mcp\",\n    \"version\": \"1.0.0\",\n    \"mode\": \"http\",\n    \"supportedDatabases\": [\n      \"mysql\", \"postgres\", \"redis\", \"oracle\", \"dm\",\n      \"sqlserver\", \"mongodb\", \"sqlite\", \"kingbase\",\n      \"gaussdb\", \"oceanbase\", \"tidb\", \"clickhouse\",\n      \"polardb\", \"vastbase\", \"highgo\", \"goldendb\"\n    ]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### 连接管理\n\n#### POST /api/connect\n\n连接到数据库并创建会话。\n\n**请求体**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"your_password\",\n  \"database\": \"mydb\",\n  \"allowWrite\": false,\n  \"permissionMode\": \"safe\",\n  \"permissions\": [\"read\", \"insert\"]\n}\n```\n\n**参数说明**:\n- `type` (字符串, 必需): 数据库类型（mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb）\n- `host` (字符串, 非 SQLite 必需): 数据库主机\n- `port` (数字, 非 SQLite 必需): 数据库端口\n- `user` (字符串, 可选): 用户名\n- `password` (字符串, 可选): 密码\n- `database` (字符串, 可选): 数据库名称\n- `filePath` (字符串, SQLite 必需): SQLite 数据库文件路径\n- `authSource` (字符串, MongoDB 可选): 认证数据库（默认: admin）\n- `allowWrite` (布尔值, 可选): 启用写操作（默认: false）- 已弃用，推荐使用 `permissionMode`\n- `permissionMode` (字符串, 可选): 权限模式：`safe`（默认）、`readwrite`、`full`\n- `permissions` (数组, 可选): 自定义权限数组：`[\"read\", \"insert\", \"update\", \"delete\", \"ddl\"]`\n\n> ⚠️ **注意**：JSON Body 使用驼峰命名（`permissionMode`），不是连字符命名如 `permission-mode`。\n\n**请求示例**:\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"testdb\"\n  }'\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**错误响应** (500):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CONNECTION_FAILED\",\n    \"message\": \"用户 'root'@'localhost' 访问被拒绝\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### POST /api/disconnect\n\n断开数据库连接并关闭会话。\n\n**请求体**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\"\n}\n```\n\n**请求示例**:\n```bash\ncurl -X POST http://localhost:3000/api/disconnect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\"}'\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"disconnected\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### 查询执行\n\n#### POST /api/query\n\n执行读取查询（SELECT、SHOW、DESCRIBE 等）。\n\n**请求体**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n  \"query\": \"SELECT * FROM users WHERE id = ?\",\n  \"params\": [1]\n}\n```\n\n**参数说明**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `query` (字符串, 必需): SQL 查询或数据库命令\n- `params` (数组, 可选): 参数化查询的参数\n\n**请求示例**:\n```bash\ncurl -X POST http://localhost:3000/api/query \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"query\": \"SELECT * FROM users LIMIT 10\"\n  }'\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [\n      {\"id\": 1, \"name\": \"Alice\", \"email\": \"alice@example.com\"},\n      {\"id\": 2, \"name\": \"Bob\", \"email\": \"bob@example.com\"}\n    ],\n    \"executionTime\": 15,\n    \"metadata\": {\n      \"fieldCount\": 3\n    }\n  },\n  \"metadata\": {\n    \"executionTime\": 15,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**错误响应 - 写操作被阻止** (500):\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"QUERY_FAILED\",\n    \"message\": \"❌ 操作被拒绝：当前处于只读安全模式\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### POST /api/execute\n\n执行写操作（INSERT、UPDATE、DELETE 等）。需要在连接配置中设置 `allowWrite: true`。\n\n**请求体**:\n```json\n{\n  \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n  \"query\": \"INSERT INTO users (name, email) VALUES (?, ?)\",\n  \"params\": [\"Charlie\", \"charlie@example.com\"]\n}\n```\n\n**请求示例**:\n```bash\ncurl -X POST http://localhost:3000/api/execute \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"query\": \"UPDATE users SET name = ? WHERE id = ?\",\n    \"params\": [\"Alice Smith\", 1]\n  }'\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [],\n    \"affectedRows\": 1,\n    \"executionTime\": 8\n  },\n  \"metadata\": {\n    \"executionTime\": 8,\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### Schema 信息\n\n#### GET /api/tables\n\n列出数据库中的所有表。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `forceRefresh` (字符串, 可选): 是否强制刷新缓存，值为 `true` 或 `false`（默认: `false`）\n\n**请求示例**:\n```bash\n# 使用缓存（默认）\ncurl \"http://localhost:3000/api/tables?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n\n# 强制刷新缓存\ncurl \"http://localhost:3000/api/tables?sessionId=V1StGXR8_Z5jdHi6B-myT&forceRefresh=true\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\", \"categories\"]\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/schema\n\n获取完整的数据库 Schema。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `forceRefresh` (字符串, 可选): 是否强制刷新缓存，值为 `true` 或 `false`（默认: `false`）\n\n**请求示例**:\n```bash\n# 使用缓存（默认，推荐）\ncurl \"http://localhost:3000/api/schema?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n\n# 强制刷新缓存（当数据库结构发生变化时使用）\ncurl \"http://localhost:3000/api/schema?sessionId=V1StGXR8_Z5jdHi6B-myT&forceRefresh=true\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"type\": \"mysql\",\n    \"name\": \"testdb\",\n    \"version\": \"8.0.32\",\n    \"tables\": [\n      {\n        \"name\": \"orders\",\n        \"columns\": [\n          {\n            \"name\": \"id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"订单ID\"\n          },\n          {\n            \"name\": \"user_id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"用户ID\"\n          }\n        ],\n        \"primaryKey\": [\"id\"],\n        \"indexes\": [\n          {\n            \"name\": \"PRIMARY\",\n            \"columns\": [\"id\"],\n            \"unique\": true\n          }\n        ],\n        \"foreignKeys\": [\n          {\n            \"name\": \"fk_orders_user\",\n            \"columns\": [\"user_id\"],\n            \"referencedTable\": \"users\",\n            \"referencedColumns\": [\"id\"],\n            \"onDelete\": \"CASCADE\",\n            \"onUpdate\": \"NO ACTION\"\n          }\n        ],\n        \"estimatedRows\": 5000\n      },\n      {\n        \"name\": \"users\",\n        \"columns\": [\n          {\n            \"name\": \"id\",\n            \"type\": \"int\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"用户ID\"\n          },\n          {\n            \"name\": \"name\",\n            \"type\": \"varchar(255)\",\n            \"nullable\": false,\n            \"default\": null,\n            \"comment\": \"用户名\"\n          }\n        ],\n        \"primaryKey\": [\"id\"],\n        \"indexes\": [\n          {\n            \"name\": \"PRIMARY\",\n            \"columns\": [\"id\"],\n            \"unique\": true\n          }\n        ],\n        \"estimatedRows\": 1000\n      }\n    ],\n    \"relationships\": [\n      {\n        \"fromTable\": \"orders\",\n        \"fromColumns\": [\"user_id\"],\n        \"toTable\": \"users\",\n        \"toColumns\": [\"id\"],\n        \"type\": \"many-to-one\",\n        \"constraintName\": \"fk_orders_user\"\n      }\n    ],\n    \"_cacheInfo\": {\n      \"cached\": true,\n      \"cachedAt\": \"2026-01-27T12:00:00.000Z\",\n      \"hitRate\": \"85.00%\"\n    }\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/schema/:table\n\n获取特定表的信息。\n\n**路径参数**:\n- `table` (字符串, 必需): 表名。支持 `schema.table_name` 格式指定 Schema（如 `analytics.users`）。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `forceRefresh` (字符串, 可选): 是否强制刷新缓存，值为 `true` 或 `false`（默认: `false`）\n\n**请求示例**:\n```bash\ncurl \"http://localhost:3000/api/schema/users?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"orders\",\n    \"columns\": [\n      {\n        \"name\": \"id\",\n        \"type\": \"int\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"订单ID\"\n      },\n      {\n        \"name\": \"user_id\",\n        \"type\": \"int\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"用户ID\"\n      },\n      {\n        \"name\": \"amount\",\n        \"type\": \"decimal(10,2)\",\n        \"nullable\": false,\n        \"default\": null,\n        \"comment\": \"订单金额\"\n      }\n    ],\n    \"primaryKey\": [\"id\"],\n    \"indexes\": [\n      {\n        \"name\": \"PRIMARY\",\n        \"columns\": [\"id\"],\n        \"unique\": true\n      },\n      {\n        \"name\": \"idx_user_id\",\n        \"columns\": [\"user_id\"],\n        \"unique\": false\n      }\n    ],\n    \"foreignKeys\": [\n      {\n        \"name\": \"fk_orders_user\",\n        \"columns\": [\"user_id\"],\n        \"referencedTable\": \"users\",\n        \"referencedColumns\": [\"id\"],\n        \"onDelete\": \"CASCADE\",\n        \"onUpdate\": \"NO ACTION\"\n      }\n    ],\n    \"estimatedRows\": 5000\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n### 枚举值查询\n\n#### GET /api/enum-values\n\n获取指定列的所有唯一值，适用于枚举类型或有限值集合的列。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `table` (字符串, 必需): 表名。支持 `schema.table_name` 格式指定 Schema（如 `analytics.users`）。\n- `column` (字符串, 必需): 列名\n- `limit` (数字, 可选): 返回的最大值数量（默认: 100）\n\n**请求示例**:\n```bash\ncurl \"http://localhost:3000/api/enum-values?sessionId=V1StGXR8_Z5jdHi6B-myT&table=orders&column=status\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"table\": \"orders\",\n    \"column\": \"status\",\n    \"values\": [\"pending\", \"processing\", \"shipped\", \"delivered\", \"cancelled\"],\n    \"totalCount\": 5,\n    \"isComplete\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**响应字段说明**:\n- `values`: 该列的所有唯一值数组\n- `totalCount`: 唯一值的总数\n- `isComplete`: 是否返回了所有唯一值（如果超过 limit 则为 false）\n\n### 示例数据查询\n\n#### GET /api/sample-data\n\n获取表的示例数据，自动对敏感数据进行脱敏处理。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n- `table` (字符串, 必需): 表名。支持 `schema.table_name` 格式指定 Schema（如 `analytics.users`）。\n- `limit` (数字, 可选): 返回的最大行数（默认: 5，最大: 100）\n- `masking` (字符串, 可选): 是否启用数据脱敏，值为 `true` 或 `false`（默认: `true`）\n\n**请求示例**:\n```bash\n# 获取示例数据（默认启用脱敏）\ncurl \"http://localhost:3000/api/sample-data?sessionId=V1StGXR8_Z5jdHi6B-myT&table=users\" \\\n  -H \"X-API-Key: your-secret-key\"\n\n# 获取更多示例数据\ncurl \"http://localhost:3000/api/sample-data?sessionId=V1StGXR8_Z5jdHi6B-myT&table=users&limit=10\" \\\n  -H \"X-API-Key: your-secret-key\"\n\n# 禁用脱敏（仅在安全环境中使用）\ncurl \"http://localhost:3000/api/sample-data?sessionId=V1StGXR8_Z5jdHi6B-myT&table=users&masking=false\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"table\": \"users\",\n    \"rows\": [\n      {\n        \"id\": 1,\n        \"name\": \"张*明\",\n        \"email\": \"z***@example.com\",\n        \"phone\": \"138****5678\",\n        \"status\": \"active\"\n      },\n      {\n        \"id\": 2,\n        \"name\": \"李*华\",\n        \"email\": \"l***@company.org\",\n        \"phone\": \"139****1234\",\n        \"status\": \"active\"\n      }\n    ],\n    \"totalRows\": 2,\n    \"maskedColumns\": [\"name\", \"email\", \"phone\"],\n    \"maskingEnabled\": true\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n**响应字段说明**:\n- `rows`: 示例数据行数组\n- `totalRows`: 返回的行数\n- `maskedColumns`: 被脱敏处理的列名列表\n- `maskingEnabled`: 是否启用了脱敏\n\n**支持的脱敏类型**:\n| 类型 | 示例 | 匹配的列名模式 |\n|------|------|----------------|\n| 手机号 | `138****5678` | phone, mobile, tel, telephone 等 |\n| 邮箱 | `z***@example.com` | email, mail, e_mail 等 |\n| 身份证 | `110***********1234` | id_card, idcard, identity 等 |\n| 银行卡 | `************1234` | bank_card, card_number 等 |\n| 密码 | `******` | password, secret, token, api_key 等 |\n| 部分隐藏 | `张*明` | real_name, address 等 |\n\n### 缓存管理\n\n为了提高大型数据库的性能，Schema 信息会被缓存。以下端点用于管理缓存。\n\n#### DELETE /api/cache\n\n清除指定会话的 Schema 缓存。当数据库结构发生变化（如新增表、修改列）时，可以调用此端点清除缓存。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n\n**请求示例**:\n```bash\ncurl -X DELETE \"http://localhost:3000/api/cache?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"cleared\": true,\n    \"message\": \"Schema 缓存已清除\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n#### GET /api/cache/status\n\n获取指定会话的缓存状态信息。\n\n**查询参数**:\n- `sessionId` (字符串, 必需): 从 `/api/connect` 获取的会话 ID\n\n**请求示例**:\n```bash\ncurl \"http://localhost:3000/api/cache/status?sessionId=V1StGXR8_Z5jdHi6B-myT\" \\\n  -H \"X-API-Key: your-secret-key\"\n```\n\n**响应** (200 OK):\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"V1StGXR8_Z5jdHi6B-myT\",\n    \"cache\": {\n      \"isCached\": true,\n      \"cachedAt\": \"2026-01-27T12:00:00.000Z\",\n      \"expiresAt\": \"2026-01-27T12:05:00.000Z\",\n      \"hitCount\": 15,\n      \"missCount\": 2\n    },\n    \"hitRate\": \"88.24%\"\n  },\n  \"metadata\": {\n    \"timestamp\": \"2026-01-27T12:00:00.000Z\",\n    \"requestId\": \"abc123\"\n  }\n}\n```\n\n## 错误代码\n\n| 代码 | HTTP 状态 | 描述 |\n|------|-----------|------|\n| `UNAUTHORIZED` | 401 | 缺少 API Key |\n| `FORBIDDEN` | 403 | 无效的 API Key |\n| `RATE_LIMIT_EXCEEDED` | 429 | 请求过多 |\n| `CONNECTION_FAILED` | 500 | 连接数据库失败 |\n| `DISCONNECTION_FAILED` | 500 | 断开数据库连接失败 |\n| `QUERY_FAILED` | 500 | 执行查询失败 |\n| `EXECUTE_FAILED` | 500 | 执行操作失败 |\n| `LIST_TABLES_FAILED` | 500 | 列出表失败 |\n| `GET_SCHEMA_FAILED` | 500 | 获取 Schema 失败 |\n| `GET_TABLE_INFO_FAILED` | 500 | 获取表信息失败 |\n| `GET_ENUM_VALUES_FAILED` | 500 | 获取枚举值失败 |\n| `GET_SAMPLE_DATA_FAILED` | 500 | 获取示例数据失败 |\n| `CLEAR_CACHE_FAILED` | 500 | 清除缓存失败 |\n| `GET_CACHE_STATUS_FAILED` | 500 | 获取缓存状态失败 |\n| `INTERNAL_ERROR` | 500 | 内部服务器错误 |\n\n## 会话管理\n\n### 会话生命周期\n\n1. **创建**: 调用 `/api/connect` 创建会话\n2. **使用**: 在后续 API 调用中使用 `sessionId`\n3. **关闭**: 调用 `/api/disconnect` 关闭会话\n\n### 会话超时\n\n会话在不活动后自动过期（默认：1 小时）。\n\n**配置**:\n```bash\nSESSION_TIMEOUT=3600000  # 1小时（毫秒）\nSESSION_CLEANUP_INTERVAL=300000  # 5分钟\n```\n\n### 会话清理\n\n过期的会话每 5 分钟自动清理一次（可配置）。\n\n## 数据库特定示例\n\n### MySQL\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"mydb\"\n  }'\n```\n\n### PostgreSQL\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"postgres\",\n    \"host\": \"localhost\",\n    \"port\": 5432,\n    \"user\": \"postgres\",\n    \"password\": \"password\",\n    \"database\": \"mydb\"\n  }'\n```\n\n### Redis\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"redis\",\n    \"host\": \"localhost\",\n    \"port\": 6379,\n    \"password\": \"password\"\n  }'\n```\n\n### MongoDB\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mongodb\",\n    \"host\": \"localhost\",\n    \"port\": 27017,\n    \"user\": \"admin\",\n    \"password\": \"password\",\n    \"database\": \"mydb\",\n    \"authSource\": \"admin\"\n  }'\n```\n\n### SQLite\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"sqlite\",\n    \"filePath\": \"/path/to/database.db\",\n    \"allowWrite\": false\n  }'\n```\n\n## 最佳实践\n\n### 安全性\n\n1. **使用强 API Keys**: 生成加密安全的随机密钥\n2. **启用 HTTPS**: 在生产环境使用反向代理（nginx、Caddy）配置 HTTPS\n3. **限制 CORS**: 设置特定的源而不是 `*`\n4. **默认只读**: 仅在必要时启用 `allowWrite`\n5. **关闭会话**: 完成后始终调用 `/api/disconnect`\n\n### 性能\n\n1. **复用会话**: 为多个查询保持会话活跃\n2. **使用参数化查询**: 防止 SQL 注入并提高性能\n3. **限制结果集**: 对大表使用 `LIMIT` 子句\n4. **监控速率限制**: 为速率限制错误实现指数退避\n\n### 错误处理\n\n1. **检查 `success` 字段**: 始终检查响应中的 `success` 字段\n2. **处理速率限制**: 实现带退避的重试逻辑\n3. **会话过期**: 如果会话过期则重新连接\n4. **记录请求 ID**: 使用元数据中的 `requestId` 进行调试\n\n## 完整工作流示例\n\n```bash\n# 1. 连接到数据库\nRESPONSE=$(curl -s -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"localhost\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"password\",\n    \"database\": \"testdb\"\n  }')\n\n# 2. 提取会话 ID\nSESSION_ID=$(echo $RESPONSE | jq -r '.data.sessionId')\n\n# 3. 列出表\ncurl \"http://localhost:3000/api/tables?sessionId=$SESSION_ID\" \\\n  -H \"X-API-Key: your-key\"\n\n# 4. 获取表 Schema\ncurl \"http://localhost:3000/api/schema/users?sessionId=$SESSION_ID\" \\\n  -H \"X-API-Key: your-key\"\n\n# 5. 执行查询\ncurl -X POST http://localhost:3000/api/query \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\n    \\\"sessionId\\\": \\\"$SESSION_ID\\\",\n    \\\"query\\\": \\\"SELECT * FROM users LIMIT 10\\\"\n  }\"\n\n# 6. 断开连接\ncurl -X POST http://localhost:3000/api/disconnect \\\n  -H \"X-API-Key: your-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"sessionId\\\": \\\"$SESSION_ID\\\"}\"\n```\n\n## 支持\n\n如有问题和疑问：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- 文档: https://github.com/Anarkh-Lee/universal-db-mcp#readme\n"
  },
  {
    "path": "docs/http-api/DEPLOYMENT.md",
    "content": "# Deployment Guide\n\nThis guide covers various deployment options for Universal Database MCP Server in HTTP API mode.\n\n## Table of Contents\n\n- [Local Deployment](#local-deployment)\n- [Docker Deployment](#docker-deployment)\n- [Serverless Deployment](#serverless-deployment)\n- [PaaS Platform Deployment](#paas-platform-deployment)\n- [Production Considerations](#production-considerations)\n\n## Local Deployment\n\n### Prerequisites\n\n- Node.js >= 20.0.0\n- npm or yarn\n- Database instance (MySQL, PostgreSQL, etc.)\n\n### Option 1: Direct Node.js\n\n#### 1. Install\n\n```bash\n# Global installation\nnpm install -g universal-db-mcp\n\n# Or local installation\nnpm install universal-db-mcp\n```\n\n#### 2. Configure\n\nCreate `.env` file:\n\n```bash\nMODE=http\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\nAPI_KEYS=your-secret-key-1,your-secret-key-2\nCORS_ORIGINS=*\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\nLOG_LEVEL=info\n```\n\n#### 3. Start\n\n```bash\n# If installed globally\nnpm run start:http\n\n# If installed locally\nnpx universal-db-mcp\n```\n\n#### 4. Verify\n\n```bash\ncurl http://localhost:3000/api/health\n```\n\n### Option 2: PM2 (Production)\n\nPM2 is a production process manager for Node.js applications.\n\n#### 1. Install PM2\n\n```bash\nnpm install -g pm2\n```\n\n#### 2. Create PM2 Configuration\n\nCreate `ecosystem.config.js`:\n\n```javascript\nmodule.exports = {\n  apps: [{\n    name: 'universal-db-mcp',\n    script: 'dist/index.js',\n    instances: 'max',\n    exec_mode: 'cluster',\n    env: {\n      NODE_ENV: 'production',\n      MODE: 'http',\n      HTTP_PORT: 3000,\n      HTTP_HOST: '0.0.0.0',\n      API_KEYS: 'your-secret-key-1,your-secret-key-2',\n      CORS_ORIGINS: '*',\n      RATE_LIMIT_MAX: 100,\n      RATE_LIMIT_WINDOW: '1m',\n      LOG_LEVEL: 'info'\n    },\n    error_file: './logs/err.log',\n    out_file: './logs/out.log',\n    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',\n    merge_logs: true,\n    max_memory_restart: '1G',\n    autorestart: true,\n    watch: false\n  }]\n};\n```\n\n#### 3. Start with PM2\n\n```bash\n# Build first\nnpm run build\n\n# Start\npm2 start ecosystem.config.js\n\n# View logs\npm2 logs universal-db-mcp\n\n# Monitor\npm2 monit\n\n# Restart\npm2 restart universal-db-mcp\n\n# Stop\npm2 stop universal-db-mcp\n\n# Delete\npm2 delete universal-db-mcp\n```\n\n#### 4. Auto-start on System Boot\n\n```bash\n# Generate startup script\npm2 startup\n\n# Save current process list\npm2 save\n```\n\n### Option 3: systemd (Linux)\n\nCreate `/etc/systemd/system/universal-db-mcp.service`:\n\n```ini\n[Unit]\nDescription=Universal Database MCP Server\nAfter=network.target\n\n[Service]\nType=simple\nUser=nodejs\nWorkingDirectory=/opt/universal-db-mcp\nEnvironment=\"NODE_ENV=production\"\nEnvironment=\"MODE=http\"\nEnvironment=\"HTTP_PORT=3000\"\nEnvironment=\"API_KEYS=your-secret-key\"\nExecStart=/usr/bin/node dist/index.js\nRestart=on-failure\nRestartSec=10\nStandardOutput=syslog\nStandardError=syslog\nSyslogIdentifier=universal-db-mcp\n\n[Install]\nWantedBy=multi-user.target\n```\n\nEnable and start:\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl enable universal-db-mcp\nsudo systemctl start universal-db-mcp\nsudo systemctl status universal-db-mcp\n```\n\n## Docker Deployment\n\n### Prerequisites\n\n- Docker >= 20.10\n- Docker Compose >= 2.0 (optional)\n\n### Option 1: Docker Run\n\n#### 1. Build Image\n\n```bash\ncd /path/to/universal-db-mcp\ndocker build -t universal-db-mcp:latest -f docker/Dockerfile .\n```\n\n#### 2. Run Container\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-key \\\n  -e CORS_ORIGINS=* \\\n  -e RATE_LIMIT_MAX=100 \\\n  -e LOG_LEVEL=info \\\n  --restart unless-stopped \\\n  universal-db-mcp:latest\n```\n\n#### 3. View Logs\n\n```bash\ndocker logs -f universal-db-mcp\n```\n\n#### 4. Stop/Remove\n\n```bash\ndocker stop universal-db-mcp\ndocker rm universal-db-mcp\n```\n\n### Option 2: Docker Compose\n\n#### 1. Create docker-compose.yml\n\n```yaml\nversion: '3.8'\n\nservices:\n  api:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n      - API_KEYS=${API_KEYS:-default-key-change-me}\n      - CORS_ORIGINS=${CORS_ORIGINS:-*}\n      - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100}\n      - LOG_LEVEL=${LOG_LEVEL:-info}\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"]\n      interval: 30s\n      timeout: 3s\n      retries: 3\n      start_period: 5s\n```\n\n#### 2. Create .env File\n\n```bash\nAPI_KEYS=your-secret-key-1,your-secret-key-2\nCORS_ORIGINS=*\nRATE_LIMIT_MAX=100\nLOG_LEVEL=info\n```\n\n#### 3. Start\n\n```bash\ndocker-compose up -d\n```\n\n#### 4. View Logs\n\n```bash\ndocker-compose logs -f\n```\n\n#### 5. Stop\n\n```bash\ndocker-compose down\n```\n\n### Docker with Database\n\nExample with MySQL:\n\n```yaml\nversion: '3.8'\n\nservices:\n  api:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - API_KEYS=your-secret-key\n    depends_on:\n      - mysql\n    networks:\n      - app-network\n\n  mysql:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: rootpassword\n      MYSQL_DATABASE: testdb\n    ports:\n      - \"3306:3306\"\n    volumes:\n      - mysql-data:/var/lib/mysql\n    networks:\n      - app-network\n\nnetworks:\n  app-network:\n    driver: bridge\n\nvolumes:\n  mysql-data:\n```\n\nConnect to MySQL from API:\n\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"mysql\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"rootpassword\",\n    \"database\": \"testdb\"\n  }'\n```\n\n## Serverless Deployment\n\n### Aliyun Function Compute\n\n#### 1. Install Funcraft\n\n```bash\nnpm install -g @alicloud/fun\n```\n\n#### 2. Create template.yml\n\n```yaml\nROSTemplateFormatVersion: '2015-09-01'\nTransform: 'Aliyun::Serverless-2018-04-03'\nResources:\n  universal-db-mcp:\n    Type: 'Aliyun::Serverless::Service'\n    Properties:\n      Description: 'Universal Database MCP Server'\n    universal-db-api:\n      Type: 'Aliyun::Serverless::Function'\n      Properties:\n        Handler: index.handler\n        Runtime: nodejs20\n        CodeUri: './'\n        MemorySize: 512\n        Timeout: 60\n        EnvironmentVariables:\n          MODE: http\n          HTTP_PORT: 9000\n          API_KEYS: your-secret-key\n        Events:\n          httpTrigger:\n            Type: HTTP\n            Properties:\n              AuthType: ANONYMOUS\n              Methods: ['GET', 'POST', 'PUT', 'DELETE']\n```\n\n#### 3. Create index.js Wrapper\n\n```javascript\nconst { startHttpServer } = require('./dist/http/http-index.js');\nconst { loadConfig } = require('./dist/utils/config-loader.js');\n\nlet server;\n\nexports.handler = async (req, res, context) => {\n  if (!server) {\n    const config = loadConfig();\n    server = await startHttpServer(config);\n  }\n\n  return server.inject({\n    method: req.method,\n    url: req.url,\n    headers: req.headers,\n    payload: req.body\n  });\n};\n```\n\n#### 4. Deploy\n\n```bash\nfun deploy\n```\n\n### Tencent Cloud SCF\n\n#### 1. Install Serverless Framework\n\n```bash\nnpm install -g serverless\n```\n\n#### 2. Create serverless.yml\n\n```yaml\ncomponent: scf\nname: universal-db-mcp\n\ninputs:\n  name: universal-db-mcp\n  src: ./\n  handler: index.handler\n  runtime: Nodejs20.15\n  region: ap-guangzhou\n  memorySize: 512\n  timeout: 60\n  environment:\n    variables:\n      MODE: http\n      HTTP_PORT: 9000\n      API_KEYS: your-secret-key\n  events:\n    - apigw:\n        parameters:\n          protocols:\n            - http\n            - https\n          environment: release\n          endpoints:\n            - path: /\n              method: ANY\n```\n\n#### 3. Deploy\n\n```bash\nserverless deploy\n```\n\n### AWS Lambda\n\n#### 1. Install AWS SAM CLI\n\n```bash\npip install aws-sam-cli\n```\n\n#### 2. Create template.yaml\n\n```yaml\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\n\nResources:\n  UniversalDbMcpFunction:\n    Type: AWS::Serverless::Function\n    Properties:\n      CodeUri: ./\n      Handler: index.handler\n      Runtime: nodejs20.x\n      MemorySize: 512\n      Timeout: 60\n      Environment:\n        Variables:\n          MODE: http\n          HTTP_PORT: 9000\n          API_KEYS: your-secret-key\n      Events:\n        ApiEvent:\n          Type: Api\n          Properties:\n            Path: /{proxy+}\n            Method: ANY\n```\n\n#### 3. Build and Deploy\n\n```bash\nsam build\nsam deploy --guided\n```\n\n### Vercel\n\n#### 1. Create vercel.json\n\n```json\n{\n  \"version\": 2,\n  \"builds\": [\n    {\n      \"src\": \"api/index.js\",\n      \"use\": \"@vercel/node\"\n    }\n  ],\n  \"routes\": [\n    {\n      \"src\": \"/api/(.*)\",\n      \"dest\": \"/api/index.js\"\n    }\n  ],\n  \"env\": {\n    \"MODE\": \"http\",\n    \"API_KEYS\": \"@api_keys\"\n  }\n}\n```\n\n#### 2. Create api/index.js\n\n```javascript\nconst { startHttpServer } = require('../dist/http/http-index.js');\nconst { loadConfig } = require('../dist/utils/config-loader.js');\n\nlet server;\n\nmodule.exports = async (req, res) => {\n  if (!server) {\n    const config = loadConfig();\n    server = await startHttpServer(config);\n  }\n\n  return server.inject({\n    method: req.method,\n    url: req.url,\n    headers: req.headers,\n    payload: req.body\n  });\n};\n```\n\n#### 3. Deploy\n\n```bash\nnpm install -g vercel\nvercel\n```\n\n## PaaS Platform Deployment\n\n### Railway\n\n#### 1. Create railway.json\n\n```json\n{\n  \"$schema\": \"https://railway.app/railway.schema.json\",\n  \"build\": {\n    \"builder\": \"NIXPACKS\",\n    \"buildCommand\": \"npm run build\"\n  },\n  \"deploy\": {\n    \"startCommand\": \"npm run start:http\",\n    \"restartPolicyType\": \"ON_FAILURE\",\n    \"restartPolicyMaxRetries\": 10\n  }\n}\n```\n\n#### 2. Deploy\n\n```bash\n# Install Railway CLI\nnpm install -g @railway/cli\n\n# Login\nrailway login\n\n# Initialize\nrailway init\n\n# Deploy\nrailway up\n```\n\n#### 3. Set Environment Variables\n\n```bash\nrailway variables set MODE=http\nrailway variables set HTTP_PORT=3000\nrailway variables set API_KEYS=your-secret-key\n```\n\n### Render\n\n#### 1. Create render.yaml\n\n```yaml\nservices:\n  - type: web\n    name: universal-db-mcp\n    env: node\n    buildCommand: npm install && npm run build\n    startCommand: npm run start:http\n    envVars:\n      - key: MODE\n        value: http\n      - key: HTTP_PORT\n        value: 3000\n      - key: API_KEYS\n        sync: false\n      - key: NODE_ENV\n        value: production\n    healthCheckPath: /api/health\n```\n\n#### 2. Deploy\n\n1. Push code to GitHub\n2. Connect repository in Render dashboard\n3. Render will auto-deploy\n\n### Fly.io\n\n#### 1. Install Fly CLI\n\n```bash\ncurl -L https://fly.io/install.sh | sh\n```\n\n#### 2. Create fly.toml\n\n```toml\napp = \"universal-db-mcp\"\nprimary_region = \"hkg\"\n\n[build]\n  builder = \"heroku/buildpacks:20\"\n\n[env]\n  MODE = \"http\"\n  HTTP_PORT = \"8080\"\n  NODE_ENV = \"production\"\n\n[http_service]\n  internal_port = 8080\n  force_https = true\n  auto_stop_machines = true\n  auto_start_machines = true\n  min_machines_running = 0\n\n[[services]]\n  http_checks = []\n  internal_port = 8080\n  processes = [\"app\"]\n  protocol = \"tcp\"\n  script_checks = []\n\n  [services.concurrency]\n    hard_limit = 25\n    soft_limit = 20\n    type = \"connections\"\n\n  [[services.ports]]\n    force_https = true\n    handlers = [\"http\"]\n    port = 80\n\n  [[services.ports]]\n    handlers = [\"tls\", \"http\"]\n    port = 443\n\n  [[services.tcp_checks]]\n    grace_period = \"1s\"\n    interval = \"15s\"\n    restart_limit = 0\n    timeout = \"2s\"\n```\n\n#### 3. Deploy\n\n```bash\n# Login\nfly auth login\n\n# Launch app\nfly launch\n\n# Set secrets\nfly secrets set API_KEYS=your-secret-key\n\n# Deploy\nfly deploy\n```\n\n## Production Considerations\n\n### Security\n\n#### 1. HTTPS/TLS\n\nUse reverse proxy (nginx, Caddy) for HTTPS:\n\n**nginx example**:\n\n```nginx\nserver {\n    listen 443 ssl http2;\n    server_name api.example.com;\n\n    ssl_certificate /path/to/cert.pem;\n    ssl_certificate_key /path/to/key.pem;\n\n    location / {\n        proxy_pass http://localhost:3000;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_cache_bypass $http_upgrade;\n    }\n}\n```\n\n#### 2. API Keys\n\nGenerate strong API keys:\n\n```bash\n# Generate random key\nopenssl rand -base64 32\n\n# Or use Node.js\nnode -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"\n```\n\n#### 3. CORS\n\nRestrict CORS origins in production:\n\n```bash\nCORS_ORIGINS=https://app.example.com,https://admin.example.com\n```\n\n#### 4. Rate Limiting\n\nAdjust rate limits based on your needs:\n\n```bash\nRATE_LIMIT_MAX=1000\nRATE_LIMIT_WINDOW=1h\n```\n\n### Monitoring\n\n#### 1. Health Checks\n\nConfigure health check endpoint:\n\n```bash\ncurl http://localhost:3000/api/health\n```\n\n#### 2. Logging\n\nUse structured logging:\n\n```bash\nLOG_LEVEL=info\nLOG_PRETTY=false  # JSON format for log aggregation\n```\n\n#### 3. Metrics\n\nMonitor key metrics:\n- Request rate\n- Response time\n- Error rate\n- Active sessions\n- Database connection pool\n\n### Performance\n\n#### 1. Clustering\n\nUse PM2 cluster mode:\n\n```javascript\n{\n  instances: 'max',  // Use all CPU cores\n  exec_mode: 'cluster'\n}\n```\n\n#### 2. Caching\n\nImplement caching for schema queries:\n\n```javascript\n// Cache schema for 5 minutes\nconst schemaCache = new Map();\n```\n\n#### 3. Connection Pooling\n\nConfigure database connection pools:\n\n```javascript\n// MySQL example\n{\n  connectionLimit: 10,\n  queueLimit: 0\n}\n```\n\n### Backup & Recovery\n\n#### 1. Database Backups\n\nRegular database backups:\n\n```bash\n# MySQL\nmysqldump -u root -p mydb > backup.sql\n\n# PostgreSQL\npg_dump mydb > backup.sql\n```\n\n#### 2. Configuration Backups\n\nBackup environment variables and configs.\n\n#### 3. Disaster Recovery\n\nDocument recovery procedures:\n1. Restore database from backup\n2. Redeploy application\n3. Restore environment variables\n4. Verify health checks\n\n## Troubleshooting\n\n### Common Issues\n\n#### Port Already in Use\n\n```bash\n# Find process using port\nlsof -i :3000\n\n# Kill process\nkill -9 <PID>\n```\n\n#### Permission Denied\n\n```bash\n# Use port > 1024 or run with sudo\nHTTP_PORT=8080\n```\n\n#### Database Connection Failed\n\nCheck:\n- Database is running\n- Credentials are correct\n- Network connectivity\n- Firewall rules\n\n#### High Memory Usage\n\n- Reduce session timeout\n- Implement connection pooling\n- Monitor for memory leaks\n\n### Logs\n\nView logs based on deployment method:\n\n```bash\n# PM2\npm2 logs universal-db-mcp\n\n# Docker\ndocker logs -f universal-db-mcp\n\n# systemd\njournalctl -u universal-db-mcp -f\n\n# Railway\nrailway logs\n\n# Render\n# View in dashboard\n\n# Fly.io\nfly logs\n```\n\n## Support\n\nFor deployment issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Documentation: https://github.com/Anarkh-Lee/universal-db-mcp#readme\n"
  },
  {
    "path": "docs/http-api/DEPLOYMENT.zh-CN.md",
    "content": "# 部署指南\n\n本指南涵盖 Universal Database MCP Server HTTP API 模式的各种部署选项。\n\n## 目录\n\n- [本地部署](#本地部署)\n- [Docker 部署](#docker-部署)\n- [Serverless 部署](#serverless-部署)\n- [PaaS 平台部署](#paas-平台部署)\n- [生产环境考虑](#生产环境考虑)\n\n## 本地部署\n\n### 前置要求\n\n- Node.js >= 20.0.0\n- npm 或 yarn\n- 数据库实例（MySQL、PostgreSQL 等）\n\n### 方式 1: 直接使用 Node.js\n\n#### 1. 安装\n\n```bash\n# 全局安装\nnpm install -g universal-db-mcp\n\n# 或本地安装\nnpm install universal-db-mcp\n```\n\n#### 2. 配置\n\n创建 `.env` 文件：\n\n```bash\nMODE=http\nHTTP_PORT=3000\nHTTP_HOST=0.0.0.0\nAPI_KEYS=your-secret-key-1,your-secret-key-2\nCORS_ORIGINS=*\nRATE_LIMIT_MAX=100\nRATE_LIMIT_WINDOW=1m\nLOG_LEVEL=info\n```\n\n#### 3. 启动\n\n```bash\n# 如果全局安装\nnpm run start:http\n\n# 如果本地安装\nnpx universal-db-mcp\n```\n\n#### 4. 验证\n\n```bash\ncurl http://localhost:3000/api/health\n```\n\n### 方式 2: PM2（生产环境）\n\nPM2 是 Node.js 应用的生产进程管理器。\n\n#### 1. 安装 PM2\n\n```bash\nnpm install -g pm2\n```\n\n#### 2. 创建 PM2 配置\n\n创建 `ecosystem.config.js`：\n\n```javascript\nmodule.exports = {\n  apps: [{\n    name: 'universal-db-mcp',\n    script: 'dist/index.js',\n    instances: 'max',\n    exec_mode: 'cluster',\n    env: {\n      NODE_ENV: 'production',\n      MODE: 'http',\n      HTTP_PORT: 3000,\n      HTTP_HOST: '0.0.0.0',\n      API_KEYS: 'your-secret-key-1,your-secret-key-2',\n      CORS_ORIGINS: '*',\n      RATE_LIMIT_MAX: 100,\n      RATE_LIMIT_WINDOW: '1m',\n      LOG_LEVEL: 'info'\n    },\n    error_file: './logs/err.log',\n    out_file: './logs/out.log',\n    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',\n    merge_logs: true,\n    max_memory_restart: '1G',\n    autorestart: true,\n    watch: false\n  }]\n};\n```\n\n#### 3. 使用 PM2 启动\n\n```bash\n# 先构建\nnpm run build\n\n# 启动\npm2 start ecosystem.config.js\n\n# 查看日志\npm2 logs universal-db-mcp\n\n# 监控\npm2 monit\n\n# 重启\npm2 restart universal-db-mcp\n\n# 停止\npm2 stop universal-db-mcp\n\n# 删除\npm2 delete universal-db-mcp\n```\n\n#### 4. 开机自启动\n\n```bash\n# 生成启动脚本\npm2 startup\n\n# 保存当前进程列表\npm2 save\n```\n\n### 方式 3: systemd（Linux）\n\n创建 `/etc/systemd/system/universal-db-mcp.service`：\n\n```ini\n[Unit]\nDescription=Universal Database MCP Server\nAfter=network.target\n\n[Service]\nType=simple\nUser=nodejs\nWorkingDirectory=/opt/universal-db-mcp\nEnvironment=\"NODE_ENV=production\"\nEnvironment=\"MODE=http\"\nEnvironment=\"HTTP_PORT=3000\"\nEnvironment=\"API_KEYS=your-secret-key\"\nExecStart=/usr/bin/node dist/index.js\nRestart=on-failure\nRestartSec=10\nStandardOutput=syslog\nStandardError=syslog\nSyslogIdentifier=universal-db-mcp\n\n[Install]\nWantedBy=multi-user.target\n```\n\n启用并启动：\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl enable universal-db-mcp\nsudo systemctl start universal-db-mcp\nsudo systemctl status universal-db-mcp\n```\n\n## Docker 部署\n\n### 前置要求\n\n- Docker >= 20.10\n- Docker Compose >= 2.0（可选）\n\n### 方式 1: Docker Run\n\n#### 1. 构建镜像\n\n```bash\ncd /path/to/universal-db-mcp\ndocker build -t universal-db-mcp:latest -f docker/Dockerfile .\n```\n\n#### 2. 运行容器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-key \\\n  -e CORS_ORIGINS=* \\\n  -e RATE_LIMIT_MAX=100 \\\n  -e LOG_LEVEL=info \\\n  --restart unless-stopped \\\n  universal-db-mcp:latest\n```\n\n#### 3. 查看日志\n\n```bash\ndocker logs -f universal-db-mcp\n```\n\n#### 4. 停止/删除\n\n```bash\ndocker stop universal-db-mcp\ndocker rm universal-db-mcp\n```\n\n### 方式 2: Docker Compose\n\n#### 1. 创建 docker-compose.yml\n\n```yaml\nversion: '3.8'\n\nservices:\n  api:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - HTTP_HOST=0.0.0.0\n      - API_KEYS=${API_KEYS:-default-key-change-me}\n      - CORS_ORIGINS=${CORS_ORIGINS:-*}\n      - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100}\n      - LOG_LEVEL=${LOG_LEVEL:-info}\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"node\", \"-e\", \"require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})\"]\n      interval: 30s\n      timeout: 3s\n      retries: 3\n      start_period: 5s\n```\n\n#### 2. 创建 .env 文件\n\n```bash\nAPI_KEYS=your-secret-key-1,your-secret-key-2\nCORS_ORIGINS=*\nRATE_LIMIT_MAX=100\nLOG_LEVEL=info\n```\n\n#### 3. 启动（根目录下执行）\n\n```bash\ndocker-compose up -d\n```\n\n#### 4. 查看日志\n\n```bash\ndocker-compose logs -f\n```\n\n#### 5. 停止\n\n```bash\ndocker-compose down\n```\n\n### Docker 配合数据库\n\nMySQL 示例：\n\n```yaml\nversion: '3.8'\n\nservices:\n  api:\n    build:\n      context: .\n      dockerfile: docker/Dockerfile\n    ports:\n      - \"3000:3000\"\n    environment:\n      - MODE=http\n      - HTTP_PORT=3000\n      - API_KEYS=your-secret-key\n    depends_on:\n      - mysql\n    networks:\n      - app-network\n\n  mysql:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: rootpassword\n      MYSQL_DATABASE: testdb\n    ports:\n      - \"3306:3306\"\n    volumes:\n      - mysql-data:/var/lib/mysql\n    networks:\n      - app-network\n\nnetworks:\n  app-network:\n    driver: bridge\n\nvolumes:\n  mysql-data:\n```\n\n从 API 连接到 MySQL：\n\n```bash\ncurl -X POST http://localhost:3000/api/connect \\\n  -H \"X-API-Key: your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"mysql\",\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"rootpassword\",\n    \"database\": \"testdb\"\n  }'\n```\n\n### 注意\n\n当你本地通过docker启动了这个mcp服务，而你的数据库也是通过docker启动的。\n\n当您的 API 服务运行在 Docker 容器中时，容器内的 localhost 指向的是容器自己，而不是宿主机（您的 Windows11）。所以容器无法通过 localhost 或 127.0.0.1 访问宿主机上的 MySQL 服务。\n\n**使用 host.docker.internal（推荐）**✅\n\n  适用场景： MySQL 容器独立运行，不在同一个 docker-compose 中\n\n  在 API 请求中修改 host：\n\n```json\n{\n    \"type\": \"mysql\",\n    \"host\": \"host.docker.internal\",  // ← 改这里\n    \"port\": 3306,\n    \"user\": \"root\",\n    \"password\": \"your_password\",\n    \"database\": \"your_database\"\n  }\n```\n\n  原理：\n  - host.docker.internal 是 Docker Desktop 提供的特殊 DNS 名称\n  - 它会自动解析为宿主机的 IP 地址\n  - 在 Windows 和 Mac 上都可用\n\n## Serverless 部署\n\n### 阿里云函数计算\n\n#### 1. 安装 Funcraft\n\n```bash\nnpm install -g @alicloud/fun\n```\n\n#### 2. 创建 template.yml\n\n```yaml\nROSTemplateFormatVersion: '2015-09-01'\nTransform: 'Aliyun::Serverless-2018-04-03'\nResources:\n  universal-db-mcp:\n    Type: 'Aliyun::Serverless::Service'\n    Properties:\n      Description: 'Universal Database MCP Server'\n    universal-db-api:\n      Type: 'Aliyun::Serverless::Function'\n      Properties:\n        Handler: index.handler\n        Runtime: nodejs20\n        CodeUri: './'\n        MemorySize: 512\n        Timeout: 60\n        EnvironmentVariables:\n          MODE: http\n          HTTP_PORT: 9000\n          API_KEYS: your-secret-key\n        Events:\n          httpTrigger:\n            Type: HTTP\n            Properties:\n              AuthType: ANONYMOUS\n              Methods: ['GET', 'POST', 'PUT', 'DELETE']\n```\n\n#### 3. 部署\n\n```bash\nfun deploy\n```\n\n### 腾讯云 SCF\n\n#### 1. 安装 Serverless Framework\n\n```bash\nnpm install -g serverless\n```\n\n#### 2. 创建 serverless.yml\n\n```yaml\ncomponent: scf\nname: universal-db-mcp\n\ninputs:\n  name: universal-db-mcp\n  src: ./\n  handler: index.handler\n  runtime: Nodejs20.15\n  region: ap-guangzhou\n  memorySize: 512\n  timeout: 60\n  environment:\n    variables:\n      MODE: http\n      HTTP_PORT: 9000\n      API_KEYS: your-secret-key\n  events:\n    - apigw:\n        parameters:\n          protocols:\n            - http\n            - https\n          environment: release\n          endpoints:\n            - path: /\n              method: ANY\n```\n\n#### 3. 部署\n\n```bash\nserverless deploy\n```\n\n### AWS Lambda\n\n#### 1. 安装 AWS SAM CLI\n\n```bash\npip install aws-sam-cli\n```\n\n#### 2. 创建 template.yaml\n\n```yaml\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\n\nResources:\n  UniversalDbMcpFunction:\n    Type: AWS::Serverless::Function\n    Properties:\n      CodeUri: ./\n      Handler: index.handler\n      Runtime: nodejs20.x\n      MemorySize: 512\n      Timeout: 60\n      Environment:\n        Variables:\n          MODE: http\n          HTTP_PORT: 9000\n          API_KEYS: your-secret-key\n      Events:\n        ApiEvent:\n          Type: Api\n          Properties:\n            Path: /{proxy+}\n            Method: ANY\n```\n\n#### 3. 构建和部署\n\n```bash\nsam build\nsam deploy --guided\n```\n\n### Vercel\n\n#### 1. 创建 vercel.json\n\n```json\n{\n  \"version\": 2,\n  \"builds\": [\n    {\n      \"src\": \"api/index.js\",\n      \"use\": \"@vercel/node\"\n    }\n  ],\n  \"routes\": [\n    {\n      \"src\": \"/api/(.*)\",\n      \"dest\": \"/api/index.js\"\n    }\n  ],\n  \"env\": {\n    \"MODE\": \"http\",\n    \"API_KEYS\": \"@api_keys\"\n  }\n}\n```\n\n#### 2. 部署\n\n```bash\nnpm install -g vercel\nvercel\n```\n\n## PaaS 平台部署\n\n### Railway\n\n#### 1. 创建 railway.json\n\n```json\n{\n  \"$schema\": \"https://railway.app/railway.schema.json\",\n  \"build\": {\n    \"builder\": \"NIXPACKS\",\n    \"buildCommand\": \"npm run build\"\n  },\n  \"deploy\": {\n    \"startCommand\": \"npm run start:http\",\n    \"restartPolicyType\": \"ON_FAILURE\",\n    \"restartPolicyMaxRetries\": 10\n  }\n}\n```\n\n#### 2. 部署\n\n```bash\n# 安装 Railway CLI\nnpm install -g @railway/cli\n\n# 登录\nrailway login\n\n# 初始化\nrailway init\n\n# 部署\nrailway up\n```\n\n#### 3. 设置环境变量\n\n```bash\nrailway variables set MODE=http\nrailway variables set HTTP_PORT=3000\nrailway variables set API_KEYS=your-secret-key\n```\n\n### Render\n\n#### 1. 创建 render.yaml\n\n```yaml\nservices:\n  - type: web\n    name: universal-db-mcp\n    env: node\n    buildCommand: npm install && npm run build\n    startCommand: npm run start:http\n    envVars:\n      - key: MODE\n        value: http\n      - key: HTTP_PORT\n        value: 3000\n      - key: API_KEYS\n        sync: false\n      - key: NODE_ENV\n        value: production\n    healthCheckPath: /api/health\n```\n\n#### 2. 部署\n\n1. 将代码推送到 GitHub\n2. 在 Render 控制台连接仓库\n3. Render 将自动部署\n\n### Fly.io\n\n#### 1. 安装 Fly CLI\n\n```bash\ncurl -L https://fly.io/install.sh | sh\n```\n\n#### 2. 创建 fly.toml\n\n```toml\napp = \"universal-db-mcp\"\nprimary_region = \"hkg\"\n\n[build]\n  builder = \"heroku/buildpacks:20\"\n\n[env]\n  MODE = \"http\"\n  HTTP_PORT = \"8080\"\n  NODE_ENV = \"production\"\n\n[http_service]\n  internal_port = 8080\n  force_https = true\n  auto_stop_machines = true\n  auto_start_machines = true\n  min_machines_running = 0\n\n[[services]]\n  http_checks = []\n  internal_port = 8080\n  processes = [\"app\"]\n  protocol = \"tcp\"\n\n  [[services.ports]]\n    force_https = true\n    handlers = [\"http\"]\n    port = 80\n\n  [[services.ports]]\n    handlers = [\"tls\", \"http\"]\n    port = 443\n```\n\n#### 3. 部署\n\n```bash\n# 登录\nfly auth login\n\n# 启动应用\nfly launch\n\n# 设置密钥\nfly secrets set API_KEYS=your-secret-key\n\n# 部署\nfly deploy\n```\n\n## 生产环境考虑\n\n### 安全性\n\n#### 1. HTTPS/TLS\n\n使用反向代理（nginx、Caddy）配置 HTTPS：\n\n**nginx 示例**:\n\n```nginx\nserver {\n    listen 443 ssl http2;\n    server_name api.example.com;\n\n    ssl_certificate /path/to/cert.pem;\n    ssl_certificate_key /path/to/key.pem;\n\n    location / {\n        proxy_pass http://localhost:3000;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_cache_bypass $http_upgrade;\n    }\n}\n```\n\n#### 2. API Keys\n\n生成强 API Keys：\n\n```bash\n# 生成随机密钥\nopenssl rand -base64 32\n\n# 或使用 Node.js\nnode -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"\n```\n\n#### 3. CORS\n\n在生产环境限制 CORS 源：\n\n```bash\nCORS_ORIGINS=https://app.example.com,https://admin.example.com\n```\n\n#### 4. 速率限制\n\n根据需求调整速率限制：\n\n```bash\nRATE_LIMIT_MAX=1000\nRATE_LIMIT_WINDOW=1h\n```\n\n### 监控\n\n#### 1. 健康检查\n\n配置健康检查端点：\n\n```bash\ncurl http://localhost:3000/api/health\n```\n\n#### 2. 日志\n\n使用结构化日志：\n\n```bash\nLOG_LEVEL=info\nLOG_PRETTY=false  # JSON 格式用于日志聚合\n```\n\n#### 3. 指标\n\n监控关键指标：\n- 请求速率\n- 响应时间\n- 错误率\n- 活跃会话数\n- 数据库连接池\n\n### 性能\n\n#### 1. 集群模式\n\n使用 PM2 集群模式：\n\n```javascript\n{\n  instances: 'max',  // 使用所有 CPU 核心\n  exec_mode: 'cluster'\n}\n```\n\n#### 2. 缓存\n\n为 Schema 查询实现缓存：\n\n```javascript\n// 缓存 Schema 5 分钟\nconst schemaCache = new Map();\n```\n\n#### 3. 连接池\n\n配置数据库连接池：\n\n```javascript\n// MySQL 示例\n{\n  connectionLimit: 10,\n  queueLimit: 0\n}\n```\n\n### 备份与恢复\n\n#### 1. 数据库备份\n\n定期数据库备份：\n\n```bash\n# MySQL\nmysqldump -u root -p mydb > backup.sql\n\n# PostgreSQL\npg_dump mydb > backup.sql\n```\n\n#### 2. 配置备份\n\n备份环境变量和配置。\n\n#### 3. 灾难恢复\n\n记录恢复流程：\n1. 从备份恢复数据库\n2. 重新部署应用\n3. 恢复环境变量\n4. 验证健康检查\n\n## 故障排除\n\n### 常见问题\n\n#### 端口已被占用\n\n```bash\n# 查找占用端口的进程\nlsof -i :3000\n\n# 终止进程\nkill -9 <PID>\n```\n\n#### 权限被拒绝\n\n```bash\n# 使用 > 1024 的端口或使用 sudo 运行\nHTTP_PORT=8080\n```\n\n#### 数据库连接失败\n\n检查：\n- 数据库是否运行\n- 凭据是否正确\n- 网络连接\n- 防火墙规则\n\n#### 内存使用过高\n\n- 减少会话超时\n- 实现连接池\n- 监控内存泄漏\n\n### 日志\n\n根据部署方式查看日志：\n\n```bash\n# PM2\npm2 logs universal-db-mcp\n\n# Docker\ndocker logs -f universal-db-mcp\n\n# systemd\njournalctl -u universal-db-mcp -f\n\n# Railway\nrailway logs\n\n# Render\n# 在控制台查看\n\n# Fly.io\nfly logs\n```\n\n## 支持\n\n如有部署问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- 文档: https://github.com/Anarkh-Lee/universal-db-mcp#readme\n"
  },
  {
    "path": "docs/integrations/5IRE.md",
    "content": "# 5ire Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with 5ire.\n\n## Overview\n\n[5ire](https://github.com/5ire-tech/5ire) is a cross-platform AI chat application. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- 5ire installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to 5ire's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk 5ire about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Resources\n\n- [5ire GitHub](https://github.com/5ire-tech/5ire)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/5IRE.zh-CN.md",
    "content": "# 5ire 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 5ire 集成。\n\n## 概述\n\n[5ire](https://github.com/5ire-tech/5ire) 是一个跨平台 AI 聊天应用。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- 已安装 5ire\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 5ire 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 5ire 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 资源\n\n- [5ire GitHub](https://github.com/5ire-tech/5ire)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/AMAZON-BEDROCK-AGENTS.md",
    "content": "# Amazon Bedrock Agents Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Amazon Bedrock Agents.\n\n## Overview\n\n[Amazon Bedrock Agents](https://aws.amazon.com/bedrock/) is AWS's AI agent service. It supports MCP via SSE/Streamable HTTP, allowing you to use database tools in your agents.\n\n## Prerequisites\n\n- AWS account\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=bedrock-agent-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Configure Bedrock Agent\n\nConfigure your Bedrock Agent in the AWS Console to use the MCP server as a tool.\n\n## Resources\n\n- [Amazon Bedrock Documentation](https://docs.aws.amazon.com/bedrock/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/AMAZON-BEDROCK-AGENTS.zh-CN.md",
    "content": "# Amazon Bedrock Agents 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Amazon Bedrock Agents 集成。\n\n## 概述\n\n[Amazon Bedrock Agents](https://aws.amazon.com/bedrock/) 是 AWS 的 AI 代理服务。它通过 SSE/Streamable HTTP 支持 MCP，允许您在代理中使用数据库工具。\n\n## 前置要求\n\n- AWS 账号\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=bedrock-agent-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：配置 Bedrock Agent\n\n在 AWS 控制台中配置 Bedrock Agent 使用 MCP 服务器作为工具。\n\n## 资源\n\n- [Amazon Bedrock 文档](https://docs.aws.amazon.com/bedrock/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/AMAZON-Q-DEVELOPER.md",
    "content": "# Amazon Q Developer Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Amazon Q Developer.\n\n## Overview\n\n[Amazon Q Developer](https://aws.amazon.com/q/developer/) is AWS's AI coding assistant. It supports MCP, allowing you to query databases while coding.\n\n## Prerequisites\n\n- Amazon Q Developer installed in VS Code or JetBrains\n- AWS account\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Amazon Q's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Amazon Q about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\nGenerate code to query the orders table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Amazon Q Developer Documentation](https://docs.aws.amazon.com/amazonq/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/AMAZON-Q-DEVELOPER.zh-CN.md",
    "content": "# Amazon Q Developer 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Amazon Q Developer 集成。\n\n## 概述\n\n[Amazon Q Developer](https://aws.amazon.com/q/developer/) 是 AWS 的 AI 编码助手。它支持 MCP，允许您在编码时查询数据库。\n\n## 前置要求\n\n- 在 VS Code 或 JetBrains 中安装了 Amazon Q Developer\n- AWS 账号\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Amazon Q 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Amazon Q 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n生成查询 orders 表的代码\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Amazon Q Developer 文档](https://docs.aws.amazon.com/amazonq/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/CHATGPT.md",
    "content": "# ChatGPT Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with ChatGPT using MCP Connectors.\n\n## Overview\n\nChatGPT supports remote MCP servers through MCP Connectors, enabling direct integration with Universal Database MCP Server via SSE or Streamable HTTP protocols. This allows ChatGPT to query and analyze your database data using natural language.\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP mode\n- ChatGPT Plus, Team, or Enterprise subscription (MCP Connectors require paid plans)\n- Database instance (MySQL, PostgreSQL, etc.)\n- Publicly accessible server URL (for ChatGPT to connect)\n\n## Setup Steps\n\n### Step 1: Deploy HTTP Server\n\nDeploy Universal Database MCP Server in HTTP mode with a publicly accessible URL:\n\n```bash\n# Using npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-api-key\nnpx universal-db-mcp\n\n# Or using Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-api-key \\\n  universal-db-mcp:latest\n```\n\nFor production, deploy to a cloud platform (Railway, Render, Fly.io, AWS, etc.). See [Deployment Guide](../http-api/DEPLOYMENT.md).\n\n> **Important**: ChatGPT requires a publicly accessible HTTPS URL. Local servers (localhost) will not work.\n\n### Step 2: Verify Server Deployment\n\nTest your server is accessible:\n\n```bash\n# Test health endpoint\ncurl https://your-server-url/health\n\n# Test MCP endpoint (should return method not allowed for GET without proper headers)\ncurl https://your-server-url/mcp\n```\n\n### Step 3: Add MCP Connector in ChatGPT\n\n1. Open [ChatGPT](https://chat.openai.com/)\n2. Click on your profile icon in the bottom-left corner\n3. Select **Settings**\n4. Navigate to **Connectors** or **MCP Connectors**\n5. Click **Add Connector** or **Add MCP Server**\n\n### Step 4: Configure MCP Connector\n\n#### Option A: Streamable HTTP Endpoint (Recommended)\n\n**Server URL**:\n```\nhttps://your-server-url/mcp\n```\n\n**Headers Configuration**:\n```\nX-API-Key: your-secret-api-key\nX-DB-Type: mysql\nX-DB-Host: your-database-host\nX-DB-Port: 3306\nX-DB-User: your-username\nX-DB-Password: your-password\nX-DB-Database: your-database-name\n```\n\n#### Option B: SSE Endpoint\n\n**Server URL**:\n```\nhttps://your-server-url/sse?type=mysql&host=your-database-host&port=3306&user=your-username&password=your-password&database=your-database-name\n```\n\n**Headers Configuration**:\n```\nX-API-Key: your-secret-api-key\n```\n\n> **Note**: SSE endpoint passes database configuration via URL parameters, while Streamable HTTP uses headers.\n\n### Step 5: Save and Test Connection\n\n1. Click **Save** or **Connect**\n2. ChatGPT will attempt to connect to your MCP server\n3. If successful, the connector will show as \"Connected\"\n\n## Available MCP Tools\n\nOnce connected, the following tools become available in ChatGPT:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Header Reference\n\n### Authentication Header\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-API-Key` | Yes* | API key for authentication (if API_KEYS is configured on server) |\n\n### Database Configuration Headers (for Streamable HTTP)\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-DB-Type` | Yes | Database type: mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `X-DB-Host` | Yes* | Database host address |\n| `X-DB-Port` | No | Database port (uses default if not specified) |\n| `X-DB-User` | Yes* | Database username |\n| `X-DB-Password` | Yes* | Database password |\n| `X-DB-Database` | Yes* | Database name |\n| `X-DB-FilePath` | Yes* | SQLite file path (for sqlite type only) |\n| `X-DB-Allow-Write` | No | Enable write operations (default: false) |\n| `X-DB-Oracle-Client-Path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## URL Parameters (for SSE Endpoint)\n\n| Parameter | Required | Description |\n|-----------|----------|-------------|\n| `type` | Yes | Database type |\n| `host` | Yes* | Database host |\n| `port` | No | Database port |\n| `user` | Yes* | Database username |\n| `password` | Yes* | Database password |\n| `database` | Yes* | Database name |\n| `filePath` | Yes* | SQLite file path (for sqlite type) |\n| `allowWrite` | No | Enable write operations (default: false) |\n\n## Configuration Examples\n\n### MySQL\n\n**Streamable HTTP Headers**:\n```\nX-API-Key: your-api-key\nX-DB-Type: mysql\nX-DB-Host: mysql.example.com\nX-DB-Port: 3306\nX-DB-User: app_user\nX-DB-Password: secure_password\nX-DB-Database: production_db\n```\n\n**SSE URL**:\n```\nhttps://your-server/sse?type=mysql&host=mysql.example.com&port=3306&user=app_user&password=secure_password&database=production_db\n```\n\n### PostgreSQL\n\n**Streamable HTTP Headers**:\n```\nX-API-Key: your-api-key\nX-DB-Type: postgres\nX-DB-Host: postgres.example.com\nX-DB-Port: 5432\nX-DB-User: postgres_user\nX-DB-Password: secure_password\nX-DB-Database: analytics_db\n```\n\n**SSE URL**:\n```\nhttps://your-server/sse?type=postgres&host=postgres.example.com&port=5432&user=postgres_user&password=secure_password&database=analytics_db\n```\n\n### SQLite\n\n**Streamable HTTP Headers**:\n```\nX-API-Key: your-api-key\nX-DB-Type: sqlite\nX-DB-FilePath: /path/to/database.db\n```\n\n**SSE URL**:\n```\nhttps://your-server/sse?type=sqlite&filePath=/path/to/database.db\n```\n\n### Redis\n\n**Streamable HTTP Headers**:\n```\nX-API-Key: your-api-key\nX-DB-Type: redis\nX-DB-Host: redis.example.com\nX-DB-Port: 6379\nX-DB-Password: redis_password\n```\n\n## Usage Examples\n\nOnce the MCP Connector is configured, you can interact with your database using natural language in ChatGPT:\n\n### Example 1: Explore Database Schema\n\n```\nUser: What tables are in my database?\n\nChatGPT: [Uses get_schema tool]\nYour database contains the following tables:\n- users (id, name, email, created_at)\n- orders (id, user_id, total, status, created_at)\n- products (id, name, price, category, stock)\n```\n\n### Example 2: Simple Query\n\n```\nUser: Show me the first 10 users\n\nChatGPT: [Uses execute_query tool with \"SELECT * FROM users LIMIT 10\"]\nHere are the first 10 users:\n| ID | Name | Email | Created At |\n|----|------|-------|------------|\n| 1 | Alice | alice@example.com | 2026-01-15 |\n| 2 | Bob | bob@example.com | 2026-01-16 |\n...\n```\n\n### Example 3: Aggregation Query\n\n```\nUser: How many orders were placed last month and what was the total revenue?\n\nChatGPT: [Uses execute_query tool]\nLast month's order statistics:\n- Total orders: 1,234\n- Total revenue: $125,430.50\n- Average order value: $101.65\n```\n\n### Example 4: Complex Analysis\n\n```\nUser: Which products have the highest sales volume this quarter?\n\nChatGPT: [Analyzes schema, generates appropriate SQL, executes query]\nTop 5 products by sales volume this quarter:\n1. Widget Pro - 523 units ($26,150)\n2. Gadget Plus - 412 units ($20,600)\n3. Super Tool - 389 units ($19,450)\n...\n```\n\n## Advanced Configuration\n\n### Enable Write Operations\n\nTo allow INSERT, UPDATE, DELETE operations:\n\n**Streamable HTTP**:\n```\nX-DB-Allow-Write: true\n```\n\n**SSE URL**:\n```\nhttps://your-server/sse?type=mysql&host=...&allowWrite=true\n```\n\n> **Warning**: Enable write operations with caution. Ensure proper access controls are in place.\n\n### Multiple Database Connections\n\nYou can add multiple MCP Connectors in ChatGPT, each connecting to a different database:\n\n1. Add first connector: \"Production MySQL\"\n2. Add second connector: \"Analytics PostgreSQL\"\n3. Add third connector: \"Cache Redis\"\n\nChatGPT will intelligently select the appropriate connector based on your queries.\n\n## Security Best Practices\n\n### 1. Use HTTPS\n\nAlways deploy your MCP server with HTTPS enabled. ChatGPT requires secure connections.\n\n### 2. Strong API Keys\n\n- Generate strong, random API keys\n- Rotate keys periodically\n- Never share keys in public repositories\n\n### 3. Database User Permissions\n\n- Create dedicated database users for ChatGPT access\n- Grant only necessary permissions (preferably read-only)\n- Avoid using root/admin credentials\n\n### 4. Network Security\n\n- Use firewall rules to restrict access\n- Consider VPN or private networking for sensitive databases\n- Monitor access logs regularly\n\n### 5. Data Sensitivity\n\n- Be aware that queries and results pass through ChatGPT\n- Avoid connecting to databases with highly sensitive data (PII, financial records)\n- Consider data masking for sensitive columns\n\n## Troubleshooting\n\n### Issue: Connection Failed\n\n**Symptoms**: ChatGPT cannot connect to MCP server\n\n**Solutions**:\n1. Verify server URL is publicly accessible (not localhost)\n2. Ensure HTTPS is properly configured\n3. Check API key is correct\n4. Verify server is running and healthy\n5. Check firewall allows incoming connections\n\n### Issue: Authentication Error\n\n**Symptoms**: \"Unauthorized\" or \"Invalid API Key\" error\n\n**Solutions**:\n1. Verify X-API-Key header is correctly set\n2. Ensure API key matches server configuration\n3. Check for extra spaces or characters in the key\n\n### Issue: Database Connection Error\n\n**Symptoms**: Server connects but database queries fail\n\n**Solutions**:\n1. Verify database credentials are correct\n2. Check database host is accessible from server\n3. Ensure database port is open\n4. Verify database name exists\n\n### Issue: Query Timeout\n\n**Symptoms**: Queries take too long or timeout\n\n**Solutions**:\n1. Optimize SQL queries\n2. Add database indexes\n3. Increase server timeout settings\n4. Use LIMIT for large result sets\n\n### Issue: SSL/TLS Errors\n\n**Symptoms**: Certificate or SSL-related errors\n\n**Solutions**:\n1. Ensure valid SSL certificate is installed\n2. Check certificate is not expired\n3. Verify certificate chain is complete\n\n## Limitations\n\n- ChatGPT MCP Connectors require a paid subscription\n- Server must be publicly accessible via HTTPS\n- Some complex queries may require multiple interactions\n- Large result sets may be truncated\n- Real-time streaming of results may vary\n\n## Resources\n\n- [ChatGPT Documentation](https://help.openai.com/)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Deployment Guide](../http-api/DEPLOYMENT.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- OpenAI Help Center: https://help.openai.com/\n"
  },
  {
    "path": "docs/integrations/CHATGPT.zh-CN.md",
    "content": "# ChatGPT 集成指南\n\n本指南展示如何通过 MCP Connectors 将 Universal Database MCP Server 与 ChatGPT 集成。\n\n## 概述\n\nChatGPT 通过 MCP Connectors 支持远程 MCP 服务器，可以通过 SSE 或 Streamable HTTP 协议直接与 Universal Database MCP Server 集成。这使得 ChatGPT 能够使用自然语言查询和分析您的数据库数据。\n\n## 前置要求\n\n- 部署了 HTTP 模式的 Universal Database MCP Server\n- ChatGPT Plus、Team 或 Enterprise 订阅（MCP Connectors 需要付费计划）\n- 数据库实例（MySQL、PostgreSQL 等）\n- 可公开访问的服务器 URL（供 ChatGPT 连接）\n\n## 设置步骤\n\n### 步骤 1: 部署 HTTP 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server，并确保可公开访问：\n\n```bash\n# 使用 npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-api-key\nnpx universal-db-mcp\n\n# 或使用 Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-api-key \\\n  universal-db-mcp:latest\n```\n\n生产环境建议部署到云平台（Railway、Render、Fly.io、AWS 等）。参见[部署指南](../http-api/DEPLOYMENT.zh-CN.md)。\n\n> **重要**：ChatGPT 需要可公开访问的 HTTPS URL。本地服务器（localhost）无法使用。\n\n### 步骤 2: 验证服务器部署\n\n测试服务器是否可访问：\n\n```bash\n# 测试健康检查端点\ncurl https://your-server-url/health\n\n# 测试 MCP 端点\ncurl https://your-server-url/mcp\n```\n\n### 步骤 3: 在 ChatGPT 中添加 MCP Connector\n\n1. 打开 [ChatGPT](https://chat.openai.com/)\n2. 点击左下角的个人头像\n3. 选择 **设置**（Settings）\n4. 导航到 **Connectors** 或 **MCP Connectors**\n5. 点击 **添加 Connector**（Add Connector）或 **添加 MCP 服务器**（Add MCP Server）\n\n### 步骤 4: 配置 MCP Connector\n\n#### 方式 A: Streamable HTTP 端点（推荐）\n\n**服务器 URL**：\n```\nhttps://your-server-url/mcp\n```\n\n**请求头配置**：\n```\nX-API-Key: your-secret-api-key\nX-DB-Type: mysql\nX-DB-Host: your-database-host\nX-DB-Port: 3306\nX-DB-User: your-username\nX-DB-Password: your-password\nX-DB-Database: your-database-name\n```\n\n#### 方式 B: SSE 端点\n\n**服务器 URL**：\n```\nhttps://your-server-url/sse?type=mysql&host=your-database-host&port=3306&user=your-username&password=your-password&database=your-database-name\n```\n\n**请求头配置**：\n```\nX-API-Key: your-secret-api-key\n```\n\n> **说明**：SSE 端点通过 URL 参数传递数据库配置，而 Streamable HTTP 使用请求头。\n\n### 步骤 5: 保存并测试连接\n\n1. 点击 **保存**（Save）或 **连接**（Connect）\n2. ChatGPT 将尝试连接到您的 MCP 服务器\n3. 如果成功，连接器将显示为\"已连接\"（Connected）\n\n## 可用的 MCP 工具\n\n连接成功后，以下工具将在 ChatGPT 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除结构缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 请求头参考\n\n### 认证请求头\n\n| 请求头 | 必需 | 描述 |\n|--------|------|------|\n| `X-API-Key` | 是* | API 密钥认证（如果服务器配置了 API_KEYS） |\n\n### 数据库配置请求头（用于 Streamable HTTP）\n\n| 请求头 | 必需 | 描述 |\n|--------|------|------|\n| `X-DB-Type` | 是 | 数据库类型：mysql、postgres、redis、oracle、dm、sqlserver、mongodb、sqlite、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `X-DB-Host` | 是* | 数据库主机地址 |\n| `X-DB-Port` | 否 | 数据库端口（未指定时使用默认值） |\n| `X-DB-User` | 是* | 数据库用户名 |\n| `X-DB-Password` | 是* | 数据库密码 |\n| `X-DB-Database` | 是* | 数据库名称 |\n| `X-DB-FilePath` | 是* | SQLite 文件路径（仅用于 sqlite 类型） |\n| `X-DB-Allow-Write` | 否 | 启用写操作（默认：false） |\n| `X-DB-Oracle-Client-Path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必需字段取决于数据库类型\n\n## URL 参数（用于 SSE 端点）\n\n| 参数 | 必需 | 描述 |\n|------|------|------|\n| `type` | 是 | 数据库类型 |\n| `host` | 是* | 数据库主机 |\n| `port` | 否 | 数据库端口 |\n| `user` | 是* | 数据库用户名 |\n| `password` | 是* | 数据库密码 |\n| `database` | 是* | 数据库名称 |\n| `filePath` | 是* | SQLite 文件路径（用于 sqlite 类型） |\n| `allowWrite` | 否 | 启用写操作（默认：false） |\n\n## 配置示例\n\n### MySQL\n\n**Streamable HTTP 请求头**：\n```\nX-API-Key: your-api-key\nX-DB-Type: mysql\nX-DB-Host: mysql.example.com\nX-DB-Port: 3306\nX-DB-User: app_user\nX-DB-Password: secure_password\nX-DB-Database: production_db\n```\n\n**SSE URL**：\n```\nhttps://your-server/sse?type=mysql&host=mysql.example.com&port=3306&user=app_user&password=secure_password&database=production_db\n```\n\n### PostgreSQL\n\n**Streamable HTTP 请求头**：\n```\nX-API-Key: your-api-key\nX-DB-Type: postgres\nX-DB-Host: postgres.example.com\nX-DB-Port: 5432\nX-DB-User: postgres_user\nX-DB-Password: secure_password\nX-DB-Database: analytics_db\n```\n\n**SSE URL**：\n```\nhttps://your-server/sse?type=postgres&host=postgres.example.com&port=5432&user=postgres_user&password=secure_password&database=analytics_db\n```\n\n### SQLite\n\n**Streamable HTTP 请求头**：\n```\nX-API-Key: your-api-key\nX-DB-Type: sqlite\nX-DB-FilePath: /path/to/database.db\n```\n\n**SSE URL**：\n```\nhttps://your-server/sse?type=sqlite&filePath=/path/to/database.db\n```\n\n### Redis\n\n**Streamable HTTP 请求头**：\n```\nX-API-Key: your-api-key\nX-DB-Type: redis\nX-DB-Host: redis.example.com\nX-DB-Port: 6379\nX-DB-Password: redis_password\n```\n\n## 使用示例\n\n配置好 MCP Connector 后，您可以在 ChatGPT 中使用自然语言与数据库交互：\n\n### 示例 1: 探索数据库结构\n\n```\n用户：我的数据库里有哪些表？\n\nChatGPT：[使用 get_schema 工具]\n您的数据库包含以下表：\n- users（id、name、email、created_at）\n- orders（id、user_id、total、status、created_at）\n- products（id、name、price、category、stock）\n```\n\n### 示例 2: 简单查询\n\n```\n用户：显示前 10 个用户\n\nChatGPT：[使用 execute_query 工具执行 \"SELECT * FROM users LIMIT 10\"]\n以下是前 10 个用户：\n| ID | 姓名 | 邮箱 | 创建时间 |\n|----|------|------|----------|\n| 1 | Alice | alice@example.com | 2026-01-15 |\n| 2 | Bob | bob@example.com | 2026-01-16 |\n...\n```\n\n### 示例 3: 聚合查询\n\n```\n用户：上个月有多少订单？总收入是多少？\n\nChatGPT：[使用 execute_query 工具]\n上个月订单统计：\n- 总订单数：1,234\n- 总收入：¥125,430.50\n- 平均订单金额：¥101.65\n```\n\n### 示例 4: 复杂分析\n\n```\n用户：本季度哪些产品销量最高？\n\nChatGPT：[分析结构，生成适当的 SQL，执行查询]\n本季度销量前 5 的产品：\n1. Widget Pro - 523 件（¥26,150）\n2. Gadget Plus - 412 件（¥20,600）\n3. Super Tool - 389 件（¥19,450）\n...\n```\n\n## 高级配置\n\n### 启用写操作\n\n允许 INSERT、UPDATE、DELETE 操作：\n\n**Streamable HTTP**：\n```\nX-DB-Allow-Write: true\n```\n\n**SSE URL**：\n```\nhttps://your-server/sse?type=mysql&host=...&allowWrite=true\n```\n\n> **警告**：请谨慎启用写操作。确保已设置适当的访问控制。\n\n### 多数据库连接\n\n您可以在 ChatGPT 中添加多个 MCP Connector，每个连接到不同的数据库：\n\n1. 添加第一个连接器：\"生产环境 MySQL\"\n2. 添加第二个连接器：\"分析 PostgreSQL\"\n3. 添加第三个连接器：\"缓存 Redis\"\n\nChatGPT 会根据您的查询智能选择适当的连接器。\n\n## 安全最佳实践\n\n### 1. 使用 HTTPS\n\n始终使用启用 HTTPS 的方式部署 MCP 服务器。ChatGPT 要求安全连接。\n\n### 2. 强 API 密钥\n\n- 生成强随机 API 密钥\n- 定期轮换密钥\n- 切勿在公共仓库中分享密钥\n\n### 3. 数据库用户权限\n\n- 为 ChatGPT 访问创建专用数据库用户\n- 仅授予必要的权限（最好是只读）\n- 避免使用 root/admin 凭据\n\n### 4. 网络安全\n\n- 使用防火墙规则限制访问\n- 对敏感数据库考虑使用 VPN 或私有网络\n- 定期监控访问日志\n\n### 5. 数据敏感性\n\n- 注意查询和结果会通过 ChatGPT 传输\n- 避免连接包含高度敏感数据的数据库（个人身份信息、财务记录）\n- 考虑对敏感列进行数据脱敏\n\n## 故障排除\n\n### 问题：连接失败\n\n**症状**：ChatGPT 无法连接到 MCP 服务器\n\n**解决方案**：\n1. 验证服务器 URL 可公开访问（不是 localhost）\n2. 确保 HTTPS 配置正确\n3. 检查 API 密钥是否正确\n4. 验证服务器正在运行且健康\n5. 检查防火墙是否允许入站连接\n\n### 问题：认证错误\n\n**症状**：\"未授权\"或\"无效 API 密钥\"错误\n\n**解决方案**：\n1. 验证 X-API-Key 请求头设置正确\n2. 确保 API 密钥与服务器配置匹配\n3. 检查密钥中是否有多余的空格或字符\n\n### 问题：数据库连接错误\n\n**症状**：服务器连接成功但数据库查询失败\n\n**解决方案**：\n1. 验证数据库凭据正确\n2. 检查数据库主机是否可从服务器访问\n3. 确保数据库端口已开放\n4. 验证数据库名称存在\n\n### 问题：查询超时\n\n**症状**：查询耗时过长或超时\n\n**解决方案**：\n1. 优化 SQL 查询\n2. 添加数据库索引\n3. 增加服务器超时设置\n4. 对大结果集使用 LIMIT\n\n### 问题：SSL/TLS 错误\n\n**症状**：证书或 SSL 相关错误\n\n**解决方案**：\n1. 确保安装了有效的 SSL 证书\n2. 检查证书是否过期\n3. 验证证书链完整\n\n## 限制\n\n- ChatGPT MCP Connectors 需要付费订阅\n- 服务器必须通过 HTTPS 公开访问\n- 某些复杂查询可能需要多次交互\n- 大结果集可能会被截断\n- 结果的实时流式传输可能有所不同\n\n## 资源\n\n- [ChatGPT 文档](https://help.openai.com/)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- OpenAI 帮助中心: https://help.openai.com/\n"
  },
  {
    "path": "docs/integrations/CHATMCP.md",
    "content": "# ChatMCP Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with ChatMCP.\n\n## Overview\n\n[ChatMCP](https://github.com/daodao97/chatmcp) is an MCP-focused chat UI. It's designed specifically for testing and using MCP servers.\n\n## Prerequisites\n\n- ChatMCP installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to ChatMCP's configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk ChatMCP about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Resources\n\n- [ChatMCP GitHub](https://github.com/daodao97/chatmcp)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/CHATMCP.zh-CN.md",
    "content": "# ChatMCP 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 ChatMCP 集成。\n\n## 概述\n\n[ChatMCP](https://github.com/daodao97/chatmcp) 是一个专注于 MCP 的聊天 UI。它专门设计用于测试和使用 MCP 服务器。\n\n## 前置要求\n\n- 已安装 ChatMCP\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 ChatMCP 的配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 ChatMCP 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 资源\n\n- [ChatMCP GitHub](https://github.com/daodao97/chatmcp)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/CHERRY-STUDIO.md",
    "content": "# Cherry Studio Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Cherry Studio.\n\n## Overview\n\nCherry Studio is a multi-model desktop chat application that supports various AI models and provides a unified interface for AI conversations. It supports the MCP (Model Context Protocol) stdio mode, allowing you to extend its capabilities with external tools. By integrating Universal Database MCP Server, you can enable Cherry Studio to directly query and analyze your database data during conversations.\n\n**Key Benefits:**\n- Query databases directly from Cherry Studio chat interface\n- Support for multiple AI models with database access\n- Explore database schema through natural language\n- Execute SQL queries and analyze results in conversations\n\n## Prerequisites\n\n- [Cherry Studio](https://cherry-ai.com/) installed (latest version recommended)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nCherry Studio uses MCP stdio mode for tool integration. Configuration is done through the application settings.\n\n### Step 1: Open Cherry Studio Settings\n\n1. Launch Cherry Studio\n2. Click on the settings icon (gear icon) in the sidebar or menu\n3. Navigate to the \"MCP Servers\" or \"Tools\" section\n\n### Step 2: Add MCP Server Configuration\n\nIn the MCP server configuration section, add a new server with the following JSON configuration:\n\n#### Basic Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Save and Restart\n\nAfter adding the configuration, save the settings and restart Cherry Studio for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### DM (Dameng Database)\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### KingbaseES\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Cherry Studio:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Cherry Studio chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Data Analysis\n\nAsk the AI to analyze your data:\n\n```\nAnalyze the sales trends for the last 6 months\n```\n\nThe AI will query the relevant tables and provide insights based on the data.\n\n### Example 5: Generate Reports\n\nRequest data summaries:\n\n```\nGenerate a summary of user registrations by month for 2024\n```\n\nThe AI will create and execute the appropriate queries to generate the report.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never share** configurations with real credentials\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Usage Tips\n\n- Be specific in your queries to get better results\n- Use natural language to describe what data you need\n- Ask the AI to explain query results when needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Cherry Studio doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the MCP server configuration is correctly entered in settings\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart Cherry Studio after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n## Resources\n\n- [Cherry Studio Official Website](https://cherry-ai.com/)\n- [Cherry Studio GitHub](https://github.com/kangfenmao/cherry-studio)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cherry Studio GitHub: https://github.com/kangfenmao/cherry-studio/issues\n"
  },
  {
    "path": "docs/integrations/CHERRY-STUDIO.zh-CN.md",
    "content": "# Cherry Studio 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Cherry Studio 集成。\n\n## 概述\n\nCherry Studio 是一款多模型桌面聊天应用，支持多种 AI 模型，并提供统一的 AI 对话界面。它支持 MCP（Model Context Protocol）stdio 模式，允许您通过外部工具扩展其功能。通过集成 Universal Database MCP Server，您可以让 Cherry Studio 在对话中直接查询和分析数据库数据。\n\n**主要优势：**\n- 直接从 Cherry Studio 聊天界面查询数据库\n- 支持多种 AI 模型访问数据库\n- 通过自然语言探索数据库结构\n- 在对话中执行 SQL 查询并分析结果\n\n## 前置要求\n\n- 已安装 [Cherry Studio](https://cherry-ai.com/)（建议使用最新版本）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nCherry Studio 使用 MCP stdio 模式进行工具集成。配置通过应用程序设置完成。\n\n### 步骤 1: 打开 Cherry Studio 设置\n\n1. 启动 Cherry Studio\n2. 点击侧边栏或菜单中的设置图标（齿轮图标）\n3. 导航到 \"MCP 服务器\" 或 \"工具\" 部分\n\n### 步骤 2: 添加 MCP 服务器配置\n\n在 MCP 服务器配置部分，添加以下 JSON 配置：\n\n#### 基本配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3: 保存并重启\n\n添加配置后，保存设置并重启 Cherry Studio 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Cherry Studio 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Cherry Studio 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 数据分析\n\n让 AI 分析您的数据：\n\n```\n分析过去 6 个月的销售趋势\n```\n\nAI 将查询相关表并根据数据提供洞察。\n\n### 示例 5: 生成报表\n\n请求数据汇总：\n\n```\n生成 2024 年按月份统计的用户注册汇总\n```\n\nAI 将创建并执行适当的查询来生成报表。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿分享**包含真实凭据的配置\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 使用技巧\n\n- 在查询中尽量具体以获得更好的结果\n- 使用自然语言描述您需要的数据\n- 需要时让 AI 解释查询结果\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：Cherry Studio 无法识别数据库工具\n\n**解决方案**：\n1. 验证 MCP 服务器配置是否正确输入到设置中\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 Cherry Studio\n4. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n## 资源\n\n- [Cherry Studio 官方网站](https://cherry-ai.com/)\n- [Cherry Studio GitHub](https://github.com/kangfenmao/cherry-studio)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cherry Studio GitHub: https://github.com/kangfenmao/cherry-studio/issues\n"
  },
  {
    "path": "docs/integrations/CLAUDE-AI.md",
    "content": "# Claude.ai Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Claude.ai web interface.\n\n## Overview\n\n[Claude.ai](https://claude.ai/) is Anthropic's web interface for Claude. It supports MCP via SSE/Streamable HTTP, allowing you to query databases from the web interface.\n\n## Prerequisites\n\n- Claude.ai account with MCP feature enabled\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server in HTTP mode with public access:\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=claude-ai-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Configure Claude.ai\n\n1. Open Claude.ai\n2. Go to Settings > Integrations\n3. Add MCP Server:\n   - URL: `https://your-server.com/mcp`\n   - Configure database headers\n\n### Step 3: Configure Database Headers\n\nWhen connecting, include database configuration in headers:\n\n```\nX-DB-Type: mysql\nX-DB-Host: localhost\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\n## Usage\n\nOnce configured, you can ask Claude about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\nHow many orders were placed this month?\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n1. Use HTTPS for production deployments\n2. Use read-only database users\n3. Protect your MCP server with API keys\n4. Limit query results to prevent large responses\n\n## Resources\n\n- [Claude.ai](https://claude.ai/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/CLAUDE-AI.zh-CN.md",
    "content": "# Claude.ai 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Claude.ai 网页界面集成。\n\n## 概述\n\n[Claude.ai](https://claude.ai/) 是 Anthropic 的 Claude 网页界面。它通过 SSE/Streamable HTTP 支持 MCP，允许您从网页界面查询数据库。\n\n## 前置要求\n\n- 启用了 MCP 功能的 Claude.ai 账号\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server，并开放公网访问：\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=claude-ai-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：配置 Claude.ai\n\n1. 打开 Claude.ai\n2. 转到 Settings > Integrations\n3. 添加 MCP Server：\n   - URL: `https://your-server.com/mcp`\n   - 配置数据库请求头\n\n### 步骤 3：配置数据库请求头\n\n连接时，在请求头中包含数据库配置：\n\n```\nX-DB-Type: mysql\nX-DB-Host: localhost\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\n## 使用方法\n\n配置完成后，您可以向 Claude 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n这个月有多少订单？\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n1. 生产环境使用 HTTPS\n2. 使用只读数据库用户\n3. 使用 API 密钥保护 MCP 服务器\n4. 限制查询结果以防止大响应\n\n## 资源\n\n- [Claude.ai](https://claude.ai/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/CLAUDE-CODE.md",
    "content": "# Claude Code Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Claude Code, Anthropic's agentic coding tool.\n\n## Overview\n\n[Claude Code](https://claude.ai/code) is Anthropic's terminal-based AI coding assistant that runs directly in your command line. It has native MCP support, allowing you to connect to databases and query them using natural language while coding.\n\n**Key Benefits:**\n- Native MCP support via stdio transport\n- Terminal-based workflow integration\n- Direct database access during coding sessions\n- Seamless natural language queries\n\n## Prerequisites\n\n- Claude Code installed and authenticated\n- Node.js 20.0.0 or later\n- Database instance accessible from your machine\n\n## Configuration\n\n### Method 1: Project-Level Configuration\n\nCreate a `.mcp.json` file in your project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Method 2: Global Configuration\n\nAdd to your Claude Code settings file:\n\n**macOS/Linux:** `~/.claude/settings.json`\n**Windows:** `%USERPROFILE%\\.claude\\settings.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"./data/app.db\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-users\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n## Usage Examples\n\n### During Coding Sessions\n\n```bash\n# Start Claude Code in your project\nclaude\n\n# Ask about your database\n> What tables are in the database?\n\n# Query data while coding\n> Show me the schema of the users table\n\n# Generate code based on database structure\n> Create a TypeScript interface for the orders table\n\n# Debug data issues\n> Find all orders with null customer_id\n```\n\n### Common Workflows\n\n**1. Understanding Database Structure**\n```\n> List all tables and their relationships\n> Show me the foreign keys in the orders table\n> What indexes exist on the products table?\n```\n\n**2. Data Exploration**\n```\n> How many users signed up this week?\n> What's the average order value?\n> Show me the top 10 products by sales\n```\n\n**3. Code Generation**\n```\n> Generate a SQL migration to add an email_verified column to users\n> Create a Node.js function to fetch user orders\n> Write a query to get monthly revenue by product category\n```\n\n**4. Debugging**\n```\n> Find duplicate email addresses in the users table\n> Show me orders that reference non-existent products\n> Check for orphaned records in order_items\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n### Security\n\n1. **Use read-only mode** (default) for safety\n2. **Create dedicated database users** with minimal permissions\n3. **Never commit credentials** to version control\n4. **Use environment variables** for sensitive data\n\n### Performance\n\n1. **Use specific queries** instead of SELECT *\n2. **Add LIMIT** to prevent large result sets\n3. **Cache schema** information (enabled by default)\n\n### Workflow\n\n1. **Start with schema exploration** to understand the database\n2. **Use natural language** for complex queries\n3. **Verify generated SQL** before running in production\n4. **Keep database connections** project-specific\n\n## Troubleshooting\n\n### MCP Server Not Found\n\n**Symptoms:** Claude Code doesn't recognize database commands\n\n**Solutions:**\n1. Verify `.mcp.json` is in project root\n2. Check JSON syntax is valid\n3. Ensure Node.js 20+ is installed\n4. Restart Claude Code\n\n### Connection Failed\n\n**Symptoms:** Database connection errors\n\n**Solutions:**\n1. Verify database is running\n2. Check credentials are correct\n3. Ensure network connectivity\n4. Test with database client first\n\n### Permission Denied\n\n**Symptoms:** Query execution fails\n\n**Solutions:**\n1. Check database user permissions\n2. Verify database name is correct\n3. Ensure user can access from localhost\n\n## Resources\n\n- [Claude Code Documentation](https://claude.ai/code/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/CLAUDE-CODE.zh-CN.md",
    "content": "# Claude Code 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Claude Code 集成。\n\n## 概述\n\n[Claude Code](https://claude.ai/code) 是 Anthropic 的终端 AI 编程助手，直接在命令行中运行。它原生支持 MCP，允许您在编码时连接数据库并使用自然语言查询。\n\n**主要优势：**\n- 通过 stdio 传输原生支持 MCP\n- 终端工作流集成\n- 编码会话中直接访问数据库\n- 无缝自然语言查询\n\n## 前置要求\n\n- Claude Code 已安装并认证\n- Node.js 20.0.0 或更高版本\n- 可从您的机器访问的数据库实例\n\n## 配置\n\n### 直接用这种方式配置就可以\n\n在项目根目录下打开PowerShell执行，这样这个mcp就可以在这个项目中使用了\n\n```\n#添加mcp\nclaude mcp add universal-db-mcp -- npx universal-db-mcp --type xxx --host xxx.xxx.xxx.xxx --port xxx --user xxx --password xxx --database xxx\n```\n\n下面还有一些命令可能会用到\n\n```\n# 删除mcp\nclaude mcp remove universal-db-mcp\n\n# 查看已配置的所有 MCP 服务器\nclaude mcp list\n\n# 查看某个服务器的详细配置\nclaude mcp get universal-db-mcp\n```\n\n### 方式 1：项目级配置\n\n在项目根目录创建 `.mcp.json` 文件：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 方式 2：全局配置\n\n添加到 Claude Code 设置文件：\n\n**macOS/Linux:** `~/.claude/settings.json`\n**Windows:** `%USERPROFILE%\\.claude\\settings.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"./data/app.db\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-users\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n## 使用示例\n\n### 编码会话中使用\n\n```bash\n# 在项目中启动 Claude Code\nclaude\n\n# 询问数据库\n> 数据库里有哪些表？\n\n# 编码时查询数据\n> 显示 users 表的结构\n\n# 基于数据库结构生成代码\n> 为 orders 表创建 TypeScript 接口\n\n# 调试数据问题\n> 找出所有 customer_id 为空的订单\n```\n\n### 常见工作流\n\n**1. 了解数据库结构**\n```\n> 列出所有表及其关系\n> 显示 orders 表的外键\n> products 表有哪些索引？\n```\n\n**2. 数据探索**\n```\n> 这周有多少用户注册？\n> 平均订单金额是多少？\n> 显示销量前 10 的产品\n```\n\n**3. 代码生成**\n```\n> 生成 SQL 迁移脚本，为 users 表添加 email_verified 列\n> 创建一个 Node.js 函数来获取用户订单\n> 编写按产品类别统计月收入的查询\n```\n\n**4. 调试**\n```\n> 找出 users 表中重复的邮箱地址\n> 显示引用了不存在产品的订单\n> 检查 order_items 中的孤立记录\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n### 安全性\n\n1. **使用只读模式**（默认）以确保安全\n2. **创建专用数据库用户**，授予最小权限\n3. **不要提交凭据**到版本控制\n4. **使用环境变量**存储敏感数据\n\n### 性能\n\n1. **使用具体查询**而不是 SELECT *\n2. **添加 LIMIT** 防止大结果集\n3. **缓存 Schema** 信息（默认启用）\n\n### 工作流\n\n1. **从探索 Schema 开始**了解数据库\n2. **使用自然语言**进行复杂查询\n3. **验证生成的 SQL** 后再在生产环境运行\n4. **保持数据库连接**项目特定\n\n## 故障排除\n\n### MCP 服务器未找到\n\n**症状：** Claude Code 不识别数据库命令\n\n**解决方案：**\n1. 验证 `.mcp.json` 在项目根目录\n2. 检查 JSON 语法是否有效\n3. 确保 Node.js 20+ 已安装\n4. 重启 Claude Code\n\n### 连接失败\n\n**症状：** 数据库连接错误\n\n**解决方案：**\n1. 验证数据库正在运行\n2. 检查凭据是否正确\n3. 确保网络连接正常\n4. 先用数据库客户端测试\n\n### 权限被拒绝\n\n**症状：** 查询执行失败\n\n**解决方案：**\n1. 检查数据库用户权限\n2. 验证数据库名称正确\n3. 确保用户可以从 localhost 访问\n\n## 资源\n\n- [Claude Code 文档](https://claude.ai/code/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/CLAUDE-DESKTOP.md",
    "content": "# Claude Desktop Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Claude Desktop, Anthropic's official desktop application.\n\n## Overview\n\n[Claude Desktop](https://claude.ai/download) is Anthropic's official desktop application for Claude AI. It provides a native desktop experience with full MCP (Model Context Protocol) support, allowing Claude to interact with external tools and data sources directly.\n\nBy integrating Universal Database MCP Server with Claude Desktop, you can:\n\n- Query databases using natural language\n- Explore database schemas conversationally\n- Generate and execute SQL queries automatically\n- Analyze data without writing code\n\n**Key Benefits:**\n- **Native MCP Support** - Claude Desktop has built-in MCP protocol support via stdio transport\n- **Local Execution** - MCP servers run locally, ensuring data security\n- **Seamless Experience** - No additional setup required beyond configuration\n- **Multi-Database Support** - Connect to 17+ database types\n\n## Prerequisites\n\nBefore you begin, ensure you have:\n\n- **Claude Desktop** installed ([Download here](https://claude.ai/download))\n  - macOS: Version 1.0.0 or later\n  - Windows: Version 1.0.0 or later\n- **Node.js** version 20.0.0 or later ([Download here](https://nodejs.org/))\n- **Database** instance accessible from your machine\n- **Database credentials** with appropriate permissions\n\n### Verify Node.js Installation\n\n```bash\nnode --version\n# Should output v20.0.0 or higher\n```\n\n## Configuration\n\n### Configuration File Location\n\nClaude Desktop uses a JSON configuration file to manage MCP servers:\n\n| Platform | Configuration File Path |\n|----------|------------------------|\n| **macOS** | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n| **Windows** | `%APPDATA%\\Claude\\claude_desktop_config.json` |\n\n> **Note**: If the file doesn't exist, create it manually.\n\n### Basic Configuration\n\nAdd the following to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Configuration Parameters\n\n| Parameter | Required | Description |\n|-----------|----------|-------------|\n| `--type` | Yes | Database type (see supported types below) |\n| `--host` | Yes* | Database host address |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite database file path (for sqlite type only) |\n| `--permission-mode` | No | Permission mode: safe (read-only), readwrite (no delete), full (all operations) |\n| `--permissions` | No | Custom permission list, comma-separated: read,insert,update,delete,ddl |\n| `--danger-allow-write` | No | Enable full write operations (equivalent to --permission-mode full) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g and earlier) |\n\n*Required fields depend on database type\n\n> ⚠️ **Note**: Claude Desktop uses STDIO transport with hyphenated CLI parameters (e.g., `--permission-mode`). If you use other transports (SSE, Streamable HTTP, REST API), parameter naming differs. See [Configuration Guide](../getting-started/configuration.md).\n\n### Supported Database Types\n\n| Database | Type Value | Default Port |\n|----------|------------|--------------|\n| MySQL | `mysql` | 3306 |\n| PostgreSQL | `postgres` | 5432 |\n| Redis | `redis` | 6379 |\n| Oracle | `oracle` | 1521 |\n| SQL Server | `sqlserver` | 1433 |\n| MongoDB | `mongodb` | 27017 |\n| SQLite | `sqlite` | - |\n| Dameng (达梦) | `dm` | 5236 |\n| KingbaseES | `kingbase` | 54321 |\n| GaussDB | `gaussdb` | 5432 |\n| OceanBase | `oceanbase` | 2881 |\n| TiDB | `tidb` | 4000 |\n| ClickHouse | `clickhouse` | 8123 |\n| PolarDB | `polardb` | 3306 |\n| Vastbase | `vastbase` | 5432 |\n| HighGo | `highgo` | 5866 |\n| GoldenDB | `goldendb` | 3306 |\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"mysql_password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"postgres_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-erp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"sqlserver_password\",\n        \"--database\", \"erp_system\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-finance\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"oracle_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle 11g (Legacy)\n\nFor Oracle 11g and earlier versions, you need to specify the Oracle Instant Client path:\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle11g-legacy\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"oracle_password\",\n        \"--database\", \"ORCL\",\n        \"--oracle-client-path\", \"/opt/oracle/instantclient_19_8\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-logs\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"mongodb_password\",\n        \"--database\", \"logs\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"redis_password\"\n      ]\n    }\n  }\n}\n```\n\n### Dameng (达梦数据库)\n\n```json\n{\n  \"mcpServers\": {\n    \"dameng-gov\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"dameng_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### KingbaseES (人大金仓)\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-enterprise\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"kingbase_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple databases simultaneously:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-users\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"mysql_password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    \"postgres-orders\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"postgres_password\",\n        \"--database\", \"orders_db\"\n      ]\n    },\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"redis_password\"\n      ]\n    }\n  }\n}\n```\n\n## Usage Examples\n\nAfter configuring and restarting Claude Desktop, you can interact with your database using natural language.\n\n### Schema Exploration\n\n**You:** \"What tables are in the database?\"\n\n**Claude:** Let me check the database schema for you.\n\n```\nAvailable tables:\n- users (12 columns)\n- orders (8 columns)\n- products (10 columns)\n- categories (4 columns)\n- order_items (6 columns)\n```\n\n---\n\n**You:** \"Show me the structure of the users table\"\n\n**Claude:** Here's the structure of the users table:\n\n| Column | Type | Nullable | Key |\n|--------|------|----------|-----|\n| id | INT | NO | PRIMARY |\n| email | VARCHAR(255) | NO | UNIQUE |\n| name | VARCHAR(100) | YES | |\n| created_at | TIMESTAMP | NO | |\n| status | ENUM | YES | |\n\n### Data Queries\n\n**You:** \"How many users signed up this month?\"\n\n**Claude:** Let me query that for you.\n\n```sql\nSELECT COUNT(*) as new_users\nFROM users\nWHERE created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')\n```\n\nResult: **247 new users** signed up this month.\n\n---\n\n**You:** \"Show me the top 5 customers by total order value\"\n\n**Claude:** I'll analyze the order data for you.\n\n```sql\nSELECT\n  u.name,\n  u.email,\n  SUM(o.total_amount) as total_spent\nFROM users u\nJOIN orders o ON u.id = o.user_id\nGROUP BY u.id\nORDER BY total_spent DESC\nLIMIT 5\n```\n\n| Name | Email | Total Spent |\n|------|-------|-------------|\n| Alice Johnson | alice@example.com | $12,450.00 |\n| Bob Smith | bob@example.com | $9,230.50 |\n| Carol White | carol@example.com | $7,890.25 |\n| David Brown | david@example.com | $6,540.00 |\n| Eve Davis | eve@example.com | $5,120.75 |\n\n### Complex Analysis\n\n**You:** \"What's the average order value by product category for the last quarter?\"\n\n**Claude:** Let me analyze the sales data by category.\n\n```sql\nSELECT\n  c.name as category,\n  COUNT(DISTINCT o.id) as order_count,\n  AVG(oi.quantity * oi.unit_price) as avg_order_value\nFROM categories c\nJOIN products p ON c.id = p.category_id\nJOIN order_items oi ON p.id = oi.product_id\nJOIN orders o ON oi.order_id = o.id\nWHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 3 MONTH)\nGROUP BY c.id\nORDER BY avg_order_value DESC\n```\n\n| Category | Orders | Avg Order Value |\n|----------|--------|-----------------|\n| Electronics | 1,234 | $245.50 |\n| Clothing | 2,456 | $89.25 |\n| Books | 890 | $32.10 |\n| Home & Garden | 567 | $156.80 |\n\n### Redis Operations\n\n**You:** \"What keys are stored in Redis?\"\n\n**Claude:** Let me scan the Redis keys.\n\n```\nFound 156 keys:\n- session:* (89 keys)\n- cache:* (45 keys)\n- rate_limit:* (22 keys)\n```\n\n---\n\n**You:** \"Get the value of key 'config:app_settings'\"\n\n**Claude:** Here's the value:\n\n```json\n{\n  \"theme\": \"dark\",\n  \"language\": \"en\",\n  \"notifications\": true\n}\n```\n\n## Advanced Configuration\n\n### Read-Only Mode (Default)\n\nBy default, Universal DB MCP runs in read-only mode, blocking all write operations (INSERT, UPDATE, DELETE, DROP, etc.). This is the recommended setting for safety.\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### Write Mode (Use with Caution)\n\nBy default, the server runs in read-only mode. Fine-grained permission control is supported:\n\n**Read-Write Mode (No Delete):**\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database-readwrite\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"admin\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"readwrite\"\n      ]\n    }\n  }\n}\n```\n\n**Custom Permissions:**\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database-custom\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"admin\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\",\n        \"--permissions\", \"read,insert,update\"\n      ]\n    }\n  }\n}\n```\n\n**Full Control Mode (Dangerous!):**\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"admin\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write mode allows Claude to execute INSERT, UPDATE, DELETE, and other data-modifying operations. Use this only in development environments or when absolutely necessary.\n\n### Environment Variables\n\nYou can also use environment variables in your configuration:\n\n**macOS/Linux:**\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"root\",\n        \"--password\", \"${DB_PASSWORD}\",\n        \"--database\", \"mydb\"\n      ],\n      \"env\": {\n        \"DB_PASSWORD\": \"your_password\"\n      }\n    }\n  }\n}\n```\n\n### Using Global Installation\n\nIf you've installed universal-db-mcp globally, you can use it directly:\n\n```bash\nnpm install -g universal-db-mcp\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"universal-db-mcp\",\n      \"args\": [\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n## Available MCP Tools\n\nOnce configured, Claude Desktop will have access to the following tools:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get complete database schema information |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Troubleshooting\n\n### Issue: Claude Desktop doesn't recognize the MCP server\n\n**Symptoms:** Claude doesn't respond to database queries or shows no tools available.\n\n**Solutions:**\n1. **Restart Claude Desktop** - After modifying the configuration file, you must restart Claude Desktop completely (quit and reopen).\n2. **Verify configuration file location** - Ensure the file is in the correct location:\n   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\n   - Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n3. **Check JSON syntax** - Validate your JSON configuration using a JSON validator.\n4. **Check Node.js installation** - Ensure Node.js v20+ is installed and accessible from the command line.\n\n### Issue: Connection failed\n\n**Symptoms:** Error messages about database connection failures.\n\n**Solutions:**\n1. **Verify credentials** - Double-check username, password, host, and port.\n2. **Test database connectivity** - Try connecting with a database client first.\n3. **Check firewall** - Ensure the database port is accessible.\n4. **Verify database is running** - Confirm the database service is active.\n\n### Issue: Permission denied\n\n**Symptoms:** Queries fail with permission errors.\n\n**Solutions:**\n1. **Check user permissions** - Ensure the database user has SELECT permissions.\n2. **Verify database access** - Confirm the user can access the specified database.\n3. **Check table permissions** - Some tables may have restricted access.\n\n### Issue: Slow queries\n\n**Symptoms:** Queries take a long time to execute.\n\n**Solutions:**\n1. **Add indexes** - Ensure frequently queried columns are indexed.\n2. **Limit result sets** - Ask Claude to limit results (e.g., \"show top 10\").\n3. **Optimize queries** - Complex queries may need optimization.\n4. **Check network latency** - Remote databases may have higher latency.\n\n### Issue: Write operations blocked\n\n**Symptoms:** INSERT, UPDATE, DELETE operations fail.\n\n**Solutions:**\n1. **Check mode** - By default, write operations are blocked.\n2. **Enable write mode** - Use `--permission-mode readwrite` for read/write without delete, or `--permission-mode full` for all operations.\n3. **Verify user permissions** - Ensure the database user has write permissions.\n\n### Viewing Logs\n\nTo debug issues, you can check Claude Desktop logs:\n\n**macOS:**\n```bash\ntail -f ~/Library/Logs/Claude/mcp*.log\n```\n\n**Windows:**\n```powershell\nGet-Content \"$env:APPDATA\\Claude\\logs\\mcp*.log\" -Wait\n```\n\n## Security Best Practices\n\n1. **Use read-only mode** - Keep the default read-only mode unless write access is absolutely necessary.\n\n2. **Create dedicated database users** - Create a specific user for Claude with minimal required permissions:\n   ```sql\n   -- MySQL example\n   CREATE USER 'claude_readonly'@'localhost' IDENTIFIED BY 'secure_password';\n   GRANT SELECT ON mydb.* TO 'claude_readonly'@'localhost';\n   FLUSH PRIVILEGES;\n   ```\n\n3. **Avoid storing passwords in plain text** - Use environment variables or secure credential management.\n\n4. **Limit network access** - Configure database to only accept connections from localhost or trusted IPs.\n\n5. **Regular auditing** - Review query logs periodically to ensure appropriate usage.\n\n6. **Use VPN for remote databases** - When connecting to remote databases, use VPN or SSH tunnels.\n\n## Resources\n\n- [Claude Desktop Download](https://claude.ai/download)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n- [MCP Protocol Documentation](https://modelcontextprotocol.io/)\n- [Database Configuration Guide](../getting-started/configuration.md)\n- [Security Guide](../guides/security.md)\n- [Troubleshooting Guide](../operations/troubleshooting.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Anthropic Support: https://support.anthropic.com/\n"
  },
  {
    "path": "docs/integrations/CLAUDE-DESKTOP.zh-CN.md",
    "content": "# Claude Desktop 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Claude Desktop 集成。\n\n## 概述\n\n[Claude Desktop](https://claude.ai/download) 是 Anthropic 官方桌面应用，原生支持 MCP（模型上下文协议）。通过集成 Universal Database MCP Server，您可以：\n\n- 使用自然语言查询数据库\n- 以对话方式探索数据库结构\n- 自动生成和执行 SQL 查询\n- 无需编写代码即可分析数据\n\n**主要优势：**\n- **原生 MCP 支持** - Claude Desktop 内置 MCP 协议支持（stdio 传输）\n- **本地执行** - MCP 服务器在本地运行，确保数据安全\n- **无缝体验** - 配置后即可使用，无需额外设置\n- **多数据库支持** - 支持 17+ 种数据库类型\n\n## 前置要求\n\n- **Claude Desktop** 已安装（[下载地址](https://claude.ai/download)）\n- **Node.js** 20.0.0 或更高版本（[下载地址](https://nodejs.org/)）\n- **数据库** 实例可从您的机器访问\n\n### 验证 Node.js 安装\n\n```bash\nnode --version\n# 应输出 v20.0.0 或更高版本\n```\n\n## 配置\n\n### 配置文件位置\n\n| 平台 | 配置文件路径 |\n|------|-------------|\n| **macOS** | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n| **Windows** | `%APPDATA%\\Claude\\claude_desktop_config.json` |\n\n> **注意**：如果文件不存在，请手动创建。\n\n### 基本配置\n\n将以下内容添加到 `claude_desktop_config.json`：\n\n```json\n{\n  \"mcpServers\": {\n    \"my-database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 配置参数\n\n| 参数 | 必需 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型（见下方支持的类型） |\n| `--host` | 是* | 数据库主机地址 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 数据库文件路径（仅 sqlite 类型） |\n| `--permission-mode` | 否 | 权限模式：safe（只读）、readwrite（读写不删）、full（完全控制） |\n| `--permissions` | 否 | 自定义权限列表，逗号分隔：read,insert,update,delete,ddl |\n| `--danger-allow-write` | 否 | 启用完全写操作（等价于 --permission-mode full） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g 及更早版本） |\n\n*必需字段取决于数据库类型\n\n> ⚠️ **注意**：Claude Desktop 使用 STDIO 传输，命令行参数使用连字符命名（如 `--permission-mode`）。如果您使用其他传输方式（SSE、Streamable HTTP、REST API），参数命名会有所不同，请参阅 [配置说明](../getting-started/configuration.md)。\n\n### 支持的数据库类型\n\n| 数据库 | 类型值 | 默认端口 |\n|--------|--------|----------|\n| MySQL | `mysql` | 3306 |\n| PostgreSQL | `postgres` | 5432 |\n| Redis | `redis` | 6379 |\n| Oracle | `oracle` | 1521 |\n| SQL Server | `sqlserver` | 1433 |\n| MongoDB | `mongodb` | 27017 |\n| SQLite | `sqlite` | - |\n| 达梦 | `dm` | 5236 |\n| 人大金仓 | `kingbase` | 54321 |\n| 华为 GaussDB | `gaussdb` | 5432 |\n| 蚂蚁 OceanBase | `oceanbase` | 2881 |\n| TiDB | `tidb` | 4000 |\n| ClickHouse | `clickhouse` | 8123 |\n| 阿里云 PolarDB | `polardb` | 3306 |\n| 海量 Vastbase | `vastbase` | 5432 |\n| 瀚高 HighGo | `highgo` | 5866 |\n| 中兴 GoldenDB | `goldendb` | 3306 |\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"mysql_password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"postgres_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-erp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"sqlserver_password\",\n        \"--database\", \"erp_system\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-finance\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"oracle_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle 11g（旧版本）\n\n对于 Oracle 11g 及更早版本，需要指定 Oracle Instant Client 路径：\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle11g-legacy\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"oracle_password\",\n        \"--database\", \"ORCL\",\n        \"--oracle-client-path\", \"/opt/oracle/instantclient_19_8\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb-logs\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"mongodb_password\",\n        \"--database\", \"logs\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis-cache\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"redis_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dameng-gov\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"dameng_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-enterprise\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"kingbase_password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以同时配置多个数据库：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-users\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"mysql_password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    \"postgres-orders\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"postgres_password\",\n        \"--database\", \"orders_db\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，服务器以只读模式运行。支持细粒度权限控制：\n\n**读写模式（不能删除）：**\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-readwrite\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--permission-mode\", \"readwrite\"\n      ]\n    }\n  }\n}\n```\n\n**自定义权限：**\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-custom\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--permissions\", \"read,insert,update\"\n      ]\n    }\n  }\n}\n```\n\n**完全控制模式（危险！）：**\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--permission-mode\", \"full\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：仅在开发环境中启用写入模式。生产环境请勿使用。\n\n## 使用示例\n\n配置并重启 Claude Desktop 后，您可以使用自然语言与数据库交互。\n\n### 探索数据库结构\n\n**您：** \"数据库里有哪些表？\"\n\n**Claude：** 让我查看一下数据库结构。\n\n```\n可用的表：\n- users（12 列）\n- orders（8 列）\n- products（10 列）\n- categories（4 列）\n- order_items（6 列）\n```\n\n---\n\n**您：** \"显示 users 表的结构\"\n\n**Claude：** 这是 users 表的结构：\n\n| 列名 | 类型 | 可空 | 键 |\n|------|------|------|-----|\n| id | INT | 否 | 主键 |\n| email | VARCHAR(255) | 否 | 唯一 |\n| name | VARCHAR(100) | 是 | |\n| created_at | TIMESTAMP | 否 | |\n| status | ENUM | 是 | |\n\n### 数据查询\n\n**您：** \"这个月有多少新注册用户？\"\n\n**Claude：** 让我帮您查询。\n\n```sql\nSELECT COUNT(*) as new_users\nFROM users\nWHERE created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')\n```\n\n结果：本月有 **247 位新用户** 注册。\n\n---\n\n**您：** \"显示订单金额最高的前 5 位客户\"\n\n**Claude：** 我来分析订单数据。\n\n| 姓名 | 邮箱 | 总消费 |\n|------|------|--------|\n| 张三 | zhang@example.com | ¥12,450.00 |\n| 李四 | li@example.com | ¥9,230.50 |\n| 王五 | wang@example.com | ¥7,890.25 |\n| 赵六 | zhao@example.com | ¥6,540.00 |\n| 钱七 | qian@example.com | ¥5,120.75 |\n\n### 复杂分析\n\n**您：** \"上个季度各产品类别的平均订单金额是多少？\"\n\n**Claude：** 让我按类别分析销售数据。\n\n| 类别 | 订单数 | 平均订单金额 |\n|------|--------|--------------|\n| 电子产品 | 1,234 | ¥245.50 |\n| 服装 | 2,456 | ¥89.25 |\n| 图书 | 890 | ¥32.10 |\n| 家居园艺 | 567 | ¥156.80 |\n\n## 可用的 MCP 工具\n\n配置完成后，Claude Desktop 将可以使用以下工具：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取完整的数据库结构信息 |\n| `get_table_info` | 获取指定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 故障排除\n\n### 问题：Claude Desktop 无法识别 MCP 服务器\n\n**症状**：Claude 不响应数据库查询或显示没有可用工具。\n\n**解决方案**：\n1. **重启 Claude Desktop** - 修改配置文件后，必须完全重启 Claude Desktop（退出并重新打开）。\n2. **验证配置文件位置** - 确保文件在正确的位置。\n3. **检查 JSON 语法** - 使用 JSON 验证器验证配置。\n4. **检查 Node.js 安装** - 确保 Node.js v20+ 已安装。\n\n### 问题：连接失败\n\n**症状**：数据库连接失败的错误消息。\n\n**解决方案**：\n1. **验证凭据** - 仔细检查用户名、密码、主机和端口。\n2. **测试数据库连接** - 先用数据库客户端测试连接。\n3. **检查防火墙** - 确保数据库端口可访问。\n4. **验证数据库运行状态** - 确认数据库服务正在运行。\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败。\n\n**解决方案**：\n1. **检查用户权限** - 确保数据库用户有 SELECT 权限。\n2. **验证数据库访问** - 确认用户可以访问指定的数据库。\n3. **检查表级权限** - 某些表可能有访问限制。\n\n### 问题：写操作被阻止\n\n**症状**：INSERT、UPDATE、DELETE 操作失败。\n\n**解决方案**：\n1. **检查模式** - 默认情况下，写操作被阻止。\n2. **启用写入模式** - 使用 `--permission-mode readwrite` 或 `--permission-mode full`。\n3. **验证用户权限** - 确保数据库用户有写入权限。\n\n## 安全最佳实践\n\n1. **使用只读模式** - 除非绝对必要，否则保持默认的只读模式。\n\n2. **创建专用数据库用户** - 为 Claude 创建具有最小必要权限的专用用户：\n   ```sql\n   -- MySQL 示例\n   CREATE USER 'claude_readonly'@'localhost' IDENTIFIED BY 'secure_password';\n   GRANT SELECT ON mydb.* TO 'claude_readonly'@'localhost';\n   FLUSH PRIVILEGES;\n   ```\n\n3. **避免明文存储密码** - 使用环境变量或安全的凭据管理。\n\n4. **限制网络访问** - 配置数据库仅接受来自 localhost 或受信任 IP 的连接。\n\n5. **定期审计** - 定期检查查询日志以确保适当使用。\n\n## 资源\n\n- [Claude Desktop 下载](https://claude.ai/download)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n- [MCP 协议文档](https://modelcontextprotocol.io/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Anthropic 支持: https://support.anthropic.com/\n"
  },
  {
    "path": "docs/integrations/CLINE.md",
    "content": "# Cline Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Cline.\n\n## Overview\n\nCline is an AI-powered coding assistant extension for VS Code that supports MCP stdio mode. It is an autonomous AI coding agent that can help you write, debug, and understand code. By integrating Universal Database MCP Server, you can enable Cline to directly query and analyze your database data, making it easier to work with database-related tasks.\n\n**Key Benefits:**\n- Query databases directly from Cline's AI chat\n- Get AI assistance for SQL query writing\n- Explore database schema without leaving VS Code\n- Debug and optimize database queries with AI help\n- Autonomous task execution with database access\n\n## Prerequisites\n\n- [Visual Studio Code](https://code.visualstudio.com/) installed\n- [Cline Extension](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev) installed\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nCline uses MCP stdio mode for tool integration. Configuration is done through a JSON file.\n\n### Configuration File Location\n\n| Platform | Path |\n|----------|------|\n| macOS | `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |\n| Linux | `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |\n| Windows | `%APPDATA%\\Code\\User\\globalStorage\\saoudrizwan.claude-dev\\settings\\cline_mcp_settings.json` |\n\n### Step 1: Install Cline Extension\n\n1. Open VS Code Extensions (`Ctrl+Shift+X` or `Cmd+Shift+X`)\n2. Search for \"Cline\"\n3. Install the Cline extension\n4. Reload VS Code if prompted\n\n### Step 2: Open MCP Settings\n\nYou can access MCP settings in two ways:\n\n**Method A: Via Cline Panel**\n1. Open Cline panel in VS Code\n2. Click the MCP Servers icon (server icon) in the top toolbar\n3. Click \"Configure MCP Servers\" or edit the settings directly\n\n**Method B: Via Settings File**\n1. Navigate to the configuration file location for your platform\n2. Create or edit the `cline_mcp_settings.json` file\n\n### Step 3: Add MCP Server Configuration\n\nAdd the Universal Database MCP Server configuration to your settings file:\n\n#### Basic Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 4: Restart Cline\n\nAfter saving the configuration file, restart the Cline extension or reload VS Code for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n### Using Environment Variables\n\nFor better security, you can use environment variables in your configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"${DB_PASSWORD}\",\n        \"--database\", \"myapp\"\n      ],\n      \"env\": {\n        \"DB_PASSWORD\": \"your_password\"\n      }\n    }\n  }\n}\n```\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Cline:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Cline's chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nCline will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk Cline to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nCline will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nCline will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nCline will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk Cline to generate database-related code:\n\n```\nGenerate a TypeScript function to insert a new user into the users table\n```\n\nCline will examine your schema and generate appropriate code.\n\n### Example 6: Autonomous Database Tasks\n\nCline can perform complex multi-step database tasks:\n\n```\nAnalyze the orders table, identify any data quality issues, and suggest improvements to the schema\n```\n\nCline will autonomously query the database, analyze the results, and provide recommendations.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** configuration files with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Cline doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the configuration file is in the correct location\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart VS Code after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n5. Check the MCP Servers panel in Cline for connection status\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n### Viewing Logs\n\nTo view Cline logs for debugging:\n1. Open VS Code Output panel (`Ctrl+Shift+U` or `Cmd+Shift+U`)\n2. Select \"Cline\" from the dropdown\n3. Look for MCP-related messages\n\n## Advanced Configuration\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n### Disabling a Server\n\nYou can temporarily disable a server without removing its configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ],\n      \"disabled\": true\n    }\n  }\n}\n```\n\n## Resources\n\n- [Cline Extension](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)\n- [Cline GitHub Repository](https://github.com/cline/cline)\n- [Visual Studio Code](https://code.visualstudio.com/)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cline Issues: https://github.com/cline/cline/issues\n"
  },
  {
    "path": "docs/integrations/CLINE.zh-CN.md",
    "content": "# Cline 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Cline 集成。\n\n## 概述\n\nCline 是一款支持 MCP stdio 模式的 VS Code AI 编程助手扩展。它是一个自主 AI 编码代理，可以帮助您编写、调试和理解代码。通过集成 Universal Database MCP Server，您可以让 Cline 直接查询和分析数据库数据，从而更轻松地处理数据库相关任务。\n\n**主要优势：**\n- 直接从 Cline 的 AI 聊天中查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 无需离开 VS Code 即可探索数据库结构\n- 借助 AI 帮助调试和优化数据库查询\n- 具有数据库访问能力的自主任务执行\n\n## 前置要求\n\n- 已安装 [Visual Studio Code](https://code.visualstudio.com/)\n- 已安装 [Cline 扩展](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nCline 使用 MCP stdio 模式进行工具集成。配置通过 JSON 文件完成。\n\n### 配置文件位置\n\n| 平台 | 路径 |\n|------|------|\n| macOS | `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |\n| Linux | `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |\n| Windows | `%APPDATA%\\Code\\User\\globalStorage\\saoudrizwan.claude-dev\\settings\\cline_mcp_settings.json` |\n\n### 步骤 1: 安装 Cline 扩展\n\n1. 打开 VS Code 扩展面板（`Ctrl+Shift+X` 或 `Cmd+Shift+X`）\n2. 搜索 \"Cline\"\n3. 安装 Cline 扩展\n4. 如有提示，重新加载 VS Code\n\n### 步骤 2: 打开 MCP 设置\n\n您可以通过两种方式访问 MCP 设置：\n\n**方法 A：通过 Cline 面板**\n1. 在 VS Code 中打开 Cline 面板\n2. 点击顶部工具栏中的 MCP Servers 图标（服务器图标）\n3. 点击 \"Configure MCP Servers\" 或直接编辑设置\n\n**方法 B：通过设置文件**\n1. 导航到您平台对应的配置文件位置\n2. 创建或编辑 `cline_mcp_settings.json` 文件\n\n### 步骤 3: 添加 MCP 服务器配置\n\n将 Universal Database MCP Server 配置添加到您的设置文件中：\n\n#### 基本配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 4: 重启 Cline\n\n保存配置文件后，重启 Cline 扩展或重新加载 VS Code 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中使用环境变量：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"${DB_PASSWORD}\",\n        \"--database\", \"myapp\"\n      ],\n      \"env\": {\n        \"DB_PASSWORD\": \"your_password\"\n      }\n    }\n  }\n}\n```\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Cline 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Cline 的聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nCline 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 Cline 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nCline 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nCline 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nCline 将分析并建议优化方案。\n\n### 示例 5: 生成代码\n\n让 Cline 生成数据库相关代码：\n\n```\n生成一个 TypeScript 函数，用于向 users 表插入新用户\n```\n\nCline 将检查您的结构并生成适当的代码。\n\n### 示例 6: 自主数据库任务\n\nCline 可以执行复杂的多步骤数据库任务：\n\n```\n分析 orders 表，识别任何数据质量问题，并建议改进 schema\n```\n\nCline 将自主查询数据库、分析结果并提供建议。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的配置文件提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：Cline 无法识别数据库工具\n\n**解决方案**：\n1. 验证配置文件位于正确位置\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 VS Code\n4. 确保 Node.js 已安装并可从 PATH 访问\n5. 检查 Cline 中的 MCP Servers 面板以查看连接状态\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n### 查看日志\n\n要查看 Cline 日志进行调试：\n1. 打开 VS Code 输出面板（`Ctrl+Shift+U` 或 `Cmd+Shift+U`）\n2. 从下拉菜单中选择 \"Cline\"\n3. 查找 MCP 相关消息\n\n## 高级配置\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n### 禁用服务器\n\n您可以在不删除配置的情况下临时禁用服务器：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ],\n      \"disabled\": true\n    }\n  }\n}\n```\n\n## 资源\n\n- [Cline 扩展](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)\n- [Cline GitHub 仓库](https://github.com/cline/cline)\n- [Visual Studio Code](https://code.visualstudio.com/)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cline Issues: https://github.com/cline/cline/issues\n"
  },
  {
    "path": "docs/integrations/CONTINUE.md",
    "content": "# Continue Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Continue, the open-source AI code assistant.\n\n## Overview\n\n[Continue](https://continue.dev/) is an open-source AI code assistant that runs in VS Code and JetBrains IDEs. It supports MCP, allowing you to connect to databases and query them using natural language.\n\n**Key Benefits:**\n- Open-source and customizable\n- Native MCP support\n- Works with multiple LLM providers\n- VS Code and JetBrains support\n\n## Prerequisites\n\n- Continue extension installed in VS Code or JetBrains\n- Node.js 20.0.0 or later\n- Database instance accessible from your machine\n\n## Configuration\n\n### Configuration File Location\n\nContinue uses a configuration file at:\n- **All platforms:** `~/.continue/config.json`\n\n### Basic Configuration\n\nAdd the MCP server to your `config.json`:\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"database\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-dev\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  ]\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"postgres-dev\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  ]\n}\n```\n\n### Multiple Databases\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-users\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n## Usage\n\n### Using MCP Tools\n\n1. Open Continue chat panel\n2. Use the `/tools` command to see available tools\n3. Ask questions about your database:\n\n```\nWhat tables are in the database?\n\nShow me the schema of the users table\n\nGenerate a TypeScript interface for the orders table\n\nFind all users who signed up this week\n```\n\n### Common Workflows\n\n**Schema Exploration:**\n```\nList all tables and their columns\nWhat are the relationships between tables?\nShow me the indexes on the products table\n```\n\n**Code Generation:**\n```\nCreate a repository class for the users table\nGenerate SQL migrations for adding a new column\nWrite a function to get user orders with pagination\n```\n\n**Data Analysis:**\n```\nHow many orders were placed this month?\nWhat's the average order value?\nFind the top 10 products by sales\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n### Security\n\n1. Use read-only database users\n2. Never commit credentials to version control\n3. Use environment variables for sensitive data\n4. Keep write mode disabled unless necessary\n\n### Performance\n\n1. Use specific queries instead of SELECT *\n2. Add LIMIT to prevent large result sets\n3. Cache schema information\n\n## Troubleshooting\n\n### MCP Server Not Found\n\n**Symptoms:** Continue doesn't show database tools\n\n**Solutions:**\n1. Verify config.json syntax is valid\n2. Check the file is at `~/.continue/config.json`\n3. Ensure Node.js 20+ is installed\n4. Restart VS Code/IDE\n\n### Connection Failed\n\n**Symptoms:** Database connection errors\n\n**Solutions:**\n1. Verify database is running\n2. Check credentials are correct\n3. Ensure network connectivity\n4. Test with database client first\n\n## Resources\n\n- [Continue Documentation](https://continue.dev/docs)\n- [Continue GitHub](https://github.com/continuedev/continue)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Continue Discord: https://discord.gg/continue\n"
  },
  {
    "path": "docs/integrations/CONTINUE.zh-CN.md",
    "content": "# Continue 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Continue 集成。\n\n## 概述\n\n[Continue](https://continue.dev/) 是一个开源的 AI 代码助手，可在 VS Code 和 JetBrains IDE 中运行。它支持 MCP，允许您连接数据库并使用自然语言查询。\n\n**主要优势：**\n- 开源且可定制\n- 原生支持 MCP\n- 支持多种 LLM 提供商\n- 支持 VS Code 和 JetBrains\n\n## 前置要求\n\n- 在 VS Code 或 JetBrains 中安装了 Continue 扩展\n- Node.js 20.0.0 或更高版本\n- 可从您的机器访问的数据库实例\n\n## 配置\n\n### 配置文件位置\n\nContinue 使用以下位置的配置文件：\n- **所有平台：** `~/.continue/config.json`\n\n### 基本配置\n\n将 MCP 服务器添加到 `config.json`：\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"database\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-dev\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  ]\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"postgres-dev\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  ]\n}\n```\n\n### 多数据库配置\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-users\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"users_db\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n## 使用方法\n\n### 使用 MCP 工具\n\n1. 打开 Continue 聊天面板\n2. 使用 `/tools` 命令查看可用工具\n3. 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n\n显示 users 表的结构\n\n为 orders 表生成 TypeScript 接口\n\n找出这周注册的所有用户\n```\n\n### 常见工作流\n\n**Schema 探索：**\n```\n列出所有表及其列\n表之间有什么关系？\n显示 products 表的索引\n```\n\n**代码生成：**\n```\n为 users 表创建一个 repository 类\n生成添加新列的 SQL 迁移\n编写一个带分页的获取用户订单的函数\n```\n\n**数据分析：**\n```\n这个月有多少订单？\n平均订单金额是多少？\n找出销量前 10 的产品\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n### 安全性\n\n1. 使用只读数据库用户\n2. 不要将凭据提交到版本控制\n3. 使用环境变量存储敏感数据\n4. 除非必要，否则禁用写入模式\n\n### 性能\n\n1. 使用具体查询而不是 SELECT *\n2. 添加 LIMIT 防止大结果集\n3. 缓存 Schema 信息\n\n## 故障排除\n\n### MCP 服务器未找到\n\n**症状：** Continue 不显示数据库工具\n\n**解决方案：**\n1. 验证 config.json 语法是否有效\n2. 检查文件是否在 `~/.continue/config.json`\n3. 确保 Node.js 20+ 已安装\n4. 重启 VS Code/IDE\n\n### 连接失败\n\n**症状：** 数据库连接错误\n\n**解决方案：**\n1. 验证数据库正在运行\n2. 检查凭据是否正确\n3. 确保网络连接正常\n4. 先用数据库客户端测试\n\n## 资源\n\n- [Continue 文档](https://continue.dev/docs)\n- [Continue GitHub](https://github.com/continuedev/continue)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Continue Discord: https://discord.gg/continue\n"
  },
  {
    "path": "docs/integrations/COZE.md",
    "content": "# Coze Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Coze platform.\n\n## Overview\n\nCoze is an AI bot development platform. By integrating Universal Database MCP Server, you can enable your Coze bots to query and analyze database data.\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP API mode\n- Coze account\n- Database instance (MySQL, PostgreSQL, etc.)\n\n## Setup Steps\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server in HTTP API mode:\n\n```bash\n# Using Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=coze-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\nOr deploy to cloud platform (Railway, Render, Fly.io). See [Deployment Guide](../http-api/DEPLOYMENT.md).\n\n### Step 2: Get API Endpoint\n\nNote your API endpoint URL:\n- Local: `http://localhost:3000`\n- Cloud: `https://your-app.railway.app` (example)\n\n### Step 3: Create Coze Bot\n\n1. Login to [Coze](https://www.coze.com/)\n2. Click \"Create Bot\"\n3. Enter bot name and description\n4. Click \"Create\"\n\n### Step 4: Add API Plugin\n\n1. In bot editor, click \"Plugins\" tab\n2. Click \"Add Plugin\"\n3. Select \"API Plugin\"\n4. Configure API:\n\n**Basic Information**:\n- Name: `Database Query`\n- Description: `Query database using natural language`\n\n**Authentication**:\n- Type: `API Key`\n- Header Name: `X-API-Key`\n- API Key: `coze-secret-key` (your API key)\n\n### Step 5: Configure API Endpoints\n\n#### Endpoint 1: Connect to Database\n\n**Name**: `connect_database`\n**Method**: `POST`\n**URL**: `https://your-api-url/api/connect`\n**Description**: Connect to a database\n\n**Request Body**:\n```json\n{\n  \"type\": \"{{database_type}}\",\n  \"host\": \"{{host}}\",\n  \"port\": {{port}},\n  \"user\": \"{{user}}\",\n  \"password\": \"{{password}}\",\n  \"database\": \"{{database}}\",\n  \"permissionMode\": \"{{permission_mode}}\"\n}\n```\n\n**Parameters**:\n- `database_type` (string, required): Database type (mysql, postgres, etc.)\n- `host` (string, required): Database host\n- `port` (number, required): Database port\n- `user` (string, required): Username\n- `password` (string, required): Password\n- `database` (string, required): Database name\n- `permission_mode` (string, optional): Permission mode: `safe` (default, read-only), `readwrite` (read/write no delete), `full` (full control)\n- `permissions` (array, optional): Custom permissions: `[\"read\", \"insert\", \"update\", \"delete\", \"ddl\"]`\n\n> ⚠️ **Note**: REST API uses camelCase (`permissionMode`), not hyphenated names.\n\n**Response Example**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"abc123\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  }\n}\n```\n\n#### Endpoint 2: Execute Query\n\n**Name**: `execute_query`\n**Method**: `POST`\n**URL**: `https://your-api-url/api/query`\n**Description**: Execute SQL query\n\n**Request Body**:\n```json\n{\n  \"sessionId\": \"{{session_id}}\",\n  \"query\": \"{{sql_query}}\"\n}\n```\n\n**Parameters**:\n- `session_id` (string, required): Session ID from connect_database\n- `sql_query` (string, required): SQL query to execute\n\n**Response Example**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [\n      {\"id\": 1, \"name\": \"Alice\"},\n      {\"id\": 2, \"name\": \"Bob\"}\n    ],\n    \"executionTime\": 15\n  }\n}\n```\n\n#### Endpoint 3: List Tables\n\n**Name**: `list_tables`\n**Method**: `GET`\n**URL**: `https://your-api-url/api/tables?sessionId={{session_id}}`\n**Description**: List all tables in database\n\n**Parameters**:\n- `session_id` (string, required): Session ID from connect_database\n\n**Response Example**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\"]\n  }\n}\n```\n\n#### Endpoint 4: Get Table Schema\n\n**Name**: `get_table_schema`\n**Method**: `GET`\n**URL**: `https://your-api-url/api/schema/{{table_name}}?sessionId={{session_id}}`\n**Description**: Get table structure\n\n**Parameters**:\n- `table_name` (string, required): Table name\n- `session_id` (string, required): Session ID from connect_database\n\n**Response Example**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"users\",\n    \"columns\": [\n      {\"name\": \"id\", \"type\": \"int\", \"nullable\": false},\n      {\"name\": \"name\", \"type\": \"varchar(255)\", \"nullable\": false}\n    ]\n  }\n}\n```\n\n### Step 6: Create Bot Skills\n\nCreate skills that use the API plugin:\n\n#### Skill 1: Database Connection\n\n**Skill Name**: `Connect to Database`\n**Description**: Connect to a database\n\n**Prompt**:\n```\nWhen user asks to connect to a database, use the connect_database API.\n\nAsk user for:\n- Database type (mysql, postgres, etc.)\n- Host\n- Port\n- Username\n- Password\n- Database name\n\nAfter connecting, save the sessionId for future queries.\n```\n\n#### Skill 2: Query Data\n\n**Skill Name**: `Query Database`\n**Description**: Query database using natural language\n\n**Prompt**:\n```\nWhen user asks a question about data:\n\n1. If not connected, ask user to connect first\n2. Use list_tables to see available tables\n3. Use get_table_schema to understand table structure\n4. Generate appropriate SQL query based on user's question\n5. Use execute_query to run the query\n6. Format and present results to user in a readable way\n\nExample:\nUser: \"Show me all users\"\nBot:\n- Lists tables to find \"users\" table\n- Gets schema of \"users\" table\n- Generates SQL: \"SELECT * FROM users LIMIT 10\"\n- Executes query\n- Presents results in a table format\n```\n\n### Step 7: Test Bot\n\nTest your bot with sample queries:\n\n**Example 1: Connect**\n```\nUser: Connect to my MySQL database at localhost:3306, user root, password xxx, database testdb\nBot: [Calls connect_database API]\nBot: Successfully connected! Session ID: abc123\n```\n\n**Example 2: Query**\n```\nUser: Show me all users\nBot: [Calls list_tables API]\nBot: [Calls get_table_schema API for \"users\" table]\nBot: [Generates SQL: SELECT * FROM users LIMIT 10]\nBot: [Calls execute_query API]\nBot: Here are the users:\n     1. Alice (alice@example.com)\n     2. Bob (bob@example.com)\n     ...\n```\n\n**Example 3: Complex Query**\n```\nUser: How many orders were placed last month?\nBot: [Analyzes tables and schema]\nBot: [Generates SQL: SELECT COUNT(*) FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)]\nBot: [Executes query]\nBot: There were 1,234 orders placed last month.\n```\n\n## Advanced Features\n\n### Session Management\n\nStore session ID in bot memory:\n\n```javascript\n// In bot skill\nconst sessionId = await connectDatabase(params);\nbot.memory.set('db_session_id', sessionId);\n\n// Later use\nconst sessionId = bot.memory.get('db_session_id');\nawait executeQuery(sessionId, query);\n```\n\n### Error Handling\n\nHandle API errors gracefully:\n\n```javascript\ntry {\n  const result = await executeQuery(sessionId, query);\n  return formatResults(result);\n} catch (error) {\n  if (error.code === 'SESSION_EXPIRED') {\n    return \"Session expired. Please reconnect to database.\";\n  }\n  return `Error: ${error.message}`;\n}\n```\n\n### Query Optimization\n\nImplement query optimization:\n\n```javascript\n// Add LIMIT to prevent large result sets\nif (!query.includes('LIMIT')) {\n  query += ' LIMIT 100';\n}\n\n// Validate query before execution\nif (isWriteOperation(query) && !allowWrite) {\n  return \"Write operations are not allowed in read-only mode.\";\n}\n```\n\n## Security Best Practices\n\n### 1. Secure API Keys\n\n- Use strong, random API keys\n- Rotate keys regularly\n- Store keys securely in Coze secrets\n\n### 2. Database Credentials\n\n- Never expose database credentials in bot responses\n- Use read-only database users when possible\n- Implement connection pooling\n\n### 3. Query Validation\n\n- Validate SQL queries before execution\n- Prevent SQL injection\n- Limit query complexity\n\n### 4. Rate Limiting\n\n- Configure appropriate rate limits\n- Monitor API usage\n- Implement exponential backoff\n\n## Example Use Cases\n\n### Use Case 1: Customer Support Bot\n\nBot helps support agents query customer data:\n\n```\nUser: Find customer with email alice@example.com\nBot: [Queries database]\nBot: Found customer:\n     - ID: 123\n     - Name: Alice Smith\n     - Email: alice@example.com\n     - Status: Active\n     - Last Order: 2026-01-20\n```\n\n### Use Case 2: Analytics Bot\n\nBot provides business insights:\n\n```\nUser: What's our revenue this month?\nBot: [Queries orders table]\nBot: Revenue this month: $125,430\n     - Total orders: 1,234\n     - Average order value: $101.65\n     - Top product: Widget Pro\n```\n\n### Use Case 3: Data Export Bot\n\nBot exports data in various formats:\n\n```\nUser: Export all active users to CSV\nBot: [Queries database]\nBot: Exported 5,432 active users\n     [Provides download link]\n```\n\n## Troubleshooting\n\n### Issue: Connection Failed\n\n**Symptoms**: Bot cannot connect to database\n\n**Solutions**:\n1. Check database is running\n2. Verify credentials\n3. Check network connectivity\n4. Ensure API server is accessible from Coze\n\n### Issue: Query Timeout\n\n**Symptoms**: Queries take too long\n\n**Solutions**:\n1. Add indexes to database tables\n2. Optimize SQL queries\n3. Increase timeout in API configuration\n4. Use pagination for large result sets\n\n### Issue: Session Expired\n\n**Symptoms**: \"Session expired\" error\n\n**Solutions**:\n1. Reconnect to database\n2. Increase session timeout\n3. Implement auto-reconnect logic\n\n## Resources\n\n- [Coze Documentation](https://www.coze.com/docs)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Deployment Guide](../http-api/DEPLOYMENT.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Coze Community: https://www.coze.com/community\n"
  },
  {
    "path": "docs/integrations/COZE.zh-CN.md",
    "content": "# Coze 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Coze 平台集成。\n\n## 概述\n\nCoze 是一个 AI 机器人开发平台。通过集成 Universal Database MCP Server，您可以让 Coze 机器人查询和分析数据库数据。\n\n## 前置要求\n\n- 部署了 HTTP API 模式的 Universal Database MCP Server\n- Coze 账号\n- 数据库实例（MySQL、PostgreSQL 等）\n\n## 设置步骤\n\n### 步骤 1: 部署 HTTP API 服务器\n\n以 HTTP API 模式部署 Universal Database MCP Server：\n\n```bash\n# 使用 Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=coze-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n或部署到云平台（Railway、Render、Fly.io）。参见[部署指南](../http-api/DEPLOYMENT.zh-CN.md)。\n\n### 步骤 2: 获取 API 端点\n\n记录您的 API 端点 URL：\n- 本地: `http://localhost:3000`\n- 云端: `https://your-app.railway.app`（示例）\n\n### 步骤 3: 创建 Coze 机器人\n\n1. 登录 [Coze](https://www.coze.com/)\n2. 点击\"创建机器人\"\n3. 输入机器人名称和描述\n4. 点击\"创建\"\n\n### 步骤 4: 添加 API 插件\n\n1. 在机器人编辑器中，点击\"插件\"标签\n2. 点击\"添加插件\"\n3. 选择\"API 插件\"\n4. 配置 API：\n\n**基本信息**:\n\n- 名称: `数据库查询`\n- 描述: `使用自然语言查询数据库`\n\n**认证**:\n- 类型: `API Key`\n- 请求头名称: `X-API-Key`\n- API Key: `coze-secret-key`（您的 API Key）\n\n### 步骤 5: 配置 API 端点\n\n#### 端点 1: 连接数据库\n\n**名称**: `connect_database`\n**方法**: `POST`\n**URL**: `https://your-api-url/api/connect`\n**描述**: 连接到数据库\n\n**请求体**:\n```json\n{\n  \"type\": \"{{database_type}}\",\n  \"host\": \"{{host}}\",\n  \"port\": {{port}},\n  \"user\": \"{{user}}\",\n  \"password\": \"{{password}}\",\n  \"database\": \"{{database}}\",\n  \"permissionMode\": \"{{permission_mode}}\"\n}\n```\n\n**参数**:\n- `database_type` (字符串, 必需): 数据库类型（mysql、postgres 等）\n- `host` (字符串, 必需): 数据库主机\n- `port` (数字, 必需): 数据库端口\n- `user` (字符串, 必需): 用户名\n- `password` (字符串, 必需): 密码\n- `database` (字符串, 必需): 数据库名称\n- `permission_mode` (字符串, 可选): 权限模式：`safe`（默认，只读）、`readwrite`（读写不删）、`full`（完全控制）\n- `permissions` (数组, 可选): 自定义权限列表：`[\"read\", \"insert\", \"update\", \"delete\", \"ddl\"]`\n\n> ⚠️ **注意**：REST API 使用驼峰命名（`permissionMode`），不是连字符命名。\n\n**响应示例**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"abc123\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  }\n}\n```\n\n#### 端点 2: 执行查询\n\n**名称**: `execute_query`\n**方法**: `POST`\n**URL**: `https://your-api-url/api/query`\n**描述**: 执行 SQL 查询\n\n**请求体**:\n```json\n{\n  \"sessionId\": \"{{session_id}}\",\n  \"query\": \"{{sql_query}}\"\n}\n```\n\n**参数**:\n- `session_id` (字符串, 必需): 从 connect_database 获取的会话 ID\n- `sql_query` (字符串, 必需): 要执行的 SQL 查询\n\n**响应示例**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [\n      {\"id\": 1, \"name\": \"Alice\"},\n      {\"id\": 2, \"name\": \"Bob\"}\n    ],\n    \"executionTime\": 15\n  }\n}\n```\n\n#### 端点 3: 列出表\n\n**名称**: `list_tables`\n**方法**: `GET`\n**URL**: `https://your-api-url/api/tables?sessionId={{session_id}}`\n**描述**: 列出数据库中的所有表\n\n**参数**:\n- `session_id` (字符串, 必需): 从 connect_database 获取的会话 ID\n\n**响应示例**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\"]\n  }\n}\n```\n\n#### 端点 4: 获取表结构\n\n**名称**: `get_table_schema`\n**方法**: `GET`\n**URL**: `https://your-api-url/api/schema/{{table_name}}?sessionId={{session_id}}`\n**描述**: 获取表结构\n\n**参数**:\n- `table_name` (字符串, 必需): 表名\n- `session_id` (字符串, 必需): 从 connect_database 获取的会话 ID\n\n**响应示例**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"name\": \"users\",\n    \"columns\": [\n      {\"name\": \"id\", \"type\": \"int\", \"nullable\": false},\n      {\"name\": \"name\", \"type\": \"varchar(255)\", \"nullable\": false}\n    ]\n  }\n}\n```\n\n### 步骤 6: 创建机器人技能\n\n创建使用 API 插件的技能：\n\n#### 技能 1: 数据库连接\n\n**技能名称**: `连接数据库`\n**描述**: 连接到数据库\n\n**提示词**:\n```\n当用户要求连接数据库时，使用 connect_database API。\n\n询问用户：\n- 数据库类型（mysql、postgres 等）\n- 主机\n- 端口\n- 用户名\n- 密码\n- 数据库名称\n\n连接后，保存 sessionId 以供后续查询使用。\n```\n\n#### 技能 2: 查询数据\n\n**技能名称**: `查询数据库`\n**描述**: 使用自然语言查询数据库\n\n**提示词**:\n```\n当用户询问数据相关问题时：\n\n1. 如果未连接，要求用户先连接\n2. 使用 list_tables 查看可用表\n3. 使用 get_table_schema 了解表结构\n4. 根据用户问题生成适当的 SQL 查询\n5. 使用 execute_query 运行查询\n6. 以可读的方式格式化并呈现结果\n\n示例：\n用户：\"显示所有用户\"\n机器人：\n- 列出表以找到\"users\"表\n- 获取\"users\"表的结构\n- 生成 SQL: \"SELECT * FROM users LIMIT 10\"\n- 执行查询\n- 以表格格式呈现结果\n```\n\n\n\n**附上自己使用过的技能提示词：**\n\n```\n# 角色\n你是一个专业的数据库查询助手，能够帮助用户连接数据库并使用自然语言查询数据。\n\n# 技能\n\n## 技能1：连接数据库\n当用户要求连接数据库时：\n1. 询问用户数据库类型（mysql、postgres、sqlite）\n2. 询问数据库连接信息（主机、端口、用户名、密码、数据库名）\n3. 调用 connect_database 接口连接数据库\n4. 保存返回的 sessionId 用于后续查询\n5. 告知用户连接结果\n\n## 技能2：查询数据\n当用户询问数据相关问题时：\n1. 如果还未连接数据库，提示用户先连接\n2. 先调用 list_tables 查看有哪些表\n3. 调用 get_table_schema 了解相关表的结构\n4. 根据用户的自然语言问题，生成合适的 SQL 查询语句\n5. 调用 execute_query 执行查询\n6. 将查询结果以易读的方式呈现给用户（使用表格或列表）\n\n## 技能3：数据分析\n当用户需要数据分析时：\n1. 理解用户的分析需求\n2. 生成适当的聚合查询（COUNT、SUM、AVG、GROUP BY等）\n3. 执行查询并解读结果\n4. 提供简洁的分析结论\n\n# 限制\n- 只执行 SELECT 查询，不执行 INSERT、UPDATE、DELETE 等写操作\n- 查询结果默认限制 100 条，避免返回过多数据\n- 如果用户的问题不清晰，主动询问澄清\n- 保护用户隐私，不在对话中暴露敏感信息\n\n# 示例对话\n\n用户：连接我的MySQL数据库\n助手：好的，请提供以下数据库连接信息：\n1. 主机地址（如：localhost 或 IP地址）\n2. 端口（MySQL默认3306）\n3. 用户名\n4. 密码\n5. 数据库名称\n\n用户：查看所有用户\n助手：[调用 list_tables 和 get_table_schema]\n      [生成 SQL: SELECT * FROM users LIMIT 100]\n      [调用 execute_query]\n      \n      查询到 10 条用户记录：\n      | ID | 姓名 | 邮箱 |\n      |-----|------|------|\n      | 1 | 张三 | zhangsan@example.com |\n      | 2 | 李四 | lisi@example.com |\n      ...\n\n用户：上个月有多少订单？\n助手：[分析问题，生成 SQL]\n      [执行查询]\n      \n      上个月共有 1,234 个订单。\n```\n\n\n\n### 步骤 7: 测试机器人\n\n使用示例查询测试您的机器人：\n\n**示例 1: 连接**\n```\n用户：连接到我的 MySQL 数据库，地址 localhost:3306，用户 root，密码 xxx，数据库 testdb\n机器人：[调用 connect_database API]\n机器人：成功连接！会话 ID: abc123\n```\n\n**示例 2: 查询**\n```\n用户：显示所有用户\n机器人：[调用 list_tables API]\n机器人：[调用 get_table_schema API 获取\"users\"表]\n机器人：[生成 SQL: SELECT * FROM users LIMIT 10]\n机器人：[调用 execute_query API]\n机器人：这是用户列表：\n     1. Alice (alice@example.com)\n     2. Bob (bob@example.com)\n     ...\n```\n\n**示例 3: 复杂查询**\n```\n用户：上个月下了多少订单？\n机器人：[分析表和结构]\n机器人：[生成 SQL: SELECT COUNT(*) FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)]\n机器人：[执行查询]\n机器人：上个月下了 1,234 个订单。\n```\n\n## 高级功能\n\n### 会话管理\n\n在机器人内存中存储会话 ID：\n\n```javascript\n// 在机器人技能中\nconst sessionId = await connectDatabase(params);\nbot.memory.set('db_session_id', sessionId);\n\n// 稍后使用\nconst sessionId = bot.memory.get('db_session_id');\nawait executeQuery(sessionId, query);\n```\n\n### 错误处理\n\n优雅地处理 API 错误：\n\n```javascript\ntry {\n  const result = await executeQuery(sessionId, query);\n  return formatResults(result);\n} catch (error) {\n  if (error.code === 'SESSION_EXPIRED') {\n    return \"会话已过期。请重新连接数据库。\";\n  }\n  return `错误: ${error.message}`;\n}\n```\n\n### 查询优化\n\n实现查询优化：\n\n```javascript\n// 添加 LIMIT 防止大结果集\nif (!query.includes('LIMIT')) {\n  query += ' LIMIT 100';\n}\n\n// 执行前验证查询\nif (isWriteOperation(query) && !allowWrite) {\n  return \"只读模式下不允许写操作。\";\n}\n```\n\n## 安全最佳实践\n\n### 1. 保护 API Keys\n\n- 使用强随机 API Keys\n- 定期轮换密钥\n- 在 Coze 密钥中安全存储密钥\n\n### 2. 数据库凭据\n\n- 不要在机器人响应中暴露数据库凭据\n- 尽可能使用只读数据库用户\n- 实现连接池\n\n### 3. 查询验证\n\n- 执行前验证 SQL 查询\n- 防止 SQL 注入\n- 限制查询复杂度\n\n### 4. 速率限制\n\n- 配置适当的速率限制\n- 监控 API 使用情况\n- 实现指数退避\n\n## 示例用例\n\n### 用例 1: 客户支持机器人\n\n机器人帮助支持人员查询客户数据：\n\n```\n用户：查找邮箱为 alice@example.com 的客户\n机器人：[查询数据库]\n机器人：找到客户：\n     - ID: 123\n     - 姓名: Alice Smith\n     - 邮箱: alice@example.com\n     - 状态: 活跃\n     - 最后订单: 2026-01-20\n```\n\n### 用例 2: 分析机器人\n\n机器人提供业务洞察：\n\n```\n用户：本月收入是多少？\n机器人：[查询订单表]\n机器人：本月收入: ¥125,430\n     - 总订单数: 1,234\n     - 平均订单价值: ¥101.65\n     - 热销产品: Widget Pro\n```\n\n### 用例 3: 数据导出机器人\n\n机器人以各种格式导出数据：\n\n```\n用户：导出所有活跃用户到 CSV\n机器人：[查询数据库]\n机器人：已导出 5,432 个活跃用户\n     [提供下载链接]\n```\n\n## 故障排除\n\n### 问题：连接失败\n\n**症状**：机器人无法连接到数据库\n\n**解决方案**：\n1. 检查数据库是否运行\n2. 验证凭据\n3. 检查网络连接\n4. 确保 API 服务器可从 Coze 访问\n\n### 问题：查询超时\n\n**症状**：查询耗时过长\n\n**解决方案**：\n1. 为数据库表添加索引\n2. 优化 SQL 查询\n3. 增加 API 配置中的超时时间\n4. 对大结果集使用分页\n\n### 问题：会话过期\n\n**症状**：\"会话已过期\"错误\n\n**解决方案**：\n1. 重新连接数据库\n2. 增加会话超时时间\n3. 实现自动重连逻辑\n\n## 资源\n\n- [Coze 文档](https://www.coze.com/docs)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Coze 社区: https://www.coze.com/community\n"
  },
  {
    "path": "docs/integrations/CURSOR.md",
    "content": "# Cursor IDE Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Cursor IDE.\n\n## Overview\n\nCursor is an AI-powered code editor built on VS Code, designed to enhance developer productivity with intelligent code completion, chat, and AI-assisted coding features. By integrating Universal Database MCP Server, you can enable Cursor's AI to directly query and analyze your database data, making it easier to write database-related code, debug queries, and understand your data schema.\n\n**Key Benefits:**\n- Query databases directly from Cursor's AI chat\n- Get AI assistance for SQL query writing\n- Explore database schema without leaving the editor\n- Debug and optimize database queries with AI help\n\n## Prerequisites\n\n- [Cursor IDE](https://cursor.sh/) installed (version 0.43.0 or later recommended)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nCursor uses MCP stdio mode for tool integration. Configuration is done through a JSON file.\n\n### Configuration File Location\n\n| Platform | Path |\n|----------|------|\n| macOS | `~/.cursor/mcp.json` |\n| Linux | `~/.cursor/mcp.json` |\n| Windows | `%USERPROFILE%\\.cursor\\mcp.json` |\n\n### Step 1: Create Configuration File\n\nCreate or edit the `mcp.json` file at the appropriate location for your platform.\n\n### Step 2: Add MCP Server Configuration\n\nAdd the Universal Database MCP Server configuration to your `mcp.json` file:\n\n#### Basic Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Restart Cursor\n\nAfter saving the configuration file, restart Cursor IDE for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Cursor:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Cursor's AI chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk the AI to generate database-related code:\n\n```\nGenerate a TypeScript function to insert a new user into the users table\n```\n\nThe AI will examine your schema and generate appropriate code.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** `mcp.json` with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Cursor doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the `mcp.json` file is in the correct location\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart Cursor after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n## Advanced Configuration\n\n### Using Environment Variables\n\nFor better security, you can reference environment variables in your configuration. First, set the environment variables:\n\n**macOS/Linux:**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\nThen use a wrapper script that reads these variables.\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n## Resources\n\n- [Cursor IDE Official Website](https://cursor.sh/)\n- [Cursor Documentation](https://docs.cursor.com/)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cursor Community: https://forum.cursor.com/\n"
  },
  {
    "path": "docs/integrations/CURSOR.zh-CN.md",
    "content": "# Cursor IDE 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Cursor IDE 集成。\n\n## 概述\n\nCursor 是一款基于 VS Code 构建的 AI 驱动代码编辑器，旨在通过智能代码补全、聊天和 AI 辅助编码功能提升开发者生产力。通过集成 Universal Database MCP Server，您可以让 Cursor 的 AI 直接查询和分析数据库数据，从而更轻松地编写数据库相关代码、调试查询和理解数据结构。\n\n**主要优势：**\n- 直接从 Cursor 的 AI 聊天中查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 无需离开编辑器即可探索数据库结构\n- 借助 AI 帮助调试和优化数据库查询\n\n## 前置要求\n\n- 已安装 [Cursor IDE](https://cursor.sh/)（建议版本 0.43.0 或更高）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nCursor 使用 MCP stdio 模式进行工具集成。配置通过 JSON 文件完成。\n\n### 配置文件位置\n\n| 平台 | 路径 |\n|------|------|\n| macOS | `~/.cursor/mcp.json` |\n| Linux | `~/.cursor/mcp.json` |\n| Windows | `%USERPROFILE%\\.cursor\\mcp.json` |\n\n### 步骤 1: 创建配置文件\n\n在适合您平台的位置创建或编辑 `mcp.json` 文件。\n\n### 步骤 2: 添加 MCP 服务器配置\n\n将 Universal Database MCP Server 配置添加到您的 `mcp.json` 文件中：\n\n#### 基本配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3: 重启 Cursor\n\n保存配置文件后，重启 Cursor IDE 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Cursor 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Cursor 的 AI 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案。\n\n### 示例 5: 生成代码\n\n让 AI 生成数据库相关代码：\n\n```\n生成一个 TypeScript 函数，用于向 users 表插入新用户\n```\n\nAI 将检查您的结构并生成适当的代码。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的 `mcp.json` 提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：Cursor 无法识别数据库工具\n\n**解决方案**：\n1. 验证 `mcp.json` 文件位于正确位置\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 Cursor\n4. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n## 高级配置\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中引用环境变量。首先，设置环境变量：\n\n**macOS/Linux：**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell)：**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n然后使用读取这些变量的包装脚本。\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n## 资源\n\n- [Cursor IDE 官方网站](https://cursor.sh/)\n- [Cursor 文档](https://docs.cursor.com/)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cursor 社区: https://forum.cursor.com/\n"
  },
  {
    "path": "docs/integrations/DEVIN.md",
    "content": "# Devin Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Devin.\n\n## Overview\n\n[Devin](https://devin.ai/) is an AI software engineer. It supports MCP, allowing it to query databases while working on your codebase.\n\n## Prerequisites\n\n- Devin access\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nConfigure MCP server in Devin's settings:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Devin about your database:\n\n```\nWhat tables are in the database?\nCreate a function to query users from the database\nGenerate TypeScript interfaces for all tables\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Devin Documentation](https://devin.ai/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/DEVIN.zh-CN.md",
    "content": "# Devin 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Devin 集成。\n\n## 概述\n\n[Devin](https://devin.ai/) 是一个 AI 软件工程师。它支持 MCP，允许它在处理代码库时查询数据库。\n\n## 前置要求\n\n- Devin 访问权限\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n在 Devin 设置中配置 MCP 服务器：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Devin 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n创建一个从数据库查询用户的函数\n为所有表生成 TypeScript 接口\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Devin 文档](https://devin.ai/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/DIFY.md",
    "content": "# Dify Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Dify AI application development platform.\n\n## Overview\n\nDify is an LLM application development platform. By integrating Universal Database MCP Server, you can enable your Dify applications to query and analyze database data.\n\n**Two Integration Methods:**\n1. **MCP Protocol (Recommended)** - Use Dify's native MCP tool support via SSE/Streamable HTTP\n2. **Custom API Tool** - Use HTTP REST API as custom tools\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP mode\n- Dify account (self-hosted or cloud)\n- Database instance (MySQL, PostgreSQL, etc.)\n\n---\n\n## Method 1: MCP Protocol Integration (Recommended)\n\nThis method uses Dify's native MCP tool support, providing a more seamless integration experience.\n\n### Step 1: Deploy HTTP Server\n\nDeploy Universal Database MCP Server in HTTP mode:\n\n```bash\n# Using npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key  # Optional: Enable API key authentication\nnpx universal-db-mcp\n\n# Or using Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-key \\\n  universal-db-mcp:latest\n```\n\n> **Note**: If `API_KEYS` is configured, all MCP endpoints require authentication via `X-API-Key` header or `Authorization: Bearer <key>`.\n\n### Step 2: Configure MCP Tool in Dify\n\n1. Login to [Dify](https://dify.ai/)\n2. Go to **Tools** > **MCP Tools**\n3. Click **Add MCP Server**\n4. Configure the MCP server using one of the following methods:\n\n#### Option A: SSE Endpoint (Legacy)\n\n**Server Name**: `Universal DB MCP`\n\n**Server URL**:\n```\nhttp://your-server:3000/sse?type=mysql&host=db-host&port=3306&user=root&password=your_password&database=your_database\n```\n\n**Headers** (if API_KEYS is configured):\n```\nX-API-Key: your-secret-key\n```\n\nDatabase configuration is passed via URL parameters.\n\n#### Option B: Streamable HTTP Endpoint (Recommended)\n\n**Server Name**: `Universal DB MCP`\n\n**Server URL**:\n```\nhttp://your-server:3000/mcp\n```\n\n**Headers**:\n```\nX-API-Key: your-secret-key\nX-DB-Type: mysql\nX-DB-Host: db-host\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\nDatabase configuration is passed via HTTP headers.\n\n### Available Endpoints\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/sse` | GET | Establish SSE connection (legacy) |\n| `/sse/message` | POST | Send message to SSE session |\n| `/mcp` | POST | Streamable HTTP endpoint (recommended) |\n| `/mcp` | GET | SSE stream for Streamable HTTP |\n| `/mcp` | DELETE | Close session |\n\n### Step 3: Use MCP Tools in Application\n\nOnce configured, the following MCP tools will be available in your Dify application:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n### MCP SSE URL Parameters\n\n| Parameter | Required | Description |\n|-----------|----------|-------------|\n| `type` | Yes | Database type: mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `host` | Yes* | Database host |\n| `port` | No | Database port (uses default if not specified) |\n| `user` | Yes* | Database username |\n| `password` | Yes* | Database password |\n| `database` | Yes* | Database name |\n| `filePath` | Yes* | SQLite file path (for sqlite type) |\n| `allowWrite` | No | Enable write operations (default: false) |\n| `permissionMode` | No | Permission mode: `safe` (default), `readwrite`, `full` |\n| `permissions` | No | Custom permissions, comma-separated: `read,insert,update,delete,ddl` |\n\n*Required fields depend on database type\n\n> ⚠️ **Note**: Use camelCase for URL parameters (`permissionMode`), not hyphenated names.\n\n### Example SSE URLs\n\n**MySQL:**\n```\nhttp://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=secret&database=myapp\n```\n\n**PostgreSQL:**\n```\nhttp://localhost:3000/sse?type=postgres&host=localhost&port=5432&user=postgres&password=secret&database=myapp\n```\n\n**SQLite:**\n```\nhttp://localhost:3000/sse?type=sqlite&filePath=/path/to/database.db\n```\n\n**Redis:**\n```\nhttp://localhost:3000/sse?type=redis&host=localhost&port=6379&password=secret\n```\n\n### Streamable HTTP Headers\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-DB-Type` | Yes | Database type: mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `X-DB-Host` | Yes* | Database host |\n| `X-DB-Port` | No | Database port (uses default if not specified) |\n| `X-DB-User` | Yes* | Database username |\n| `X-DB-Password` | Yes* | Database password |\n| `X-DB-Database` | Yes* | Database name |\n| `X-DB-FilePath` | Yes* | SQLite file path (for sqlite type) |\n| `X-DB-Allow-Write` | No | Enable write operations (default: false) |\n| `X-DB-Permission-Mode` | No | Permission mode: `safe` (default), `readwrite`, `full` |\n| `X-DB-Permissions` | No | Custom permissions, comma-separated: `read,insert,update,delete,ddl` |\n| `X-DB-Oracle-Client-Path` | No | Oracle Instant Client path (for Oracle 11g) |\n| `mcp-session-id` | No | Session ID for subsequent requests |\n\n*Required fields depend on database type\n\n> ⚠️ **Note**: Use hyphenated names for HTTP headers (`X-DB-Permission-Mode`).\n\n### Example Streamable HTTP Requests\n\n**Initialize Connection (MySQL):**\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-DB-Type: mysql\" \\\n  -H \"X-DB-Host: localhost\" \\\n  -H \"X-DB-Port: 3306\" \\\n  -H \"X-DB-User: root\" \\\n  -H \"X-DB-Password: secret\" \\\n  -H \"X-DB-Database: myapp\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}},\"id\":1}'\n```\n\n**Subsequent Requests (with session ID):**\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"mcp-session-id: your-session-id\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":2}'\n```\n\n---\n\n## Method 2: Custom API Tool Integration\n\nThis method uses Dify's custom API tool feature with the REST API endpoints.\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server:\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=dify-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Create Dify Application\n\n1. Login to [Dify](https://dify.ai/)\n2. Click \"Create Application\"\n3. Select application type:\n   - **Chatbot**: For conversational database queries\n   - **Agent**: For autonomous database operations\n   - **Workflow**: For structured database workflows\n4. Name your application (e.g., \"Database Assistant\")\n\n### Step 3: Add API Tool\n\n1. In application editor, go to \"Tools\" section\n2. Click \"Add Tool\"\n3. Select \"Custom API\"\n4. Configure API tool\n\n### Step 4: Configure API Tool\n\n#### Basic Information\n\n**Tool Name**: `Database Query Tool`\n**Description**: `Query and analyze database data`\n**Icon**: Choose database icon\n\n#### Authentication\n\n**Type**: `API Key`\n**Header Name**: `X-API-Key`\n**API Key**: `dify-secret-key`\n\n#### API Endpoints\n\nAdd the following endpoints:\n\n##### Endpoint 1: Connect Database\n\n**Name**: `connect_database`\n**Method**: `POST`\n**URL**: `https://your-api-url/api/connect`\n**Description**: Connect to a database\n\n**Request Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"type\": {\n      \"type\": \"string\",\n      \"description\": \"Database type (mysql, postgres, redis, etc.)\",\n      \"enum\": [\"mysql\", \"postgres\", \"redis\", \"mongodb\", \"sqlite\"]\n    },\n    \"host\": {\n      \"type\": \"string\",\n      \"description\": \"Database host\"\n    },\n    \"port\": {\n      \"type\": \"integer\",\n      \"description\": \"Database port\"\n    },\n    \"user\": {\n      \"type\": \"string\",\n      \"description\": \"Username\"\n    },\n    \"password\": {\n      \"type\": \"string\",\n      \"description\": \"Password\"\n    },\n    \"database\": {\n      \"type\": \"string\",\n      \"description\": \"Database name\"\n    }\n  },\n  \"required\": [\"type\", \"host\", \"port\"]\n}\n```\n\n**Response Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"success\": {\"type\": \"boolean\"},\n    \"data\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"sessionId\": {\"type\": \"string\"},\n        \"databaseType\": {\"type\": \"string\"},\n        \"connected\": {\"type\": \"boolean\"}\n      }\n    }\n  }\n}\n```\n\n##### Endpoint 2: Execute Query\n\n**Name**: `execute_query`\n**Method**: `POST`\n**URL**: `https://your-api-url/api/query`\n**Description**: Execute SQL query\n\n**Request Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"sessionId\": {\n      \"type\": \"string\",\n      \"description\": \"Session ID from connect_database\"\n    },\n    \"query\": {\n      \"type\": \"string\",\n      \"description\": \"SQL query to execute\"\n    },\n    \"params\": {\n      \"type\": \"array\",\n      \"description\": \"Query parameters (optional)\"\n    }\n  },\n  \"required\": [\"sessionId\", \"query\"]\n}\n```\n\n**Response Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"success\": {\"type\": \"boolean\"},\n    \"data\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"rows\": {\"type\": \"array\"},\n        \"executionTime\": {\"type\": \"number\"}\n      }\n    }\n  }\n}\n```\n\n##### Endpoint 3: List Tables\n\n**Name**: `list_tables`\n**Method**: `GET`\n**URL**: `https://your-api-url/api/tables`\n**Description**: List all tables\n\n**Query Parameters**:\n```json\n{\n  \"sessionId\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"Session ID\"\n  }\n}\n```\n\n##### Endpoint 4: Get Table Schema\n\n**Name**: `get_table_schema`\n**Method**: `GET`\n**URL**: `https://your-api-url/api/schema/{table}`\n**Description**: Get table structure\n\n**Path Parameters**:\n```json\n{\n  \"table\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"Table name\"\n  }\n}\n```\n\n**Query Parameters**:\n```json\n{\n  \"sessionId\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"Session ID\"\n  }\n}\n```\n\n### Step 5: Configure Application Prompt\n\n#### For Chatbot Application\n\n**System Prompt**:\n```\nYou are a database assistant that helps users query and analyze database data.\n\nAvailable tools:\n- connect_database: Connect to a database\n- execute_query: Execute SQL queries\n- list_tables: List all tables in database\n- get_table_schema: Get table structure\n\nWorkflow:\n1. When user wants to query data, first check if connected to database\n2. If not connected, ask for database credentials and use connect_database\n3. Use list_tables to see available tables\n4. Use get_table_schema to understand table structure\n5. Generate appropriate SQL query based on user's question\n6. Use execute_query to run the query\n7. Format and present results in a clear, readable way\n\nGuidelines:\n- Always validate SQL queries before execution\n- Use parameterized queries when possible\n- Limit result sets to prevent overwhelming output\n- Explain query logic to users\n- Handle errors gracefully\n```\n\n**Opening Statement**:\n```\nHello! I'm your database assistant. I can help you query and analyze your database data using natural language.\n\nTo get started, please provide your database connection details:\n- Database type (MySQL, PostgreSQL, etc.)\n- Host and port\n- Username and password\n- Database name\n\nOr you can ask me questions like:\n- \"Show me all users\"\n- \"How many orders were placed last month?\"\n- \"What's the average order value?\"\n```\n\n#### For Agent Application\n\n**Agent Instructions**:\n```\nYou are an autonomous database agent that can:\n1. Connect to databases\n2. Explore database schema\n3. Execute queries\n4. Analyze data\n5. Generate reports\n\nTools available:\n- connect_database\n- execute_query\n- list_tables\n- get_table_schema\n\nWhen given a task:\n1. Break it down into steps\n2. Use tools to gather information\n3. Execute queries as needed\n4. Synthesize results\n5. Present findings clearly\n```\n\n#### For Workflow Application\n\nCreate a workflow with these nodes:\n\n1. **Start Node**: Receives user input\n2. **LLM Node**: Analyzes user request\n3. **Tool Node**: Connects to database\n4. **Tool Node**: Lists tables\n5. **Tool Node**: Gets table schema\n6. **LLM Node**: Generates SQL query\n7. **Tool Node**: Executes query\n8. **LLM Node**: Formats results\n9. **End Node**: Returns response\n\n### Step 6: Test Application\n\nTest with sample queries:\n\n**Example 1: Simple Query**\n```\nUser: Show me all users\nAssistant: Let me query the database for you.\n[Calls list_tables]\n[Calls get_table_schema for \"users\"]\n[Generates SQL: SELECT * FROM users LIMIT 10]\n[Calls execute_query]\nAssistant: Here are the users:\n1. Alice (alice@example.com)\n2. Bob (bob@example.com)\n...\n```\n\n**Example 2: Aggregation**\n```\nUser: How many orders were placed last month?\nAssistant: I'll check the orders for you.\n[Analyzes schema]\n[Generates SQL: SELECT COUNT(*) FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)]\n[Executes query]\nAssistant: There were 1,234 orders placed last month.\n```\n\n**Example 3: Complex Analysis**\n```\nUser: What's the revenue by product category?\nAssistant: Let me analyze the revenue data.\n[Joins orders and products tables]\n[Groups by category]\n[Calculates sum]\nAssistant: Revenue by category:\n- Electronics: $45,230\n- Clothing: $32,100\n- Books: $18,450\n```\n\n## Advanced Features\n\n### Variable Management\n\nStore session ID in Dify variables:\n\n```python\n# In workflow\nsession_id = connect_database(params)\nset_variable(\"db_session_id\", session_id)\n\n# Later use\nsession_id = get_variable(\"db_session_id\")\nexecute_query(session_id, query)\n```\n\n### Context Memory\n\nUse Dify's memory feature to remember database connections:\n\n```python\n# Store in conversation memory\nmemory.set(\"database_type\", \"mysql\")\nmemory.set(\"session_id\", session_id)\n\n# Retrieve later\nsession_id = memory.get(\"session_id\")\n```\n\n### Query Templates\n\nCreate reusable query templates:\n\n```sql\n-- Template: Get user by email\nSELECT * FROM users WHERE email = ?\n\n-- Template: Get orders by date range\nSELECT * FROM orders\nWHERE created_at BETWEEN ? AND ?\nORDER BY created_at DESC\n\n-- Template: Revenue by period\nSELECT\n  DATE_FORMAT(created_at, '%Y-%m') as month,\n  SUM(total_amount) as revenue\nFROM orders\nWHERE created_at >= ?\nGROUP BY month\nORDER BY month DESC\n```\n\n### Data Visualization\n\nIntegrate with Dify's visualization features:\n\n```python\n# Query data\nresults = execute_query(session_id, query)\n\n# Format for chart\nchart_data = {\n  \"type\": \"bar\",\n  \"data\": {\n    \"labels\": [row[\"month\"] for row in results],\n    \"datasets\": [{\n      \"label\": \"Revenue\",\n      \"data\": [row[\"revenue\"] for row in results]\n    }]\n  }\n}\n\nreturn chart_data\n```\n\n## Use Cases\n\n### Use Case 1: Customer Service Bot\n\n**Scenario**: Customer service agents query customer data\n\n**Features**:\n- Look up customer information\n- Check order status\n- View purchase history\n- Update customer notes\n\n**Example Queries**:\n```\n- \"Find customer with email alice@example.com\"\n- \"Show orders for customer ID 123\"\n- \"What's the status of order #456?\"\n```\n\n### Use Case 2: Business Intelligence Agent\n\n**Scenario**: Executives get business insights\n\n**Features**:\n- Revenue analysis\n- Customer metrics\n- Product performance\n- Trend analysis\n\n**Example Queries**:\n```\n- \"What's our revenue this quarter?\"\n- \"Show top 10 customers by revenue\"\n- \"Which products are selling best?\"\n- \"What's the customer retention rate?\"\n```\n\n### Use Case 3: Data Export Workflow\n\n**Scenario**: Automated data export and reporting\n\n**Workflow**:\n1. Schedule trigger (daily)\n2. Connect to database\n3. Execute export query\n4. Format as CSV/Excel\n5. Send via email/Slack\n6. Disconnect\n\n### Use Case 4: Database Monitoring\n\n**Scenario**: Monitor database health and performance\n\n**Features**:\n- Table size monitoring\n- Query performance tracking\n- Alert on anomalies\n- Automated reports\n\n## Best Practices\n\n### 1. Security\n\n- Use read-only database users\n- Store credentials securely in Dify secrets\n- Validate all SQL queries\n- Implement query whitelisting\n\n### 2. Performance\n\n- Add LIMIT to queries\n- Use indexes on frequently queried columns\n- Implement caching for schema information\n- Monitor query execution time\n\n### 3. Error Handling\n\n- Catch and handle database errors\n- Provide user-friendly error messages\n- Implement retry logic\n- Log errors for debugging\n\n### 4. User Experience\n\n- Provide clear instructions\n- Show query progress\n- Format results nicely\n- Offer query suggestions\n\n## Integration Patterns\n\n### Pattern 1: RAG with Database\n\nCombine database queries with RAG:\n\n```python\n# 1. Query database for structured data\ndb_results = execute_query(session_id, query)\n\n# 2. Use RAG for unstructured data\nrag_results = search_knowledge_base(question)\n\n# 3. Combine results\ncombined = merge_results(db_results, rag_results)\n\n# 4. Generate response\nresponse = llm.generate(combined)\n```\n\n### Pattern 2: Multi-Database Queries\n\nQuery multiple databases:\n\n```python\n# Connect to multiple databases\nmysql_session = connect_database(mysql_config)\npostgres_session = connect_database(postgres_config)\n\n# Query each database\nmysql_data = execute_query(mysql_session, mysql_query)\npostgres_data = execute_query(postgres_session, postgres_query)\n\n# Merge results\nmerged = merge_data(mysql_data, postgres_data)\n```\n\n### Pattern 3: Streaming Results\n\nStream large result sets:\n\n```python\n# Execute query with pagination\noffset = 0\nbatch_size = 100\n\nwhile True:\n    query = f\"SELECT * FROM users LIMIT {batch_size} OFFSET {offset}\"\n    results = execute_query(session_id, query)\n\n    if not results:\n        break\n\n    # Process batch\n    process_batch(results)\n\n    offset += batch_size\n```\n\n## Troubleshooting\n\n### Issue: Connection Failed\n\n**Symptoms**: Cannot connect to database\n\n**Solutions**:\n1. Verify database credentials\n2. Check network connectivity\n3. Ensure API server is accessible\n4. Check firewall rules\n\n### Issue: Query Timeout\n\n**Symptoms**: Queries take too long\n\n**Solutions**:\n1. Add indexes to tables\n2. Optimize SQL queries\n3. Increase timeout setting\n4. Use pagination\n\n### Issue: Memory Errors\n\n**Symptoms**: Out of memory errors\n\n**Solutions**:\n1. Limit result set size\n2. Use streaming for large datasets\n3. Implement pagination\n4. Increase memory allocation\n\n## Resources\n\n- [Dify Documentation](https://docs.dify.ai/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Deployment Guide](../http-api/DEPLOYMENT.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Dify Community: https://discord.gg/dify\n"
  },
  {
    "path": "docs/integrations/DIFY.zh-CN.md",
    "content": "# Dify 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Dify AI 应用开发平台集成。\n\n## 概述\n\nDify 是一个 LLM 应用开发平台。通过集成 Universal Database MCP Server，您可以让 Dify 应用查询和分析数据库数据。\n\n**两种集成方式：**\n1. **MCP 协议（推荐）** - 使用 Dify 原生 MCP 工具支持，通过 SSE/Streamable HTTP 连接\n2. **自定义 API 工具** - 使用 HTTP REST API 作为自定义工具\n\n## 前置要求\n\n- 部署了 HTTP 模式的 Universal Database MCP Server\n- Dify 账号（自托管或云端）\n- 数据库实例（MySQL、PostgreSQL 等）\n\n---\n\n## 方式一：MCP 协议集成（推荐）\n\n此方式使用 Dify 原生的 MCP 工具支持，提供更无缝的集成体验。\n\n### 步骤 1: 部署 HTTP 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server：\n\n```bash\n# 使用 npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=your-secret-key  # 可选：启用 API Key 认证\nnpx universal-db-mcp\n\n# 或使用 Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=your-secret-key \\\n  universal-db-mcp:latest\n```\n\n> **注意**: 如果配置了 `API_KEYS`，所有 MCP 端点都需要通过 `X-API-Key` 请求头或 `Authorization: Bearer <key>` 进行认证。\n\n### 步骤 2: 在 Dify 中配置 MCP 工具\n\n1. 登录 [Dify](https://dify.ai/)\n2. 进入 **工具** > **MCP 工具**\n3. 点击 **添加 MCP 服务器**\n4. 使用以下方式之一配置 MCP 服务器：\n\n#### 选项 A：SSE 端点（传统方式）\n\n**服务器名称**: `Universal DB MCP`\n\n**服务器 URL**:\n```\nhttp://your-server:3000/sse?type=mysql&host=db-host&port=3306&user=root&password=your_password&database=your_database\n```\n\n**请求头**（如果配置了 API_KEYS）:\n```\nX-API-Key: your-secret-key\n```\n\n数据库配置通过 URL 参数传递。\n\n#### 选项 B：Streamable HTTP 端点（推荐）\n\n**服务器名称**: `Universal DB MCP`\n\n**服务器 URL**:\n```\nhttp://your-server:3000/mcp\n```\n\n**请求头**:\n```\nX-API-Key: your-secret-key\nX-DB-Type: mysql\nX-DB-Host: db-host\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\n数据库配置通过 HTTP 请求头传递。\n\n### 可用端点\n\n| 端点 | 方法 | 说明 |\n|------|------|------|\n| `/sse` | GET | 建立 SSE 连接（传统方式） |\n| `/sse/message` | POST | 向 SSE 会话发送消息 |\n| `/mcp` | POST | Streamable HTTP 端点（推荐） |\n| `/mcp` | GET | Streamable HTTP 的 SSE 流 |\n| `/mcp` | DELETE | 关闭会话 |\n\n### 步骤 3: 在应用中使用 MCP 工具\n\n配置完成后，以下 MCP 工具将在您的 Dify 应用中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取表详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n### MCP SSE URL 参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `type` | 是 | 数据库类型：mysql、postgres、redis、oracle、dm、sqlserver、mongodb、sqlite、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `host` | 是* | 数据库主机 |\n| `port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `user` | 是* | 数据库用户名 |\n| `password` | 是* | 数据库密码 |\n| `database` | 是* | 数据库名称 |\n| `filePath` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `allowWrite` | 否 | 启用写操作（默认：false） |\n| `permissionMode` | 否 | 权限模式：`safe`（默认）、`readwrite`、`full` |\n| `permissions` | 否 | 自定义权限，逗号分隔：`read,insert,update,delete,ddl` |\n\n*必填字段取决于数据库类型\n\n> ⚠️ **注意**：URL 参数使用驼峰命名（`permissionMode`），不是连字符命名。\n\n### SSE URL 示例\n\n**MySQL:**\n```\nhttp://localhost:3000/sse?type=mysql&host=localhost&port=3306&user=root&password=secret&database=myapp\n```\n\n**PostgreSQL:**\n```\nhttp://localhost:3000/sse?type=postgres&host=localhost&port=5432&user=postgres&password=secret&database=myapp\n```\n\n**SQLite:**\n```\nhttp://localhost:3000/sse?type=sqlite&filePath=/path/to/database.db\n```\n\n**Redis:**\n```\nhttp://localhost:3000/sse?type=redis&host=localhost&port=6379&password=secret\n```\n\n**达梦数据库:**\n```\nhttp://localhost:3000/sse?type=dm&host=localhost&port=5236&user=SYSDBA&password=secret&database=DAMENG\n```\n\n**人大金仓:**\n```\nhttp://localhost:3000/sse?type=kingbase&host=localhost&port=54321&user=system&password=secret&database=mydb\n```\n\n### Streamable HTTP 请求头参数\n\n| 请求头 | 必填 | 描述 |\n|--------|------|------|\n| `X-DB-Type` | 是 | 数据库类型：mysql、postgres、redis、oracle、dm、sqlserver、mongodb、sqlite、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `X-DB-Host` | 是* | 数据库主机 |\n| `X-DB-Port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `X-DB-User` | 是* | 数据库用户名 |\n| `X-DB-Password` | 是* | 数据库密码 |\n| `X-DB-Database` | 是* | 数据库名称 |\n| `X-DB-FilePath` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `X-DB-Allow-Write` | 否 | 启用写操作（默认：false） |\n| `X-DB-Permission-Mode` | 否 | 权限模式：`safe`（默认）、`readwrite`、`full` |\n| `X-DB-Permissions` | 否 | 自定义权限，逗号分隔：`read,insert,update,delete,ddl` |\n| `X-DB-Oracle-Client-Path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n| `mcp-session-id` | 否 | 后续请求的会话 ID |\n\n*必填字段取决于数据库类型\n\n> ⚠️ **注意**：HTTP Header 使用连字符命名（`X-DB-Permission-Mode`）。\n\n### Streamable HTTP 请求示例\n\n**初始化连接（MySQL）：**\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-DB-Type: mysql\" \\\n  -H \"X-DB-Host: localhost\" \\\n  -H \"X-DB-Port: 3306\" \\\n  -H \"X-DB-User: root\" \\\n  -H \"X-DB-Password: secret\" \\\n  -H \"X-DB-Database: myapp\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}},\"id\":1}'\n```\n\n**后续请求（带会话 ID）：**\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"mcp-session-id: your-session-id\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":2}'\n```\n\n---\n\n## 方式二：自定义 API 工具集成\n\n此方式使用 Dify 的自定义 API 工具功能，通过 REST API 端点集成。\n\n### 步骤 1: 部署 HTTP API 服务器\n\n部署 Universal Database MCP Server：\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=dify-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2: 创建 Dify 应用\n\n1. 登录 [Dify](https://dify.ai/)\n2. 点击\"创建应用\"\n3. 选择应用类型：\n   - **聊天助手**: 用于对话式数据库查询\n   - **Agent**: 用于自主数据库操作\n   - **工作流**: 用于结构化数据库工作流\n4. 命名您的应用（例如：\"数据库助手\"）\n\n### 步骤 3: 添加 API 工具\n\n1. 在应用编辑器中，转到\"工具\"部分\n2. 点击\"添加工具\"\n3. 选择\"自定义 API\"\n4. 配置 API 工具\n\n### 步骤 4: 配置 API 工具\n\n#### 基本信息\n\n**工具名称**: `数据库查询工具`\n**描述**: `查询和分析数据库数据`\n**图标**: 选择数据库图标\n\n#### 认证\n\n**类型**: `API Key`\n**请求头名称**: `X-API-Key`\n**API Key**: `dify-secret-key`\n\n#### API 端点\n\n添加以下端点：\n\n##### 端点 1: 连接数据库\n\n**名称**: `connect_database`\n**方法**: `POST`\n**URL**: `https://your-api-url/api/connect`\n**描述**: 连接到数据库\n\n**请求 Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"type\": {\n      \"type\": \"string\",\n      \"description\": \"数据库类型（mysql、postgres、redis 等）\",\n      \"enum\": [\"mysql\", \"postgres\", \"redis\", \"mongodb\", \"sqlite\"]\n    },\n    \"host\": {\n      \"type\": \"string\",\n      \"description\": \"数据库主机\"\n    },\n    \"port\": {\n      \"type\": \"integer\",\n      \"description\": \"数据库端口\"\n    },\n    \"user\": {\n      \"type\": \"string\",\n      \"description\": \"用户名\"\n    },\n    \"password\": {\n      \"type\": \"string\",\n      \"description\": \"密码\"\n    },\n    \"database\": {\n      \"type\": \"string\",\n      \"description\": \"数据库名称\"\n    }\n  },\n  \"required\": [\"type\", \"host\", \"port\"]\n}\n```\n\n**响应 Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"success\": {\"type\": \"boolean\"},\n    \"data\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"sessionId\": {\"type\": \"string\"},\n        \"databaseType\": {\"type\": \"string\"},\n        \"connected\": {\"type\": \"boolean\"}\n      }\n    }\n  }\n}\n```\n\n##### 端点 2: 执行查询\n\n**名称**: `execute_query`\n**方法**: `POST`\n**URL**: `https://your-api-url/api/query`\n**描述**: 执行 SQL 查询\n\n**请求 Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"sessionId\": {\n      \"type\": \"string\",\n      \"description\": \"从 connect_database 获取的会话 ID\"\n    },\n    \"query\": {\n      \"type\": \"string\",\n      \"description\": \"要执行的 SQL 查询\"\n    },\n    \"params\": {\n      \"type\": \"array\",\n      \"description\": \"查询参数（可选）\"\n    }\n  },\n  \"required\": [\"sessionId\", \"query\"]\n}\n```\n\n**响应 Schema**:\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"success\": {\"type\": \"boolean\"},\n    \"data\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"rows\": {\"type\": \"array\"},\n        \"executionTime\": {\"type\": \"number\"}\n      }\n    }\n  }\n}\n```\n\n##### 端点 3: 列出表\n\n**名称**: `list_tables`\n**方法**: `GET`\n**URL**: `https://your-api-url/api/tables`\n**描述**: 列出所有表\n\n**查询参数**:\n```json\n{\n  \"sessionId\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"会话 ID\"\n  }\n}\n```\n\n##### 端点 4: 获取表结构\n\n**名称**: `get_table_schema`\n**方法**: `GET`\n**URL**: `https://your-api-url/api/schema/{table}`\n**描述**: 获取表结构\n\n**路径参数**:\n```json\n{\n  \"table\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"表名\"\n  }\n}\n```\n\n**查询参数**:\n```json\n{\n  \"sessionId\": {\n    \"type\": \"string\",\n    \"required\": true,\n    \"description\": \"会话 ID\"\n  }\n}\n```\n\n### 步骤 5: 配置应用提示词\n\n#### 聊天助手应用\n\n**系统提示词**:\n```\n你是一个数据库助手，帮助用户查询和分析数据库数据。\n\n可用工具：\n- connect_database: 连接到数据库\n- execute_query: 执行 SQL 查询\n- list_tables: 列出数据库中的所有表\n- get_table_schema: 获取表结构\n\n工作流程：\n1. 当用户想要查询数据时，首先检查是否已连接到数据库\n2. 如果未连接，询问数据库凭据并使用 connect_database\n3. 使用 list_tables 查看可用表\n4. 使用 get_table_schema 了解表结构\n5. 根据用户问题生成适当的 SQL 查询\n6. 使用 execute_query 运行查询\n7. 以清晰、可读的方式格式化并呈现结果\n\n指南：\n- 执行前始终验证 SQL 查询\n- 尽可能使用参数化查询\n- 限制结果集以防止输出过多\n- 向用户解释查询逻辑\n- 优雅地处理错误\n```\n\n**开场白**:\n```\n您好！我是您的数据库助手。我可以帮助您使用自然语言查询和分析数据库数据。\n\n要开始，请提供您的数据库连接详情：\n- 数据库类型（MySQL、PostgreSQL 等）\n- 主机和端口\n- 用户名和密码\n- 数据库名称\n\n或者您可以问我这样的问题：\n- \"显示所有用户\"\n- \"上个月下了多少订单？\"\n- \"平均订单价值是多少？\"\n```\n\n#### Agent 应用\n\n**Agent 指令**:\n```\n你是一个自主数据库 Agent，可以：\n1. 连接到数据库\n2. 探索数据库结构\n3. 执行查询\n4. 分析数据\n5. 生成报告\n\n可用工具：\n- connect_database\n- execute_query\n- list_tables\n- get_table_schema\n\n当给定任务时：\n1. 将其分解为步骤\n2. 使用工具收集信息\n3. 根据需要执行查询\n4. 综合结果\n5. 清晰地呈现发现\n```\n\n#### 工作流应用\n\n创建包含以下节点的工作流：\n\n1. **开始节点**: 接收用户输入\n2. **LLM 节点**: 分析用户请求\n3. **工具节点**: 连接到数据库\n4. **工具节点**: 列出表\n5. **工具节点**: 获取表结构\n6. **LLM 节点**: 生成 SQL 查询\n7. **工具节点**: 执行查询\n8. **LLM 节点**: 格式化结果\n9. **结束节点**: 返回响应\n\n### 步骤 6: 测试应用\n\n使用示例查询测试：\n\n**示例 1: 简单查询**\n```\n用户：显示所有用户\n助手：让我为您查询数据库。\n[调用 list_tables]\n[调用 get_table_schema 获取\"users\"]\n[生成 SQL: SELECT * FROM users LIMIT 10]\n[调用 execute_query]\n助手：这是用户列表：\n1. Alice (alice@example.com)\n2. Bob (bob@example.com)\n...\n```\n\n**示例 2: 聚合**\n```\n用户：上个月下了多少订单？\n助手：我来为您检查订单。\n[分析结构]\n[生成 SQL: SELECT COUNT(*) FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)]\n[执行查询]\n助手：上个月下了 1,234 个订单。\n```\n\n**示例 3: 复杂分析**\n```\n用户：按产品类别的收入是多少？\n助手：让我分析收入数据。\n[连接订单和产品表]\n[按类别分组]\n[计算总和]\n助手：按类别的收入：\n- 电子产品: ¥45,230\n- 服装: ¥32,100\n- 图书: ¥18,450\n```\n\n## 高级功能\n\n### 变量管理\n\n在 Dify 变量中存储会话 ID：\n\n```python\n# 在工作流中\nsession_id = connect_database(params)\nset_variable(\"db_session_id\", session_id)\n\n# 稍后使用\nsession_id = get_variable(\"db_session_id\")\nexecute_query(session_id, query)\n```\n\n### 上下文记忆\n\n使用 Dify 的记忆功能记住数据库连接：\n\n```python\n# 存储在对话记忆中\nmemory.set(\"database_type\", \"mysql\")\nmemory.set(\"session_id\", session_id)\n\n# 稍后检索\nsession_id = memory.get(\"session_id\")\n```\n\n### 查询模板\n\n创建可重用的查询模板：\n\n```sql\n-- 模板：按邮箱获取用户\nSELECT * FROM users WHERE email = ?\n\n-- 模板：按日期范围获取订单\nSELECT * FROM orders\nWHERE created_at BETWEEN ? AND ?\nORDER BY created_at DESC\n\n-- 模板：按期间的收入\nSELECT\n  DATE_FORMAT(created_at, '%Y-%m') as month,\n  SUM(total_amount) as revenue\nFROM orders\nWHERE created_at >= ?\nGROUP BY month\nORDER BY month DESC\n```\n\n### 数据可视化\n\n与 Dify 的可视化功能集成：\n\n```python\n# 查询数据\nresults = execute_query(session_id, query)\n\n# 格式化为图表\nchart_data = {\n  \"type\": \"bar\",\n  \"data\": {\n    \"labels\": [row[\"month\"] for row in results],\n    \"datasets\": [{\n      \"label\": \"收入\",\n      \"data\": [row[\"revenue\"] for row in results]\n    }]\n  }\n}\n\nreturn chart_data\n```\n\n## 用例\n\n### 用例 1: 客户服务机器人\n\n**场景**: 客服人员查询客户数据\n\n**功能**:\n- 查找客户信息\n- 检查订单状态\n- 查看购买历史\n- 更新客户备注\n\n**示例查询**:\n```\n- \"查找邮箱为 alice@example.com 的客户\"\n- \"显示客户 ID 123 的订单\"\n- \"订单 #456 的状态是什么？\"\n```\n\n### 用例 2: 商业智能 Agent\n\n**场景**: 高管获取业务洞察\n\n**功能**:\n- 收入分析\n- 客户指标\n- 产品性能\n- 趋势分析\n\n**示例查询**:\n```\n- \"本季度的收入是多少？\"\n- \"显示按收入排名前 10 的客户\"\n- \"哪些产品卖得最好？\"\n- \"客户留存率是多少？\"\n```\n\n### 用例 3: 数据导出工作流\n\n**场景**: 自动化数据导出和报告\n\n**工作流**:\n1. 定时触发（每天）\n2. 连接到数据库\n3. 执行导出查询\n4. 格式化为 CSV/Excel\n5. 通过邮件/Slack 发送\n6. 断开连接\n\n### 用例 4: 数据库监控\n\n**场景**: 监控数据库健康和性能\n\n**功能**:\n- 表大小监控\n- 查询性能跟踪\n- 异常告警\n- 自动化报告\n\n## 最佳实践\n\n### 1. 安全性\n\n- 使用只读数据库用户\n- 在 Dify 密钥中安全存储凭据\n- 验证所有 SQL 查询\n- 实现查询白名单\n\n### 2. 性能\n\n- 为查询添加 LIMIT\n- 在频繁查询的列上使用索引\n- 为 Schema 信息实现缓存\n- 监控查询执行时间\n\n### 3. 错误处理\n\n- 捕获并处理数据库错误\n- 提供用户友好的错误消息\n- 实现重试逻辑\n- 记录错误以供调试\n\n### 4. 用户体验\n\n- 提供清晰的说明\n- 显示查询进度\n- 格式化结果美观\n- 提供查询建议\n\n## 集成模式\n\n### 模式 1: RAG 与数据库\n\n结合数据库查询与 RAG：\n\n```python\n# 1. 查询数据库获取结构化数据\ndb_results = execute_query(session_id, query)\n\n# 2. 使用 RAG 获取非结构化数据\nrag_results = search_knowledge_base(question)\n\n# 3. 合并结果\ncombined = merge_results(db_results, rag_results)\n\n# 4. 生成响应\nresponse = llm.generate(combined)\n```\n\n### 模式 2: 多数据库查询\n\n查询多个数据库：\n\n```python\n# 连接到多个数据库\nmysql_session = connect_database(mysql_config)\npostgres_session = connect_database(postgres_config)\n\n# 查询每个数据库\nmysql_data = execute_query(mysql_session, mysql_query)\npostgres_data = execute_query(postgres_session, postgres_query)\n\n# 合并结果\nmerged = merge_data(mysql_data, postgres_data)\n```\n\n### 模式 3: 流式结果\n\n流式传输大结果集：\n\n```python\n# 使用分页执行查询\noffset = 0\nbatch_size = 100\n\nwhile True:\n    query = f\"SELECT * FROM users LIMIT {batch_size} OFFSET {offset}\"\n    results = execute_query(session_id, query)\n\n    if not results:\n        break\n\n    # 处理批次\n    process_batch(results)\n\n    offset += batch_size\n```\n\n## 故障排除\n\n### 问题：连接失败\n\n**症状**：无法连接到数据库\n\n**解决方案**：\n1. 验证数据库凭据\n2. 检查网络连接\n3. 确保 API 服务器可访问\n4. 检查防火墙规则\n\n### 问题：查询超时\n\n**症状**：查询耗时过长\n\n**解决方案**：\n1. 为表添加索引\n2. 优化 SQL 查询\n3. 增加超时设置\n4. 使用分页\n\n### 问题：内存错误\n\n**症状**：内存不足错误\n\n**解决方案**：\n1. 限制结果集大小\n2. 对大数据集使用流式传输\n3. 实现分页\n4. 增加内存分配\n\n## 资源\n\n- [Dify 文档](https://docs.dify.ai/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Dify 社区: https://discord.gg/dify\n"
  },
  {
    "path": "docs/integrations/DISCORD.md",
    "content": "# Discord Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Discord through a bot.\n\n## Overview\n\nDiscord is a popular communication platform. By creating a Discord bot that connects to Universal Database MCP Server via REST API, you can enable database queries directly from Discord channels.\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP API mode\n- Discord account with bot creation permissions\n- Node.js 20.0.0 or later\n- Database instance (MySQL, PostgreSQL, etc.)\n\n## Setup Steps\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server in HTTP mode:\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=discord-bot-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Create Discord Application\n\n1. Go to [Discord Developer Portal](https://discord.com/developers/applications)\n2. Click \"New Application\"\n3. Enter application name (e.g., \"Database Bot\")\n4. Go to \"Bot\" section\n5. Click \"Add Bot\"\n6. Copy the bot token\n\n### Step 3: Configure Bot Permissions\n\n1. Go to \"OAuth2\" > \"URL Generator\"\n2. Select scopes: `bot`, `applications.commands`\n3. Select bot permissions:\n   - Send Messages\n   - Read Message History\n   - Use Slash Commands\n4. Copy the generated URL and invite bot to your server\n\n### Step 4: Create Bot Server\n\n```javascript\nconst { Client, GatewayIntentBits, SlashCommandBuilder, REST, Routes } = require('discord.js');\nconst axios = require('axios');\n\nconst client = new Client({\n  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]\n});\n\nconst MCP_API_URL = 'http://localhost:3000';\nconst MCP_API_KEY = 'discord-bot-secret-key';\nconst DISCORD_TOKEN = 'your-discord-bot-token';\nconst CLIENT_ID = 'your-client-id';\n\n// Store sessions per user\nconst userSessions = new Map();\n\n// Register slash commands\nconst commands = [\n  new SlashCommandBuilder()\n    .setName('db-connect')\n    .setDescription('Connect to a database')\n    .addStringOption(opt => opt.setName('type').setDescription('Database type').setRequired(true))\n    .addStringOption(opt => opt.setName('host').setDescription('Host').setRequired(true))\n    .addIntegerOption(opt => opt.setName('port').setDescription('Port').setRequired(true))\n    .addStringOption(opt => opt.setName('user').setDescription('Username').setRequired(true))\n    .addStringOption(opt => opt.setName('password').setDescription('Password').setRequired(true))\n    .addStringOption(opt => opt.setName('database').setDescription('Database name').setRequired(true)),\n  new SlashCommandBuilder()\n    .setName('db-query')\n    .setDescription('Execute SQL query')\n    .addStringOption(opt => opt.setName('sql').setDescription('SQL query').setRequired(true)),\n  new SlashCommandBuilder()\n    .setName('db-schema')\n    .setDescription('Get database schema')\n    .addStringOption(opt => opt.setName('table').setDescription('Table name (optional)')),\n  new SlashCommandBuilder()\n    .setName('db-disconnect')\n    .setDescription('Disconnect from database')\n].map(cmd => cmd.toJSON());\n\nconst rest = new REST({ version: '10' }).setToken(DISCORD_TOKEN);\n\n// Register commands\n(async () => {\n  await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });\n})();\n\nclient.on('interactionCreate', async interaction => {\n  if (!interaction.isChatInputCommand()) return;\n\n  const userId = interaction.user.id;\n\n  if (interaction.commandName === 'db-connect') {\n    await interaction.deferReply({ ephemeral: true });\n\n    try {\n      const response = await axios.post(`${MCP_API_URL}/api/connect`, {\n        type: interaction.options.getString('type'),\n        host: interaction.options.getString('host'),\n        port: interaction.options.getInteger('port'),\n        user: interaction.options.getString('user'),\n        password: interaction.options.getString('password'),\n        database: interaction.options.getString('database')\n      }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        userSessions.set(userId, response.data.data.sessionId);\n        await interaction.editReply('Connected to database successfully!');\n      } else {\n        await interaction.editReply(`Connection failed: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`Error: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-query') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: 'Not connected. Use /db-connect first.', ephemeral: true });\n    }\n\n    await interaction.deferReply();\n\n    try {\n      const response = await axios.post(`${MCP_API_URL}/api/query`, {\n        sessionId,\n        query: interaction.options.getString('sql')\n      }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        const rows = response.data.data.rows;\n        const result = formatResult(rows);\n        await interaction.editReply(`\\`\\`\\`\\n${result}\\n\\`\\`\\``);\n      } else {\n        await interaction.editReply(`Query failed: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`Error: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-schema') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: 'Not connected. Use /db-connect first.', ephemeral: true });\n    }\n\n    await interaction.deferReply({ ephemeral: true });\n\n    try {\n      const table = interaction.options.getString('table');\n      const url = table\n        ? `${MCP_API_URL}/api/schema/${table}?sessionId=${sessionId}`\n        : `${MCP_API_URL}/api/schema?sessionId=${sessionId}`;\n\n      const response = await axios.get(url, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        const schema = JSON.stringify(response.data.data, null, 2);\n        await interaction.editReply(`\\`\\`\\`json\\n${schema.slice(0, 1900)}\\n\\`\\`\\``);\n      } else {\n        await interaction.editReply(`Failed: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`Error: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-disconnect') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: 'Not connected.', ephemeral: true });\n    }\n\n    try {\n      await axios.post(`${MCP_API_URL}/api/disconnect`, { sessionId }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n      userSessions.delete(userId);\n      await interaction.reply({ content: 'Disconnected successfully.', ephemeral: true });\n    } catch (error) {\n      await interaction.reply({ content: `Error: ${error.message}`, ephemeral: true });\n    }\n  }\n});\n\nfunction formatResult(rows) {\n  if (!rows || rows.length === 0) return 'No results';\n  const headers = Object.keys(rows[0]);\n  const headerRow = headers.join(' | ');\n  const separator = headers.map(() => '---').join(' | ');\n  const dataRows = rows.slice(0, 10).map(row =>\n    headers.map(h => String(row[h] ?? '')).join(' | ')\n  ).join('\\n');\n  let result = `${headerRow}\\n${separator}\\n${dataRows}`;\n  if (rows.length > 10) result += `\\n... and ${rows.length - 10} more rows`;\n  return result;\n}\n\nclient.login(DISCORD_TOKEN);\n```\n\n## Usage Examples\n\n```\n/db-connect type:mysql host:localhost port:3306 user:root password:xxx database:mydb\nBot: Connected to database successfully!\n\n/db-query sql:SELECT * FROM users LIMIT 5\nBot:\nid | name  | email\n---|-------|-------------------\n1  | Alice | alice@example.com\n2  | Bob   | bob@example.com\n\n/db-schema table:users\nBot: {\n  \"table\": \"users\",\n  \"columns\": [...]\n}\n\n/db-disconnect\nBot: Disconnected successfully.\n```\n\n## Best Practices\n\n1. **Security**: Use ephemeral replies for sensitive data\n2. **Permissions**: Restrict bot commands to specific channels/roles\n3. **Rate Limiting**: Implement rate limiting to prevent abuse\n4. **Error Handling**: Provide clear error messages\n\n## Resources\n\n- [Discord.js Documentation](https://discord.js.org/)\n- [Discord Developer Portal](https://discord.com/developers)\n- [API Reference](../http-api/API_REFERENCE.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/DISCORD.zh-CN.md",
    "content": "# Discord 集成指南\n\n本指南展示如何通过机器人将 Universal Database MCP Server 与 Discord 集成。\n\n## 概述\n\nDiscord 是一个流行的通讯平台。通过创建一个连接到 Universal Database MCP Server REST API 的 Discord 机器人，您可以直接从 Discord 频道进行数据库查询。\n\n## 前置要求\n\n- 部署了 HTTP API 模式的 Universal Database MCP Server\n- 具有机器人创建权限的 Discord 账号\n- Node.js 20.0.0 或更高版本\n- 数据库实例（MySQL、PostgreSQL 等）\n\n## 设置步骤\n\n### 步骤 1：部署 HTTP API 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server：\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=discord-bot-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：创建 Discord 应用\n\n1. 访问 [Discord 开发者门户](https://discord.com/developers/applications)\n2. 点击\"New Application\"\n3. 输入应用名称（例如：\"Database Bot\"）\n4. 转到\"Bot\"部分\n5. 点击\"Add Bot\"\n6. 复制机器人令牌\n\n### 步骤 3：配置机器人权限\n\n1. 转到\"OAuth2\" > \"URL Generator\"\n2. 选择范围：`bot`、`applications.commands`\n3. 选择机器人权限：\n   - Send Messages\n   - Read Message History\n   - Use Slash Commands\n4. 复制生成的 URL 并邀请机器人到您的服务器\n\n### 步骤 4：创建机器人服务器\n\n```javascript\nconst { Client, GatewayIntentBits, SlashCommandBuilder, REST, Routes } = require('discord.js');\nconst axios = require('axios');\n\nconst client = new Client({\n  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]\n});\n\nconst MCP_API_URL = 'http://localhost:3000';\nconst MCP_API_KEY = 'discord-bot-secret-key';\nconst DISCORD_TOKEN = 'your-discord-bot-token';\nconst CLIENT_ID = 'your-client-id';\n\n// 为每个用户存储会话\nconst userSessions = new Map();\n\n// 注册斜杠命令\nconst commands = [\n  new SlashCommandBuilder()\n    .setName('db-connect')\n    .setDescription('连接到数据库')\n    .addStringOption(opt => opt.setName('type').setDescription('数据库类型').setRequired(true))\n    .addStringOption(opt => opt.setName('host').setDescription('主机').setRequired(true))\n    .addIntegerOption(opt => opt.setName('port').setDescription('端口').setRequired(true))\n    .addStringOption(opt => opt.setName('user').setDescription('用户名').setRequired(true))\n    .addStringOption(opt => opt.setName('password').setDescription('密码').setRequired(true))\n    .addStringOption(opt => opt.setName('database').setDescription('数据库名').setRequired(true)),\n  new SlashCommandBuilder()\n    .setName('db-query')\n    .setDescription('执行 SQL 查询')\n    .addStringOption(opt => opt.setName('sql').setDescription('SQL 查询').setRequired(true)),\n  new SlashCommandBuilder()\n    .setName('db-schema')\n    .setDescription('获取数据库结构')\n    .addStringOption(opt => opt.setName('table').setDescription('表名（可选）')),\n  new SlashCommandBuilder()\n    .setName('db-disconnect')\n    .setDescription('断开数据库连接')\n].map(cmd => cmd.toJSON());\n\nconst rest = new REST({ version: '10' }).setToken(DISCORD_TOKEN);\n\n// 注册命令\n(async () => {\n  await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });\n})();\n\nclient.on('interactionCreate', async interaction => {\n  if (!interaction.isChatInputCommand()) return;\n\n  const userId = interaction.user.id;\n\n  if (interaction.commandName === 'db-connect') {\n    await interaction.deferReply({ ephemeral: true });\n\n    try {\n      const response = await axios.post(`${MCP_API_URL}/api/connect`, {\n        type: interaction.options.getString('type'),\n        host: interaction.options.getString('host'),\n        port: interaction.options.getInteger('port'),\n        user: interaction.options.getString('user'),\n        password: interaction.options.getString('password'),\n        database: interaction.options.getString('database')\n      }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        userSessions.set(userId, response.data.data.sessionId);\n        await interaction.editReply('成功连接到数据库！');\n      } else {\n        await interaction.editReply(`连接失败: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`错误: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-query') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: '未连接。请先使用 /db-connect。', ephemeral: true });\n    }\n\n    await interaction.deferReply();\n\n    try {\n      const response = await axios.post(`${MCP_API_URL}/api/query`, {\n        sessionId,\n        query: interaction.options.getString('sql')\n      }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        const rows = response.data.data.rows;\n        const result = formatResult(rows);\n        await interaction.editReply(`\\`\\`\\`\\n${result}\\n\\`\\`\\``);\n      } else {\n        await interaction.editReply(`查询失败: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`错误: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-schema') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: '未连接。请先使用 /db-connect。', ephemeral: true });\n    }\n\n    await interaction.deferReply({ ephemeral: true });\n\n    try {\n      const table = interaction.options.getString('table');\n      const url = table\n        ? `${MCP_API_URL}/api/schema/${table}?sessionId=${sessionId}`\n        : `${MCP_API_URL}/api/schema?sessionId=${sessionId}`;\n\n      const response = await axios.get(url, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n\n      if (response.data.success) {\n        const schema = JSON.stringify(response.data.data, null, 2);\n        await interaction.editReply(`\\`\\`\\`json\\n${schema.slice(0, 1900)}\\n\\`\\`\\``);\n      } else {\n        await interaction.editReply(`失败: ${response.data.error.message}`);\n      }\n    } catch (error) {\n      await interaction.editReply(`错误: ${error.message}`);\n    }\n  }\n\n  if (interaction.commandName === 'db-disconnect') {\n    const sessionId = userSessions.get(userId);\n    if (!sessionId) {\n      return interaction.reply({ content: '未连接。', ephemeral: true });\n    }\n\n    try {\n      await axios.post(`${MCP_API_URL}/api/disconnect`, { sessionId }, {\n        headers: { 'X-API-Key': MCP_API_KEY }\n      });\n      userSessions.delete(userId);\n      await interaction.reply({ content: '已成功断开连接。', ephemeral: true });\n    } catch (error) {\n      await interaction.reply({ content: `错误: ${error.message}`, ephemeral: true });\n    }\n  }\n});\n\nfunction formatResult(rows) {\n  if (!rows || rows.length === 0) return '无结果';\n  const headers = Object.keys(rows[0]);\n  const headerRow = headers.join(' | ');\n  const separator = headers.map(() => '---').join(' | ');\n  const dataRows = rows.slice(0, 10).map(row =>\n    headers.map(h => String(row[h] ?? '')).join(' | ')\n  ).join('\\n');\n  let result = `${headerRow}\\n${separator}\\n${dataRows}`;\n  if (rows.length > 10) result += `\\n... 还有 ${rows.length - 10} 行`;\n  return result;\n}\n\nclient.login(DISCORD_TOKEN);\n```\n\n## 使用示例\n\n```\n/db-connect type:mysql host:localhost port:3306 user:root password:xxx database:mydb\nBot: 成功连接到数据库！\n\n/db-query sql:SELECT * FROM users LIMIT 5\nBot:\nid | name  | email\n---|-------|-------------------\n1  | 张三  | zhang@example.com\n2  | 李四  | li@example.com\n\n/db-schema table:users\nBot: {\n  \"table\": \"users\",\n  \"columns\": [...]\n}\n\n/db-disconnect\nBot: 已成功断开连接。\n```\n\n## 最佳实践\n\n1. **安全性**：对敏感数据使用临时回复\n2. **权限**：将机器人命令限制在特定频道/角色\n3. **速率限制**：实现速率限制以防止滥用\n4. **错误处理**：提供清晰的错误消息\n\n## 资源\n\n- [Discord.js 文档](https://discord.js.org/)\n- [Discord 开发者门户](https://discord.com/developers)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/EMACS.md",
    "content": "# Emacs Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Emacs using the mcp.el package.\n\n## Overview\n\nEmacs is a powerful, extensible text editor that supports MCP integration through the mcp.el package. By integrating Universal Database MCP Server, you can query and analyze database data directly within Emacs using AI assistants.\n\n**Key Benefits:**\n- Query databases directly from Emacs\n- Get AI assistance for SQL query writing\n- Explore database schema without leaving the editor\n- Debug and optimize database queries with AI help\n\n## Prerequisites\n\n- [Emacs](https://www.gnu.org/software/emacs/) 27.1 or later installed\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n- mcp.el package installed\n\n---\n\n## Step 1: Install mcp.el Package\n\n### Using use-package (Recommended)\n\nAdd the following to your Emacs configuration file (`~/.emacs.d/init.el` or `~/.emacs`):\n\n```elisp\n(use-package mcp\n  :ensure t)\n```\n\n### Using package.el\n\n1. Add MELPA to your package archives if not already configured:\n\n```elisp\n(require 'package)\n(add-to-list 'package-archives '(\"melpa\" . \"https://melpa.org/packages/\") t)\n(package-initialize)\n```\n\n2. Install the package:\n\n```\nM-x package-refresh-contents\nM-x package-install RET mcp RET\n```\n\n### Manual Installation\n\n1. Clone the mcp.el repository:\n\n```bash\ngit clone https://github.com/lizqwerscott/mcp.el.git ~/.emacs.d/site-lisp/mcp.el\n```\n\n2. Add to your configuration:\n\n```elisp\n(add-to-list 'load-path \"~/.emacs.d/site-lisp/mcp.el\")\n(require 'mcp)\n```\n\n---\n\n## Step 2: Configure MCP Server\n\nAdd the Universal Database MCP Server configuration to your Emacs configuration file.\n\n### Basic Configuration\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"universal-db-mcp\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n---\n\n## Configuration Examples\n\n### MySQL\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### PostgreSQL\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"postgres-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"postgres\" \"--host\" \"localhost\" \"--port\" \"5432\" \"--user\" \"postgres\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### SQLite\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"sqlite-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"sqlite\" \"--file\" \"/path/to/your/database.db\")))))\n```\n\n### SQL Server\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"sqlserver-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"sqlserver\" \"--host\" \"localhost\" \"--port\" \"1433\" \"--user\" \"sa\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### Oracle\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"oracle-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"oracle\" \"--host\" \"localhost\" \"--port\" \"1521\" \"--user\" \"system\" \"--password\" \"your_password\" \"--database\" \"ORCL\")))))\n```\n\n### MongoDB\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mongodb\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mongodb\" \"--host\" \"localhost\" \"--port\" \"27017\" \"--user\" \"admin\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### Redis\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"redis\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"redis\" \"--host\" \"localhost\" \"--port\" \"6379\" \"--password\" \"your_password\")))))\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-production\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"prod-db.example.com\" \"--port\" \"3306\" \"--user\" \"readonly_user\" \"--password\" \"prod_password\" \"--database\" \"production_db\"))\n          (\"mysql-development\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"dev_password\" \"--database\" \"development_db\"))\n          (\"postgres-analytics\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"postgres\" \"--host\" \"analytics-db.example.com\" \"--port\" \"5432\" \"--user\" \"analyst\" \"--password\" \"analytics_password\" \"--database\" \"analytics\")))))\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-db-writable\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\" \"--allow-write\" \"true\")))))\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n---\n\n## Step 3: Start MCP Server\n\nAfter configuring, start the MCP server:\n\n```\nM-x mcp-start-server\n```\n\nSelect the server you want to start from the list.\n\n---\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nUse the MCP tools to explore your database:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk the AI to generate database-related code:\n\n```\nGenerate an Elisp function to insert a new user into the users table\n```\n\nThe AI will examine your schema and generate appropriate code.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** configuration files with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Starting\n\n**Symptoms**: The MCP server fails to start or connect\n\n**Solutions**:\n1. Verify the configuration syntax is correct in your init file\n2. Check that all parentheses and quotes are properly balanced\n3. Restart Emacs after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n5. Run `M-x mcp-start-server` and check the *Messages* buffer for errors\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Add Node.js path to Emacs exec-path:\n\n```elisp\n(add-to-list 'exec-path \"/usr/local/bin\")\n;; Or on macOS with Homebrew:\n(add-to-list 'exec-path \"/opt/homebrew/bin\")\n```\n\n4. On Windows, you may need to restart after installing Node.js\n\n### Issue: Package Not Found\n\n**Symptoms**: mcp.el package cannot be installed\n\n**Solutions**:\n1. Ensure MELPA is added to your package archives\n2. Run `M-x package-refresh-contents` to update package list\n3. Try manual installation from GitHub\n\n## Advanced Configuration\n\n### Using Environment Variables\n\nFor better security, you can use environment variables in your configuration:\n\n**Shell Configuration:**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Emacs Configuration:**\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        `((\"mysql-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" ,(getenv \"DB_PASSWORD\") \"--database\" \"your_database\")))))\n```\n\nNote the use of backtick (`) instead of single quote (') to enable evaluation of `(getenv \"DB_PASSWORD\")`.\n\n### Integration with gptel\n\nIf you use gptel for AI interactions in Emacs, you can integrate MCP tools:\n\n```elisp\n(use-package gptel\n  :ensure t\n  :config\n  ;; Configure gptel with your preferred AI backend\n  )\n\n(use-package mcp\n  :ensure t\n  :after gptel\n  :config\n  (setq mcp-servers\n        '((\"universal-db-mcp\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"docker-mysql\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"127.0.0.1\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"root_password\" \"--database\" \"app_db\")))))\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n## Resources\n\n- [GNU Emacs Official Website](https://www.gnu.org/software/emacs/)\n- [mcp.el GitHub Repository](https://github.com/lizqwerscott/mcp.el)\n- [MELPA Package Archive](https://melpa.org/)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- mcp.el Issues: https://github.com/lizqwerscott/mcp.el/issues\n"
  },
  {
    "path": "docs/integrations/EMACS.zh-CN.md",
    "content": "# Emacs 集成指南\n\n本指南展示如何通过 mcp.el 包将 Universal Database MCP Server 与 Emacs 集成。\n\n## 概述\n\nEmacs 是一款功能强大、可扩展的文本编辑器，通过 mcp.el 包支持 MCP 集成。通过集成 Universal Database MCP Server，您可以使用 AI 助手直接在 Emacs 中查询和分析数据库数据。\n\n**主要优势：**\n- 直接从 Emacs 查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 无需离开编辑器即可探索数据库结构\n- 借助 AI 帮助调试和优化数据库查询\n\n## 前置要求\n\n- 已安装 [Emacs](https://www.gnu.org/software/emacs/) 27.1 或更高版本\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n- 已安装 mcp.el 包\n\n---\n\n## 步骤 1：安装 mcp.el 包\n\n### 使用 use-package（推荐）\n\n将以下内容添加到您的 Emacs 配置文件（`~/.emacs.d/init.el` 或 `~/.emacs`）：\n\n```elisp\n(use-package mcp\n  :ensure t)\n```\n\n### 使用 package.el\n\n1. 如果尚未配置，将 MELPA 添加到您的包存档：\n\n```elisp\n(require 'package)\n(add-to-list 'package-archives '(\"melpa\" . \"https://melpa.org/packages/\") t)\n(package-initialize)\n```\n\n2. 安装包：\n\n```\nM-x package-refresh-contents\nM-x package-install RET mcp RET\n```\n\n### 手动安装\n\n1. 克隆 mcp.el 仓库：\n\n```bash\ngit clone https://github.com/lizqwerscott/mcp.el.git ~/.emacs.d/site-lisp/mcp.el\n```\n\n2. 添加到您的配置：\n\n```elisp\n(add-to-list 'load-path \"~/.emacs.d/site-lisp/mcp.el\")\n(require 'mcp)\n```\n\n---\n\n## 步骤 2：配置 MCP 服务器\n\n将 Universal Database MCP Server 配置添加到您的 Emacs 配置文件。\n\n### 基本配置\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"universal-db-mcp\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n---\n\n## 配置示例\n\n### MySQL\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### PostgreSQL\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"postgres-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"postgres\" \"--host\" \"localhost\" \"--port\" \"5432\" \"--user\" \"postgres\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### SQLite\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"sqlite-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"sqlite\" \"--file\" \"/path/to/your/database.db\")))))\n```\n\n### SQL Server\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"sqlserver-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"sqlserver\" \"--host\" \"localhost\" \"--port\" \"1433\" \"--user\" \"sa\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### Oracle\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"oracle-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"oracle\" \"--host\" \"localhost\" \"--port\" \"1521\" \"--user\" \"system\" \"--password\" \"your_password\" \"--database\" \"ORCL\")))))\n```\n\n### MongoDB\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mongodb\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mongodb\" \"--host\" \"localhost\" \"--port\" \"27017\" \"--user\" \"admin\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### Redis\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"redis\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"redis\" \"--host\" \"localhost\" \"--port\" \"6379\" \"--password\" \"your_password\")))))\n```\n\n### 达梦数据库\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"dm-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"dm\" \"--host\" \"localhost\" \"--port\" \"5236\" \"--user\" \"SYSDBA\" \"--password\" \"your_password\" \"--database\" \"DAMENG\")))))\n```\n\n### 人大金仓\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"kingbase-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"kingbase\" \"--host\" \"localhost\" \"--port\" \"54321\" \"--user\" \"system\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-production\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"prod-db.example.com\" \"--port\" \"3306\" \"--user\" \"readonly_user\" \"--password\" \"prod_password\" \"--database\" \"production_db\"))\n          (\"mysql-development\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"dev_password\" \"--database\" \"development_db\"))\n          (\"postgres-analytics\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"postgres\" \"--host\" \"analytics-db.example.com\" \"--port\" \"5432\" \"--user\" \"analyst\" \"--password\" \"analytics_password\" \"--database\" \"analytics\")))))\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"mysql-db-writable\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\" \"--allow-write\" \"true\")))))\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n---\n\n## 步骤 3：启动 MCP 服务器\n\n配置完成后，启动 MCP 服务器：\n\n```\nM-x mcp-start-server\n```\n\n从列表中选择要启动的服务器。\n\n---\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1：探索数据库结构\n\n使用 MCP 工具探索您的数据库：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2：查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3：编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4：调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案。\n\n### 示例 5：生成代码\n\n让 AI 生成数据库相关代码：\n\n```\n生成一个 Elisp 函数，用于向 users 表插入新用户\n```\n\nAI 将检查您的结构并生成适当的代码。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的配置文件提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器无法启动\n\n**症状**：MCP 服务器无法启动或连接\n\n**解决方案**：\n1. 验证 init 文件中的配置语法是否正确\n2. 检查所有括号和引号是否正确配对\n3. 更改配置后重启 Emacs\n4. 确保 Node.js 已安装并可从 PATH 访问\n5. 运行 `M-x mcp-start-server` 并检查 *Messages* 缓冲区中的错误\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 将 Node.js 路径添加到 Emacs exec-path：\n\n```elisp\n(add-to-list 'exec-path \"/usr/local/bin\")\n;; 或者在使用 Homebrew 的 macOS 上：\n(add-to-list 'exec-path \"/opt/homebrew/bin\")\n```\n\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n### 问题：找不到包\n\n**症状**：无法安装 mcp.el 包\n\n**解决方案**：\n1. 确保 MELPA 已添加到您的包存档\n2. 运行 `M-x package-refresh-contents` 更新包列表\n3. 尝试从 GitHub 手动安装\n\n## 高级配置\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中使用环境变量：\n\n**Shell 配置：**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Emacs 配置：**\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        `((\"mysql-db\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" ,(getenv \"DB_PASSWORD\") \"--database\" \"your_database\")))))\n```\n\n注意使用反引号 (`) 而非单引号 (') 以启用 `(getenv \"DB_PASSWORD\")` 的求值。\n\n### 与 gptel 集成\n\n如果您在 Emacs 中使用 gptel 进行 AI 交互，可以集成 MCP 工具：\n\n```elisp\n(use-package gptel\n  :ensure t\n  :config\n  ;; 配置 gptel 使用您首选的 AI 后端\n  )\n\n(use-package mcp\n  :ensure t\n  :after gptel\n  :config\n  (setq mcp-servers\n        '((\"universal-db-mcp\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"localhost\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"your_password\" \"--database\" \"your_database\")))))\n```\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```elisp\n(use-package mcp\n  :ensure t\n  :config\n  (setq mcp-servers\n        '((\"docker-mysql\"\n           :command \"npx\"\n           :args (\"universal-db-mcp\" \"--type\" \"mysql\" \"--host\" \"127.0.0.1\" \"--port\" \"3306\" \"--user\" \"root\" \"--password\" \"root_password\" \"--database\" \"app_db\")))))\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n## 资源\n\n- [GNU Emacs 官方网站](https://www.gnu.org/software/emacs/)\n- [mcp.el GitHub 仓库](https://github.com/lizqwerscott/mcp.el)\n- [MELPA 包存档](https://melpa.org/)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- mcp.el Issues: https://github.com/lizqwerscott/mcp.el/issues\n"
  },
  {
    "path": "docs/integrations/GEMINI-CLI.md",
    "content": "# Gemini CLI Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Gemini CLI.\n\n## Overview\n\n[Gemini CLI](https://github.com/google-gemini/gemini-cli) is Google's command-line AI tool. It supports MCP, allowing you to query databases from the terminal.\n\n## Prerequisites\n\n- Gemini CLI installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Gemini CLI configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\n```bash\ngemini chat\n> What tables are in the database?\n> Show me the schema of the users table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Gemini CLI GitHub](https://github.com/google-gemini/gemini-cli)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/GEMINI-CLI.zh-CN.md",
    "content": "# Gemini CLI 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Gemini CLI 集成。\n\n## 概述\n\n[Gemini CLI](https://github.com/google-gemini/gemini-cli) 是 Google 的命令行 AI 工具。它支持 MCP，允许您从终端查询数据库。\n\n## 前置要求\n\n- 已安装 Gemini CLI\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Gemini CLI 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n```bash\ngemini chat\n> 数据库里有哪些表？\n> 显示 users 表的结构\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Gemini CLI GitHub](https://github.com/google-gemini/gemini-cli)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/GITHUB-COPILOT.md",
    "content": "# GitHub Copilot Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with GitHub Copilot.\n\n## Overview\n\n[GitHub Copilot](https://github.com/features/copilot) is GitHub's AI coding assistant. With the Agent Mode feature in VS Code and JetBrains IDEs, Copilot can use MCP servers to interact with external tools including databases.\n\n**Key Benefits:**\n- Native MCP support in Agent Mode\n- Seamless integration with VS Code and JetBrains\n- Natural language database queries while coding\n- Context-aware code suggestions based on database schema\n\n## Prerequisites\n\n- GitHub Copilot subscription (Individual, Business, or Enterprise)\n- VS Code or JetBrains IDE with Copilot extension\n- Node.js 20.0.0 or later\n- Database instance accessible from your machine\n\n## Configuration\n\n### VS Code Configuration\n\n1. Open VS Code Settings (Cmd/Ctrl + ,)\n2. Search for \"github.copilot.chat.experimental.mcpServers\"\n3. Click \"Edit in settings.json\"\n4. Add the MCP server configuration:\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### JetBrains Configuration\n\n1. Open Settings/Preferences\n2. Navigate to Tools > GitHub Copilot > MCP Servers\n3. Add a new MCP server with the configuration\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"postgres-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"${workspaceFolder}/data/app.db\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\n### Using Agent Mode\n\n1. Open Copilot Chat (Cmd/Ctrl + Shift + I)\n2. Switch to Agent Mode by clicking the agent icon\n3. Ask questions about your database:\n\n```\n@workspace What tables are in the database?\n\n@workspace Show me the schema of the users table\n\n@workspace Generate a TypeScript interface for the orders table\n\n@workspace Find all users who haven't placed an order\n```\n\n### Common Workflows\n\n**Schema Exploration:**\n```\n@workspace List all tables and their columns\n@workspace What are the relationships between users and orders?\n@workspace Show me the indexes on the products table\n```\n\n**Code Generation:**\n```\n@workspace Create a repository class for the users table\n@workspace Generate SQL migrations for adding a new column\n@workspace Write a function to get user orders with pagination\n```\n\n**Data Analysis:**\n```\n@workspace How many orders were placed this month?\n@workspace What's the average order value by customer segment?\n@workspace Find the top 10 products by revenue\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n### Security\n\n1. Use read-only database users\n2. Never commit credentials to version control\n3. Use VS Code's secret storage for passwords\n4. Keep write mode disabled unless necessary\n\n### Performance\n\n1. Use specific queries instead of SELECT *\n2. Add LIMIT to prevent large result sets\n3. Let Copilot cache schema information\n\n### Workflow\n\n1. Start by exploring the database schema\n2. Use natural language for complex queries\n3. Review generated SQL before execution\n4. Combine with Copilot's code suggestions\n\n## Troubleshooting\n\n### MCP Server Not Available\n\n**Symptoms:** Copilot doesn't show database tools\n\n**Solutions:**\n1. Ensure Agent Mode is enabled\n2. Check the MCP server configuration in settings\n3. Verify Node.js 20+ is installed\n4. Restart VS Code/IDE\n\n### Connection Failed\n\n**Symptoms:** Database connection errors\n\n**Solutions:**\n1. Verify database is running\n2. Check credentials are correct\n3. Ensure network connectivity\n4. Test with database client first\n\n### Agent Mode Not Available\n\n**Symptoms:** Can't switch to Agent Mode\n\n**Solutions:**\n1. Update Copilot extension to latest version\n2. Check your Copilot subscription includes Agent Mode\n3. Enable experimental features in settings\n\n## Resources\n\n- [GitHub Copilot Documentation](https://docs.github.com/en/copilot)\n- [Copilot Agent Mode](https://docs.github.com/en/copilot/using-github-copilot/using-extensions-to-integrate-external-tools-with-copilot-chat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- GitHub Copilot Support: https://support.github.com/\n"
  },
  {
    "path": "docs/integrations/GITHUB-COPILOT.zh-CN.md",
    "content": "# GitHub Copilot 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 GitHub Copilot 集成。\n\n## 概述\n\n[GitHub Copilot](https://github.com/features/copilot) 是 GitHub 的 AI 编程助手。通过 VS Code 和 JetBrains IDE 中的 Agent Mode 功能，Copilot 可以使用 MCP 服务器与外部工具（包括数据库）交互。\n\n**主要优势：**\n- Agent Mode 原生支持 MCP\n- 与 VS Code 和 JetBrains 无缝集成\n- 编码时使用自然语言查询数据库\n- 基于数据库结构的上下文感知代码建议\n\n## 前置要求\n\n- GitHub Copilot 订阅（Individual、Business 或 Enterprise）\n- 安装了 Copilot 扩展的 VS Code 或 JetBrains IDE\n- Node.js 20.0.0 或更高版本\n- 可从您的机器访问的数据库实例\n\n## 配置\n\n### VS Code 配置\n\n1. 打开 VS Code 设置（Cmd/Ctrl + ,）\n2. 搜索 \"github.copilot.chat.experimental.mcpServers\"\n3. 点击\"在 settings.json 中编辑\"\n4. 添加 MCP 服务器配置：\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### JetBrains 配置\n\n1. 打开设置/首选项\n2. 导航到 Tools > GitHub Copilot > MCP Servers\n3. 添加新的 MCP 服务器配置\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"mysql-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"postgres-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"github.copilot.chat.experimental.mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"${workspaceFolder}/data/app.db\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n### 使用 Agent Mode\n\n1. 打开 Copilot Chat（Cmd/Ctrl + Shift + I）\n2. 点击 agent 图标切换到 Agent Mode\n3. 询问关于数据库的问题：\n\n```\n@workspace 数据库里有哪些表？\n\n@workspace 显示 users 表的结构\n\n@workspace 为 orders 表生成 TypeScript 接口\n\n@workspace 找出所有没有下过订单的用户\n```\n\n### 常见工作流\n\n**Schema 探索：**\n```\n@workspace 列出所有表及其列\n@workspace users 和 orders 之间有什么关系？\n@workspace 显示 products 表的索引\n```\n\n**代码生成：**\n```\n@workspace 为 users 表创建一个 repository 类\n@workspace 生成添加新列的 SQL 迁移\n@workspace 编写一个带分页的获取用户订单的函数\n```\n\n**数据分析：**\n```\n@workspace 这个月有多少订单？\n@workspace 按客户细分的平均订单金额是多少？\n@workspace 找出收入前 10 的产品\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n### 安全性\n\n1. 使用只读数据库用户\n2. 不要将凭据提交到版本控制\n3. 使用 VS Code 的密钥存储来保存密码\n4. 除非必要，否则禁用写入模式\n\n### 性能\n\n1. 使用具体查询而不是 SELECT *\n2. 添加 LIMIT 防止大结果集\n3. 让 Copilot 缓存 Schema 信息\n\n### 工作流\n\n1. 从探索数据库结构开始\n2. 使用自然语言进行复杂查询\n3. 执行前检查生成的 SQL\n4. 结合 Copilot 的代码建议\n\n## 故障排除\n\n### MCP 服务器不可用\n\n**症状：** Copilot 不显示数据库工具\n\n**解决方案：**\n1. 确保 Agent Mode 已启用\n2. 检查设置中的 MCP 服务器配置\n3. 验证 Node.js 20+ 已安装\n4. 重启 VS Code/IDE\n\n### 连接失败\n\n**症状：** 数据库连接错误\n\n**解决方案：**\n1. 验证数据库正在运行\n2. 检查凭据是否正确\n3. 确保网络连接正常\n4. 先用数据库客户端测试\n\n### Agent Mode 不可用\n\n**症状：** 无法切换到 Agent Mode\n\n**解决方案：**\n1. 将 Copilot 扩展更新到最新版本\n2. 检查您的 Copilot 订阅是否包含 Agent Mode\n3. 在设置中启用实验性功能\n\n## 资源\n\n- [GitHub Copilot 文档](https://docs.github.com/en/copilot)\n- [Copilot Agent Mode](https://docs.github.com/en/copilot/using-github-copilot/using-extensions-to-integrate-external-tools-with-copilot-chat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- GitHub Copilot 支持: https://support.github.com/\n"
  },
  {
    "path": "docs/integrations/GOOGLE-ADK.md",
    "content": "# Google ADK Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Google ADK.\n\n## Overview\n\n[Google ADK](https://cloud.google.com/) (Agent Development Kit) is Google's agent development toolkit. It supports MCP, allowing you to use database tools in your agents.\n\n## Prerequisites\n\n- Google Cloud account\n- Google ADK installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to ADK configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nUse the database tools in your ADK agents to query data.\n\n## Resources\n\n- [Google Cloud Documentation](https://cloud.google.com/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/GOOGLE-ADK.zh-CN.md",
    "content": "# Google ADK 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Google ADK 集成。\n\n## 概述\n\n[Google ADK](https://cloud.google.com/) (Agent Development Kit) 是 Google 的代理开发工具包。它支持 MCP，允许您在代理中使用数据库工具。\n\n## 前置要求\n\n- Google Cloud 账号\n- 已安装 Google ADK\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 ADK 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n在 ADK 代理中使用数据库工具查询数据。\n\n## 资源\n\n- [Google Cloud 文档](https://cloud.google.com/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/GOOSE.md",
    "content": "# Goose Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Goose.\n\n## Overview\n\n[Goose](https://github.com/block/goose) is Block's AI coding agent. It supports MCP, allowing you to query databases while coding.\n\n## Prerequisites\n\n- Goose installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to `~/.config/goose/config.yaml`:\n\n```yaml\nmcpServers:\n  database:\n    command: npx\n    args:\n      - universal-db-mcp\n      - --type\n      - mysql\n      - --host\n      - localhost\n      - --port\n      - \"3306\"\n      - --user\n      - root\n      - --password\n      - your_password\n      - --database\n      - your_database\n```\n\n## Usage\n\n```bash\ngoose chat\n> What tables are in the database?\n> Show me the schema of the users table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Goose GitHub](https://github.com/block/goose)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/GOOSE.zh-CN.md",
    "content": "# Goose 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Goose 集成。\n\n## 概述\n\n[Goose](https://github.com/block/goose) 是 Block 的 AI 编码代理。它支持 MCP，允许您在编码时查询数据库。\n\n## 前置要求\n\n- 已安装 Goose\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 `~/.config/goose/config.yaml`：\n\n```yaml\nmcpServers:\n  database:\n    command: npx\n    args:\n      - universal-db-mcp\n      - --type\n      - mysql\n      - --host\n      - localhost\n      - --port\n      - \"3306\"\n      - --user\n      - root\n      - --password\n      - your_password\n      - --database\n      - your_database\n```\n\n## 使用方法\n\n```bash\ngoose chat\n> 数据库里有哪些表？\n> 显示 users 表的结构\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Goose GitHub](https://github.com/block/goose)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/HOME-ASSISTANT.md",
    "content": "# Home Assistant Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Home Assistant.\n\n## Overview\n\n[Home Assistant](https://www.home-assistant.io/) is an open-source home automation platform. With MCP support, you can query databases to enhance your smart home automations.\n\n## Prerequisites\n\n- Home Assistant installed\n- Universal Database MCP Server deployed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\n### Step 1: Install MCP Integration\n\nAdd the MCP integration to Home Assistant through HACS or manual installation.\n\n### Step 2: Configure MCP Server\n\nAdd to your Home Assistant configuration:\n\n```yaml\nmcp:\n  servers:\n    - name: database\n      command: npx\n      args:\n        - universal-db-mcp\n        - --type\n        - mysql\n        - --host\n        - localhost\n        - --port\n        - \"3306\"\n        - --user\n        - root\n        - --password\n        - your_password\n        - --database\n        - your_database\n```\n\n### Step 3: Restart Home Assistant\n\nRestart Home Assistant to apply the configuration.\n\n## Usage\n\nUse the MCP tools in automations or through the AI assistant:\n\n```yaml\nautomation:\n  - alias: \"Daily Database Report\"\n    trigger:\n      - platform: time\n        at: \"09:00:00\"\n    action:\n      - service: mcp.call_tool\n        data:\n          server: database\n          tool: execute_query\n          arguments:\n            query: \"SELECT COUNT(*) FROM sensor_data WHERE date = CURDATE()\"\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Use Cases\n\n1. **Sensor Data Analysis**: Query historical sensor data\n2. **Energy Monitoring**: Analyze energy consumption patterns\n3. **Device Statistics**: Track device usage over time\n4. **Custom Dashboards**: Pull data for Lovelace dashboards\n\n## Best Practices\n\n1. Use read-only database users\n2. Limit query frequency to prevent overload\n3. Cache results when possible\n4. Use parameterized queries\n\n## Resources\n\n- [Home Assistant Documentation](https://www.home-assistant.io/docs/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/HOME-ASSISTANT.zh-CN.md",
    "content": "# Home Assistant 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Home Assistant 集成。\n\n## 概述\n\n[Home Assistant](https://www.home-assistant.io/) 是一个开源的家庭自动化平台。通过 MCP 支持，您可以查询数据库来增强智能家居自动化。\n\n## 前置要求\n\n- 已安装 Home Assistant\n- 已部署 Universal Database MCP Server\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n### 步骤 1：安装 MCP 集成\n\n通过 HACS 或手动安装将 MCP 集成添加到 Home Assistant。\n\n### 步骤 2：配置 MCP 服务器\n\n添加到 Home Assistant 配置：\n\n```yaml\nmcp:\n  servers:\n    - name: database\n      command: npx\n      args:\n        - universal-db-mcp\n        - --type\n        - mysql\n        - --host\n        - localhost\n        - --port\n        - \"3306\"\n        - --user\n        - root\n        - --password\n        - your_password\n        - --database\n        - your_database\n```\n\n### 步骤 3：重启 Home Assistant\n\n重启 Home Assistant 以应用配置。\n\n## 使用方法\n\n在自动化或通过 AI 助手使用 MCP 工具：\n\n```yaml\nautomation:\n  - alias: \"每日数据库报告\"\n    trigger:\n      - platform: time\n        at: \"09:00:00\"\n    action:\n      - service: mcp.call_tool\n        data:\n          server: database\n          tool: execute_query\n          arguments:\n            query: \"SELECT COUNT(*) FROM sensor_data WHERE date = CURDATE()\"\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用场景\n\n1. **传感器数据分析**：查询历史传感器数据\n2. **能源监控**：分析能源消耗模式\n3. **设备统计**：跟踪设备使用情况\n4. **自定义仪表板**：为 Lovelace 仪表板拉取数据\n\n## 最佳实践\n\n1. 使用只读数据库用户\n2. 限制查询频率以防止过载\n3. 尽可能缓存结果\n4. 使用参数化查询\n\n## 资源\n\n- [Home Assistant 文档](https://www.home-assistant.io/docs/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/HYPERCHAT.md",
    "content": "# HyperChat Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with HyperChat.\n\n## Overview\n\n[HyperChat](https://github.com/BigSweetPotatoStudio/HyperChat) is a multi-platform chat application. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- HyperChat installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to HyperChat's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk HyperChat about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Resources\n\n- [HyperChat GitHub](https://github.com/BigSweetPotatoStudio/HyperChat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/HYPERCHAT.zh-CN.md",
    "content": "# HyperChat 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 HyperChat 集成。\n\n## 概述\n\n[HyperChat](https://github.com/BigSweetPotatoStudio/HyperChat) 是一个多平台聊天应用。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- 已安装 HyperChat\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 HyperChat 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 HyperChat 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 资源\n\n- [HyperChat GitHub](https://github.com/BigSweetPotatoStudio/HyperChat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/JAN.md",
    "content": "# Jan Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Jan, the open-source ChatGPT alternative.\n\n## Overview\n\n[Jan](https://jan.ai/) is an open-source, offline-first ChatGPT alternative that runs local LLMs. It supports MCP, allowing you to connect to databases and query them using natural language.\n\n**Key Benefits:**\n- Open-source and privacy-focused\n- Runs completely offline\n- Native MCP support\n- Works with various local LLMs\n\n## Prerequisites\n\n- Jan installed ([Download here](https://jan.ai/))\n- Node.js 20.0.0 or later\n- Database instance accessible from your machine\n\n## Configuration\n\n### Step 1: Open Jan Settings\n\n1. Launch Jan\n2. Click the gear icon to open Settings\n3. Navigate to \"Extensions\" or \"MCP Servers\"\n\n### Step 2: Add MCP Server\n\nAdd the following configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\n### Querying Your Database\n\nOnce configured, you can ask Jan about your database:\n\n```\nWhat tables are in the database?\n\nShow me the schema of the users table\n\nHow many users signed up this week?\n\nFind the top 10 products by sales\n```\n\n### Common Workflows\n\n**Schema Exploration:**\n```\nList all tables and their columns\nWhat are the relationships between tables?\nShow me the indexes on the products table\n```\n\n**Data Analysis:**\n```\nWhat's the total revenue this month?\nHow many active users do we have?\nShow me orders from the last 7 days\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n### Security\n\n1. Use read-only database users\n2. Keep credentials secure\n3. Use local databases when possible\n4. Disable write mode unless necessary\n\n### Performance\n\n1. Use specific queries instead of SELECT *\n2. Add LIMIT to prevent large result sets\n3. Choose appropriate local LLM for your hardware\n\n## Troubleshooting\n\n### MCP Server Not Found\n\n**Symptoms:** Jan doesn't show database tools\n\n**Solutions:**\n1. Verify MCP configuration is correct\n2. Ensure Node.js 20+ is installed\n3. Restart Jan after configuration changes\n\n### Connection Failed\n\n**Symptoms:** Database connection errors\n\n**Solutions:**\n1. Verify database is running\n2. Check credentials are correct\n3. Ensure network connectivity\n4. Test with database client first\n\n## Resources\n\n- [Jan Documentation](https://jan.ai/docs)\n- [Jan GitHub](https://github.com/janhq/jan)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Jan Discord: https://discord.gg/jan\n"
  },
  {
    "path": "docs/integrations/JAN.zh-CN.md",
    "content": "# Jan 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Jan 集成。\n\n## 概述\n\n[Jan](https://jan.ai/) 是一个开源的、离线优先的 ChatGPT 替代品，可运行本地 LLM。它支持 MCP，允许您连接数据库并使用自然语言查询。\n\n**主要优势：**\n- 开源且注重隐私\n- 完全离线运行\n- 原生支持 MCP\n- 支持多种本地 LLM\n\n## 前置要求\n\n- 已安装 Jan（[下载地址](https://jan.ai/)）\n- Node.js 20.0.0 或更高版本\n- 可从您的机器访问的数据库实例\n\n## 配置\n\n### 步骤 1：打开 Jan 设置\n\n1. 启动 Jan\n2. 点击齿轮图标打开设置\n3. 导航到\"Extensions\"或\"MCP Servers\"\n\n### 步骤 2：添加 MCP 服务器\n\n添加以下配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n### 查询数据库\n\n配置完成后，您可以向 Jan 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n\n显示 users 表的结构\n\n这周有多少用户注册？\n\n找出销量前 10 的产品\n```\n\n### 常见工作流\n\n**Schema 探索：**\n```\n列出所有表及其列\n表之间有什么关系？\n显示 products 表的索引\n```\n\n**数据分析：**\n```\n这个月的总收入是多少？\n我们有多少活跃用户？\n显示最近 7 天的订单\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n### 安全性\n\n1. 使用只读数据库用户\n2. 保护好凭据安全\n3. 尽可能使用本地数据库\n4. 除非必要，否则禁用写入模式\n\n### 性能\n\n1. 使用具体查询而不是 SELECT *\n2. 添加 LIMIT 防止大结果集\n3. 根据硬件选择合适的本地 LLM\n\n## 故障排除\n\n### MCP 服务器未找到\n\n**症状：** Jan 不显示数据库工具\n\n**解决方案：**\n1. 验证 MCP 配置是否正确\n2. 确保 Node.js 20+ 已安装\n3. 配置更改后重启 Jan\n\n### 连接失败\n\n**症状：** 数据库连接错误\n\n**解决方案：**\n1. 验证数据库正在运行\n2. 检查凭据是否正确\n3. 确保网络连接正常\n4. 先用数据库客户端测试\n\n## 资源\n\n- [Jan 文档](https://jan.ai/docs)\n- [Jan GitHub](https://github.com/janhq/jan)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Jan Discord: https://discord.gg/jan\n"
  },
  {
    "path": "docs/integrations/JETBRAINS.md",
    "content": "# JetBrains IDE Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with JetBrains IDEs.\n\n## Overview\n\nJetBrains IDEs (IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RubyMine, Android Studio, etc.) support MCP (Model Context Protocol) integration starting from version 2025.1. This allows you to connect AI Assistant directly to your databases for intelligent code assistance, query generation, and data analysis.\n\n**Supported IDEs:**\n- IntelliJ IDEA (Ultimate & Community)\n- PyCharm (Professional & Community)\n- WebStorm\n- GoLand\n- PhpStorm\n- Rider\n- CLion\n- RubyMine\n- DataGrip\n- Android Studio\n\n**Key Benefits:**\n- Query databases directly from AI Assistant chat\n- Get AI-powered SQL query generation and optimization\n- Explore database schema without leaving the IDE\n- Generate data models and ORM code based on actual database structure\n- Debug and analyze database queries with AI assistance\n\n## Prerequisites\n\n- JetBrains IDE version **2025.1 or later**\n- AI Assistant plugin enabled (bundled with JetBrains IDEs)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nJetBrains IDEs use a JSON-based configuration for MCP servers, accessible through the IDE settings.\n\n### Step 1: Open MCP Settings\n\n1. Open your JetBrains IDE\n2. Go to **Settings/Preferences** (`Ctrl+Alt+S` on Windows/Linux, `Cmd+,` on macOS)\n3. Navigate to **Tools > AI Assistant > Model Context Protocol**\n\n### Step 2: Add MCP Server\n\n1. Click the **+** button or **Add** to create a new MCP server configuration\n2. Enter the server configuration in JSON format\n\n### Step 3: Configure the Server\n\nAdd the Universal Database MCP Server configuration:\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"universal-db-mcp\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Step 4: Apply and Restart\n\n1. Click **Apply** and then **OK**\n2. Restart the IDE for changes to take effect\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"postgres-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### SQLite\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"sqlite-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  ]\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"sqlserver-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Oracle\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"oracle-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  ]\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mongodb\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Redis\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"redis\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  ]\n}\n```\n\n### DM (Dameng Database)\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"dm-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  ]\n}\n```\n\n### KingbaseES\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"kingbase-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-production\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    {\n      \"name\": \"mysql-development\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-db-writable\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  ]\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in AI Assistant:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn AI Assistant chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Generate Entity Classes\n\nAsk the AI to generate code based on your database schema:\n\n```\nGenerate a Java entity class for the users table with JPA annotations\n```\n\nThe AI will analyze your table structure and generate:\n\n```java\n@Entity\n@Table(name = \"users\")\npublic class User {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    @Column(name = \"username\", nullable = false, length = 50)\n    private String username;\n\n    @Column(name = \"email\", nullable = false, unique = true)\n    private String email;\n\n    @Column(name = \"created_at\")\n    private LocalDateTime createdAt;\n\n    // Getters and setters...\n}\n```\n\n### Example 4: Write Complex Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value with their contact information\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  c.email,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name, c.email\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 5: Debug and Optimize Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations:\n\n```sql\nSELECT u.*\nFROM users u\nINNER JOIN orders o ON u.id = o.user_id\nWHERE o.created_at > '2024-01-01'\nGROUP BY u.id\n```\n\n### Example 6: Generate Repository Code\n\nAsk the AI to generate data access code:\n\n```\nGenerate a Spring Data JPA repository for the products table with custom query methods\n```\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** configuration with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n- Leverage AI Assistant for code generation based on actual schema\n\n### 4. IDE Integration\n\n- Use JetBrains Database Tools alongside MCP for visual database management\n- Combine AI Assistant suggestions with IDE's built-in SQL support\n- Take advantage of IDE's code completion for generated code\n\n## Troubleshooting\n\n### Issue: MCP Server Not Appearing\n\n**Symptoms**: AI Assistant doesn't recognize the database tools\n\n**Solutions**:\n1. Verify IDE version is 2025.1 or later\n2. Check that AI Assistant plugin is enabled\n3. Verify the JSON configuration syntax is valid\n4. Restart the IDE after making configuration changes\n5. Check **Help > Show Log in Explorer/Finder** for error messages\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx:\n   - Windows: `C:\\Program Files\\nodejs\\npx.cmd`\n   - macOS/Linux: `/usr/local/bin/npx`\n4. On Windows, you may need to restart after installing Node.js\n5. Alternatively, install globally and use direct command:\n   ```bash\n   npm install -g universal-db-mcp\n   ```\n   Then use `universal-db-mcp` instead of `npx universal-db-mcp` in the configuration\n\n### Issue: Slow Response\n\n**Symptoms**: AI Assistant takes a long time to respond to database queries\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica for analytics queries\n\n### Viewing Logs\n\nTo view MCP-related logs:\n\n1. Go to **Help > Show Log in Explorer/Finder**\n2. Open the `idea.log` file\n3. Search for \"MCP\" or \"universal-db-mcp\" related messages\n\n## Advanced Configuration\n\n### Using Environment Variables\n\nFor better security, you can use environment variables. Set them in your system before launching the IDE:\n\n**Windows (PowerShell):**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n**Windows (Command Prompt):**\n```cmd\nset DB_PASSWORD=your_secure_password\n```\n\n**macOS/Linux:**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"docker-mysql\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  ]\n}\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n### Project-Specific Configuration\n\nFor project-specific database configurations, you can:\n\n1. Create a `.idea/mcp.json` file in your project root (if supported by your IDE version)\n2. Or use different IDE configurations for different projects via **File > Manage IDE Settings > Settings Repository**\n\n## Resources\n\n- [JetBrains AI Assistant Documentation](https://www.jetbrains.com/help/idea/ai-assistant.html)\n- [IntelliJ IDEA Documentation](https://www.jetbrains.com/help/idea/)\n- [PyCharm Documentation](https://www.jetbrains.com/help/pycharm/)\n- [WebStorm Documentation](https://www.jetbrains.com/help/webstorm/)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- JetBrains Support: https://www.jetbrains.com/support/\n- JetBrains Community Forum: https://intellij-support.jetbrains.com/\n"
  },
  {
    "path": "docs/integrations/JETBRAINS.zh-CN.md",
    "content": "# JetBrains IDE 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 JetBrains IDE 集成。\n\n## 概述\n\nJetBrains IDE（IntelliJ IDEA、PyCharm、WebStorm、GoLand、PhpStorm、Rider、CLion、RubyMine、Android Studio 等）从 2025.1 版本开始支持 MCP（Model Context Protocol）集成。这使您可以将 AI Assistant 直接连接到数据库，实现智能代码辅助、查询生成和数据分析。\n\n**支持的 IDE：**\n- IntelliJ IDEA（Ultimate 和 Community 版本）\n- PyCharm（Professional 和 Community 版本）\n- WebStorm\n- GoLand\n- PhpStorm\n- Rider\n- CLion\n- RubyMine\n- DataGrip\n- Android Studio\n\n**主要优势：**\n- 直接从 AI Assistant 聊天中查询数据库\n- 获得 AI 驱动的 SQL 查询生成和优化\n- 无需离开 IDE 即可探索数据库结构\n- 基于实际数据库结构生成数据模型和 ORM 代码\n- 借助 AI 帮助调试和分析数据库查询\n\n## 前置要求\n\n- JetBrains IDE 版本 **2025.1 或更高**\n- AI Assistant 插件已启用（JetBrains IDE 内置）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nJetBrains IDE 使用基于 JSON 的配置来管理 MCP 服务器，可通过 IDE 设置访问。\n\n### 步骤 1：打开 MCP 设置\n\n1. 打开您的 JetBrains IDE\n2. 进入 **Settings/Preferences**（Windows/Linux 上按 `Ctrl+Alt+S`，macOS 上按 `Cmd+,`）\n3. 导航到 **Tools > AI Assistant > Model Context Protocol**\n\n### 步骤 2：添加 MCP 服务器\n\n1. 点击 **+** 按钮或 **Add** 创建新的 MCP 服务器配置\n2. 以 JSON 格式输入服务器配置\n\n### 步骤 3：配置服务器\n\n添加 Universal Database MCP Server 配置：\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"universal-db-mcp\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### 步骤 4：应用并重启\n\n1. 点击 **Apply** 然后点击 **OK**\n2. 重启 IDE 使更改生效\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"postgres-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### SQLite\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"sqlite-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  ]\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"sqlserver-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Oracle\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"oracle-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  ]\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mongodb\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Redis\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"redis\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  ]\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"dm-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  ]\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"kingbase-db\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-production\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    {\n      \"name\": \"mysql-development\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"mysql-db-writable\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  ]\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 AI Assistant 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1：探索数据库结构\n\n在 AI Assistant 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2：查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3：生成实体类\n\n让 AI 基于数据库结构生成代码：\n\n```\n为 users 表生成一个带有 JPA 注解的 Java 实体类\n```\n\nAI 将分析您的表结构并生成：\n\n```java\n@Entity\n@Table(name = \"users\")\npublic class User {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    @Column(name = \"username\", nullable = false, length = 50)\n    private String username;\n\n    @Column(name = \"email\", nullable = false, unique = true)\n    private String email;\n\n    @Column(name = \"created_at\")\n    private LocalDateTime createdAt;\n\n    // Getters and setters...\n}\n```\n\n### 示例 4：编写复杂查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户及其联系信息\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  c.email,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name, c.email\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 5：调试和优化查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案：\n\n```sql\nSELECT u.*\nFROM users u\nINNER JOIN orders o ON u.id = o.user_id\nWHERE o.created_at > '2024-01-01'\nGROUP BY u.id\n```\n\n### 示例 6：生成 Repository 代码\n\n让 AI 生成数据访问代码：\n\n```\n为 products 表生成一个 Spring Data JPA Repository，包含自定义查询方法\n```\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的配置提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n- 利用 AI Assistant 基于实际结构生成代码\n\n### 4. IDE 集成\n\n- 将 JetBrains 数据库工具与 MCP 结合使用，实现可视化数据库管理\n- 将 AI Assistant 建议与 IDE 内置的 SQL 支持结合使用\n- 利用 IDE 的代码补全功能处理生成的代码\n\n## 故障排除\n\n### 问题：MCP 服务器未显示\n\n**症状**：AI Assistant 无法识别数据库工具\n\n**解决方案**：\n1. 验证 IDE 版本是 2025.1 或更高\n2. 检查 AI Assistant 插件是否已启用\n3. 验证 JSON 配置语法是否有效\n4. 更改配置后重启 IDE\n5. 检查 **Help > Show Log in Explorer/Finder** 查看错误消息\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径：\n   - Windows：`C:\\Program Files\\nodejs\\npx.cmd`\n   - macOS/Linux：`/usr/local/bin/npx`\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n5. 或者，全局安装后使用直接命令：\n   ```bash\n   npm install -g universal-db-mcp\n   ```\n   然后在配置中使用 `universal-db-mcp` 代替 `npx universal-db-mcp`\n\n### 问题：响应缓慢\n\n**症状**：AI Assistant 响应数据库查询需要很长时间\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本进行分析查询\n\n### 查看日志\n\n要查看 MCP 相关日志：\n\n1. 进入 **Help > Show Log in Explorer/Finder**\n2. 打开 `idea.log` 文件\n3. 搜索 \"MCP\" 或 \"universal-db-mcp\" 相关消息\n\n## 高级配置\n\n### 使用环境变量\n\n为了更好的安全性，您可以使用环境变量。在启动 IDE 之前在系统中设置它们：\n\n**Windows (PowerShell)：**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n**Windows (命令提示符)：**\n```cmd\nset DB_PASSWORD=your_secure_password\n```\n\n**macOS/Linux：**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```json\n{\n  \"servers\": [\n    {\n      \"name\": \"docker-mysql\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  ]\n}\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n### 项目特定配置\n\n对于项目特定的数据库配置，您可以：\n\n1. 在项目根目录创建 `.idea/mcp.json` 文件（如果您的 IDE 版本支持）\n2. 或通过 **File > Manage IDE Settings > Settings Repository** 为不同项目使用不同的 IDE 配置\n\n## 资源\n\n- [JetBrains AI Assistant 文档](https://www.jetbrains.com/help/idea/ai-assistant.html)\n- [IntelliJ IDEA 文档](https://www.jetbrains.com/help/idea/)\n- [PyCharm 文档](https://www.jetbrains.com/help/pycharm/)\n- [WebStorm 文档](https://www.jetbrains.com/help/webstorm/)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- JetBrains 支持: https://www.jetbrains.com/support/\n- JetBrains 社区论坛: https://intellij-support.jetbrains.com/\n"
  },
  {
    "path": "docs/integrations/LANGCHAIN.md",
    "content": "# LangChain Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with LangChain.\n\n## Overview\n\n[LangChain](https://langchain.com/) is a popular framework for building LLM applications. It supports MCP, allowing you to use database tools in your LangChain agents.\n\n## Prerequisites\n\n- Python 3.9+ or Node.js 18+\n- LangChain installed\n- Universal Database MCP Server\n- Database instance\n\n## Installation\n\n```bash\npip install langchain langchain-mcp\n```\n\n## Configuration\n\n### Python Example\n\n```python\nfrom langchain_mcp import MCPToolkit\nfrom langchain.agents import create_tool_calling_agent, AgentExecutor\nfrom langchain_openai import ChatOpenAI\n\n# Create MCP toolkit\ntoolkit = MCPToolkit(\n    server_command=\"npx\",\n    server_args=[\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n    ]\n)\n\n# Get tools\ntools = toolkit.get_tools()\n\n# Create agent\nllm = ChatOpenAI(model=\"gpt-4\")\nagent = create_tool_calling_agent(llm, tools, prompt)\nagent_executor = AgentExecutor(agent=agent, tools=tools)\n\n# Run query\nresult = agent_executor.invoke({\n    \"input\": \"What tables are in the database?\"\n})\nprint(result[\"output\"])\n```\n\n### Node.js Example\n\n```javascript\nconst { MCPToolkit } = require('langchain/tools/mcp');\nconst { ChatOpenAI } = require('@langchain/openai');\nconst { createToolCallingAgent, AgentExecutor } = require('langchain/agents');\n\nasync function main() {\n  const toolkit = new MCPToolkit({\n    serverCommand: 'npx',\n    serverArgs: [\n      'universal-db-mcp',\n      '--type', 'mysql',\n      '--host', 'localhost',\n      '--port', '3306',\n      '--user', 'root',\n      '--password', 'your_password',\n      '--database', 'your_database'\n    ]\n  });\n\n  const tools = await toolkit.getTools();\n  const llm = new ChatOpenAI({ model: 'gpt-4' });\n\n  const agent = createToolCallingAgent({ llm, tools, prompt });\n  const executor = new AgentExecutor({ agent, tools });\n\n  const result = await executor.invoke({\n    input: 'What tables are in the database?'\n  });\n\n  console.log(result.output);\n}\n\nmain();\n```\n\n## Available Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Use Cases\n\n1. **RAG with Database**: Combine document retrieval with database queries\n2. **Data Analysis Agents**: Build agents that analyze database data\n3. **Chatbots**: Create chatbots that can answer questions about your data\n4. **Automated Reports**: Generate reports from database queries\n\n## Best Practices\n\n1. Use read-only database users\n2. Implement query validation\n3. Add rate limiting\n4. Cache schema information\n\n## Resources\n\n- [LangChain Documentation](https://python.langchain.com/docs/)\n- [LangChain MCP Integration](https://python.langchain.com/docs/integrations/tools/mcp)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/LANGCHAIN.zh-CN.md",
    "content": "# LangChain 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 LangChain 集成。\n\n## 概述\n\n[LangChain](https://langchain.com/) 是一个流行的 LLM 应用开发框架。它支持 MCP，允许您在 LangChain 代理中使用数据库工具。\n\n## 前置要求\n\n- Python 3.9+ 或 Node.js 18+\n- 已安装 LangChain\n- Universal Database MCP Server\n- 数据库实例\n\n## 安装\n\n```bash\npip install langchain langchain-mcp\n```\n\n## 配置\n\n### Python 示例\n\n```python\nfrom langchain_mcp import MCPToolkit\nfrom langchain.agents import create_tool_calling_agent, AgentExecutor\nfrom langchain_openai import ChatOpenAI\n\n# 创建 MCP 工具包\ntoolkit = MCPToolkit(\n    server_command=\"npx\",\n    server_args=[\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n    ]\n)\n\n# 获取工具\ntools = toolkit.get_tools()\n\n# 创建代理\nllm = ChatOpenAI(model=\"gpt-4\")\nagent = create_tool_calling_agent(llm, tools, prompt)\nagent_executor = AgentExecutor(agent=agent, tools=tools)\n\n# 运行查询\nresult = agent_executor.invoke({\n    \"input\": \"数据库里有哪些表？\"\n})\nprint(result[\"output\"])\n```\n\n### Node.js 示例\n\n```javascript\nconst { MCPToolkit } = require('langchain/tools/mcp');\nconst { ChatOpenAI } = require('@langchain/openai');\nconst { createToolCallingAgent, AgentExecutor } = require('langchain/agents');\n\nasync function main() {\n  const toolkit = new MCPToolkit({\n    serverCommand: 'npx',\n    serverArgs: [\n      'universal-db-mcp',\n      '--type', 'mysql',\n      '--host', 'localhost',\n      '--port', '3306',\n      '--user', 'root',\n      '--password', 'your_password',\n      '--database', 'your_database'\n    ]\n  });\n\n  const tools = await toolkit.getTools();\n  const llm = new ChatOpenAI({ model: 'gpt-4' });\n\n  const agent = createToolCallingAgent({ llm, tools, prompt });\n  const executor = new AgentExecutor({ agent, tools });\n\n  const result = await executor.invoke({\n    input: '数据库里有哪些表？'\n  });\n\n  console.log(result.output);\n}\n\nmain();\n```\n\n## 可用工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用场景\n\n1. **RAG 与数据库结合**：将文档检索与数据库查询结合\n2. **数据分析代理**：构建分析数据库数据的代理\n3. **聊天机器人**：创建能回答数据问题的聊天机器人\n4. **自动化报告**：从数据库查询生成报告\n\n## 最佳实践\n\n1. 使用只读数据库用户\n2. 实现查询验证\n3. 添加速率限制\n4. 缓存 Schema 信息\n\n## 资源\n\n- [LangChain 文档](https://python.langchain.com/docs/)\n- [LangChain MCP 集成](https://python.langchain.com/docs/integrations/tools/mcp)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/LIBRECHAT.md",
    "content": "# LibreChat Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with LibreChat.\n\n## Overview\n\n[LibreChat](https://github.com/danny-avila/LibreChat) is an open-source chat interface. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- LibreChat installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to LibreChat's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk LibreChat about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [LibreChat GitHub](https://github.com/danny-avila/LibreChat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/LIBRECHAT.zh-CN.md",
    "content": "# LibreChat 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 LibreChat 集成。\n\n## 概述\n\n[LibreChat](https://github.com/danny-avila/LibreChat) 是一个开源的聊天界面。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- 已安装 LibreChat\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 LibreChat 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 LibreChat 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [LibreChat GitHub](https://github.com/danny-avila/LibreChat)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/LM-STUDIO.md",
    "content": "# LM Studio Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with LM Studio.\n\n## Overview\n\nLM Studio is a desktop application for running local large language models (LLMs) on your computer. Starting from version 0.3.17, LM Studio supports the MCP (Model Context Protocol), allowing you to extend its capabilities with external tools. By integrating Universal Database MCP Server, you can enable LM Studio to directly query and analyze your database data during conversations with local AI models.\n\n**Key Benefits:**\n- Query databases directly from LM Studio chat interface\n- Run completely offline with local AI models\n- Explore database schema through natural language\n- Execute SQL queries and analyze results in conversations\n- Full privacy - your data never leaves your machine\n\n## Prerequisites\n\n- [LM Studio](https://lmstudio.ai/) installed (version 0.3.17 or later required)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nLM Studio uses MCP stdio mode for tool integration. Configuration is done through the application settings.\n\n### Step 1: Open LM Studio Settings\n\n1. Launch LM Studio\n2. Click on the settings icon (gear icon) in the sidebar or menu\n3. Navigate to **Plugins > MCP Servers**\n\n### Step 2: Add MCP Server Configuration\n\nIn the MCP server configuration section, add a new server with the following JSON configuration:\n\n#### Basic Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Save and Restart\n\nAfter adding the configuration, save the settings and restart LM Studio for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### DM (Dameng Database)\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### KingbaseES\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in LM Studio:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn LM Studio chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Data Analysis\n\nAsk the AI to analyze your data:\n\n```\nAnalyze the sales trends for the last 6 months\n```\n\nThe AI will query the relevant tables and provide insights based on the data.\n\n### Example 5: Generate Reports\n\nRequest data summaries:\n\n```\nGenerate a summary of user registrations by month for 2024\n```\n\nThe AI will create and execute the appropriate queries to generate the report.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never share** configurations with real credentials\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Model Selection\n\n- Choose models with good instruction-following capabilities for better tool usage\n- Larger models generally perform better with complex database queries\n- Test different models to find the best balance between speed and accuracy\n\n### 4. Usage Tips\n\n- Be specific in your queries to get better results\n- Use natural language to describe what data you need\n- Ask the AI to explain query results when needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: LM Studio doesn't recognize the database tools\n\n**Solutions**:\n1. Verify LM Studio version is 0.3.17 or later\n2. Check that MCP server configuration is correctly entered in Plugins > MCP Servers\n3. Verify JSON syntax is valid (no trailing commas, proper quotes)\n4. Restart LM Studio after making configuration changes\n5. Ensure Node.js is installed and accessible from PATH\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n### Issue: Model Not Using Tools\n\n**Symptoms**: The AI model doesn't use the database tools even when asked\n\n**Solutions**:\n1. Ensure you're using a model that supports function calling/tool use\n2. Try being more explicit in your prompts (e.g., \"Use the database tool to...\")\n3. Check if the MCP server is properly connected in LM Studio settings\n4. Try a different model that has better tool-use capabilities\n\n## Resources\n\n- [LM Studio Official Website](https://lmstudio.ai/)\n- [LM Studio Documentation](https://lmstudio.ai/docs)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- LM Studio Discord: https://discord.gg/lmstudio\n"
  },
  {
    "path": "docs/integrations/LM-STUDIO.zh-CN.md",
    "content": "# LM Studio 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 LM Studio 集成。\n\n## 概述\n\nLM Studio 是一款用于在本地计算机上运行大型语言模型（LLM）的桌面应用程序。从 0.3.17 版本开始，LM Studio 支持 MCP（Model Context Protocol），允许您通过外部工具扩展其功能。通过集成 Universal Database MCP Server，您可以让 LM Studio 在与本地 AI 模型对话时直接查询和分析数据库数据。\n\n**主要优势：**\n- 直接从 LM Studio 聊天界面查询数据库\n- 使用本地 AI 模型完全离线运行\n- 通过自然语言探索数据库结构\n- 在对话中执行 SQL 查询并分析结果\n- 完全隐私 - 您的数据永远不会离开您的机器\n\n## 前置要求\n\n- 已安装 [LM Studio](https://lmstudio.ai/)（需要 0.3.17 或更高版本）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nLM Studio 使用 MCP stdio 模式进行工具集成。配置通过应用程序设置完成。\n\n### 步骤 1: 打开 LM Studio 设置\n\n1. 启动 LM Studio\n2. 点击侧边栏或菜单中的设置图标（齿轮图标）\n3. 导航到 **Plugins > MCP Servers**\n\n### 步骤 2: 添加 MCP 服务器配置\n\n在 MCP 服务器配置部分，添加以下 JSON 配置：\n\n#### 基本配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3: 保存并重启\n\n添加配置后，保存设置并重启 LM Studio 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 LM Studio 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 LM Studio 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 数据分析\n\n让 AI 分析您的数据：\n\n```\n分析过去 6 个月的销售趋势\n```\n\nAI 将查询相关表并根据数据提供洞察。\n\n### 示例 5: 生成报表\n\n请求数据汇总：\n\n```\n生成 2024 年按月份统计的用户注册汇总\n```\n\nAI 将创建并执行适当的查询来生成报表。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿分享**包含真实凭据的配置\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 模型选择\n\n- 选择具有良好指令遵循能力的模型以获得更好的工具使用效果\n- 较大的模型通常在处理复杂数据库查询时表现更好\n- 测试不同的模型以找到速度和准确性之间的最佳平衡\n\n### 4. 使用技巧\n\n- 在查询中尽量具体以获得更好的结果\n- 使用自然语言描述您需要的数据\n- 需要时让 AI 解释查询结果\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：LM Studio 无法识别数据库工具\n\n**解决方案**：\n1. 验证 LM Studio 版本是否为 0.3.17 或更高\n2. 检查 MCP 服务器配置是否正确输入到 Plugins > MCP Servers\n3. 验证 JSON 语法是否有效（无尾随逗号、正确的引号）\n4. 更改配置后重启 LM Studio\n5. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n### 问题：模型不使用工具\n\n**症状**：即使被要求，AI 模型也不使用数据库工具\n\n**解决方案**：\n1. 确保您使用的模型支持函数调用/工具使用\n2. 尝试在提示中更明确（例如，\"使用数据库工具来...\"）\n3. 检查 MCP 服务器是否在 LM Studio 设置中正确连接\n4. 尝试使用具有更好工具使用能力的不同模型\n\n## 资源\n\n- [LM Studio 官方网站](https://lmstudio.ai/)\n- [LM Studio 文档](https://lmstudio.ai/docs)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- LM Studio Discord: https://discord.gg/lmstudio\n"
  },
  {
    "path": "docs/integrations/MATTERMOST.md",
    "content": "# Mattermost Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Mattermost.\n\n## Overview\n\n[Mattermost](https://mattermost.com/) is an open-source messaging platform. You can integrate Universal Database MCP Server via a bot that calls the REST API.\n\n## Prerequisites\n\n- Mattermost server\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=mattermost-bot-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Create Mattermost Bot\n\n1. Go to System Console > Integrations > Bot Accounts\n2. Create a new bot\n3. Copy the bot token\n\n### Step 3: Create Bot Server\n\nCreate a bot server that handles Mattermost commands and calls the MCP REST API (similar to Slack integration).\n\n## Usage\n\n```\n/db-connect mysql localhost 3306 root password mydb\n/db-query SELECT * FROM users LIMIT 5\n/db-schema users\n/db-disconnect\n```\n\n## Resources\n\n- [Mattermost Documentation](https://docs.mattermost.com/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MATTERMOST.zh-CN.md",
    "content": "# Mattermost 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Mattermost 集成。\n\n## 概述\n\n[Mattermost](https://mattermost.com/) 是一个开源的消息平台。您可以通过调用 REST API 的机器人集成 Universal Database MCP Server。\n\n## 前置要求\n\n- Mattermost 服务器\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=mattermost-bot-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：创建 Mattermost 机器人\n\n1. 转到 System Console > Integrations > Bot Accounts\n2. 创建新的机器人\n3. 复制机器人令牌\n\n### 步骤 3：创建机器人服务器\n\n创建一个处理 Mattermost 命令并调用 MCP REST API 的机器人服务器（类似于 Slack 集成）。\n\n## 使用方法\n\n```\n/db-connect mysql localhost 3306 root password mydb\n/db-query SELECT * FROM users LIMIT 5\n/db-schema users\n/db-disconnect\n```\n\n## 资源\n\n- [Mattermost 文档](https://docs.mattermost.com/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MCP-INSPECTOR.md",
    "content": "# MCP Inspector Integration Guide\n\nThis guide shows how to use Universal Database MCP Server with MCP Inspector for debugging and testing.\n\n## Overview\n\n[MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the official debugging tool for MCP servers. It allows you to test and inspect MCP server functionality.\n\n## Prerequisites\n\n- Node.js 20.0.0 or later\n- Database instance\n\n## Installation\n\n```bash\nnpx @modelcontextprotocol/inspector\n```\n\n## Usage\n\n### Start Inspector with Database Server\n\n```bash\nnpx @modelcontextprotocol/inspector npx universal-db-mcp \\\n  --type mysql \\\n  --host localhost \\\n  --port 3306 \\\n  --user root \\\n  --password your_password \\\n  --database your_database\n```\n\n### Using the Inspector UI\n\n1. Open the Inspector URL shown in terminal (usually http://localhost:5173)\n2. View available tools in the \"Tools\" tab\n3. Test tools by clicking on them\n4. View server logs in the \"Logs\" tab\n\n### Testing Tools\n\n**Test execute_query:**\n```json\n{\n  \"query\": \"SELECT * FROM users LIMIT 5\"\n}\n```\n\n**Test get_schema:**\n```json\n{}\n```\n\n**Test get_table_info:**\n```json\n{\n  \"tableName\": \"users\"\n}\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Debugging Tips\n\n1. Check server logs for errors\n2. Verify tool input schemas\n3. Test with simple queries first\n4. Monitor response times\n\n## Resources\n\n- [MCP Inspector GitHub](https://github.com/modelcontextprotocol/inspector)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/MCP-INSPECTOR.zh-CN.md",
    "content": "# MCP Inspector 集成指南\n\n本指南展示如何使用 MCP Inspector 调试和测试 Universal Database MCP Server。\n\n## 概述\n\n[MCP Inspector](https://github.com/modelcontextprotocol/inspector) 是 MCP 服务器的官方调试工具。它允许您测试和检查 MCP 服务器功能。\n\n## 前置要求\n\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 安装\n\n```bash\nnpx @modelcontextprotocol/inspector\n```\n\n## 使用方法\n\n### 使用数据库服务器启动 Inspector\n\n```bash\nnpx @modelcontextprotocol/inspector npx universal-db-mcp \\\n  --type mysql \\\n  --host localhost \\\n  --port 3306 \\\n  --user root \\\n  --password your_password \\\n  --database your_database\n```\n\n### 使用 Inspector UI\n\n1. 打开终端中显示的 Inspector URL（通常是 http://localhost:5173）\n2. 在\"Tools\"标签中查看可用工具\n3. 点击工具进行测试\n4. 在\"Logs\"标签中查看服务器日志\n\n### 测试工具\n\n**测试 execute_query：**\n```json\n{\n  \"query\": \"SELECT * FROM users LIMIT 5\"\n}\n```\n\n**测试 get_schema：**\n```json\n{}\n```\n\n**测试 get_table_info：**\n```json\n{\n  \"tableName\": \"users\"\n}\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 调试技巧\n\n1. 检查服务器日志中的错误\n2. 验证工具输入 Schema\n3. 先用简单查询测试\n4. 监控响应时间\n\n## 资源\n\n- [MCP Inspector GitHub](https://github.com/modelcontextprotocol/inspector)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/MCPHOST.md",
    "content": "# MCPHost Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with MCPHost.\n\n## Overview\n\n[MCPHost](https://github.com/mark3labs/mcphost) is a CLI tool for chatting with LLMs using MCP. It allows you to query databases from the command line.\n\n## Prerequisites\n\n- MCPHost installed (`go install github.com/mark3labs/mcphost@latest`)\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nCreate `~/.mcphost/config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  },\n  \"llm\": {\n    \"provider\": \"openai\",\n    \"model\": \"gpt-4\"\n  }\n}\n```\n\n## Usage\n\n```bash\nmcphost chat\n> What tables are in the database?\n> Show me the schema of the users table\n```\n\n## Resources\n\n- [MCPHost GitHub](https://github.com/mark3labs/mcphost)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MCPHOST.zh-CN.md",
    "content": "# MCPHost 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 MCPHost 集成。\n\n## 概述\n\n[MCPHost](https://github.com/mark3labs/mcphost) 是一个使用 MCP 与 LLM 聊天的 CLI 工具。它允许您从命令行查询数据库。\n\n## 前置要求\n\n- 已安装 MCPHost（`go install github.com/mark3labs/mcphost@latest`）\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n创建 `~/.mcphost/config.json`：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  },\n  \"llm\": {\n    \"provider\": \"openai\",\n    \"model\": \"gpt-4\"\n  }\n}\n```\n\n## 使用方法\n\n```bash\nmcphost chat\n> 数据库里有哪些表？\n> 显示 users 表的结构\n```\n\n## 资源\n\n- [MCPHost GitHub](https://github.com/mark3labs/mcphost)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MINDPAL.md",
    "content": "# MindPal Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with MindPal.\n\n## Overview\n\n[MindPal](https://mindpal.io/) is a no-code AI agent builder. It supports MCP via SSE/Streamable HTTP, allowing you to query databases from your AI agents.\n\n## Prerequisites\n\n- MindPal account\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=mindpal-secret-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Configure MindPal\n\n1. Open MindPal\n2. Navigate to Integrations\n3. Add MCP Server:\n   - URL: `https://your-server.com/mcp`\n   - Headers: Include database configuration\n\n## Usage\n\nUse the database tools in your MindPal agents to query data.\n\n## Resources\n\n- [MindPal Website](https://mindpal.io/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MINDPAL.zh-CN.md",
    "content": "# MindPal 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 MindPal 集成。\n\n## 概述\n\n[MindPal](https://mindpal.io/) 是一个无代码 AI 代理构建器。它通过 SSE/Streamable HTTP 支持 MCP，允许您从 AI 代理查询数据库。\n\n## 前置要求\n\n- MindPal 账号\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=mindpal-secret-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：配置 MindPal\n\n1. 打开 MindPal\n2. 导航到 Integrations\n3. 添加 MCP Server：\n   - URL: `https://your-server.com/mcp`\n   - Headers: 包含数据库配置\n\n## 使用方法\n\n在 MindPal 代理中使用数据库工具查询数据。\n\n## 资源\n\n- [MindPal 网站](https://mindpal.io/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/MSTY.md",
    "content": "# Msty Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Msty.\n\n## Overview\n\n[Msty](https://msty.app/) is a desktop AI chat application. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- Msty installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Msty's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Msty about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\nHow many orders were placed today?\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Msty Website](https://msty.app/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/MSTY.zh-CN.md",
    "content": "# Msty 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Msty 集成。\n\n## 概述\n\n[Msty](https://msty.app/) 是一个桌面 AI 聊天应用。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- 已安装 Msty\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Msty 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Msty 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n今天有多少订单？\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Msty 网站](https://msty.app/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/N8N.md",
    "content": "# n8n Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with n8n workflow automation platform.\n\n## Overview\n\nn8n is a workflow automation tool. By integrating Universal Database MCP Server, you can create workflows that query and manipulate database data.\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP API mode\n- n8n instance (self-hosted or cloud)\n- Database instance (MySQL, PostgreSQL, etc.)\n\n## Setup Steps\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server:\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=n8n-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Create n8n Workflow\n\n1. Login to n8n\n2. Click \"New Workflow\"\n3. Name your workflow (e.g., \"Database Query Workflow\")\n\n### Step 3: Add HTTP Request Nodes\n\nn8n uses HTTP Request nodes to call APIs. Add nodes for each operation:\n\n#### Node 1: Connect to Database\n\n**Node Type**: HTTP Request\n**Name**: `Connect Database`\n\n**Settings**:\n- **Method**: POST\n- **URL**: `http://localhost:3000/api/connect`\n- **Authentication**: Generic Credential Type\n  - Header Auth\n  - Name: `X-API-Key`\n  - Value: `n8n-secret-key`\n- **Body Content Type**: JSON\n- **Body**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"password\",\n  \"database\": \"testdb\"\n}\n```\n\n**Output**: Extracts `sessionId` from response\n\n#### Node 2: Execute Query\n\n**Node Type**: HTTP Request\n**Name**: `Execute Query`\n\n**Settings**:\n- **Method**: POST\n- **URL**: `http://localhost:3000/api/query`\n- **Authentication**: Header Auth (X-API-Key)\n- **Body**:\n```json\n{\n  \"sessionId\": \"{{$node['Connect Database'].json.data.sessionId}}\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n#### Node 3: Process Results\n\n**Node Type**: Code\n**Name**: `Process Results`\n\n**Code**:\n```javascript\nconst results = $input.all()[0].json.data.rows;\n\nreturn results.map(row => ({\n  json: row\n}));\n```\n\n## Example Workflows\n\n### Workflow 1: Scheduled Database Backup\n\n**Trigger**: Schedule (daily at 2 AM)\n\n**Nodes**:\n1. **Schedule Trigger** - Runs daily at 2 AM\n2. **Connect Database** - Connects to database\n3. **Execute Query** - `SELECT * FROM users`\n4. **Convert to CSV** - Converts results to CSV\n5. **Send Email** - Emails CSV file\n6. **Disconnect Database** - Closes connection\n\n**n8n Workflow JSON**:\n```json\n{\n  \"nodes\": [\n    {\n      \"parameters\": {\n        \"rule\": {\n          \"interval\": [\n            {\n              \"field\": \"hours\",\n              \"hoursInterval\": 24\n            }\n          ]\n        }\n      },\n      \"name\": \"Schedule Trigger\",\n      \"type\": \"n8n-nodes-base.scheduleTrigger\",\n      \"position\": [250, 300]\n    },\n    {\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/connect\",\n        \"authentication\": \"genericCredentialType\",\n        \"genericAuthType\": \"httpHeaderAuth\",\n        \"options\": {},\n        \"bodyParametersJson\": \"{\\n  \\\"type\\\": \\\"mysql\\\",\\n  \\\"host\\\": \\\"localhost\\\",\\n  \\\"port\\\": 3306,\\n  \\\"user\\\": \\\"root\\\",\\n  \\\"password\\\": \\\"password\\\",\\n  \\\"database\\\": \\\"testdb\\\"\\n}\"\n      },\n      \"name\": \"Connect Database\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"position\": [450, 300]\n    },\n    {\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/query\",\n        \"authentication\": \"genericCredentialType\",\n        \"genericAuthType\": \"httpHeaderAuth\",\n        \"bodyParametersJson\": \"{\\n  \\\"sessionId\\\": \\\"{{$node['Connect Database'].json.data.sessionId}}\\\",\\n  \\\"query\\\": \\\"SELECT * FROM users\\\"\\n}\"\n      },\n      \"name\": \"Execute Query\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"position\": [650, 300]\n    }\n  ]\n}\n```\n\n### Workflow 2: Webhook to Database\n\n**Trigger**: Webhook\n\n**Nodes**:\n1. **Webhook** - Receives HTTP POST\n2. **Connect Database** - Connects to database\n3. **Execute Query** - Inserts data from webhook\n4. **Respond to Webhook** - Returns success/error\n5. **Disconnect Database** - Closes connection\n\n**Example**:\n```bash\n# Trigger workflow\ncurl -X POST https://your-n8n.com/webhook/insert-user \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Alice\",\n    \"email\": \"alice@example.com\"\n  }'\n```\n\n**Query Node**:\n```json\n{\n  \"sessionId\": \"{{$node['Connect Database'].json.data.sessionId}}\",\n  \"query\": \"INSERT INTO users (name, email) VALUES (?, ?)\",\n  \"params\": [\n    \"{{$json.name}}\",\n    \"{{$json.email}}\"\n  ]\n}\n```\n\n### Workflow 3: Data Sync Between Databases\n\n**Trigger**: Schedule (every hour)\n\n**Nodes**:\n1. **Schedule Trigger** - Runs hourly\n2. **Connect Source DB** - Connects to source database\n3. **Query Source** - Gets new records\n4. **Connect Target DB** - Connects to target database\n5. **Insert to Target** - Inserts records\n6. **Disconnect Both** - Closes connections\n\n### Workflow 4: Database Monitoring\n\n**Trigger**: Schedule (every 5 minutes)\n\n**Nodes**:\n1. **Schedule Trigger** - Runs every 5 minutes\n2. **Connect Database** - Connects to database\n3. **Check Table Size** - `SELECT COUNT(*) FROM users`\n4. **Check Slow Queries** - Queries performance schema\n5. **Send Alert** - Sends Slack/email if threshold exceeded\n6. **Disconnect Database** - Closes connection\n\n## Advanced Patterns\n\n### Pattern 1: Dynamic Query Builder\n\nUse n8n's Code node to build queries dynamically:\n\n```javascript\n// Code node\nconst filters = $input.all()[0].json;\n\nlet query = \"SELECT * FROM users WHERE 1=1\";\nconst params = [];\n\nif (filters.name) {\n  query += \" AND name LIKE ?\";\n  params.push(`%${filters.name}%`);\n}\n\nif (filters.email) {\n  query += \" AND email = ?\";\n  params.push(filters.email);\n}\n\nquery += \" LIMIT 100\";\n\nreturn [{\n  json: {\n    query: query,\n    params: params\n  }\n}];\n```\n\n### Pattern 2: Batch Processing\n\nProcess large datasets in batches:\n\n```javascript\n// Code node\nconst batchSize = 1000;\nconst totalRecords = $input.all()[0].json.data.totalRecords;\nconst batches = Math.ceil(totalRecords / batchSize);\n\nconst results = [];\nfor (let i = 0; i < batches; i++) {\n  const offset = i * batchSize;\n  results.push({\n    json: {\n      query: `SELECT * FROM users LIMIT ${batchSize} OFFSET ${offset}`\n    }\n  });\n}\n\nreturn results;\n```\n\n### Pattern 3: Error Handling\n\nImplement robust error handling:\n\n```javascript\n// Code node\ntry {\n  const result = $input.all()[0].json;\n\n  if (!result.success) {\n    throw new Error(result.error.message);\n  }\n\n  return [{\n    json: {\n      success: true,\n      data: result.data\n    }\n  }];\n} catch (error) {\n  return [{\n    json: {\n      success: false,\n      error: error.message\n    }\n  }];\n}\n```\n\n### Pattern 4: Connection Pooling\n\nReuse connections across workflow executions:\n\n```javascript\n// Use n8n's static data to store session ID\nconst staticData = this.getWorkflowStaticData('global');\n\nif (!staticData.sessionId) {\n  // Connect to database\n  const response = await this.helpers.httpRequest({\n    method: 'POST',\n    url: 'http://localhost:3000/api/connect',\n    body: {\n      type: 'mysql',\n      host: 'localhost',\n      port: 3306,\n      user: 'root',\n      password: 'password',\n      database: 'testdb'\n    }\n  });\n\n  staticData.sessionId = response.data.sessionId;\n}\n\nreturn [{\n  json: {\n    sessionId: staticData.sessionId\n  }\n}];\n```\n\n## Integration with Other n8n Nodes\n\n### With Google Sheets\n\n**Workflow**: Database → Google Sheets\n\n1. Query database\n2. Format results\n3. Write to Google Sheets\n\n### With Slack\n\n**Workflow**: Database Alert → Slack\n\n1. Query database for metrics\n2. Check thresholds\n3. Send Slack message if alert\n\n### With Airtable\n\n**Workflow**: Database → Airtable Sync\n\n1. Query database\n2. Transform data\n3. Update Airtable records\n\n### With Email\n\n**Workflow**: Database Report → Email\n\n1. Query database\n2. Generate HTML report\n3. Send email with report\n\n## Best Practices\n\n### 1. Use Credentials\n\nStore API keys in n8n credentials:\n\n1. Go to Credentials\n2. Create new \"Header Auth\" credential\n3. Name: `X-API-Key`\n4. Value: Your API key\n5. Use in HTTP Request nodes\n\n### 2. Error Handling\n\nAdd error handling to all workflows:\n\n```javascript\n// In HTTP Request node settings\n// Enable \"Continue On Fail\"\n// Add error handling node\n```\n\n### 3. Logging\n\nLog important events:\n\n```javascript\n// Code node\nconsole.log('Query executed:', query);\nconsole.log('Results:', results.length, 'rows');\n```\n\n### 4. Testing\n\nTest workflows before production:\n\n1. Use test database\n2. Test with small datasets\n3. Verify error handling\n4. Check performance\n\n## Monitoring & Debugging\n\n### View Execution Logs\n\n1. Go to \"Executions\" tab\n2. Click on execution\n3. View node outputs\n4. Check error messages\n\n### Debug Mode\n\nEnable debug mode in n8n:\n\n```bash\n# In docker-compose.yml\nenvironment:\n  - N8N_LOG_LEVEL=debug\n```\n\n### Performance Monitoring\n\nMonitor workflow performance:\n\n1. Check execution time\n2. Identify slow nodes\n3. Optimize queries\n4. Add caching\n\n## Troubleshooting\n\n### Issue: Connection Timeout\n\n**Solution**:\n- Increase timeout in HTTP Request node\n- Check network connectivity\n- Verify API server is running\n\n### Issue: Session Expired\n\n**Solution**:\n- Reconnect to database\n- Increase session timeout\n- Implement connection pooling\n\n### Issue: Large Result Sets\n\n**Solution**:\n- Add LIMIT to queries\n- Use pagination\n- Process in batches\n\n## Example: Complete ETL Workflow\n\n```json\n{\n  \"name\": \"ETL: MySQL to PostgreSQL\",\n  \"nodes\": [\n    {\n      \"name\": \"Schedule\",\n      \"type\": \"n8n-nodes-base.scheduleTrigger\",\n      \"parameters\": {\n        \"rule\": {\n          \"interval\": [{\"field\": \"hours\", \"hoursInterval\": 1}]\n        }\n      }\n    },\n    {\n      \"name\": \"Connect MySQL\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/connect\",\n        \"bodyParametersJson\": \"{\\\"type\\\":\\\"mysql\\\",\\\"host\\\":\\\"localhost\\\",\\\"port\\\":3306,\\\"user\\\":\\\"root\\\",\\\"password\\\":\\\"pass\\\",\\\"database\\\":\\\"source_db\\\"}\"\n      }\n    },\n    {\n      \"name\": \"Extract Data\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/query\",\n        \"bodyParametersJson\": \"{\\\"sessionId\\\":\\\"{{$node['Connect MySQL'].json.data.sessionId}}\\\",\\\"query\\\":\\\"SELECT * FROM users WHERE updated_at > NOW() - INTERVAL 1 HOUR\\\"}\"\n      }\n    },\n    {\n      \"name\": \"Transform Data\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"parameters\": {\n        \"jsCode\": \"const rows = $input.all()[0].json.data.rows;\\nreturn rows.map(row => ({\\n  json: {\\n    id: row.id,\\n    name: row.name.toUpperCase(),\\n    email: row.email.toLowerCase(),\\n    created_at: new Date(row.created_at).toISOString()\\n  }\\n}));\"\n      }\n    },\n    {\n      \"name\": \"Connect PostgreSQL\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/connect\",\n        \"bodyParametersJson\": \"{\\\"type\\\":\\\"postgres\\\",\\\"host\\\":\\\"localhost\\\",\\\"port\\\":5432,\\\"user\\\":\\\"postgres\\\",\\\"password\\\":\\\"pass\\\",\\\"database\\\":\\\"target_db\\\",\\\"allowWrite\\\":true}\"\n      }\n    },\n    {\n      \"name\": \"Load Data\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/execute\",\n        \"bodyParametersJson\": \"{\\\"sessionId\\\":\\\"{{$node['Connect PostgreSQL'].json.data.sessionId}}\\\",\\\"query\\\":\\\"INSERT INTO users (id, name, email, created_at) VALUES (?, ?, ?, ?) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, email = EXCLUDED.email\\\",\\\"params\\\":[\\\"{{$json.id}}\\\",\\\"{{$json.name}}\\\",\\\"{{$json.email}}\\\",\\\"{{$json.created_at}}\\\"]}\"\n      }\n    }\n  ]\n}\n```\n\n## Resources\n\n- [n8n Documentation](https://docs.n8n.io/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Deployment Guide](../http-api/DEPLOYMENT.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- n8n Community: https://community.n8n.io/\n"
  },
  {
    "path": "docs/integrations/N8N.zh-CN.md",
    "content": "# n8n 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 n8n 工作流自动化平台集成。\n\n## 概述\n\nn8n 是一个工作流自动化工具。通过集成 Universal Database MCP Server，您可以创建查询和操作数据库数据的工作流。\n\n## 前置要求\n\n- 部署了 HTTP API 模式的 Universal Database MCP Server\n- n8n 实例（自托管或云端）\n- 数据库实例（MySQL、PostgreSQL 等）\n\n## 设置步骤\n\n### 步骤 1: 部署 HTTP API 服务器\n\n部署 Universal Database MCP Server：\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=n8n-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2: 创建 n8n 工作流\n\n1. 登录 n8n\n2. 点击\"新建工作流\"\n3. 命名您的工作流（例如：\"数据库查询工作流\"）\n\n### 步骤 3: 添加 HTTP 请求节点\n\nn8n 使用 HTTP 请求节点调用 API。为每个操作添加节点：\n\n#### 节点 1: 连接数据库\n\n**节点类型**: HTTP Request\n**名称**: `连接数据库`\n\n**设置**:\n- **方法**: POST\n- **URL**: `http://localhost:3000/api/connect`\n- **认证**: Generic Credential Type\n  - Header Auth\n  - 名称: `X-API-Key`\n  - 值: `n8n-secret-key`\n- **Body Content Type**: JSON\n- **Body**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"password\",\n  \"database\": \"testdb\"\n}\n```\n\n**输出**: 从响应中提取 `sessionId`\n\n#### 节点 2: 执行查询\n\n**节点类型**: HTTP Request\n**名称**: `执行查询`\n\n**设置**:\n- **方法**: POST\n- **URL**: `http://localhost:3000/api/query`\n- **认证**: Header Auth (X-API-Key)\n- **Body**:\n```json\n{\n  \"sessionId\": \"{{$node['连接数据库'].json.data.sessionId}}\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n#### 节点 3: 处理结果\n\n**节点类型**: Code\n**名称**: `处理结果`\n\n**代码**:\n```javascript\nconst results = $input.all()[0].json.data.rows;\n\nreturn results.map(row => ({\n  json: row\n}));\n```\n\n## 示例工作流\n\n### 工作流 1: 定时数据库备份\n\n**触发器**: 定时（每天凌晨 2 点）\n\n**节点**:\n1. **定时触发器** - 每天凌晨 2 点运行\n2. **连接数据库** - 连接到数据库\n3. **执行查询** - `SELECT * FROM users`\n4. **转换为 CSV** - 将结果转换为 CSV\n5. **发送邮件** - 通过邮件发送 CSV 文件\n6. **断开数据库** - 关闭连接\n\n### 工作流 2: Webhook 到数据库\n\n**触发器**: Webhook\n\n**节点**:\n1. **Webhook** - 接收 HTTP POST\n2. **连接数据库** - 连接到数据库\n3. **执行查询** - 从 webhook 插入数据\n4. **响应 Webhook** - 返回成功/错误\n5. **断开数据库** - 关闭连接\n\n**示例**:\n```bash\n# 触发工作流\ncurl -X POST https://your-n8n.com/webhook/insert-user \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Alice\",\n    \"email\": \"alice@example.com\"\n  }'\n```\n\n**查询节点**:\n```json\n{\n  \"sessionId\": \"{{$node['连接数据库'].json.data.sessionId}}\",\n  \"query\": \"INSERT INTO users (name, email) VALUES (?, ?)\",\n  \"params\": [\n    \"{{$json.name}}\",\n    \"{{$json.email}}\"\n  ]\n}\n```\n\n### 工作流 3: 数据库间数据同步\n\n**触发器**: 定时（每小时）\n\n**节点**:\n1. **定时触发器** - 每小时运行\n2. **连接源数据库** - 连接到源数据库\n3. **查询源数据** - 获取新记录\n4. **连接目标数据库** - 连接到目标数据库\n5. **插入到目标** - 插入记录\n6. **断开两个连接** - 关闭连接\n\n### 工作流 4: 数据库监控\n\n**触发器**: 定时（每 5 分钟）\n\n**节点**:\n1. **定时触发器** - 每 5 分钟运行\n2. **连接数据库** - 连接到数据库\n3. **检查表大小** - `SELECT COUNT(*) FROM users`\n4. **检查慢查询** - 查询性能模式\n5. **发送告警** - 如果超过阈值发送 Slack/邮件\n6. **断开数据库** - 关闭连接\n\n## 高级模式\n\n### 模式 1: 动态查询构建器\n\n使用 n8n 的 Code 节点动态构建查询：\n\n```javascript\n// Code 节点\nconst filters = $input.all()[0].json;\n\nlet query = \"SELECT * FROM users WHERE 1=1\";\nconst params = [];\n\nif (filters.name) {\n  query += \" AND name LIKE ?\";\n  params.push(`%${filters.name}%`);\n}\n\nif (filters.email) {\n  query += \" AND email = ?\";\n  params.push(filters.email);\n}\n\nquery += \" LIMIT 100\";\n\nreturn [{\n  json: {\n    query: query,\n    params: params\n  }\n}];\n```\n\n### 模式 2: 批量处理\n\n分批处理大数据集：\n\n```javascript\n// Code 节点\nconst batchSize = 1000;\nconst totalRecords = $input.all()[0].json.data.totalRecords;\nconst batches = Math.ceil(totalRecords / batchSize);\n\nconst results = [];\nfor (let i = 0; i < batches; i++) {\n  const offset = i * batchSize;\n  results.push({\n    json: {\n      query: `SELECT * FROM users LIMIT ${batchSize} OFFSET ${offset}`\n    }\n  });\n}\n\nreturn results;\n```\n\n### 模式 3: 错误处理\n\n实现健壮的错误处理：\n\n```javascript\n// Code 节点\ntry {\n  const result = $input.all()[0].json;\n\n  if (!result.success) {\n    throw new Error(result.error.message);\n  }\n\n  return [{\n    json: {\n      success: true,\n      data: result.data\n    }\n  }];\n} catch (error) {\n  return [{\n    json: {\n      success: false,\n      error: error.message\n    }\n  }];\n}\n```\n\n### 模式 4: 连接池\n\n跨工作流执行复用连接：\n\n```javascript\n// 使用 n8n 的静态数据存储会话 ID\nconst staticData = this.getWorkflowStaticData('global');\n\nif (!staticData.sessionId) {\n  // 连接到数据库\n  const response = await this.helpers.httpRequest({\n    method: 'POST',\n    url: 'http://localhost:3000/api/connect',\n    body: {\n      type: 'mysql',\n      host: 'localhost',\n      port: 3306,\n      user: 'root',\n      password: 'password',\n      database: 'testdb'\n    }\n  });\n\n  staticData.sessionId = response.data.sessionId;\n}\n\nreturn [{\n  json: {\n    sessionId: staticData.sessionId\n  }\n}];\n```\n\n## 与其他 n8n 节点集成\n\n### 与 Google Sheets\n\n**工作流**: 数据库 → Google Sheets\n\n1. 查询数据库\n2. 格式化结果\n3. 写入 Google Sheets\n\n### 与 Slack\n\n**工作流**: 数据库告警 → Slack\n\n1. 查询数据库指标\n2. 检查阈值\n3. 如果告警则发送 Slack 消息\n\n### 与 Airtable\n\n**工作流**: 数据库 → Airtable 同步\n\n1. 查询数据库\n2. 转换数据\n3. 更新 Airtable 记录\n\n### 与邮件\n\n**工作流**: 数据库报告 → 邮件\n\n1. 查询数据库\n2. 生成 HTML 报告\n3. 发送带报告的邮件\n\n## 最佳实践\n\n### 1. 使用凭据\n\n在 n8n 凭据中存储 API Keys：\n\n1. 转到凭据\n2. 创建新的\"Header Auth\"凭据\n3. 名称: `X-API-Key`\n4. 值: 您的 API Key\n5. 在 HTTP 请求节点中使用\n\n### 2. 错误处理\n\n为所有工作流添加错误处理：\n\n```javascript\n// 在 HTTP 请求节点设置中\n// 启用\"Continue On Fail\"\n// 添加错误处理节点\n```\n\n### 3. 日志记录\n\n记录重要事件：\n\n```javascript\n// Code 节点\nconsole.log('查询已执行:', query);\nconsole.log('结果:', results.length, '行');\n```\n\n### 4. 测试\n\n在生产前测试工作流：\n\n1. 使用测试数据库\n2. 使用小数据集测试\n3. 验证错误处理\n4. 检查性能\n\n## 监控与调试\n\n### 查看执行日志\n\n1. 转到\"执行\"标签\n2. 点击执行\n3. 查看节点输出\n4. 检查错误消息\n\n### 调试模式\n\n在 n8n 中启用调试模式：\n\n```bash\n# 在 docker-compose.yml 中\nenvironment:\n  - N8N_LOG_LEVEL=debug\n```\n\n### 性能监控\n\n监控工作流性能：\n\n1. 检查执行时间\n2. 识别慢节点\n3. 优化查询\n4. 添加缓存\n\n## 故障排除\n\n### 问题：连接超时\n\n**解决方案**:\n- 增加 HTTP 请求节点中的超时时间\n- 检查网络连接\n- 验证 API 服务器正在运行\n\n### 问题：会话过期\n\n**解决方案**:\n- 重新连接数据库\n- 增加会话超时时间\n- 实现连接池\n\n### 问题：大结果集\n\n**解决方案**:\n- 为查询添加 LIMIT\n- 使用分页\n- 分批处理\n\n## 完整 ETL 工作流示例\n\n```json\n{\n  \"name\": \"ETL: MySQL 到 PostgreSQL\",\n  \"nodes\": [\n    {\n      \"name\": \"定时\",\n      \"type\": \"n8n-nodes-base.scheduleTrigger\",\n      \"parameters\": {\n        \"rule\": {\n          \"interval\": [{\"field\": \"hours\", \"hoursInterval\": 1}]\n        }\n      }\n    },\n    {\n      \"name\": \"连接 MySQL\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/connect\",\n        \"bodyParametersJson\": \"{\\\"type\\\":\\\"mysql\\\",\\\"host\\\":\\\"localhost\\\",\\\"port\\\":3306,\\\"user\\\":\\\"root\\\",\\\"password\\\":\\\"pass\\\",\\\"database\\\":\\\"source_db\\\"}\"\n      }\n    },\n    {\n      \"name\": \"提取数据\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/query\",\n        \"bodyParametersJson\": \"{\\\"sessionId\\\":\\\"{{$node['连接 MySQL'].json.data.sessionId}}\\\",\\\"query\\\":\\\"SELECT * FROM users WHERE updated_at > NOW() - INTERVAL 1 HOUR\\\"}\"\n      }\n    },\n    {\n      \"name\": \"转换数据\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"parameters\": {\n        \"jsCode\": \"const rows = $input.all()[0].json.data.rows;\\nreturn rows.map(row => ({\\n  json: {\\n    id: row.id,\\n    name: row.name.toUpperCase(),\\n    email: row.email.toLowerCase(),\\n    created_at: new Date(row.created_at).toISOString()\\n  }\\n}));\"\n      }\n    },\n    {\n      \"name\": \"连接 PostgreSQL\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/connect\",\n        \"bodyParametersJson\": \"{\\\"type\\\":\\\"postgres\\\",\\\"host\\\":\\\"localhost\\\",\\\"port\\\":5432,\\\"user\\\":\\\"postgres\\\",\\\"password\\\":\\\"pass\\\",\\\"database\\\":\\\"target_db\\\",\\\"allowWrite\\\":true}\"\n      }\n    },\n    {\n      \"name\": \"加载数据\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"parameters\": {\n        \"method\": \"POST\",\n        \"url\": \"http://localhost:3000/api/execute\",\n        \"bodyParametersJson\": \"{\\\"sessionId\\\":\\\"{{$node['连接 PostgreSQL'].json.data.sessionId}}\\\",\\\"query\\\":\\\"INSERT INTO users (id, name, email, created_at) VALUES (?, ?, ?, ?) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, email = EXCLUDED.email\\\",\\\"params\\\":[\\\"{{$json.id}}\\\",\\\"{{$json.name}}\\\",\\\"{{$json.email}}\\\",\\\"{{$json.created_at}}\\\"]}\"\n      }\n    }\n  ]\n}\n```\n\n## 资源\n\n- [n8n 文档](https://docs.n8n.io/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- n8n 社区: https://community.n8n.io/\n"
  },
  {
    "path": "docs/integrations/NEOVIM.md",
    "content": "# Neovim Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Neovim.\n\n## Overview\n\nNeovim is a highly extensible, Vim-based text editor that supports modern features through its Lua API and plugin ecosystem. By using the MCPHub.nvim plugin, you can integrate Universal Database MCP Server with Neovim, enabling AI-powered database interactions directly within your editor.\n\n**Key Benefits:**\n- Query databases directly from Neovim\n- Get AI assistance for SQL query writing\n- Explore database schema without leaving the editor\n- Seamless integration with Neovim's workflow\n\n## Prerequisites\n\n- [Neovim](https://neovim.io/) installed (version 0.8.0 or later recommended)\n- Node.js 18+ installed\n- A plugin manager (lazy.nvim, packer.nvim, or similar)\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Plugin Installation\n\nNeovim supports MCP through the MCPHub.nvim plugin. Below are installation instructions for popular plugin managers.\n\n### Using lazy.nvim\n\nAdd the following to your Neovim configuration:\n\n```lua\n{\n  \"ravitemer/mcphub.nvim\",\n  dependencies = {\n    \"nvim-lua/plenary.nvim\",\n  },\n  config = function()\n    require(\"mcphub\").setup({\n      -- Configuration goes here\n    })\n  end,\n}\n```\n\n### Using packer.nvim\n\nAdd the following to your Neovim configuration:\n\n```lua\nuse {\n  \"ravitemer/mcphub.nvim\",\n  requires = {\n    \"nvim-lua/plenary.nvim\",\n  },\n  config = function()\n    require(\"mcphub\").setup({\n      -- Configuration goes here\n    })\n  end,\n}\n```\n\n### Using vim-plug\n\nAdd the following to your Neovim configuration:\n\n```vim\nPlug 'nvim-lua/plenary.nvim'\nPlug 'ravitemer/mcphub.nvim'\n```\n\nThen add the Lua configuration:\n\n```lua\nlua << EOF\nrequire(\"mcphub\").setup({\n  -- Configuration goes here\n})\nEOF\n```\n\n## Configuration\n\nAfter installing the plugin, configure the MCP server in your Neovim setup.\n\n### Basic Configuration\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"universal-db-mcp\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n## Configuration Examples\n\n### MySQL\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### PostgreSQL\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"postgres-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### SQLite\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"sqlite-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      }\n    }\n  }\n})\n```\n\n### SQL Server\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"sqlserver-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### Oracle\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"oracle-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      }\n    }\n  }\n})\n```\n\n### MongoDB\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mongodb\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### Redis\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"redis\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      }\n    }\n  }\n})\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-production\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      }\n    },\n    [\"mysql-development\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      }\n    },\n    [\"postgres-analytics\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      }\n    }\n  }\n})\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db-writable\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      }\n    }\n  }\n})\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nUse the MCPHub commands to interact with your database:\n\n```\n:MCPHub\n```\n\nThen ask the AI:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk the AI to generate database-related code:\n\n```\nGenerate a Lua function to insert a new user into the users table\n```\n\nThe AI will examine your schema and generate appropriate code.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** configuration files with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: Plugin Not Loading\n\n**Symptoms**: MCPHub commands are not available\n\n**Solutions**:\n1. Verify the plugin is correctly installed\n2. Check that plenary.nvim dependency is installed\n3. Run `:checkhealth mcphub` to diagnose issues\n4. Ensure your Neovim version is 0.8.0 or later\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Cannot connect to the database through MCPHub\n\n**Solutions**:\n1. Verify the configuration syntax is correct\n2. Check that Node.js is installed and accessible from PATH\n3. Ensure npx command is available\n4. Restart Neovim after making configuration changes\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n## Advanced Configuration\n\n### Using Environment Variables\n\nFor better security, you can use environment variables in your configuration:\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", os.getenv(\"DB_PASSWORD\") or \"default_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\nSet the environment variable before starting Neovim:\n\n**macOS/Linux:**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n### Integration with Other Plugins\n\nMCPHub.nvim can work alongside other Neovim plugins for enhanced functionality:\n\n- **nvim-cmp**: For AI-powered completions\n- **telescope.nvim**: For fuzzy finding database objects\n- **which-key.nvim**: For keybinding discovery\n\n## Resources\n\n- [Neovim Official Website](https://neovim.io/)\n- [MCPHub.nvim GitHub Repository](https://github.com/ravitemer/mcphub.nvim)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Neovim Community: https://neovim.io/community/\n"
  },
  {
    "path": "docs/integrations/NEOVIM.zh-CN.md",
    "content": "# Neovim 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Neovim 集成。\n\n## 概述\n\nNeovim 是一款高度可扩展的、基于 Vim 的文本编辑器，通过其 Lua API 和插件生态系统支持现代功能。通过使用 MCPHub.nvim 插件，您可以将 Universal Database MCP Server 与 Neovim 集成，在编辑器中直接实现 AI 驱动的数据库交互。\n\n**主要优势：**\n- 直接从 Neovim 查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 无需离开编辑器即可探索数据库结构\n- 与 Neovim 工作流无缝集成\n\n## 前置要求\n\n- 已安装 [Neovim](https://neovim.io/)（建议版本 0.8.0 或更高）\n- 已安装 Node.js 18+\n- 插件管理器（lazy.nvim、packer.nvim 或类似工具）\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 插件安装\n\nNeovim 通过 MCPHub.nvim 插件支持 MCP。以下是常用插件管理器的安装说明。\n\n### 使用 lazy.nvim\n\n将以下内容添加到您的 Neovim 配置中：\n\n```lua\n{\n  \"ravitemer/mcphub.nvim\",\n  dependencies = {\n    \"nvim-lua/plenary.nvim\",\n  },\n  config = function()\n    require(\"mcphub\").setup({\n      -- 配置在此处\n    })\n  end,\n}\n```\n\n### 使用 packer.nvim\n\n将以下内容添加到您的 Neovim 配置中：\n\n```lua\nuse {\n  \"ravitemer/mcphub.nvim\",\n  requires = {\n    \"nvim-lua/plenary.nvim\",\n  },\n  config = function()\n    require(\"mcphub\").setup({\n      -- 配置在此处\n    })\n  end,\n}\n```\n\n### 使用 vim-plug\n\n将以下内容添加到您的 Neovim 配置中：\n\n```vim\nPlug 'nvim-lua/plenary.nvim'\nPlug 'ravitemer/mcphub.nvim'\n```\n\n然后添加 Lua 配置：\n\n```lua\nlua << EOF\nrequire(\"mcphub\").setup({\n  -- 配置在此处\n})\nEOF\n```\n\n## 配置\n\n安装插件后，在 Neovim 设置中配置 MCP 服务器。\n\n### 基本配置\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"universal-db-mcp\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n## 配置示例\n\n### MySQL\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### PostgreSQL\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"postgres-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### SQLite\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"sqlite-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      }\n    }\n  }\n})\n```\n\n### SQL Server\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"sqlserver-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### Oracle\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"oracle-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      }\n    }\n  }\n})\n```\n\n### MongoDB\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mongodb\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### Redis\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"redis\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      }\n    }\n  }\n})\n```\n\n### 达梦数据库\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"dm-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      }\n    }\n  }\n})\n```\n\n### 人大金仓\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"kingbase-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-production\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      }\n    },\n    [\"mysql-development\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      }\n    },\n    [\"postgres-analytics\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      }\n    }\n  }\n})\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db-writable\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      }\n    }\n  }\n})\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n使用 MCPHub 命令与数据库交互：\n\n```\n:MCPHub\n```\n\n然后询问 AI：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案。\n\n### 示例 5: 生成代码\n\n让 AI 生成数据库相关代码：\n\n```\n生成一个 Lua 函数，用于向 users 表插入新用户\n```\n\nAI 将检查您的结构并生成适当的代码。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的配置文件提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：插件未加载\n\n**症状**：MCPHub 命令不可用\n\n**解决方案**：\n1. 验证插件是否正确安装\n2. 检查 plenary.nvim 依赖是否已安装\n3. 运行 `:checkhealth mcphub` 诊断问题\n4. 确保 Neovim 版本为 0.8.0 或更高\n\n### 问题：MCP 服务器未连接\n\n**症状**：无法通过 MCPHub 连接到数据库\n\n**解决方案**：\n1. 验证配置语法是否正确\n2. 检查 Node.js 是否已安装并可从 PATH 访问\n3. 确保 npx 命令可用\n4. 更改配置后重启 Neovim\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n## 高级配置\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中使用环境变量：\n\n```lua\nrequire(\"mcphub\").setup({\n  servers = {\n    [\"mysql-db\"] = {\n      command = \"npx\",\n      args = {\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", os.getenv(\"DB_PASSWORD\") or \"default_password\",\n        \"--database\", \"your_database\"\n      }\n    }\n  }\n})\n```\n\n在启动 Neovim 之前设置环境变量：\n\n**macOS/Linux：**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell)：**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n### 与其他插件集成\n\nMCPHub.nvim 可以与其他 Neovim 插件配合使用以增强功能：\n\n- **nvim-cmp**：用于 AI 驱动的补全\n- **telescope.nvim**：用于模糊查找数据库对象\n- **which-key.nvim**：用于快捷键发现\n\n## 资源\n\n- [Neovim 官方网站](https://neovim.io/)\n- [MCPHub.nvim GitHub 仓库](https://github.com/ravitemer/mcphub.nvim)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Neovim 社区: https://neovim.io/community/\n"
  },
  {
    "path": "docs/integrations/NOTION.md",
    "content": "# Notion Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Notion.\n\n## Overview\n\n[Notion](https://notion.so/) is a productivity and note-taking application. Through Notion's AI features and MCP support, you can query databases directly from your Notion workspace.\n\n## Prerequisites\n\n- Notion account with AI features enabled\n- Universal Database MCP Server deployed with HTTP mode\n- Database instance (MySQL, PostgreSQL, etc.)\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server in HTTP mode with SSE/Streamable HTTP support:\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=notion-secret-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Configure Notion MCP Connection\n\n1. Open Notion Settings\n2. Navigate to \"Connections\" or \"AI Settings\"\n3. Add MCP Server connection:\n   - URL: `https://your-server.com/mcp`\n   - Authentication: API Key\n\n### Step 3: Configure Database Headers\n\nWhen connecting, include database configuration in headers:\n\n```\nX-DB-Type: mysql\nX-DB-Host: localhost\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\n## Usage\n\nOnce configured, you can use Notion AI to query your database:\n\n```\n@AI What tables are in my database?\n\n@AI Show me the schema of the users table\n\n@AI How many orders were placed this month?\n\n@AI Find the top 10 customers by revenue\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n1. Use read-only database users\n2. Keep your MCP server secure with API keys\n3. Use HTTPS for production deployments\n4. Limit query results to prevent large responses\n\n## Resources\n\n- [Notion Documentation](https://notion.so/help)\n- [API Reference](../http-api/API_REFERENCE.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/NOTION.zh-CN.md",
    "content": "# Notion 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Notion 集成。\n\n## 概述\n\n[Notion](https://notion.so/) 是一个生产力和笔记应用。通过 Notion 的 AI 功能和 MCP 支持，您可以直接从 Notion 工作区查询数据库。\n\n## 前置要求\n\n- 启用了 AI 功能的 Notion 账号\n- 部署了 HTTP 模式的 Universal Database MCP Server\n- 数据库实例（MySQL、PostgreSQL 等）\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server，支持 SSE/Streamable HTTP：\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=notion-secret-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：配置 Notion MCP 连接\n\n1. 打开 Notion 设置\n2. 导航到\"Connections\"或\"AI Settings\"\n3. 添加 MCP 服务器连接：\n   - URL: `https://your-server.com/mcp`\n   - 认证: API Key\n\n### 步骤 3：配置数据库请求头\n\n连接时，在请求头中包含数据库配置：\n\n```\nX-DB-Type: mysql\nX-DB-Host: localhost\nX-DB-Port: 3306\nX-DB-User: root\nX-DB-Password: your_password\nX-DB-Database: your_database\n```\n\n## 使用方法\n\n配置完成后，您可以使用 Notion AI 查询数据库：\n\n```\n@AI 我的数据库里有哪些表？\n\n@AI 显示 users 表的结构\n\n@AI 这个月有多少订单？\n\n@AI 找出收入前 10 的客户\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n1. 使用只读数据库用户\n2. 使用 API 密钥保护 MCP 服务器\n3. 生产环境使用 HTTPS\n4. 限制查询结果以防止大响应\n\n## 资源\n\n- [Notion 文档](https://notion.so/help)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/OBSIDIAN.md",
    "content": "# Obsidian Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Obsidian.\n\n## Overview\n\nObsidian is a powerful knowledge base application that works on top of local Markdown files. Through the MCP Tools plugin, Obsidian supports the MCP (Model Context Protocol), allowing you to extend its AI capabilities with external tools. By integrating Universal Database MCP Server, you can enable Obsidian to directly query and analyze your database data during AI-assisted note-taking and research.\n\n**Key Benefits:**\n- Query databases directly from Obsidian's AI chat interface\n- Integrate database insights into your knowledge base\n- Explore database schema through natural language\n- Execute SQL queries and incorporate results into your notes\n\n## Prerequisites\n\n- [Obsidian](https://obsidian.md/) installed (latest version recommended)\n- [MCP Tools](https://github.com/jacksteamdev/obsidian-mcp-tools) plugin installed\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nObsidian uses the MCP Tools plugin for MCP integration. Configuration is done through the plugin settings.\n\n### Step 1: Install MCP Tools Plugin\n\n1. Open Obsidian\n2. Go to Settings > Community plugins\n3. Click \"Browse\" and search for \"MCP Tools\"\n4. Install and enable the MCP Tools plugin\n\n### Step 2: Open Plugin Settings\n\n1. Go to Settings > MCP Tools\n2. Navigate to the MCP server configuration section\n\n### Step 3: Add MCP Server Configuration\n\nIn the MCP server configuration section, add the following JSON configuration:\n\n#### Basic Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 4: Save and Restart\n\nAfter adding the configuration, save the settings and restart Obsidian for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### DM (Dameng Database)\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### KingbaseES\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Obsidian:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Obsidian's AI chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Data Analysis\n\nAsk the AI to analyze your data:\n\n```\nAnalyze the sales trends for the last 6 months\n```\n\nThe AI will query the relevant tables and provide insights based on the data.\n\n### Example 5: Generate Reports\n\nRequest data summaries:\n\n```\nGenerate a summary of user registrations by month for 2024\n```\n\nThe AI will create and execute the appropriate queries to generate the report.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never share** configurations with real credentials\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Usage Tips\n\n- Be specific in your queries to get better results\n- Use natural language to describe what data you need\n- Ask the AI to explain query results when needed\n\n## Troubleshooting\n\n### Issue: MCP Tools Plugin Not Working\n\n**Symptoms**: Obsidian doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the MCP Tools plugin is installed and enabled\n2. Check the plugin settings for any error messages\n3. Restart Obsidian after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Plugin shows connection errors\n\n**Solutions**:\n1. Verify the MCP server configuration is correctly entered in settings\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart Obsidian after making configuration changes\n4. Check the plugin console for detailed error messages\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n## Resources\n\n- [Obsidian Official Website](https://obsidian.md/)\n- [MCP Tools Plugin](https://github.com/jacksteamdev/obsidian-mcp-tools)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- MCP Tools Plugin Issues: https://github.com/jacksteamdev/obsidian-mcp-tools/issues\n"
  },
  {
    "path": "docs/integrations/OBSIDIAN.zh-CN.md",
    "content": "# Obsidian 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Obsidian 集成。\n\n## 概述\n\nObsidian 是一款强大的知识库应用，基于本地 Markdown 文件工作。通过 MCP Tools 插件，Obsidian 支持 MCP（Model Context Protocol），允许您通过外部工具扩展其 AI 功能。通过集成 Universal Database MCP Server，您可以让 Obsidian 在 AI 辅助笔记和研究过程中直接查询和分析数据库数据。\n\n**主要优势：**\n\n- 直接从 Obsidian 的 AI 聊天界面查询数据库\n- 将数据库洞察集成到您的知识库中\n- 通过自然语言探索数据库结构\n- 执行 SQL 查询并将结果整合到笔记中\n\n## 前置要求\n\n- 已安装 [Obsidian](https://obsidian.md/)（建议使用最新版本）\n- 已安装 [MCP Tools](https://github.com/jacksteamdev/obsidian-mcp-tools) 插件\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nObsidian 使用 MCP Tools 插件进行 MCP 集成。配置通过插件设置完成。\n\n### 步骤 1: 安装 MCP Tools 插件\n\n1. 打开 Obsidian\n2. 进入 设置 > 第三方插件\n3. 点击\"浏览\"并搜索\"MCP Tools\"\n4. 安装并启用 MCP Tools 插件\n\n### 步骤 2: 打开插件设置\n\n1. 进入 设置 > MCP Tools\n2. 导航到 MCP 服务器配置部分\n\n### 步骤 3: 添加 MCP 服务器配置\n\n在 MCP 服务器配置部分，添加以下 JSON 配置：\n\n#### 基本配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 4: 保存并重启\n\n添加配置后，保存设置并重启 Obsidian 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Obsidian 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Obsidian 的 AI 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 数据分析\n\n让 AI 分析您的数据：\n\n```\n分析过去 6 个月的销售趋势\n```\n\nAI 将查询相关表并根据数据提供洞察。\n\n### 示例 5: 生成报表\n\n请求数据汇总：\n\n```\n生成 2024 年按月份统计的用户注册汇总\n```\n\nAI 将创建并执行适当的查询来生成报表。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿分享**包含真实凭据的配置\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 使用技巧\n\n- 在查询中尽量具体以获得更好的结果\n- 使用自然语言描述您需要的数据\n- 需要时让 AI 解释查询结果\n\n## 故障排除\n\n### 问题：MCP Tools 插件无法工作\n\n**症状**：Obsidian 无法识别数据库工具\n\n**解决方案**：\n1. 验证 MCP Tools 插件已安装并启用\n2. 检查插件设置中是否有错误消息\n3. 更改配置后重启 Obsidian\n4. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：MCP 服务器未连接\n\n**症状**：插件显示连接错误\n\n**解决方案**：\n1. 验证 MCP 服务器配置是否正确输入到设置中\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 Obsidian\n4. 检查插件控制台以获取详细错误消息\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n## 资源\n\n- [Obsidian 官方网站](https://obsidian.md/)\n- [MCP Tools 插件](https://github.com/jacksteamdev/obsidian-mcp-tools)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- MCP Tools 插件 Issues: https://github.com/jacksteamdev/obsidian-mcp-tools/issues\n"
  },
  {
    "path": "docs/integrations/OLLAMA.md",
    "content": "# Ollama Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Ollama for local LLM database queries.\n\n## Overview\n\n[Ollama](https://ollama.ai/) is a tool for running large language models locally. While Ollama itself doesn't have native MCP support, you can use it with MCP-compatible clients like Oterm, MCPHost, or custom applications.\n\n**Key Benefits:**\n- Run LLMs completely locally\n- Privacy-focused - data never leaves your machine\n- Works with various open-source models\n- Combine with MCP clients for database access\n\n## Prerequisites\n\n- Ollama installed ([Download here](https://ollama.ai/))\n- An MCP-compatible client (Oterm, MCPHost, etc.)\n- Node.js 20.0.0 or later\n- Database instance accessible from your machine\n\n## Integration Methods\n\n### Method 1: Using Oterm\n\n[Oterm](https://github.com/ggozad/oterm) is a terminal-based Ollama client with MCP support.\n\n**Installation:**\n```bash\npip install oterm\n```\n\n**Configuration:**\nCreate `~/.config/oterm/config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n**Usage:**\n```bash\noterm\n# Then ask questions about your database\n```\n\n### Method 2: Using MCPHost\n\n[MCPHost](https://github.com/mark3labs/mcphost) is a CLI tool for chatting with LLMs using MCP.\n\n**Installation:**\n```bash\ngo install github.com/mark3labs/mcphost@latest\n```\n\n**Configuration:**\nCreate `~/.mcphost/config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  },\n  \"llm\": {\n    \"provider\": \"ollama\",\n    \"model\": \"llama3.2\"\n  }\n}\n```\n\n**Usage:**\n```bash\nmcphost chat\n# Then ask questions about your database\n```\n\n### Method 3: Custom Application\n\nBuild a custom application using Ollama's API with MCP:\n\n```javascript\nconst { Client } = require('@modelcontextprotocol/sdk/client/index.js');\nconst { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');\nconst ollama = require('ollama');\n\nasync function main() {\n  // Start MCP server\n  const transport = new StdioClientTransport({\n    command: 'npx',\n    args: [\n      'universal-db-mcp',\n      '--type', 'mysql',\n      '--host', 'localhost',\n      '--port', '3306',\n      '--user', 'root',\n      '--password', 'password',\n      '--database', 'mydb'\n    ]\n  });\n\n  const client = new Client({ name: 'ollama-client', version: '1.0.0' });\n  await client.connect(transport);\n\n  // Get available tools\n  const tools = await client.listTools();\n\n  // Chat with Ollama using tools\n  const response = await ollama.chat({\n    model: 'llama3.2',\n    messages: [{ role: 'user', content: 'What tables are in the database?' }],\n    tools: tools.tools.map(t => ({\n      type: 'function',\n      function: {\n        name: t.name,\n        description: t.description,\n        parameters: t.inputSchema\n      }\n    }))\n  });\n\n  console.log(response.message.content);\n}\n\nmain();\n```\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n## Recommended Models\n\nFor database queries, these Ollama models work well:\n\n| Model | Size | Best For |\n|-------|------|----------|\n| llama3.2 | 3B | General queries, fast responses |\n| llama3.1 | 8B | Complex queries, better reasoning |\n| codellama | 7B | SQL generation, code tasks |\n| mistral | 7B | Balanced performance |\n| mixtral | 47B | Complex analysis (requires more RAM) |\n\n**Pull a model:**\n```bash\nollama pull llama3.2\n```\n\n## Usage Examples\n\n### Basic Queries\n\n```\nWhat tables are in the database?\n\nShow me the schema of the users table\n\nHow many users signed up this week?\n\nFind the top 10 products by sales\n```\n\n### SQL Generation\n\n```\nWrite a query to find users who haven't ordered in 30 days\n\nGenerate SQL to calculate monthly revenue by category\n\nCreate a query to find duplicate email addresses\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table information |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n### Security\n\n1. Use read-only database users\n2. Keep credentials secure\n3. Run everything locally for privacy\n4. Disable write mode unless necessary\n\n### Performance\n\n1. Use smaller models for simple queries\n2. Use larger models for complex analysis\n3. Add LIMIT to prevent large result sets\n4. Cache schema information\n\n## Troubleshooting\n\n### Ollama Not Responding\n\n**Symptoms:** No response from Ollama\n\n**Solutions:**\n1. Ensure Ollama is running: `ollama serve`\n2. Check model is downloaded: `ollama list`\n3. Verify system has enough RAM\n\n### MCP Server Not Found\n\n**Symptoms:** Tools not available\n\n**Solutions:**\n1. Verify MCP configuration is correct\n2. Ensure Node.js 20+ is installed\n3. Check the MCP client supports tools\n\n### Slow Responses\n\n**Symptoms:** Queries take too long\n\n**Solutions:**\n1. Use a smaller model\n2. Ensure GPU acceleration is enabled\n3. Reduce context length\n4. Use simpler queries\n\n## Resources\n\n- [Ollama Documentation](https://ollama.ai/docs)\n- [Ollama GitHub](https://github.com/ollama/ollama)\n- [Oterm GitHub](https://github.com/ggozad/oterm)\n- [MCPHost GitHub](https://github.com/mark3labs/mcphost)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Ollama Discord: https://discord.gg/ollama\n"
  },
  {
    "path": "docs/integrations/OLLAMA.zh-CN.md",
    "content": "# Ollama 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Ollama 集成，实现本地 LLM 数据库查询。\n\n## 概述\n\n[Ollama](https://ollama.ai/) 是一个在本地运行大型语言模型的工具。虽然 Ollama 本身没有原生 MCP 支持，但您可以通过 MCP 兼容的客户端（如 Oterm、MCPHost 或自定义应用）来使用它。\n\n**主要优势：**\n- 完全在本地运行 LLM\n- 注重隐私 - 数据永不离开您的机器\n- 支持多种开源模型\n- 结合 MCP 客户端访问数据库\n\n## 前置要求\n\n- 已安装 Ollama（[下载地址](https://ollama.ai/)）\n- MCP 兼容的客户端（Oterm、MCPHost 等）\n- Node.js 20.0.0 或更高版本\n- 可从您的机器访问的数据库实例\n\n## 集成方式\n\n### 方式 1：使用 Oterm\n\n[Oterm](https://github.com/ggozad/oterm) 是一个支持 MCP 的终端 Ollama 客户端。\n\n**安装：**\n```bash\npip install oterm\n```\n\n**配置：**\n创建 `~/.config/oterm/config.json`：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n**使用：**\n```bash\noterm\n# 然后询问关于数据库的问题\n```\n\n### 方式 2：使用 MCPHost\n\n[MCPHost](https://github.com/mark3labs/mcphost) 是一个使用 MCP 与 LLM 聊天的 CLI 工具。\n\n**安装：**\n```bash\ngo install github.com/mark3labs/mcphost@latest\n```\n\n**配置：**\n创建 `~/.mcphost/config.json`：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  },\n  \"llm\": {\n    \"provider\": \"ollama\",\n    \"model\": \"llama3.2\"\n  }\n}\n```\n\n**使用：**\n```bash\nmcphost chat\n# 然后询问关于数据库的问题\n```\n\n### 方式 3：自定义应用\n\n使用 Ollama API 和 MCP 构建自定义应用：\n\n```javascript\nconst { Client } = require('@modelcontextprotocol/sdk/client/index.js');\nconst { StdioClientTransport } = require('@modelcontextprotocol/sdk/client/stdio.js');\nconst ollama = require('ollama');\n\nasync function main() {\n  // 启动 MCP 服务器\n  const transport = new StdioClientTransport({\n    command: 'npx',\n    args: [\n      'universal-db-mcp',\n      '--type', 'mysql',\n      '--host', 'localhost',\n      '--port', '3306',\n      '--user', 'root',\n      '--password', 'password',\n      '--database', 'mydb'\n    ]\n  });\n\n  const client = new Client({ name: 'ollama-client', version: '1.0.0' });\n  await client.connect(transport);\n\n  // 获取可用工具\n  const tools = await client.listTools();\n\n  // 使用工具与 Ollama 聊天\n  const response = await ollama.chat({\n    model: 'llama3.2',\n    messages: [{ role: 'user', content: '数据库里有哪些表？' }],\n    tools: tools.tools.map(t => ({\n      type: 'function',\n      function: {\n        name: t.name,\n        description: t.description,\n        parameters: t.inputSchema\n      }\n    }))\n  });\n\n  console.log(response.message.content);\n}\n\nmain();\n```\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"password\",\n        \"--database\", \"myapp\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-local\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/database.db\"\n      ]\n    }\n  }\n}\n```\n\n## 推荐模型\n\n对于数据库查询，这些 Ollama 模型效果较好：\n\n| 模型 | 大小 | 最适合 |\n|------|------|--------|\n| llama3.2 | 3B | 一般查询，快速响应 |\n| llama3.1 | 8B | 复杂查询，更好的推理 |\n| codellama | 7B | SQL 生成，代码任务 |\n| mistral | 7B | 平衡性能 |\n| mixtral | 47B | 复杂分析（需要更多内存） |\n\n**拉取模型：**\n```bash\nollama pull llama3.2\n```\n\n## 使用示例\n\n### 基本查询\n\n```\n数据库里有哪些表？\n\n显示 users 表的结构\n\n这周有多少用户注册？\n\n找出销量前 10 的产品\n```\n\n### SQL 生成\n\n```\n编写一个查询，找出 30 天内没有下单的用户\n\n生成按类别计算月收入的 SQL\n\n创建一个查找重复邮箱地址的查询\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息 |\n| `get_table_info` | 获取详细的表信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n### 安全性\n\n1. 使用只读数据库用户\n2. 保护好凭据安全\n3. 本地运行一切以保护隐私\n4. 除非必要，否则禁用写入模式\n\n### 性能\n\n1. 简单查询使用较小的模型\n2. 复杂分析使用较大的模型\n3. 添加 LIMIT 防止大结果集\n4. 缓存 Schema 信息\n\n## 故障排除\n\n### Ollama 无响应\n\n**症状：** Ollama 没有响应\n\n**解决方案：**\n1. 确保 Ollama 正在运行：`ollama serve`\n2. 检查模型已下载：`ollama list`\n3. 验证系统有足够的内存\n\n### MCP 服务器未找到\n\n**症状：** 工具不可用\n\n**解决方案：**\n1. 验证 MCP 配置是否正确\n2. 确保 Node.js 20+ 已安装\n3. 检查 MCP 客户端是否支持工具\n\n### 响应缓慢\n\n**症状：** 查询耗时过长\n\n**解决方案：**\n1. 使用较小的模型\n2. 确保启用了 GPU 加速\n3. 减少上下文长度\n4. 使用更简单的查询\n\n## 资源\n\n- [Ollama 文档](https://ollama.ai/docs)\n- [Ollama GitHub](https://github.com/ollama/ollama)\n- [Oterm GitHub](https://github.com/ggozad/oterm)\n- [MCPHost GitHub](https://github.com/mark3labs/mcphost)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Ollama Discord: https://discord.gg/ollama\n"
  },
  {
    "path": "docs/integrations/OPENAI-AGENTS-SDK.md",
    "content": "# OpenAI Agents SDK Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with OpenAI Agents SDK.\n\n## Overview\n\n[OpenAI Agents SDK](https://platform.openai.com/) is OpenAI's agent framework. It supports MCP via SSE/Streamable HTTP, allowing you to use database tools in your agents.\n\n## Prerequisites\n\n- OpenAI API key\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Configuration\n\n### Step 1: Deploy HTTP API Server\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=openai-agent-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Configure Agent\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI()\n\n# Configure MCP server as a tool\ntools = [\n    {\n        \"type\": \"mcp\",\n        \"mcp\": {\n            \"url\": \"https://your-server.com/mcp\",\n            \"headers\": {\n                \"X-DB-Type\": \"mysql\",\n                \"X-DB-Host\": \"localhost\",\n                \"X-DB-Port\": \"3306\",\n                \"X-DB-User\": \"root\",\n                \"X-DB-Password\": \"password\",\n                \"X-DB-Database\": \"mydb\"\n            }\n        }\n    }\n]\n\nresponse = client.chat.completions.create(\n    model=\"gpt-4\",\n    messages=[{\"role\": \"user\", \"content\": \"What tables are in the database?\"}],\n    tools=tools\n)\n```\n\n## Resources\n\n- [OpenAI Platform](https://platform.openai.com/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/OPENAI-AGENTS-SDK.zh-CN.md",
    "content": "# OpenAI Agents SDK 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 OpenAI Agents SDK 集成。\n\n## 概述\n\n[OpenAI Agents SDK](https://platform.openai.com/) 是 OpenAI 的代理框架。它通过 SSE/Streamable HTTP 支持 MCP，允许您在代理中使用数据库工具。\n\n## 前置要求\n\n- OpenAI API 密钥\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 配置\n\n### 步骤 1：部署 HTTP API 服务器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=openai-agent-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：配置代理\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI()\n\n# 将 MCP 服务器配置为工具\ntools = [\n    {\n        \"type\": \"mcp\",\n        \"mcp\": {\n            \"url\": \"https://your-server.com/mcp\",\n            \"headers\": {\n                \"X-DB-Type\": \"mysql\",\n                \"X-DB-Host\": \"localhost\",\n                \"X-DB-Port\": \"3306\",\n                \"X-DB-User\": \"root\",\n                \"X-DB-Password\": \"password\",\n                \"X-DB-Database\": \"mydb\"\n            }\n        }\n    }\n]\n\nresponse = client.chat.completions.create(\n    model=\"gpt-4\",\n    messages=[{\"role\": \"user\", \"content\": \"数据库里有哪些表？\"}],\n    tools=tools\n)\n```\n\n## 资源\n\n- [OpenAI Platform](https://platform.openai.com/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/OTERM.md",
    "content": "# Oterm Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Oterm.\n\n## Overview\n\n[Oterm](https://github.com/ggozad/oterm) is a terminal-based Ollama client with MCP support. It allows you to query databases while chatting with local LLMs.\n\n## Prerequisites\n\n- Oterm installed (`pip install oterm`)\n- Ollama installed and running\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nCreate `~/.config/oterm/config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\n```bash\noterm\n> What tables are in the database?\n> Show me the schema of the users table\n```\n\n## Resources\n\n- [Oterm GitHub](https://github.com/ggozad/oterm)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/OTERM.zh-CN.md",
    "content": "# Oterm 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Oterm 集成。\n\n## 概述\n\n[Oterm](https://github.com/ggozad/oterm) 是一个支持 MCP 的终端 Ollama 客户端。它允许您在与本地 LLM 聊天时查询数据库。\n\n## 前置要求\n\n- 已安装 Oterm（`pip install oterm`）\n- 已安装并运行 Ollama\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n创建 `~/.config/oterm/config.json`：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n```bash\noterm\n> 数据库里有哪些表？\n> 显示 users 表的结构\n```\n\n## 资源\n\n- [Oterm GitHub](https://github.com/ggozad/oterm)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/POSTMAN.md",
    "content": "# Postman Integration Guide\n\nThis guide shows how to test Universal Database MCP Server REST API with Postman.\n\n## Overview\n\n[Postman](https://postman.com/) is a popular API testing platform. You can use it to test the REST API endpoints of Universal Database MCP Server.\n\n## Prerequisites\n\n- Postman installed ([Download here](https://postman.com/downloads/))\n- Universal Database MCP Server deployed in HTTP mode\n- Database instance\n\n## Setup\n\n### Step 1: Deploy HTTP API Server\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=postman-test-key \\\n  universal-db-mcp:latest\n```\n\n### Step 2: Create Postman Collection\n\n1. Open Postman\n2. Create a new Collection: \"Universal DB MCP\"\n3. Add environment variable: `API_KEY` = `postman-test-key`\n\n### Step 3: Configure Authentication\n\nIn Collection settings, add:\n- Header: `X-API-Key`\n- Value: `{{API_KEY}}`\n\n## API Endpoints\n\n### Connect to Database\n\n**POST** `/api/connect`\n\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"your_password\",\n  \"database\": \"your_database\"\n}\n```\n\n### Execute Query\n\n**POST** `/api/query`\n\n```json\n{\n  \"sessionId\": \"{{sessionId}}\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n### Get Schema\n\n**GET** `/api/schema?sessionId={{sessionId}}`\n\n### Get Table Info\n\n**GET** `/api/schema/users?sessionId={{sessionId}}`\n\n### Disconnect\n\n**POST** `/api/disconnect`\n\n```json\n{\n  \"sessionId\": \"{{sessionId}}\"\n}\n```\n\n## Testing Workflow\n\n1. **Connect**: Call `/api/connect`, save `sessionId`\n2. **Query**: Use `sessionId` to execute queries\n3. **Explore**: Get schema and table info\n4. **Disconnect**: Close the session\n\n## Resources\n\n- [Postman Documentation](https://learning.postman.com/)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/POSTMAN.zh-CN.md",
    "content": "# Postman 集成指南\n\n本指南展示如何使用 Postman 测试 Universal Database MCP Server REST API。\n\n## 概述\n\n[Postman](https://postman.com/) 是一个流行的 API 测试平台。您可以使用它来测试 Universal Database MCP Server 的 REST API 端点。\n\n## 前置要求\n\n- 已安装 Postman（[下载地址](https://postman.com/downloads/)）\n- 以 HTTP 模式部署的 Universal Database MCP Server\n- 数据库实例\n\n## 设置\n\n### 步骤 1：部署 HTTP API 服务器\n\n```bash\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=postman-test-key \\\n  universal-db-mcp:latest\n```\n\n### 步骤 2：创建 Postman Collection\n\n1. 打开 Postman\n2. 创建新的 Collection：\"Universal DB MCP\"\n3. 添加环境变量：`API_KEY` = `postman-test-key`\n\n### 步骤 3：配置认证\n\n在 Collection 设置中添加：\n- Header: `X-API-Key`\n- Value: `{{API_KEY}}`\n\n## API 端点\n\n### 连接数据库\n\n**POST** `/api/connect`\n\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"your_password\",\n  \"database\": \"your_database\"\n}\n```\n\n### 执行查询\n\n**POST** `/api/query`\n\n```json\n{\n  \"sessionId\": \"{{sessionId}}\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n### 获取结构\n\n**GET** `/api/schema?sessionId={{sessionId}}`\n\n### 获取表信息\n\n**GET** `/api/schema/users?sessionId={{sessionId}}`\n\n### 断开连接\n\n**POST** `/api/disconnect`\n\n```json\n{\n  \"sessionId\": \"{{sessionId}}\"\n}\n```\n\n## 测试工作流\n\n1. **连接**：调用 `/api/connect`，保存 `sessionId`\n2. **查询**：使用 `sessionId` 执行查询\n3. **探索**：获取结构和表信息\n4. **断开**：关闭会话\n\n## 资源\n\n- [Postman 文档](https://learning.postman.com/)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/RAYCAST.md",
    "content": "# Raycast Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Raycast.\n\n## Overview\n\nRaycast is a blazingly fast, totally extendable launcher for macOS. Starting from version 1.98, Raycast supports the Model Context Protocol (MCP), allowing you to connect AI assistants to external tools and data sources. By integrating Universal Database MCP Server, you can enable Raycast's AI to directly query and analyze your database data, making it easier to explore data, generate reports, and get insights without leaving your launcher.\n\n**Key Benefits:**\n\n- Query databases directly from Raycast's AI chat\n- Get AI assistance for SQL query writing\n- Explore database schema quickly\n- Generate data insights on the fly\n\n## Prerequisites\n\n- [Raycast](https://raycast.com/) installed (version 1.98 or later required)\n- Raycast Pro subscription (required for AI features)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nRaycast uses MCP stdio mode for tool integration. Configuration is done through the Raycast settings interface or by importing a JSON configuration file.\n\n### Step 1: Open Raycast Settings\n\nOpen Raycast Settings using the keyboard shortcut `Cmd + ,` or by searching for \"Settings\" in Raycast.\n\n### Step 2: Navigate to MCP Servers\n\nNavigate to **Extensions > AI > MCP Servers** in the settings sidebar.\n\n### Step 3: Add MCP Server Configuration\n\nYou can either:\n- Click **\"Import MCP Servers\"** to import a JSON configuration file\n- Click **\"Add Server\"** to manually add a server configuration\n\n#### Import Configuration\n\nCreate a JSON file with the following structure and import it:\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### Manual Configuration\n\nIf adding manually, enter the following details:\n- **Name**: `universal-db-mcp`\n- **Command**: `npx`\n- **Arguments**: `universal-db-mcp --type mysql --host localhost --port 3306 --user root --password your_password --database your_database`\n\n### Step 4: Enable the Server\n\nAfter adding the configuration, ensure the MCP server is enabled in the list.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Raycast:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Raycast's AI chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Generate Reports\n\nAsk for quick data summaries:\n\n```\nGive me a summary of sales by month for the last year\n```\n\nThe AI will query your database and provide insights.\n\n### Example 5: Data Analysis\n\nGet AI-powered analysis:\n\n```\nAnalyze the user signup trends and identify any patterns\n```\n\nThe AI will examine your data and provide analytical insights.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never share** configuration files with real credentials\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Appearing\n\n**Symptoms**: The database tools are not available in Raycast AI\n\n**Solutions**:\n1. Verify Raycast version is 1.98 or later\n2. Ensure you have a Raycast Pro subscription\n3. Check that the MCP server is enabled in Settings > Extensions > AI > MCP Servers\n4. Restart Raycast after making configuration changes\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. Restart Raycast after installing Node.js\n\n### Issue: Server Timeout\n\n**Symptoms**: MCP server takes too long to respond\n\n**Solutions**:\n1. Check database server performance\n2. Optimize slow queries\n3. Ensure stable network connection to the database\n4. Consider using a local database for testing\n\n## Resources\n\n- [Raycast Official Website](https://raycast.com/)\n- [Raycast Documentation](https://developers.raycast.com/)\n- [Raycast MCP Documentation](https://developers.raycast.com/ai/mcp)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Raycast Community: https://raycast.com/community\n"
  },
  {
    "path": "docs/integrations/RAYCAST.zh-CN.md",
    "content": "# Raycast 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Raycast 集成。\n\n## 概述\n\nRaycast 是一款极速、可扩展的 macOS 启动器。从 1.98 版本开始，Raycast 支持模型上下文协议（MCP），允许您将 AI 助手连接到外部工具和数据源。通过集成 Universal Database MCP Server，您可以让 Raycast 的 AI 直接查询和分析数据库数据，从而更轻松地探索数据、生成报告和获取洞察，而无需离开启动器。\n\n**主要优势：**\n- 直接从 Raycast 的 AI 聊天中查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 快速探索数据库结构\n- 即时生成数据洞察\n\n## 前置要求\n\n- 已安装 [Raycast](https://raycast.com/)（需要 1.98 或更高版本）\n- Raycast Pro 订阅（AI 功能需要）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nRaycast 使用 MCP stdio 模式进行工具集成。配置通过 Raycast 设置界面或导入 JSON 配置文件完成。\n\n### 步骤 1: 打开 Raycast 设置\n\n使用快捷键 `Cmd + ,` 打开 Raycast 设置，或在 Raycast 中搜索\"Settings\"。\n\n### 步骤 2: 导航到 MCP 服务器\n\n在设置侧边栏中导航到 **Extensions > AI > MCP Servers**。\n\n### 步骤 3: 添加 MCP 服务器配置\n\n您可以选择：\n- 点击 **\"Import MCP Servers\"** 导入 JSON 配置文件\n- 点击 **\"Add Server\"** 手动添加服务器配置\n\n#### 导入配置\n\n创建一个包含以下结构的 JSON 文件并导入：\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### 手动配置\n\n如果手动添加，请输入以下详细信息：\n- **名称**: `universal-db-mcp`\n- **命令**: `npx`\n- **参数**: `universal-db-mcp --type mysql --host localhost --port 3306 --user root --password your_password --database your_database`\n\n### 步骤 4: 启用服务器\n\n添加配置后，确保在列表中启用 MCP 服务器。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Raycast 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Raycast 的 AI 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 生成报告\n\n请求快速数据摘要：\n\n```\n给我过去一年按月份的销售汇总\n```\n\nAI 将查询您的数据库并提供洞察。\n\n### 示例 5: 数据分析\n\n获取 AI 驱动的分析：\n\n```\n分析用户注册趋势并识别任何模式\n```\n\nAI 将检查您的数据并提供分析洞察。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿分享**包含真实凭据的配置文件\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器未显示\n\n**症状**：数据库工具在 Raycast AI 中不可用\n\n**解决方案**：\n1. 验证 Raycast 版本是否为 1.98 或更高\n2. 确保您有 Raycast Pro 订阅\n3. 检查 MCP 服务器是否在 Settings > Extensions > AI > MCP Servers 中启用\n4. 更改配置后重启 Raycast\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 安装 Node.js 后可能需要重启 Raycast\n\n### 问题：服务器超时\n\n**症状**：MCP 服务器响应时间过长\n\n**解决方案**：\n1. 检查数据库服务器性能\n2. 优化慢查询\n3. 确保到数据库的网络连接稳定\n4. 考虑使用本地数据库进行测试\n\n## 资源\n\n- [Raycast 官方网站](https://raycast.com/)\n- [Raycast 文档](https://developers.raycast.com/)\n- [Raycast MCP 文档](https://developers.raycast.com/ai/mcp)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Raycast 社区: https://raycast.com/community\n"
  },
  {
    "path": "docs/integrations/REPLIT.md",
    "content": "# Replit Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Replit.\n\n## Overview\n\n[Replit](https://replit.com/) is an online IDE with AI agent capabilities. It supports MCP, allowing you to query databases directly from your Replit workspace.\n\n## Prerequisites\n\n- Replit account\n- Database instance accessible from Replit\n\n## Configuration\n\n### Step 1: Create Replit Project\n\n1. Create a new Repl\n2. Add `.replit` configuration for MCP\n\n### Step 2: Configure MCP Server\n\nAdd to your project's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"your-db-host\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Use Replit AI Agent\n\nAsk the AI agent about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\nHow many orders were placed today?\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n1. Use environment secrets for credentials\n2. Use read-only database users\n3. Ensure database is accessible from Replit\n\n## Resources\n\n- [Replit Documentation](https://docs.replit.com/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/REPLIT.zh-CN.md",
    "content": "# Replit 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Replit 集成。\n\n## 概述\n\n[Replit](https://replit.com/) 是一个具有 AI 代理功能的在线 IDE。它支持 MCP，允许您直接从 Replit 工作区查询数据库。\n\n## 前置要求\n\n- Replit 账号\n- 可从 Replit 访问的数据库实例\n\n## 配置\n\n### 步骤 1：创建 Replit 项目\n\n1. 创建新的 Repl\n2. 添加 MCP 的 `.replit` 配置\n\n### 步骤 2：配置 MCP 服务器\n\n添加到项目的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"your-db-host\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3：使用 Replit AI 代理\n\n向 AI 代理询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n今天有多少订单？\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n1. 使用环境密钥存储凭据\n2. 使用只读数据库用户\n3. 确保数据库可从 Replit 访问\n\n## 资源\n\n- [Replit 文档](https://docs.replit.com/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/ROO-CODE.md",
    "content": "# Roo Code Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Roo Code.\n\n## Overview\n\n[Roo Code](https://github.com/roovet/roo-code) is a fork of Cline, an autonomous coding agent for VS Code. It supports MCP, allowing you to query databases while coding.\n\n## Prerequisites\n\n- VS Code installed\n- Roo Code extension installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\n### Step 1: Open Roo Code Settings\n\n1. Open VS Code\n2. Click on Roo Code icon in sidebar\n3. Open Settings\n\n### Step 2: Configure MCP Server\n\nAdd to MCP Servers configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Roo Code about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\nGenerate a TypeScript interface for the orders table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Roo Code GitHub](https://github.com/roovet/roo-code)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/ROO-CODE.zh-CN.md",
    "content": "# Roo Code 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Roo Code 集成。\n\n## 概述\n\n[Roo Code](https://github.com/roovet/roo-code) 是 Cline 的一个分支，是 VS Code 的自主编码代理。它支持 MCP，允许您在编码时查询数据库。\n\n## 前置要求\n\n- 已安装 VS Code\n- 已安装 Roo Code 扩展\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n### 步骤 1：打开 Roo Code 设置\n\n1. 打开 VS Code\n2. 点击侧边栏中的 Roo Code 图标\n3. 打开设置\n\n### 步骤 2：配置 MCP 服务器\n\n添加到 MCP Servers 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Roo Code 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n为 orders 表生成 TypeScript 接口\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Roo Code GitHub](https://github.com/roovet/roo-code)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/SLACK.md",
    "content": "# Slack Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Slack through an MCP Bot.\n\n## Overview\n\nSlack is a team collaboration platform. By integrating Universal Database MCP Server via an MCP Bot, you can enable your team to query and analyze database data directly from Slack channels using REST API.\n\n## Prerequisites\n\n- Universal Database MCP Server deployed with HTTP API mode\n- Slack workspace with admin permissions\n- Database instance (MySQL, PostgreSQL, etc.)\n\n## Setup Steps\n\n### Step 1: Deploy HTTP API Server\n\nDeploy Universal Database MCP Server in HTTP mode:\n\n```bash\n# Using npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=slack-bot-secret-key\nexport CORS_ORIGINS=*\nnpx universal-db-mcp\n\n# Or using Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=slack-bot-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n> **Note**: Ensure your server is accessible from the internet or your Slack Bot's hosting environment.\n\n### Step 2: Create Slack App\n\n1. Go to [Slack API](https://api.slack.com/apps)\n2. Click \"Create New App\"\n3. Select \"From scratch\"\n4. Enter App Name (e.g., \"Database MCP Bot\")\n5. Select your workspace\n6. Click \"Create App\"\n\n### Step 3: Configure Bot Permissions\n\n1. In the app settings, go to \"OAuth & Permissions\"\n2. Under \"Scopes\" > \"Bot Token Scopes\", add:\n   - `app_mentions:read` - Read mentions of the bot\n   - `chat:write` - Send messages\n   - `commands` - Add slash commands\n   - `im:history` - Read direct messages\n   - `im:read` - View direct messages\n   - `im:write` - Send direct messages\n\n3. Click \"Install to Workspace\"\n4. Copy the \"Bot User OAuth Token\" (starts with `xoxb-`)\n\n### Step 4: Configure Slash Commands\n\n1. Go to \"Slash Commands\" in app settings\n2. Click \"Create New Command\"\n3. Configure commands:\n\n#### Command 1: /db-connect\n\n**Command**: `/db-connect`\n**Request URL**: `https://your-bot-server.com/slack/connect`\n**Short Description**: Connect to a database\n**Usage Hint**: `[type] [host] [port] [user] [password] [database]`\n\n#### Command 2: /db-query\n\n**Command**: `/db-query`\n**Request URL**: `https://your-bot-server.com/slack/query`\n**Short Description**: Execute SQL query\n**Usage Hint**: `[SQL query]`\n\n#### Command 3: /db-schema\n\n**Command**: `/db-schema`\n**Request URL**: `https://your-bot-server.com/slack/schema`\n**Short Description**: Get database schema\n**Usage Hint**: `[table_name (optional)]`\n\n#### Command 4: /db-disconnect\n\n**Command**: `/db-disconnect`\n**Request URL**: `https://your-bot-server.com/slack/disconnect`\n**Short Description**: Disconnect from database\n\n### Step 5: Create Slack Bot Server\n\nCreate a bot server that handles Slack commands and calls the MCP REST API.\n\n**Example Node.js Bot Server**:\n\n```javascript\nconst express = require('express');\nconst axios = require('axios');\nconst app = express();\n\napp.use(express.urlencoded({ extended: true }));\napp.use(express.json());\n\nconst MCP_API_URL = 'http://localhost:3000';\nconst MCP_API_KEY = 'slack-bot-secret-key';\n\n// Store sessions per Slack user\nconst userSessions = new Map();\n\n// Connect to database\napp.post('/slack/connect', async (req, res) => {\n  const { user_id, text } = req.body;\n  const [type, host, port, user, password, database] = text.split(' ');\n\n  try {\n    const response = await axios.post(`${MCP_API_URL}/api/connect`, {\n      type,\n      host,\n      port: parseInt(port),\n      user,\n      password,\n      database\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      userSessions.set(user_id, response.data.data.sessionId);\n      res.json({\n        response_type: 'ephemeral',\n        text: `Connected to ${type} database successfully!`\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `Connection failed: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `Error: ${error.message}`\n    });\n  }\n});\n\n// Execute query\napp.post('/slack/query', async (req, res) => {\n  const { user_id, text } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: 'Not connected. Use /db-connect first.'\n    });\n  }\n\n  try {\n    const response = await axios.post(`${MCP_API_URL}/api/query`, {\n      sessionId,\n      query: text\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      const rows = response.data.data.rows;\n      const formattedResult = formatQueryResult(rows);\n      res.json({\n        response_type: 'in_channel',\n        text: `Query executed successfully!\\n\\`\\`\\`${formattedResult}\\`\\`\\``\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `Query failed: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `Error: ${error.message}`\n    });\n  }\n});\n\n// Get schema\napp.post('/slack/schema', async (req, res) => {\n  const { user_id, text } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: 'Not connected. Use /db-connect first.'\n    });\n  }\n\n  try {\n    const url = text\n      ? `${MCP_API_URL}/api/schema/${text}?sessionId=${sessionId}`\n      : `${MCP_API_URL}/api/schema?sessionId=${sessionId}`;\n\n    const response = await axios.get(url, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      const schema = JSON.stringify(response.data.data, null, 2);\n      res.json({\n        response_type: 'ephemeral',\n        text: `Database Schema:\\n\\`\\`\\`${schema}\\`\\`\\``\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `Failed to get schema: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `Error: ${error.message}`\n    });\n  }\n});\n\n// Disconnect\napp.post('/slack/disconnect', async (req, res) => {\n  const { user_id } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: 'Not connected.'\n    });\n  }\n\n  try {\n    await axios.post(`${MCP_API_URL}/api/disconnect`, {\n      sessionId\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    userSessions.delete(user_id);\n    res.json({\n      response_type: 'ephemeral',\n      text: 'Disconnected successfully.'\n    });\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `Error: ${error.message}`\n    });\n  }\n});\n\nfunction formatQueryResult(rows) {\n  if (!rows || rows.length === 0) return 'No results';\n\n  const headers = Object.keys(rows[0]);\n  const headerRow = headers.join(' | ');\n  const separator = headers.map(() => '---').join(' | ');\n  const dataRows = rows.slice(0, 10).map(row =>\n    headers.map(h => String(row[h] ?? '')).join(' | ')\n  ).join('\\n');\n\n  let result = `${headerRow}\\n${separator}\\n${dataRows}`;\n  if (rows.length > 10) {\n    result += `\\n... and ${rows.length - 10} more rows`;\n  }\n  return result;\n}\n\napp.listen(3001, () => {\n  console.log('Slack Bot Server running on port 3001');\n});\n```\n\n## REST API Endpoints\n\nThe MCP Server provides the following REST API endpoints for Slack Bot integration:\n\n### POST /api/connect\n\nConnect to a database.\n\n**Request**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"password\",\n  \"database\": \"mydb\"\n}\n```\n\n**Response**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"abc123\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  }\n}\n```\n\n### POST /api/query\n\nExecute a SQL query.\n\n**Request**:\n```json\n{\n  \"sessionId\": \"abc123\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n**Response**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [...],\n    \"rowCount\": 10,\n    \"executionTime\": 15\n  }\n}\n```\n\n### GET /api/schema\n\nGet database schema information.\n\n**Request**:\n```\nGET /api/schema?sessionId=abc123\nGET /api/schema/users?sessionId=abc123\n```\n\n**Response**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\"],\n    \"schema\": {...}\n  }\n}\n```\n\n### POST /api/disconnect\n\nDisconnect from database.\n\n**Request**:\n```json\n{\n  \"sessionId\": \"abc123\"\n}\n```\n\n**Response**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"disconnected\": true\n  }\n}\n```\n\n## Usage Examples\n\n### Example 1: Basic Query Workflow\n\n```\nUser: /db-connect mysql db.example.com 3306 admin password mydb\nBot: Connected to mysql database successfully!\n\nUser: /db-schema\nBot: Database Schema:\n     tables: users, orders, products\n\nUser: /db-query SELECT * FROM users LIMIT 5\nBot: Query executed successfully!\n     id | name  | email\n     ---|-------|-------------------\n     1  | Alice | alice@example.com\n     2  | Bob   | bob@example.com\n     ...\n\nUser: /db-disconnect\nBot: Disconnected successfully.\n```\n\n### Example 2: Data Analysis\n\n```\nUser: /db-connect postgres analytics.example.com 5432 analyst pass analytics_db\nBot: Connected to postgres database successfully!\n\nUser: /db-query SELECT COUNT(*) as total_orders, SUM(amount) as revenue FROM orders WHERE created_at >= '2024-01-01'\nBot: Query executed successfully!\n     total_orders | revenue\n     -------------|----------\n     1234         | 56789.00\n\nUser: /db-query SELECT product_name, COUNT(*) as sales FROM order_items GROUP BY product_name ORDER BY sales DESC LIMIT 5\nBot: Query executed successfully!\n     product_name | sales\n     -------------|------\n     Widget A     | 500\n     Widget B     | 350\n     ...\n```\n\n### Example 3: Schema Exploration\n\n```\nUser: /db-schema users\nBot: Database Schema:\n     {\n       \"table\": \"users\",\n       \"columns\": [\n         {\"name\": \"id\", \"type\": \"int\", \"nullable\": false},\n         {\"name\": \"name\", \"type\": \"varchar(255)\", \"nullable\": false},\n         {\"name\": \"email\", \"type\": \"varchar(255)\", \"nullable\": false},\n         {\"name\": \"created_at\", \"type\": \"timestamp\", \"nullable\": true}\n       ],\n       \"primaryKey\": \"id\",\n       \"indexes\": [\"idx_email\"]\n     }\n```\n\n## Advanced Features\n\n### Interactive Messages with Block Kit\n\nEnhance bot responses with Slack Block Kit:\n\n```javascript\napp.post('/slack/query', async (req, res) => {\n  // ... query execution ...\n\n  res.json({\n    response_type: 'in_channel',\n    blocks: [\n      {\n        type: 'header',\n        text: {\n          type: 'plain_text',\n          text: 'Query Results'\n        }\n      },\n      {\n        type: 'section',\n        text: {\n          type: 'mrkdwn',\n          text: `*Query:* \\`${text}\\``\n        }\n      },\n      {\n        type: 'section',\n        text: {\n          type: 'mrkdwn',\n          text: `\\`\\`\\`${formattedResult}\\`\\`\\``\n        }\n      },\n      {\n        type: 'context',\n        elements: [\n          {\n            type: 'mrkdwn',\n            text: `Execution time: ${executionTime}ms | Rows: ${rowCount}`\n          }\n        ]\n      }\n    ]\n  });\n});\n```\n\n### Modal Dialogs for Complex Queries\n\nUse Slack modals for complex query input:\n\n```javascript\napp.post('/slack/query-modal', async (req, res) => {\n  const { trigger_id } = req.body;\n\n  await axios.post('https://slack.com/api/views.open', {\n    trigger_id,\n    view: {\n      type: 'modal',\n      callback_id: 'query_modal',\n      title: {\n        type: 'plain_text',\n        text: 'Execute Query'\n      },\n      blocks: [\n        {\n          type: 'input',\n          block_id: 'query_block',\n          element: {\n            type: 'plain_text_input',\n            action_id: 'query_input',\n            multiline: true,\n            placeholder: {\n              type: 'plain_text',\n              text: 'Enter your SQL query...'\n            }\n          },\n          label: {\n            type: 'plain_text',\n            text: 'SQL Query'\n          }\n        }\n      ],\n      submit: {\n        type: 'plain_text',\n        text: 'Execute'\n      }\n    }\n  }, {\n    headers: {\n      'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,\n      'Content-Type': 'application/json'\n    }\n  });\n\n  res.status(200).send();\n});\n```\n\n### Scheduled Reports\n\nSend scheduled database reports to Slack channels:\n\n```javascript\nconst cron = require('node-cron');\n\n// Daily report at 9 AM\ncron.schedule('0 9 * * *', async () => {\n  const sessionId = await connectToDatabase();\n\n  const result = await axios.post(`${MCP_API_URL}/api/query`, {\n    sessionId,\n    query: `\n      SELECT\n        DATE(created_at) as date,\n        COUNT(*) as orders,\n        SUM(amount) as revenue\n      FROM orders\n      WHERE created_at >= CURDATE() - INTERVAL 7 DAY\n      GROUP BY DATE(created_at)\n      ORDER BY date DESC\n    `\n  }, {\n    headers: { 'X-API-Key': MCP_API_KEY }\n  });\n\n  await axios.post('https://slack.com/api/chat.postMessage', {\n    channel: '#daily-reports',\n    text: 'Daily Sales Report',\n    blocks: formatReportBlocks(result.data.data.rows)\n  }, {\n    headers: {\n      'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,\n      'Content-Type': 'application/json'\n    }\n  });\n\n  await disconnectFromDatabase(sessionId);\n});\n```\n\n### Alert Notifications\n\nSend database alerts to Slack:\n\n```javascript\nasync function checkDatabaseAlerts() {\n  const sessionId = await connectToDatabase();\n\n  // Check for anomalies\n  const result = await axios.post(`${MCP_API_URL}/api/query`, {\n    sessionId,\n    query: `\n      SELECT COUNT(*) as error_count\n      FROM logs\n      WHERE level = 'ERROR'\n      AND created_at >= NOW() - INTERVAL 1 HOUR\n    `\n  }, {\n    headers: { 'X-API-Key': MCP_API_KEY }\n  });\n\n  const errorCount = result.data.data.rows[0].error_count;\n\n  if (errorCount > 100) {\n    await axios.post('https://slack.com/api/chat.postMessage', {\n      channel: '#alerts',\n      text: `:warning: High error rate detected: ${errorCount} errors in the last hour!`\n    }, {\n      headers: {\n        'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,\n        'Content-Type': 'application/json'\n      }\n    });\n  }\n\n  await disconnectFromDatabase(sessionId);\n}\n\n// Check every 5 minutes\nsetInterval(checkDatabaseAlerts, 5 * 60 * 1000);\n```\n\n## Best Practices\n\n### 1. Security\n\n- Store database credentials securely (use environment variables or secrets manager)\n- Use read-only database users for query operations\n- Validate and sanitize SQL queries before execution\n- Implement query whitelisting for sensitive environments\n- Use ephemeral messages for sensitive data\n\n### 2. Performance\n\n- Add LIMIT to queries to prevent large result sets\n- Implement query timeout\n- Cache frequently accessed schema information\n- Use connection pooling for high-traffic bots\n\n### 3. User Experience\n\n- Provide clear error messages\n- Format query results in readable tables\n- Show execution time and row count\n- Implement pagination for large results\n- Use Slack Block Kit for rich formatting\n\n### 4. Error Handling\n\n- Handle connection timeouts gracefully\n- Implement retry logic for transient failures\n- Log errors for debugging\n- Notify users of failures with actionable messages\n\n## Troubleshooting\n\n### Issue: Connection Timeout\n\n**Symptoms**: Bot fails to connect to database\n\n**Solutions**:\n1. Verify database host is accessible from bot server\n2. Check firewall rules\n3. Increase connection timeout\n4. Verify database credentials\n\n### Issue: Query Timeout\n\n**Symptoms**: Queries take too long and timeout\n\n**Solutions**:\n1. Add LIMIT to queries\n2. Optimize SQL queries\n3. Add indexes to frequently queried columns\n4. Increase query timeout setting\n\n### Issue: Large Result Sets\n\n**Symptoms**: Bot crashes or Slack message too long\n\n**Solutions**:\n1. Limit results to 10-20 rows\n2. Implement pagination\n3. Use file upload for large exports\n4. Summarize data instead of showing all rows\n\n### Issue: Session Expired\n\n**Symptoms**: Queries fail with session not found\n\n**Solutions**:\n1. Implement automatic reconnection\n2. Increase session timeout on MCP server\n3. Store session state persistently\n4. Prompt user to reconnect\n\n## Resources\n\n- [Slack API Documentation](https://api.slack.com/)\n- [Slack Block Kit Builder](https://app.slack.com/block-kit-builder)\n- [API Reference](../http-api/API_REFERENCE.md)\n- [Deployment Guide](../http-api/DEPLOYMENT.md)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Slack Community: https://slack.com/community\n"
  },
  {
    "path": "docs/integrations/SLACK.zh-CN.md",
    "content": "# Slack 集成指南\n\n本指南展示如何通过 MCP Bot 将 Universal Database MCP Server 与 Slack 集成。\n\n## 概述\n\nSlack 是一个团队协作平台。通过 MCP Bot 集成 Universal Database MCP Server，您可以让团队成员直接在 Slack 频道中使用 REST API 查询和分析数据库数据。\n\n## 前置要求\n\n- 部署了 HTTP API 模式的 Universal Database MCP Server\n- 具有管理员权限的 Slack 工作区\n- 数据库实例（MySQL、PostgreSQL 等）\n\n## 设置步骤\n\n### 步骤 1: 部署 HTTP API 服务器\n\n以 HTTP 模式部署 Universal Database MCP Server：\n\n```bash\n# 使用 npm\nexport MODE=http\nexport HTTP_PORT=3000\nexport API_KEYS=slack-bot-secret-key\nexport CORS_ORIGINS=*\nnpx universal-db-mcp\n\n# 或使用 Docker\ndocker run -d \\\n  --name universal-db-mcp \\\n  -p 3000:3000 \\\n  -e MODE=http \\\n  -e HTTP_PORT=3000 \\\n  -e API_KEYS=slack-bot-secret-key \\\n  -e CORS_ORIGINS=* \\\n  universal-db-mcp:latest\n```\n\n> **注意**：确保您的服务器可从互联网或 Slack Bot 的托管环境访问。\n\n### 步骤 2: 创建 Slack App\n\n1. 访问 [Slack API](https://api.slack.com/apps)\n2. 点击\"Create New App\"\n3. 选择\"From scratch\"\n4. 输入 App 名称（例如：\"Database MCP Bot\"）\n5. 选择您的工作区\n6. 点击\"Create App\"\n\n### 步骤 3: 配置 Bot 权限\n\n1. 在应用设置中，转到\"OAuth & Permissions\"\n2. 在\"Scopes\" > \"Bot Token Scopes\"下，添加：\n   - `app_mentions:read` - 读取 bot 的提及\n   - `chat:write` - 发送消息\n   - `commands` - 添加斜杠命令\n   - `im:history` - 读取私信历史\n   - `im:read` - 查看私信\n   - `im:write` - 发送私信\n\n3. 点击\"Install to Workspace\"\n4. 复制\"Bot User OAuth Token\"（以 `xoxb-` 开头）\n\n### 步骤 4: 配置斜杠命令\n\n1. 在应用设置中转到\"Slash Commands\"\n2. 点击\"Create New Command\"\n3. 配置命令：\n\n#### 命令 1: /db-connect\n\n**命令**: `/db-connect`\n**请求 URL**: `https://your-bot-server.com/slack/connect`\n**简短描述**: 连接到数据库\n**使用提示**: `[type] [host] [port] [user] [password] [database]`\n\n#### 命令 2: /db-query\n\n**命令**: `/db-query`\n**请求 URL**: `https://your-bot-server.com/slack/query`\n**简短描述**: 执行 SQL 查询\n**使用提示**: `[SQL 查询]`\n\n#### 命令 3: /db-schema\n\n**命令**: `/db-schema`\n**请求 URL**: `https://your-bot-server.com/slack/schema`\n**简短描述**: 获取数据库结构\n**使用提示**: `[表名（可选）]`\n\n#### 命令 4: /db-disconnect\n\n**命令**: `/db-disconnect`\n**请求 URL**: `https://your-bot-server.com/slack/disconnect`\n**简短描述**: 断开数据库连接\n\n### 步骤 5: 创建 Slack Bot 服务器\n\n创建一个处理 Slack 命令并调用 MCP REST API 的 bot 服务器。\n\n**Node.js Bot 服务器示例**：\n\n```javascript\nconst express = require('express');\nconst axios = require('axios');\nconst app = express();\n\napp.use(express.urlencoded({ extended: true }));\napp.use(express.json());\n\nconst MCP_API_URL = 'http://localhost:3000';\nconst MCP_API_KEY = 'slack-bot-secret-key';\n\n// 为每个 Slack 用户存储会话\nconst userSessions = new Map();\n\n// 连接数据库\napp.post('/slack/connect', async (req, res) => {\n  const { user_id, text } = req.body;\n  const [type, host, port, user, password, database] = text.split(' ');\n\n  try {\n    const response = await axios.post(`${MCP_API_URL}/api/connect`, {\n      type,\n      host,\n      port: parseInt(port),\n      user,\n      password,\n      database\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      userSessions.set(user_id, response.data.data.sessionId);\n      res.json({\n        response_type: 'ephemeral',\n        text: `成功连接到 ${type} 数据库！`\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `连接失败: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `错误: ${error.message}`\n    });\n  }\n});\n\n// 执行查询\napp.post('/slack/query', async (req, res) => {\n  const { user_id, text } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: '未连接。请先使用 /db-connect。'\n    });\n  }\n\n  try {\n    const response = await axios.post(`${MCP_API_URL}/api/query`, {\n      sessionId,\n      query: text\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      const rows = response.data.data.rows;\n      const formattedResult = formatQueryResult(rows);\n      res.json({\n        response_type: 'in_channel',\n        text: `查询执行成功！\\n\\`\\`\\`${formattedResult}\\`\\`\\``\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `查询失败: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `错误: ${error.message}`\n    });\n  }\n});\n\n// 获取结构\napp.post('/slack/schema', async (req, res) => {\n  const { user_id, text } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: '未连接。请先使用 /db-connect。'\n    });\n  }\n\n  try {\n    const url = text\n      ? `${MCP_API_URL}/api/schema/${text}?sessionId=${sessionId}`\n      : `${MCP_API_URL}/api/schema?sessionId=${sessionId}`;\n\n    const response = await axios.get(url, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    if (response.data.success) {\n      const schema = JSON.stringify(response.data.data, null, 2);\n      res.json({\n        response_type: 'ephemeral',\n        text: `数据库结构:\\n\\`\\`\\`${schema}\\`\\`\\``\n      });\n    } else {\n      res.json({\n        response_type: 'ephemeral',\n        text: `获取结构失败: ${response.data.error.message}`\n      });\n    }\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `错误: ${error.message}`\n    });\n  }\n});\n\n// 断开连接\napp.post('/slack/disconnect', async (req, res) => {\n  const { user_id } = req.body;\n  const sessionId = userSessions.get(user_id);\n\n  if (!sessionId) {\n    return res.json({\n      response_type: 'ephemeral',\n      text: '未连接。'\n    });\n  }\n\n  try {\n    await axios.post(`${MCP_API_URL}/api/disconnect`, {\n      sessionId\n    }, {\n      headers: { 'X-API-Key': MCP_API_KEY }\n    });\n\n    userSessions.delete(user_id);\n    res.json({\n      response_type: 'ephemeral',\n      text: '已成功断开连接。'\n    });\n  } catch (error) {\n    res.json({\n      response_type: 'ephemeral',\n      text: `错误: ${error.message}`\n    });\n  }\n});\n\nfunction formatQueryResult(rows) {\n  if (!rows || rows.length === 0) return '无结果';\n\n  const headers = Object.keys(rows[0]);\n  const headerRow = headers.join(' | ');\n  const separator = headers.map(() => '---').join(' | ');\n  const dataRows = rows.slice(0, 10).map(row =>\n    headers.map(h => String(row[h] ?? '')).join(' | ')\n  ).join('\\n');\n\n  let result = `${headerRow}\\n${separator}\\n${dataRows}`;\n  if (rows.length > 10) {\n    result += `\\n... 还有 ${rows.length - 10} 行`;\n  }\n  return result;\n}\n\napp.listen(3001, () => {\n  console.log('Slack Bot 服务器运行在端口 3001');\n});\n```\n\n## REST API 端点\n\nMCP Server 为 Slack Bot 集成提供以下 REST API 端点：\n\n### POST /api/connect\n\n连接到数据库。\n\n**请求**:\n```json\n{\n  \"type\": \"mysql\",\n  \"host\": \"localhost\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"password\": \"password\",\n  \"database\": \"mydb\"\n}\n```\n\n**响应**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"sessionId\": \"abc123\",\n    \"databaseType\": \"mysql\",\n    \"connected\": true\n  }\n}\n```\n\n### POST /api/query\n\n执行 SQL 查询。\n\n**请求**:\n```json\n{\n  \"sessionId\": \"abc123\",\n  \"query\": \"SELECT * FROM users LIMIT 10\"\n}\n```\n\n**响应**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"rows\": [...],\n    \"rowCount\": 10,\n    \"executionTime\": 15\n  }\n}\n```\n\n### GET /api/schema\n\n获取数据库结构信息。\n\n**请求**:\n```\nGET /api/schema?sessionId=abc123\nGET /api/schema/users?sessionId=abc123\n```\n\n**响应**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tables\": [\"users\", \"orders\", \"products\"],\n    \"schema\": {...}\n  }\n}\n```\n\n### POST /api/disconnect\n\n断开数据库连接。\n\n**请求**:\n```json\n{\n  \"sessionId\": \"abc123\"\n}\n```\n\n**响应**:\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"disconnected\": true\n  }\n}\n```\n\n## 使用示例\n\n### 示例 1: 基本查询工作流\n\n```\n用户: /db-connect mysql db.example.com 3306 admin password mydb\nBot: 成功连接到 mysql 数据库！\n\n用户: /db-schema\nBot: 数据库结构:\n     tables: users, orders, products\n\n用户: /db-query SELECT * FROM users LIMIT 5\nBot: 查询执行成功！\n     id | name  | email\n     ---|-------|-------------------\n     1  | 张三  | zhang@example.com\n     2  | 李四  | li@example.com\n     ...\n\n用户: /db-disconnect\nBot: 已成功断开连接。\n```\n\n### 示例 2: 数据分析\n\n```\n用户: /db-connect postgres analytics.example.com 5432 analyst pass analytics_db\nBot: 成功连接到 postgres 数据库！\n\n用户: /db-query SELECT COUNT(*) as total_orders, SUM(amount) as revenue FROM orders WHERE created_at >= '2024-01-01'\nBot: 查询执行成功！\n     total_orders | revenue\n     -------------|----------\n     1234         | 56789.00\n\n用户: /db-query SELECT product_name, COUNT(*) as sales FROM order_items GROUP BY product_name ORDER BY sales DESC LIMIT 5\nBot: 查询执行成功！\n     product_name | sales\n     -------------|------\n     产品 A       | 500\n     产品 B       | 350\n     ...\n```\n\n### 示例 3: 结构探索\n\n```\n用户: /db-schema users\nBot: 数据库结构:\n     {\n       \"table\": \"users\",\n       \"columns\": [\n         {\"name\": \"id\", \"type\": \"int\", \"nullable\": false},\n         {\"name\": \"name\", \"type\": \"varchar(255)\", \"nullable\": false},\n         {\"name\": \"email\", \"type\": \"varchar(255)\", \"nullable\": false},\n         {\"name\": \"created_at\", \"type\": \"timestamp\", \"nullable\": true}\n       ],\n       \"primaryKey\": \"id\",\n       \"indexes\": [\"idx_email\"]\n     }\n```\n\n## 高级功能\n\n### 使用 Block Kit 的交互式消息\n\n使用 Slack Block Kit 增强 bot 响应：\n\n```javascript\napp.post('/slack/query', async (req, res) => {\n  // ... 查询执行 ...\n\n  res.json({\n    response_type: 'in_channel',\n    blocks: [\n      {\n        type: 'header',\n        text: {\n          type: 'plain_text',\n          text: '查询结果'\n        }\n      },\n      {\n        type: 'section',\n        text: {\n          type: 'mrkdwn',\n          text: `*查询:* \\`${text}\\``\n        }\n      },\n      {\n        type: 'section',\n        text: {\n          type: 'mrkdwn',\n          text: `\\`\\`\\`${formattedResult}\\`\\`\\``\n        }\n      },\n      {\n        type: 'context',\n        elements: [\n          {\n            type: 'mrkdwn',\n            text: `执行时间: ${executionTime}ms | 行数: ${rowCount}`\n          }\n        ]\n      }\n    ]\n  });\n});\n```\n\n### 定时报告\n\n向 Slack 频道发送定时数据库报告：\n\n```javascript\nconst cron = require('node-cron');\n\n// 每天早上 9 点的报告\ncron.schedule('0 9 * * *', async () => {\n  const sessionId = await connectToDatabase();\n\n  const result = await axios.post(`${MCP_API_URL}/api/query`, {\n    sessionId,\n    query: `\n      SELECT\n        DATE(created_at) as date,\n        COUNT(*) as orders,\n        SUM(amount) as revenue\n      FROM orders\n      WHERE created_at >= CURDATE() - INTERVAL 7 DAY\n      GROUP BY DATE(created_at)\n      ORDER BY date DESC\n    `\n  }, {\n    headers: { 'X-API-Key': MCP_API_KEY }\n  });\n\n  await axios.post('https://slack.com/api/chat.postMessage', {\n    channel: '#daily-reports',\n    text: '每日销售报告',\n    blocks: formatReportBlocks(result.data.data.rows)\n  }, {\n    headers: {\n      'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,\n      'Content-Type': 'application/json'\n    }\n  });\n\n  await disconnectFromDatabase(sessionId);\n});\n```\n\n### 告警通知\n\n向 Slack 发送数据库告警：\n\n```javascript\nasync function checkDatabaseAlerts() {\n  const sessionId = await connectToDatabase();\n\n  // 检查异常\n  const result = await axios.post(`${MCP_API_URL}/api/query`, {\n    sessionId,\n    query: `\n      SELECT COUNT(*) as error_count\n      FROM logs\n      WHERE level = 'ERROR'\n      AND created_at >= NOW() - INTERVAL 1 HOUR\n    `\n  }, {\n    headers: { 'X-API-Key': MCP_API_KEY }\n  });\n\n  const errorCount = result.data.data.rows[0].error_count;\n\n  if (errorCount > 100) {\n    await axios.post('https://slack.com/api/chat.postMessage', {\n      channel: '#alerts',\n      text: `:warning: 检测到高错误率: 过去一小时有 ${errorCount} 个错误！`\n    }, {\n      headers: {\n        'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,\n        'Content-Type': 'application/json'\n      }\n    });\n  }\n\n  await disconnectFromDatabase(sessionId);\n}\n\n// 每 5 分钟检查一次\nsetInterval(checkDatabaseAlerts, 5 * 60 * 1000);\n```\n\n## 最佳实践\n\n### 1. 安全性\n\n- 安全存储数据库凭据（使用环境变量或密钥管理器）\n- 对查询操作使用只读数据库用户\n- 执行前验证和清理 SQL 查询\n- 对敏感环境实施查询白名单\n- 对敏感数据使用临时消息\n\n### 2. 性能\n\n- 为查询添加 LIMIT 以防止大结果集\n- 实现查询超时\n- 缓存频繁访问的结构信息\n- 对高流量 bot 使用连接池\n\n### 3. 用户体验\n\n- 提供清晰的错误消息\n- 以可读的表格格式化查询结果\n- 显示执行时间和行数\n- 对大结果实现分页\n- 使用 Slack Block Kit 进行丰富的格式化\n\n### 4. 错误处理\n\n- 优雅地处理连接超时\n- 对瞬时故障实现重试逻辑\n- 记录错误以便调试\n- 用可操作的消息通知用户失败\n\n## 故障排除\n\n### 问题：连接超时\n\n**症状**：Bot 无法连接到数据库\n\n**解决方案**：\n1. 验证数据库主机可从 bot 服务器访问\n2. 检查防火墙规则\n3. 增加连接超时时间\n4. 验证数据库凭据\n\n### 问题：查询超时\n\n**症状**：查询耗时过长并超时\n\n**解决方案**：\n1. 为查询添加 LIMIT\n2. 优化 SQL 查询\n3. 为频繁查询的列添加索引\n4. 增加查询超时设置\n\n### 问题：大结果集\n\n**症状**：Bot 崩溃或 Slack 消息过长\n\n**解决方案**：\n1. 将结果限制为 10-20 行\n2. 实现分页\n3. 对大型导出使用文件上传\n4. 汇总数据而不是显示所有行\n\n### 问题：会话过期\n\n**症状**：查询失败，提示会话未找到\n\n**解决方案**：\n1. 实现自动重连\n2. 增加 MCP 服务器上的会话超时时间\n3. 持久化存储会话状态\n4. 提示用户重新连接\n\n## 资源\n\n- [Slack API 文档](https://api.slack.com/)\n- [Slack Block Kit Builder](https://app.slack.com/block-kit-builder)\n- [API 参考](../http-api/API_REFERENCE.zh-CN.md)\n- [部署指南](../http-api/DEPLOYMENT.zh-CN.md)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Slack 社区: https://slack.com/community\n"
  },
  {
    "path": "docs/integrations/SMOLAGENTS.md",
    "content": "# Smolagents Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Smolagents.\n\n## Overview\n\n[Smolagents](https://github.com/huggingface/smolagents) is Hugging Face's agent library. It supports MCP, allowing you to use database tools in your agents.\n\n## Prerequisites\n\n- Python 3.9+\n- Smolagents installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Installation\n\n```bash\npip install smolagents\n```\n\n## Configuration\n\n```python\nfrom smolagents import MCPClient, Agent\n\nmcp_client = MCPClient(\n    command=\"npx\",\n    args=[\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n    ]\n)\n\ntools = mcp_client.get_tools()\nagent = Agent(tools=tools)\n\nresult = agent.run(\"What tables are in the database?\")\nprint(result)\n```\n\n## Resources\n\n- [Smolagents GitHub](https://github.com/huggingface/smolagents)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/SMOLAGENTS.zh-CN.md",
    "content": "# Smolagents 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Smolagents 集成。\n\n## 概述\n\n[Smolagents](https://github.com/huggingface/smolagents) 是 Hugging Face 的代理库。它支持 MCP，允许您在代理中使用数据库工具。\n\n## 前置要求\n\n- Python 3.9+\n- 已安装 Smolagents\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 安装\n\n```bash\npip install smolagents\n```\n\n## 配置\n\n```python\nfrom smolagents import MCPClient, Agent\n\nmcp_client = MCPClient(\n    command=\"npx\",\n    args=[\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n    ]\n)\n\ntools = mcp_client.get_tools()\nagent = Agent(tools=tools)\n\nresult = agent.run(\"数据库里有哪些表？\")\nprint(result)\n```\n\n## 资源\n\n- [Smolagents GitHub](https://github.com/huggingface/smolagents)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/SOURCEGRAPH-CODY.md",
    "content": "# Sourcegraph Cody Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Sourcegraph Cody.\n\n## Overview\n\n[Sourcegraph Cody](https://sourcegraph.com/cody) is an AI coding assistant. It supports MCP, allowing you to query databases while coding.\n\n## Prerequisites\n\n- Cody extension installed in VS Code or JetBrains\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Cody's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Cody about your database:\n\n```\n@database What tables are in the database?\n@database Show me the schema of the users table\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Sourcegraph Cody Documentation](https://sourcegraph.com/docs/cody)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/SOURCEGRAPH-CODY.zh-CN.md",
    "content": "# Sourcegraph Cody 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Sourcegraph Cody 集成。\n\n## 概述\n\n[Sourcegraph Cody](https://sourcegraph.com/cody) 是一个 AI 编码助手。它支持 MCP，允许您在编码时查询数据库。\n\n## 前置要求\n\n- 在 VS Code 或 JetBrains 中安装了 Cody 扩展\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Cody 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Cody 询问关于数据库的问题：\n\n```\n@database 数据库里有哪些表？\n@database 显示 users 表的结构\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Sourcegraph Cody 文档](https://sourcegraph.com/docs/cody)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/SPRING-AI.md",
    "content": "# Spring AI Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Spring AI.\n\n## Overview\n\n[Spring AI](https://spring.io/projects/spring-ai) is a Java/Spring framework for AI applications. It supports MCP, allowing you to use database tools in your Spring applications.\n\n## Prerequisites\n\n- Java 17+\n- Spring Boot 3.2+\n- Maven or Gradle\n- Database instance\n\n## Installation\n\n### Maven\n\n```xml\n<dependency>\n    <groupId>org.springframework.ai</groupId>\n    <artifactId>spring-ai-mcp</artifactId>\n    <version>1.0.0</version>\n</dependency>\n```\n\n### Gradle\n\n```groovy\nimplementation 'org.springframework.ai:spring-ai-mcp:1.0.0'\n```\n\n## Configuration\n\n### application.yml\n\n```yaml\nspring:\n  ai:\n    mcp:\n      servers:\n        database:\n          command: npx\n          args:\n            - universal-db-mcp\n            - --type\n            - mysql\n            - --host\n            - localhost\n            - --port\n            - \"3306\"\n            - --user\n            - root\n            - --password\n            - ${DB_PASSWORD}\n            - --database\n            - mydb\n```\n\n### Java Configuration\n\n```java\n@Configuration\npublic class McpConfig {\n\n    @Bean\n    public McpClient mcpClient() {\n        return McpClient.builder()\n            .command(\"npx\")\n            .args(\"universal-db-mcp\",\n                  \"--type\", \"mysql\",\n                  \"--host\", \"localhost\",\n                  \"--port\", \"3306\",\n                  \"--user\", \"root\",\n                  \"--password\", \"password\",\n                  \"--database\", \"mydb\")\n            .build();\n    }\n}\n```\n\n## Usage\n\n```java\n@Service\npublic class DatabaseService {\n\n    private final McpClient mcpClient;\n\n    public DatabaseService(McpClient mcpClient) {\n        this.mcpClient = mcpClient;\n    }\n\n    public String queryDatabase(String query) {\n        return mcpClient.callTool(\"execute_query\",\n            Map.of(\"query\", query));\n    }\n\n    public String getSchema() {\n        return mcpClient.callTool(\"get_schema\", Map.of());\n    }\n}\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n1. Use environment variables for credentials\n2. Use read-only database users\n3. Implement proper error handling\n4. Use connection pooling\n\n## Resources\n\n- [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/SPRING-AI.zh-CN.md",
    "content": "# Spring AI 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Spring AI 集成。\n\n## 概述\n\n[Spring AI](https://spring.io/projects/spring-ai) 是一个用于 AI 应用的 Java/Spring 框架。它支持 MCP，允许您在 Spring 应用中使用数据库工具。\n\n## 前置要求\n\n- Java 17+\n- Spring Boot 3.2+\n- Maven 或 Gradle\n- 数据库实例\n\n## 安装\n\n### Maven\n\n```xml\n<dependency>\n    <groupId>org.springframework.ai</groupId>\n    <artifactId>spring-ai-mcp</artifactId>\n    <version>1.0.0</version>\n</dependency>\n```\n\n### Gradle\n\n```groovy\nimplementation 'org.springframework.ai:spring-ai-mcp:1.0.0'\n```\n\n## 配置\n\n### application.yml\n\n```yaml\nspring:\n  ai:\n    mcp:\n      servers:\n        database:\n          command: npx\n          args:\n            - universal-db-mcp\n            - --type\n            - mysql\n            - --host\n            - localhost\n            - --port\n            - \"3306\"\n            - --user\n            - root\n            - --password\n            - ${DB_PASSWORD}\n            - --database\n            - mydb\n```\n\n### Java 配置\n\n```java\n@Configuration\npublic class McpConfig {\n\n    @Bean\n    public McpClient mcpClient() {\n        return McpClient.builder()\n            .command(\"npx\")\n            .args(\"universal-db-mcp\",\n                  \"--type\", \"mysql\",\n                  \"--host\", \"localhost\",\n                  \"--port\", \"3306\",\n                  \"--user\", \"root\",\n                  \"--password\", \"password\",\n                  \"--database\", \"mydb\")\n            .build();\n    }\n}\n```\n\n## 使用方法\n\n```java\n@Service\npublic class DatabaseService {\n\n    private final McpClient mcpClient;\n\n    public DatabaseService(McpClient mcpClient) {\n        this.mcpClient = mcpClient;\n    }\n\n    public String queryDatabase(String query) {\n        return mcpClient.callTool(\"execute_query\",\n            Map.of(\"query\", query));\n    }\n\n    public String getSchema() {\n        return mcpClient.callTool(\"get_schema\", Map.of());\n    }\n}\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n1. 使用环境变量存储凭据\n2. 使用只读数据库用户\n3. 实现适当的错误处理\n4. 使用连接池\n\n## 资源\n\n- [Spring AI 文档](https://docs.spring.io/spring-ai/reference/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/TOME.md",
    "content": "# Tome Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Tome.\n\n## Overview\n\n[Tome](https://github.com/runebook/tome) is a macOS app for local LLMs. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- macOS\n- Tome installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Tome's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Tome about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Resources\n\n- [Tome GitHub](https://github.com/runebook/tome)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/TOME.zh-CN.md",
    "content": "# Tome 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Tome 集成。\n\n## 概述\n\n[Tome](https://github.com/runebook/tome) 是一个用于本地 LLM 的 macOS 应用。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- macOS\n- 已安装 Tome\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Tome 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Tome 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 资源\n\n- [Tome GitHub](https://github.com/runebook/tome)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/VERCEL-AI-SDK.md",
    "content": "# Vercel AI SDK Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Vercel AI SDK.\n\n## Overview\n\n[Vercel AI SDK](https://sdk.vercel.ai/) is a toolkit for building AI-powered applications. It supports MCP, allowing you to use database tools in your AI applications.\n\n## Prerequisites\n\n- Node.js 18+\n- Vercel AI SDK installed\n- Database instance\n\n## Installation\n\n```bash\nnpm install ai @ai-sdk/openai\n```\n\n## Configuration\n\n```typescript\nimport { createMCPClient } from 'ai/mcp';\n\nconst mcpClient = createMCPClient({\n  command: 'npx',\n  args: [\n    'universal-db-mcp',\n    '--type', 'mysql',\n    '--host', 'localhost',\n    '--port', '3306',\n    '--user', 'root',\n    '--password', 'your_password',\n    '--database', 'your_database'\n  ]\n});\n\nconst tools = await mcpClient.getTools();\n```\n\n## Usage\n\n```typescript\nimport { generateText } from 'ai';\nimport { openai } from '@ai-sdk/openai';\n\nconst result = await generateText({\n  model: openai('gpt-4'),\n  tools,\n  prompt: 'What tables are in the database?'\n});\n\nconsole.log(result.text);\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Resources\n\n- [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/VERCEL-AI-SDK.zh-CN.md",
    "content": "# Vercel AI SDK 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Vercel AI SDK 集成。\n\n## 概述\n\n[Vercel AI SDK](https://sdk.vercel.ai/) 是一个用于构建 AI 应用的工具包。它支持 MCP，允许您在 AI 应用中使用数据库工具。\n\n## 前置要求\n\n- Node.js 18+\n- 已安装 Vercel AI SDK\n- 数据库实例\n\n## 安装\n\n```bash\nnpm install ai @ai-sdk/openai\n```\n\n## 配置\n\n```typescript\nimport { createMCPClient } from 'ai/mcp';\n\nconst mcpClient = createMCPClient({\n  command: 'npx',\n  args: [\n    'universal-db-mcp',\n    '--type', 'mysql',\n    '--host', 'localhost',\n    '--port', '3306',\n    '--user', 'root',\n    '--password', 'your_password',\n    '--database', 'your_database'\n  ]\n});\n\nconst tools = await mcpClient.getTools();\n```\n\n## 使用方法\n\n```typescript\nimport { generateText } from 'ai';\nimport { openai } from '@ai-sdk/openai';\n\nconst result = await generateText({\n  model: openai('gpt-4'),\n  tools,\n  prompt: '数据库里有哪些表？'\n});\n\nconsole.log(result.text);\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 资源\n\n- [Vercel AI SDK 文档](https://sdk.vercel.ai/docs)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/VSCODE.md",
    "content": "# VS Code Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Visual Studio Code using AI coding extensions.\n\n## Overview\n\nVisual Studio Code is a popular code editor that supports MCP integration through various AI coding extensions. By integrating Universal Database MCP Server, you can query and analyze database data directly within VS Code using AI assistants.\n\n**Key Benefits:**\n- Query databases directly from VS Code's AI chat\n- Get AI assistance for SQL query writing\n- Explore database schema without leaving the editor\n- Debug and optimize database queries with AI help\n\n## Prerequisites\n\n- [Visual Studio Code](https://code.visualstudio.com/) installed\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n- AI coding extension installed (Cline or Continue)\n\n---\n\n## Method 1: Cline Extension\n\nCline is an autonomous AI coding agent that supports MCP integration for database operations.\n\n### Step 1: Install Cline Extension\n\n1. Open VS Code Extensions (`Ctrl+Shift+X` or `Cmd+Shift+X`)\n2. Search for \"Cline\"\n3. Install the Cline extension\n4. Reload VS Code if prompted\n\n### Step 2: Configure MCP Server\n\nOpen Cline settings and configure the MCP server. The configuration is stored in Cline's settings.\n\n**Access Cline Settings:**\n1. Open Cline panel in VS Code\n2. Click the settings icon (gear icon)\n3. Navigate to MCP Servers section\n4. Add the Universal Database MCP Server configuration\n\n**Configuration Format:**\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Restart Cline\n\nAfter saving the configuration, restart Cline or reload VS Code for the changes to take effect.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n---\n\n## Method 2: Continue Extension\n\nContinue is an open-source AI code assistant that supports MCP integration.\n\n### Step 1: Install Continue Extension\n\n1. Open VS Code Extensions (`Ctrl+Shift+X` or `Cmd+Shift+X`)\n2. Search for \"Continue\"\n3. Install the Continue extension\n4. Reload VS Code if prompted\n\n### Step 2: Configure MCP Server\n\nContinue stores configuration in a JSON file.\n\n**Configuration File Location:**\n- **Windows**: `%USERPROFILE%\\.continue\\config.json`\n- **macOS/Linux**: `~/.continue/config.json`\n\nAdd MCP server configuration to your `config.json`:\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"universal-db-mcp\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### Configuration Examples\n\n**Multiple Databases:**\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-production\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n### Step 3: Use in Continue\n\n1. Open Continue panel in VS Code (`Ctrl+L` or `Cmd+L`)\n2. The MCP tools will be available automatically\n3. Ask database-related questions\n\n---\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn the AI chat, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk the AI to generate database-related code:\n\n```\nGenerate a TypeScript function to insert a new user into the users table\n```\n\nThe AI will examine your schema and generate appropriate code.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** configuration files with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: The AI assistant doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the configuration is correct in Cline/Continue settings\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart VS Code after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx\n4. On Windows, you may need to restart after installing Node.js\n\n## Advanced Configuration\n\n### Using Environment Variables\n\nFor better security, you can reference environment variables in your configuration. First, set the environment variables:\n\n**macOS/Linux:**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\nThen use a wrapper script that reads these variables.\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n## Resources\n\n- [Visual Studio Code Official Website](https://code.visualstudio.com/)\n- [Cline Extension](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)\n- [Continue Extension](https://marketplace.visualstudio.com/items?itemName=Continue.continue)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cline Issues: https://github.com/cline/cline/issues\n- Continue Issues: https://github.com/continuedev/continue/issues\n"
  },
  {
    "path": "docs/integrations/VSCODE.zh-CN.md",
    "content": "# VS Code 集成指南\n\n本指南展示如何通过 AI 编码扩展将 Universal Database MCP Server 与 Visual Studio Code 集成。\n\n## 概述\n\nVisual Studio Code 是一款流行的代码编辑器，支持通过各种 AI 编码扩展进行 MCP 集成。通过集成 Universal Database MCP Server，您可以使用 AI 助手直接在 VS Code 中查询和分析数据库数据。\n\n**主要优势：**\n- 直接从 VS Code 的 AI 聊天中查询数据库\n- 获得 AI 辅助编写 SQL 查询\n- 无需离开编辑器即可探索数据库结构\n- 借助 AI 帮助调试和优化数据库查询\n\n## 前置要求\n\n- 已安装 [Visual Studio Code](https://code.visualstudio.com/)\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n- 已安装 AI 编码扩展（Cline 或 Continue）\n\n---\n\n## 方法 1：Cline 扩展\n\nCline 是一个自主 AI 编码代理，支持 MCP 集成进行数据库操作。\n\n### 步骤 1：安装 Cline 扩展\n\n1. 打开 VS Code 扩展面板（`Ctrl+Shift+X` 或 `Cmd+Shift+X`）\n2. 搜索 \"Cline\"\n3. 安装 Cline 扩展\n4. 如有提示，重新加载 VS Code\n\n### 步骤 2：配置 MCP 服务器\n\n打开 Cline 设置并配置 MCP 服务器。配置存储在 Cline 的设置中。\n\n**访问 Cline 设置：**\n1. 在 VS Code 中打开 Cline 面板\n2. 点击设置图标（齿轮图标）\n3. 导航到 MCP Servers 部分\n4. 添加 Universal Database MCP Server 配置\n\n**配置格式：**\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"password\",\n        \"--database\", \"mydb\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3：重启 Cline\n\n保存配置后，重启 Cline 或重新加载 VS Code 以使更改生效。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"mcpServers\": {\n    \"postgres-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlserver-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"mcpServers\": {\n    \"oracle-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"mcpServers\": {\n    \"mongodb\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"mcpServers\": {\n    \"redis\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"mcpServers\": {\n    \"dm-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"dm\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5236\",\n        \"--user\", \"SYSDBA\",\n        \"--password\", \"your_password\",\n        \"--database\", \"DAMENG\"\n      ]\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"mcpServers\": {\n    \"kingbase-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"kingbase\",\n        \"--host\", \"localhost\",\n        \"--port\", \"54321\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly_user\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production_db\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development_db\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-db-writable\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\", \"true\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n---\n\n## 方法 2：Continue 扩展\n\nContinue 是一个开源 AI 代码助手，支持 MCP 集成。\n\n### 步骤 1：安装 Continue 扩展\n\n1. 打开 VS Code 扩展面板（`Ctrl+Shift+X` 或 `Cmd+Shift+X`）\n2. 搜索 \"Continue\"\n3. 安装 Continue 扩展\n4. 如有提示，重新加载 VS Code\n\n### 步骤 2：配置 MCP 服务器\n\nContinue 将配置存储在 JSON 文件中。\n\n**配置文件位置：**\n- **Windows**：`%USERPROFILE%\\.continue\\config.json`\n- **macOS/Linux**：`~/.continue/config.json`\n\n将 MCP 服务器配置添加到您的 `config.json`：\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"universal-db-mcp\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  ]\n}\n```\n\n### 配置示例\n\n**多数据库配置：**\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mysql-production\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    {\n      \"name\": \"postgres-analytics\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  ]\n}\n```\n\n### 步骤 3：在 Continue 中使用\n\n1. 在 VS Code 中打开 Continue 面板（`Ctrl+L` 或 `Cmd+L`）\n2. MCP 工具将自动可用\n3. 询问数据库相关问题\n\n---\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1：探索数据库结构\n\n在 AI 聊天中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2：查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3：编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4：调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案。\n\n### 示例 5：生成代码\n\n让 AI 生成数据库相关代码：\n\n```\n生成一个 TypeScript 函数，用于向 users 表插入新用户\n```\n\nAI 将检查您的结构并生成适当的代码。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的配置文件提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：AI 助手无法识别数据库工具\n\n**解决方案**：\n1. 验证 Cline/Continue 设置中的配置是否正确\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 VS Code\n4. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径\n4. 在 Windows 上，安装 Node.js 后可能需要重启\n\n## 高级配置\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中引用环境变量。首先，设置环境变量：\n\n**macOS/Linux：**\n```bash\nexport DB_PASSWORD=\"your_secure_password\"\n```\n\n**Windows (PowerShell)：**\n```powershell\n$env:DB_PASSWORD = \"your_secure_password\"\n```\n\n然后使用读取这些变量的包装脚本。\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```json\n{\n  \"mcpServers\": {\n    \"docker-mysql\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"127.0.0.1\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"root_password\",\n        \"--database\", \"app_db\"\n      ]\n    }\n  }\n}\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n## 资源\n\n- [Visual Studio Code 官方网站](https://code.visualstudio.com/)\n- [Cline 扩展](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)\n- [Continue 扩展](https://marketplace.visualstudio.com/items?itemName=Continue.continue)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Cline Issues: https://github.com/cline/cline/issues\n- Continue Issues: https://github.com/continuedev/continue/issues\n"
  },
  {
    "path": "docs/integrations/WARP.md",
    "content": "# Warp Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Warp terminal.\n\n## Overview\n\n[Warp](https://www.warp.dev/) is an AI-powered terminal with MCP support. You can query databases directly from your terminal using natural language.\n\n## Prerequisites\n\n- Warp installed ([Download here](https://www.warp.dev/))\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\n### Step 1: Open Warp Settings\n\n1. Launch Warp\n2. Open Settings (Cmd + ,)\n3. Navigate to \"AI\" > \"MCP Servers\"\n\n### Step 2: Add MCP Server\n\nAdd the following configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nUse Warp AI to query your database:\n\n```bash\n# Press Ctrl+` to open Warp AI\n> What tables are in the database?\n> Show me the schema of the users table\n> How many orders were placed today?\n```\n\n## Available MCP Tools\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries |\n| `get_schema` | Get database schema |\n| `get_table_info` | Get table details |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Best Practices\n\n1. Use read-only database users\n2. Keep credentials secure\n3. Use specific queries\n\n## Resources\n\n- [Warp Documentation](https://docs.warp.dev/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/WARP.zh-CN.md",
    "content": "# Warp 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Warp 终端集成。\n\n## 概述\n\n[Warp](https://www.warp.dev/) 是一个支持 MCP 的 AI 驱动终端。您可以直接从终端使用自然语言查询数据库。\n\n## 前置要求\n\n- 已安装 Warp（[下载地址](https://www.warp.dev/)）\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n### 步骤 1：打开 Warp 设置\n\n1. 启动 Warp\n2. 打开设置（Cmd + ,）\n3. 导航到\"AI\" > \"MCP Servers\"\n\n### 步骤 2：添加 MCP 服务器\n\n添加以下配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n使用 Warp AI 查询数据库：\n\n```bash\n# 按 Ctrl+` 打开 Warp AI\n> 数据库里有哪些表？\n> 显示 users 表的结构\n> 今天有多少订单？\n```\n\n## 可用的 MCP 工具\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询 |\n| `get_schema` | 获取数据库结构 |\n| `get_table_info` | 获取表详情 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 最佳实践\n\n1. 使用只读数据库用户\n2. 保护好凭据安全\n3. 使用具体查询\n\n## 资源\n\n- [Warp 文档](https://docs.warp.dev/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n"
  },
  {
    "path": "docs/integrations/WINDSURF.md",
    "content": "# Windsurf IDE Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Windsurf IDE (Codeium).\n\n## Overview\n\nWindsurf is Codeium's AI-powered IDE, featuring the Cascade intelligent agent that can understand context, execute multi-step tasks, and interact with external tools through the Model Context Protocol (MCP). By integrating Universal Database MCP Server, you can enable Cascade to query and analyze database data directly within your development environment.\n\n**Key Features:**\n- Native MCP support via stdio mode\n- Cascade AI agent for intelligent database interactions\n- Seamless integration with your development workflow\n- Support for multiple database types\n\n## Prerequisites\n\n- [Windsurf IDE](https://codeium.com/windsurf) installed\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n- Basic familiarity with MCP configuration\n\n## Setup Steps\n\n### Step 1: Locate Configuration File\n\nWindsurf stores MCP configuration in the following location:\n\n| Platform | Configuration Path |\n|----------|-------------------|\n| Windows | `%USERPROFILE%\\.codeium\\windsurf\\mcp_config.json` |\n| macOS | `~/.codeium/windsurf/mcp_config.json` |\n| Linux | `~/.codeium/windsurf/mcp_config.json` |\n\nIf the file doesn't exist, create it manually.\n\n### Step 2: Configure MCP Server\n\nEdit the `mcp_config.json` file to add Universal Database MCP Server:\n\n#### Basic Configuration (MySQL)\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### PostgreSQL Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### SQLite Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n#### SQL Server Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### Oracle Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n#### MongoDB Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### Redis Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### Step 3: Enable Write Operations (Optional)\n\nBy default, the MCP server operates in read-only mode. To enable write operations, add the `--allow-write` flag:\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\"\n      ]\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to modify your database. Use with caution, especially in production environments.\n\n### Step 4: Restart Windsurf\n\nAfter saving the configuration file, restart Windsurf IDE to load the MCP server.\n\n### Step 5: Verify Connection\n\n1. Open Windsurf IDE\n2. Open the Cascade panel (usually on the right side)\n3. Ask Cascade to list database tables:\n   ```\n   List all tables in the database\n   ```\n4. If configured correctly, Cascade will use the MCP tools to query your database\n\n## Configuration Options\n\n### Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host address |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite database file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g and earlier) |\n\n*Required fields depend on database type\n\n### Default Ports\n\n| Database | Default Port |\n|----------|-------------|\n| MySQL | 3306 |\n| PostgreSQL | 5432 |\n| SQL Server | 1433 |\n| Oracle | 1521 |\n| MongoDB | 27017 |\n| Redis | 6379 |\n| ClickHouse | 8123 |\n\n## Available MCP Tools\n\nOnce configured, Cascade can use the following tools:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries and return results |\n| `get_schema` | Get database schema information |\n| `get_table_info` | Get detailed table structure |\n| `clear_cache` | Clear schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\n```\nUser: What tables are in my database?\n\nCascade: [Uses get_schema tool]\n         Your database contains the following tables:\n         - users (id, name, email, created_at)\n         - orders (id, user_id, total, status, created_at)\n         - products (id, name, price, stock)\n```\n\n### Example 2: Query Data\n\n```\nUser: Show me the top 5 users by order count\n\nCascade: [Uses execute_query tool]\n         Here are the top 5 users by order count:\n\n         | User       | Email              | Orders |\n         |------------|-------------------|--------|\n         | Alice      | alice@example.com | 45     |\n         | Bob        | bob@example.com   | 38     |\n         | Charlie    | charlie@test.com  | 32     |\n         | Diana      | diana@example.com | 28     |\n         | Eve        | eve@test.com      | 25     |\n```\n\n### Example 3: Analyze Data\n\n```\nUser: What's the total revenue by month for the last 6 months?\n\nCascade: [Uses execute_query tool]\n         Revenue analysis for the last 6 months:\n\n         | Month    | Revenue    |\n         |----------|------------|\n         | 2026-01  | $125,430   |\n         | 2025-12  | $142,850   |\n         | 2025-11  | $98,320    |\n         | 2025-10  | $115,670   |\n         | 2025-09  | $108,940   |\n         | 2025-08  | $95,280    |\n```\n\n### Example 4: Get Table Structure\n\n```\nUser: What's the structure of the users table?\n\nCascade: [Uses get_table_info tool]\n         The users table has the following structure:\n\n         | Column     | Type         | Nullable | Key     |\n         |------------|--------------|----------|---------|\n         | id         | int          | NO       | PRIMARY |\n         | name       | varchar(255) | NO       |         |\n         | email      | varchar(255) | NO       | UNIQUE  |\n         | password   | varchar(255) | NO       |         |\n         | created_at | datetime     | YES      |         |\n         | updated_at | datetime     | YES      |         |\n```\n\n### Example 5: Write Operations (if enabled)\n\n```\nUser: Insert a new user with name \"John\" and email \"john@example.com\"\n\nCascade: [Uses execute_query tool with INSERT]\n         Successfully inserted new user:\n         - Name: John\n         - Email: john@example.com\n         - ID: 156\n```\n\n## Multiple Database Configuration\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development\",\n        \"--allow-write\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only mode** for production databases\n- **Create dedicated database users** with minimal permissions\n- **Never commit** `mcp_config.json` with passwords to version control\n- **Use environment variables** for sensitive data when possible\n\n### 2. Performance\n\n- Add appropriate indexes to frequently queried columns\n- Use LIMIT clauses for large tables\n- Consider connection pooling for high-frequency queries\n\n### 3. Development Workflow\n\n- Use separate configurations for development and production\n- Enable write operations only in development environments\n- Regularly clear cache when schema changes\n\n## Troubleshooting\n\n### Issue: MCP Server Not Starting\n\n**Symptoms**: Cascade cannot access database tools\n\n**Solutions**:\n1. Verify Node.js is installed: `node --version`\n2. Check configuration file syntax (valid JSON)\n3. Ensure file path is correct\n4. Check Windsurf logs for errors\n\n### Issue: Connection Failed\n\n**Symptoms**: \"Connection refused\" or timeout errors\n\n**Solutions**:\n1. Verify database is running\n2. Check host, port, and credentials\n3. Ensure firewall allows connection\n4. Test connection with database client first\n\n### Issue: Authentication Failed\n\n**Symptoms**: \"Access denied\" errors\n\n**Solutions**:\n1. Verify username and password\n2. Check user permissions\n3. Ensure user can connect from your host\n4. For MySQL, check `mysql.user` table\n\n### Issue: Permission Denied\n\n**Symptoms**: Cannot execute certain queries\n\n**Solutions**:\n1. Check database user permissions\n2. For write operations, ensure `--allow-write` is set\n3. Verify user has SELECT/INSERT/UPDATE/DELETE grants\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take too long\n\n**Solutions**:\n1. Add indexes to queried columns\n2. Use LIMIT for large result sets\n3. Optimize SQL queries\n4. Check database server performance\n\n### Issue: Configuration Not Loading\n\n**Symptoms**: Changes to config not taking effect\n\n**Solutions**:\n1. Restart Windsurf IDE completely\n2. Verify JSON syntax is valid\n3. Check file is saved in correct location\n4. Look for error messages in Windsurf logs\n\n## Environment Variables\n\nYou can use environment variables in your configuration for better security:\n\n### Windows (PowerShell)\n\n```powershell\n$env:DB_PASSWORD = \"your_password\"\n```\n\n### macOS/Linux\n\n```bash\nexport DB_PASSWORD=\"your_password\"\n```\n\nThen reference in configuration (if supported by your shell):\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"${DB_PASSWORD}\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Resources\n\n- [Windsurf IDE](https://codeium.com/windsurf)\n- [Codeium Documentation](https://codeium.com/docs)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n- [Universal Database MCP Server](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Codeium Community: https://discord.gg/codeium\n"
  },
  {
    "path": "docs/integrations/WINDSURF.zh-CN.md",
    "content": "# Windsurf IDE 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Windsurf IDE (Codeium) 集成。\n\n## 概述\n\nWindsurf 是 Codeium 推出的 AI 驱动的 IDE，具有 Cascade 智能代理，能够理解上下文、执行多步骤任务，并通过模型上下文协议（MCP）与外部工具交互。通过集成 Universal Database MCP Server，您可以让 Cascade 在开发环境中直接查询和分析数据库数据。\n\n**主要特性：**\n- 通过 stdio 模式原生支持 MCP\n- Cascade AI 代理实现智能数据库交互\n- 与开发工作流无缝集成\n- 支持多种数据库类型\n\n## 前置要求\n\n- 已安装 [Windsurf IDE](https://codeium.com/windsurf)\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n- 基本了解 MCP 配置\n\n## 设置步骤\n\n### 步骤 1: 定位配置文件\n\nWindsurf 的 MCP 配置存储在以下位置：\n\n| 平台 | 配置路径 |\n|------|---------|\n| Windows | `%USERPROFILE%\\.codeium\\windsurf\\mcp_config.json` |\n| macOS | `~/.codeium/windsurf/mcp_config.json` |\n| Linux | `~/.codeium/windsurf/mcp_config.json` |\n\n如果文件不存在，请手动创建。\n\n### 步骤 2: 配置 MCP 服务器\n\n编辑 `mcp_config.json` 文件，添加 Universal Database MCP Server：\n\n#### 基本配置（MySQL）\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### PostgreSQL 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"localhost\",\n        \"--port\", \"5432\",\n        \"--user\", \"postgres\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### SQLite 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlite\",\n        \"--file\", \"/path/to/your/database.db\"\n      ]\n    }\n  }\n}\n```\n\n#### SQL Server 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"sqlserver\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1433\",\n        \"--user\", \"sa\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### Oracle 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"oracle\",\n        \"--host\", \"localhost\",\n        \"--port\", \"1521\",\n        \"--user\", \"system\",\n        \"--password\", \"your_password\",\n        \"--database\", \"ORCL\"\n      ]\n    }\n  }\n}\n```\n\n#### MongoDB 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mongodb\",\n        \"--host\", \"localhost\",\n        \"--port\", \"27017\",\n        \"--user\", \"admin\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n#### Redis 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"redis\",\n        \"--host\", \"localhost\",\n        \"--port\", \"6379\",\n        \"--password\", \"your_password\"\n      ]\n    }\n  }\n}\n```\n\n### 步骤 3: 启用写操作（可选）\n\n默认情况下，MCP 服务器以只读模式运行。要启用写操作，请添加 `--allow-write` 参数：\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\",\n        \"--allow-write\"\n      ]\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 修改您的数据库。请谨慎使用，尤其是在生产环境中。\n\n### 步骤 4: 重启 Windsurf\n\n保存配置文件后，重启 Windsurf IDE 以加载 MCP 服务器。\n\n### 步骤 5: 验证连接\n\n1. 打开 Windsurf IDE\n2. 打开 Cascade 面板（通常在右侧）\n3. 让 Cascade 列出数据库表：\n   ```\n   列出数据库中的所有表\n   ```\n4. 如果配置正确，Cascade 将使用 MCP 工具查询您的数据库\n\n## 配置选项\n\n### 命令行参数\n\n| 参数 | 必需 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机地址 |\n| `--port` | 否 | 数据库端口（未指定时使用默认值） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 数据库文件路径（仅用于 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g 及更早版本） |\n\n*必需字段取决于数据库类型\n\n### 默认端口\n\n| 数据库 | 默认端口 |\n|--------|---------|\n| MySQL | 3306 |\n| PostgreSQL | 5432 |\n| SQL Server | 1433 |\n| Oracle | 1521 |\n| MongoDB | 27017 |\n| Redis | 6379 |\n| ClickHouse | 8123 |\n\n## 可用的 MCP 工具\n\n配置完成后，Cascade 可以使用以下工具：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 执行 SQL 查询并返回结果 |\n| `get_schema` | 获取数据库架构信息 |\n| `get_table_info` | 获取详细的表结构 |\n| `clear_cache` | 清除架构缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库架构\n\n```\n用户：我的数据库中有哪些表？\n\nCascade：[使用 get_schema 工具]\n         您的数据库包含以下表：\n         - users（id、name、email、created_at）\n         - orders（id、user_id、total、status、created_at）\n         - products（id、name、price、stock）\n```\n\n### 示例 2: 查询数据\n\n```\n用户：显示订单数量最多的前 5 名用户\n\nCascade：[使用 execute_query 工具]\n         以下是订单数量最多的前 5 名用户：\n\n         | 用户    | 邮箱               | 订单数 |\n         |---------|-------------------|--------|\n         | Alice   | alice@example.com | 45     |\n         | Bob     | bob@example.com   | 38     |\n         | Charlie | charlie@test.com  | 32     |\n         | Diana   | diana@example.com | 28     |\n         | Eve     | eve@test.com      | 25     |\n```\n\n### 示例 3: 分析数据\n\n```\n用户：最近 6 个月每月的总收入是多少？\n\nCascade：[使用 execute_query 工具]\n         最近 6 个月的收入分析：\n\n         | 月份    | 收入       |\n         |---------|------------|\n         | 2026-01 | ¥125,430   |\n         | 2025-12 | ¥142,850   |\n         | 2025-11 | ¥98,320    |\n         | 2025-10 | ¥115,670   |\n         | 2025-09 | ¥108,940   |\n         | 2025-08 | ¥95,280    |\n```\n\n### 示例 4: 获取表结构\n\n```\n用户：users 表的结构是什么？\n\nCascade：[使用 get_table_info 工具]\n         users 表具有以下结构：\n\n         | 列名       | 类型         | 可空 | 键      |\n         |------------|--------------|------|---------|\n         | id         | int          | 否   | PRIMARY |\n         | name       | varchar(255) | 否   |         |\n         | email      | varchar(255) | 否   | UNIQUE  |\n         | password   | varchar(255) | 否   |         |\n         | created_at | datetime     | 是   |         |\n         | updated_at | datetime     | 是   |         |\n```\n\n### 示例 5: 写操作（如果已启用）\n\n```\n用户：插入一个新用户，姓名为\"张三\"，邮箱为\"zhangsan@example.com\"\n\nCascade：[使用 execute_query 工具执行 INSERT]\n         成功插入新用户：\n         - 姓名：张三\n         - 邮箱：zhangsan@example.com\n         - ID：156\n```\n\n## 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"mcpServers\": {\n    \"mysql-production\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"prod-db.example.com\",\n        \"--port\", \"3306\",\n        \"--user\", \"readonly\",\n        \"--password\", \"prod_password\",\n        \"--database\", \"production\"\n      ]\n    },\n    \"mysql-development\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"dev_password\",\n        \"--database\", \"development\",\n        \"--allow-write\"\n      ]\n    },\n    \"postgres-analytics\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"postgres\",\n        \"--host\", \"analytics-db.example.com\",\n        \"--port\", \"5432\",\n        \"--user\", \"analyst\",\n        \"--password\", \"analytics_password\",\n        \"--database\", \"analytics\"\n      ]\n    }\n  }\n}\n```\n\n## 最佳实践\n\n### 1. 安全性\n\n- 对生产数据库**使用只读模式**\n- **创建专用数据库用户**，授予最小权限\n- **切勿将** `mcp_config.json` 中的密码提交到版本控制\n- 尽可能**使用环境变量**存储敏感数据\n\n### 2. 性能\n\n- 为经常查询的列添加适当的索引\n- 对大表使用 LIMIT 子句\n- 考虑对高频查询使用连接池\n\n### 3. 开发工作流\n\n- 为开发和生产使用不同的配置\n- 仅在开发环境中启用写操作\n- 当架构更改时定期清除缓存\n\n## 故障排除\n\n### 问题：MCP 服务器未启动\n\n**症状**：Cascade 无法访问数据库工具\n\n**解决方案**：\n1. 验证 Node.js 已安装：`node --version`\n2. 检查配置文件语法（有效的 JSON）\n3. 确保文件路径正确\n4. 检查 Windsurf 日志中的错误\n\n### 问题：连接失败\n\n**症状**：\"连接被拒绝\"或超时错误\n\n**解决方案**：\n1. 验证数据库正在运行\n2. 检查主机、端口和凭据\n3. 确保防火墙允许连接\n4. 先使用数据库客户端测试连接\n\n### 问题：认证失败\n\n**症状**：\"访问被拒绝\"错误\n\n**解决方案**：\n1. 验证用户名和密码\n2. 检查用户权限\n3. 确保用户可以从您的主机连接\n4. 对于 MySQL，检查 `mysql.user` 表\n\n### 问题：权限不足\n\n**症状**：无法执行某些查询\n\n**解决方案**：\n1. 检查数据库用户权限\n2. 对于写操作，确保设置了 `--allow-write`\n3. 验证用户具有 SELECT/INSERT/UPDATE/DELETE 权限\n\n### 问题：查询缓慢\n\n**症状**：查询耗时过长\n\n**解决方案**：\n1. 为查询的列添加索引\n2. 对大结果集使用 LIMIT\n3. 优化 SQL 查询\n4. 检查数据库服务器性能\n\n### 问题：配置未加载\n\n**症状**：配置更改未生效\n\n**解决方案**：\n1. 完全重启 Windsurf IDE\n2. 验证 JSON 语法有效\n3. 检查文件是否保存在正确位置\n4. 查看 Windsurf 日志中的错误消息\n\n## 环境变量\n\n您可以在配置中使用环境变量以提高安全性：\n\n### Windows (PowerShell)\n\n```powershell\n$env:DB_PASSWORD = \"your_password\"\n```\n\n### macOS/Linux\n\n```bash\nexport DB_PASSWORD=\"your_password\"\n```\n\n然后在配置中引用（如果您的 shell 支持）：\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"${DB_PASSWORD}\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 资源\n\n- [Windsurf IDE](https://codeium.com/windsurf)\n- [Codeium 文档](https://codeium.com/docs)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n- [Universal Database MCP Server](https://github.com/Anarkh-Lee/universal-db-mcp)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Codeium 社区: https://discord.gg/codeium\n"
  },
  {
    "path": "docs/integrations/WITSY.md",
    "content": "# Witsy Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Witsy.\n\n## Overview\n\n[Witsy](https://witsy.app/) is a desktop AI assistant. It supports MCP, allowing you to query databases from the chat interface.\n\n## Prerequisites\n\n- Witsy installed\n- Node.js 20.0.0 or later\n- Database instance\n\n## Configuration\n\nAdd to Witsy's MCP configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## Usage\n\nAsk Witsy about your database:\n\n```\nWhat tables are in the database?\nShow me the schema of the users table\n```\n\n## Resources\n\n- [Witsy Website](https://witsy.app/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/WITSY.zh-CN.md",
    "content": "# Witsy 集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Witsy 集成。\n\n## 概述\n\n[Witsy](https://witsy.app/) 是一个桌面 AI 助手。它支持 MCP，允许您从聊天界面查询数据库。\n\n## 前置要求\n\n- 已安装 Witsy\n- Node.js 20.0.0 或更高版本\n- 数据库实例\n\n## 配置\n\n添加到 Witsy 的 MCP 配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"database\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"localhost\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"your_password\",\n        \"--database\", \"your_database\"\n      ]\n    }\n  }\n}\n```\n\n## 使用方法\n\n向 Witsy 询问关于数据库的问题：\n\n```\n数据库里有哪些表？\n显示 users 表的结构\n```\n\n## 资源\n\n- [Witsy 网站](https://witsy.app/)\n- [Universal DB MCP GitHub](https://github.com/Anarkh-Lee/universal-db-mcp)\n"
  },
  {
    "path": "docs/integrations/ZED.md",
    "content": "# Zed Editor Integration Guide\n\nThis guide shows how to integrate Universal Database MCP Server with Zed Editor.\n\n## Overview\n\nZed is a high-performance, open-source code editor built in Rust, designed for speed and collaboration. Zed natively supports the Model Context Protocol (MCP), allowing seamless integration with AI assistants and database tools. By integrating Universal Database MCP Server, you can query and analyze database data directly within Zed using its built-in AI features.\n\n**Key Benefits:**\n- Native MCP support with zero additional extensions required\n- Lightning-fast performance for database queries\n- Query databases directly from Zed's AI assistant\n- Explore database schema without leaving the editor\n- Get AI assistance for SQL query writing and optimization\n\n## Prerequisites\n\n- [Zed Editor](https://zed.dev/) installed (version 0.131.0 or later recommended)\n- Node.js 18+ installed\n- Database instance (MySQL, PostgreSQL, SQLite, etc.)\n\n## Configuration\n\nZed uses MCP stdio mode for context server integration. Configuration is done through the `settings.json` file.\n\n### Configuration File Location\n\n| Platform | Path |\n|----------|------|\n| macOS | `~/.config/zed/settings.json` |\n| Linux | `~/.config/zed/settings.json` |\n\n> **Note**: Zed is currently available for macOS and Linux. Windows support is in development.\n\n### Step 1: Open Zed Settings\n\n1. Open Zed Editor\n2. Press `Cmd+,` (macOS) or `Ctrl+,` (Linux) to open Settings\n3. Click \"Open settings.json\" in the bottom right corner of the settings panel\n\nAlternatively, you can directly edit the file at `~/.config/zed/settings.json`.\n\n### Step 2: Add MCP Server Configuration\n\nAdd the Universal Database MCP Server configuration to your `settings.json` file using the `context_servers` key:\n\n#### Basic Configuration\n\n```json\n{\n  \"context_servers\": {\n    \"universal-db-mcp\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Step 3: Restart Zed\n\nAfter saving the configuration file, restart Zed Editor for the changes to take effect. You can also use `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Linux) and search for \"Reload\" to reload the configuration.\n\n## Configuration Examples\n\n### MySQL\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"context_servers\": {\n    \"postgres-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"postgres\",\n          \"--host\", \"localhost\",\n          \"--port\", \"5432\",\n          \"--user\", \"postgres\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"context_servers\": {\n    \"sqlite-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"sqlite\",\n          \"--file\", \"/path/to/your/database.db\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"context_servers\": {\n    \"sqlserver-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"sqlserver\",\n          \"--host\", \"localhost\",\n          \"--port\", \"1433\",\n          \"--user\", \"sa\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"context_servers\": {\n    \"oracle-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"oracle\",\n          \"--host\", \"localhost\",\n          \"--port\", \"1521\",\n          \"--user\", \"system\",\n          \"--password\", \"your_password\",\n          \"--database\", \"ORCL\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"context_servers\": {\n    \"mongodb\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mongodb\",\n          \"--host\", \"localhost\",\n          \"--port\", \"27017\",\n          \"--user\", \"admin\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"context_servers\": {\n    \"redis\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"redis\",\n          \"--host\", \"localhost\",\n          \"--port\", \"6379\",\n          \"--password\", \"your_password\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Multiple Databases\n\nYou can configure multiple database connections:\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-production\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"prod-db.example.com\",\n          \"--port\", \"3306\",\n          \"--user\", \"readonly_user\",\n          \"--password\", \"prod_password\",\n          \"--database\", \"production_db\"\n        ]\n      }\n    },\n    \"mysql-development\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"dev_password\",\n          \"--database\", \"development_db\"\n        ]\n      }\n    },\n    \"postgres-analytics\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"postgres\",\n          \"--host\", \"analytics-db.example.com\",\n          \"--port\", \"5432\",\n          \"--user\", \"analyst\",\n          \"--password\", \"analytics_password\",\n          \"--database\", \"analytics\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Enable Write Operations\n\nBy default, write operations are disabled for safety. To enable them:\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db-writable\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\",\n          \"--allow-write\", \"true\"\n        ]\n      }\n    }\n  }\n}\n```\n\n> **Warning**: Enabling write operations allows the AI to execute INSERT, UPDATE, DELETE, and other modifying queries. Use with caution, especially in production environments.\n\n### Using Environment Variables\n\nFor better security, you can use environment variables in your configuration:\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ],\n        \"env\": {\n          \"NODE_ENV\": \"production\"\n        }\n      }\n    }\n  }\n}\n```\n\n## Available Tools\n\nOnce configured, the following MCP tools will be available in Zed:\n\n| Tool | Description |\n|------|-------------|\n| `execute_query` | Execute SQL queries against the database |\n| `get_schema` | Get database schema information (tables, columns, types) |\n| `get_table_info` | Get detailed information about a specific table |\n| `clear_cache` | Clear the schema cache |\n| `get_enum_values` | Get all unique values for a specified column |\n| `get_sample_data` | Get sample data from a table (with automatic data masking) |\n| `connect_database` | Dynamically connect to a database (supports all 17 types) |\n| `disconnect_database` | Disconnect from the current database |\n| `get_connection_status` | Get current database connection status |\n\n## Usage Examples\n\n### Example 1: Explore Database Schema\n\nIn Zed's AI assistant panel, you can ask:\n\n```\nWhat tables are in my database?\n```\n\nThe AI will use the `get_schema` tool to retrieve and display your database structure.\n\n### Example 2: Query Data\n\nAsk the AI to query your data:\n\n```\nShow me the last 10 orders from the orders table\n```\n\nThe AI will generate and execute the appropriate SQL query:\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### Example 3: Write SQL Queries\n\nGet help writing complex queries:\n\n```\nWrite a query to find the top 5 customers by total order value\n```\n\nThe AI will analyze your schema and generate:\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### Example 4: Debug Queries\n\nShare a problematic query and ask for help:\n\n```\nThis query is slow, can you help optimize it?\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nThe AI will analyze and suggest optimizations.\n\n### Example 5: Generate Code\n\nAsk the AI to generate database-related code:\n\n```\nGenerate a TypeScript function to insert a new user into the users table\n```\n\nThe AI will examine your schema and generate appropriate code.\n\n## Command Line Arguments\n\n| Argument | Required | Description |\n|----------|----------|-------------|\n| `--type` | Yes | Database type: mysql, postgres, sqlite, sqlserver, oracle, mongodb, redis, dm, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb |\n| `--host` | Yes* | Database host |\n| `--port` | No | Database port (uses default if not specified) |\n| `--user` | Yes* | Database username |\n| `--password` | Yes* | Database password |\n| `--database` | Yes* | Database name |\n| `--file` | Yes* | SQLite file path (for sqlite type only) |\n| `--allow-write` | No | Enable write operations (default: false) |\n| `--oracle-client-path` | No | Oracle Instant Client path (for Oracle 11g) |\n\n*Required fields depend on database type\n\n## Best Practices\n\n### 1. Security\n\n- **Use read-only database users** for production databases\n- **Never commit** `settings.json` with real credentials to version control\n- **Use environment variables** for sensitive data when possible\n- **Limit database permissions** to only what's necessary\n\n### 2. Performance\n\n- Use specific queries instead of `SELECT *`\n- Add `LIMIT` clauses to prevent large result sets\n- Consider using a read replica for heavy queries\n\n### 3. Development Workflow\n\n- Configure separate connections for development and production\n- Use descriptive names for multiple database connections\n- Keep write operations disabled unless specifically needed\n\n## Troubleshooting\n\n### Issue: MCP Server Not Connecting\n\n**Symptoms**: Zed doesn't recognize the database tools\n\n**Solutions**:\n1. Verify the `settings.json` file is in the correct location (`~/.config/zed/settings.json`)\n2. Check JSON syntax is valid (no trailing commas, proper quotes)\n3. Restart Zed after making configuration changes\n4. Ensure Node.js is installed and accessible from PATH\n\n### Issue: Connection Refused\n\n**Symptoms**: Error message about connection being refused\n\n**Solutions**:\n1. Verify database host and port are correct\n2. Check if the database server is running\n3. Ensure firewall allows connections to the database port\n4. Verify network connectivity to the database host\n\n### Issue: Authentication Failed\n\n**Symptoms**: Error message about invalid credentials\n\n**Solutions**:\n1. Double-check username and password\n2. Verify the user has permission to access the specified database\n3. Check if the database requires SSL/TLS connection\n4. Ensure the user can connect from your IP address\n\n### Issue: Permission Denied\n\n**Symptoms**: Queries fail with permission errors\n\n**Solutions**:\n1. Verify the database user has SELECT permissions\n2. Check if specific tables require additional permissions\n3. For write operations, ensure `--allow-write` is set and user has write permissions\n\n### Issue: Slow Queries\n\n**Symptoms**: Queries take a long time to execute\n\n**Solutions**:\n1. Add appropriate indexes to your database tables\n2. Use `LIMIT` clauses to restrict result sets\n3. Optimize complex queries\n4. Consider using a read replica\n\n### Issue: npx Command Not Found\n\n**Symptoms**: Error indicating npx is not recognized\n\n**Solutions**:\n1. Install Node.js (version 18 or later)\n2. Ensure Node.js bin directory is in your system PATH\n3. Try using the full path to npx (e.g., `/usr/local/bin/npx`)\n4. Verify installation with `which npx` or `npx --version`\n\n### Issue: Context Server Not Starting\n\n**Symptoms**: Zed shows error about context server failing to start\n\n**Solutions**:\n1. Check Zed's log files for detailed error messages\n2. Verify the command path is correct (use `which npx` to find the full path)\n3. Test the MCP server manually in terminal:\n   ```bash\n   npx universal-db-mcp --type mysql --host localhost --port 3306 --user root --password your_password --database your_database\n   ```\n4. Ensure all required arguments are provided\n\n## Advanced Configuration\n\n### Using with Docker\n\nIf your database runs in Docker, ensure the container is accessible:\n\n```json\n{\n  \"context_servers\": {\n    \"docker-mysql\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"127.0.0.1\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"root_password\",\n          \"--database\", \"app_db\"\n        ]\n      }\n    }\n  }\n}\n```\n\n> **Note**: Use `127.0.0.1` instead of `localhost` when connecting to Docker containers on some systems.\n\n### Full Settings Example\n\nHere's a complete `settings.json` example with database MCP server alongside other Zed settings:\n\n```json\n{\n  \"theme\": \"One Dark\",\n  \"buffer_font_size\": 14,\n  \"format_on_save\": \"on\",\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n## Resources\n\n- [Zed Editor Official Website](https://zed.dev/)\n- [Zed Documentation](https://zed.dev/docs)\n- [Zed Context Servers Documentation](https://zed.dev/docs/context-servers)\n- [Universal Database MCP Server Documentation](../README.md)\n- [MCP Protocol Specification](https://modelcontextprotocol.io/)\n\n## Support\n\nFor integration issues:\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Zed Community: https://zed.dev/community\n- Zed Discord: https://discord.gg/zed-community\n"
  },
  {
    "path": "docs/integrations/ZED.zh-CN.md",
    "content": "# Zed 编辑器集成指南\n\n本指南展示如何将 Universal Database MCP Server 与 Zed 编辑器集成。\n\n## 概述\n\nZed 是一款使用 Rust 构建的高性能开源代码编辑器，专为速度和协作而设计。Zed 原生支持模型上下文协议（MCP），可与 AI 助手和数据库工具无缝集成。通过集成 Universal Database MCP Server，您可以使用 Zed 内置的 AI 功能直接查询和分析数据库数据。\n\n**主要优势：**\n- 原生 MCP 支持，无需安装额外扩展\n- 闪电般快速的数据库查询性能\n- 直接从 Zed 的 AI 助手查询数据库\n- 无需离开编辑器即可探索数据库结构\n- 获得 AI 辅助编写和优化 SQL 查询\n\n## 前置要求\n\n- 已安装 [Zed 编辑器](https://zed.dev/)（建议版本 0.131.0 或更高）\n- 已安装 Node.js 18+\n- 数据库实例（MySQL、PostgreSQL、SQLite 等）\n\n## 配置\n\nZed 使用 MCP stdio 模式进行上下文服务器集成。配置通过 `settings.json` 文件完成。\n\n### 配置文件位置\n\n| 平台 | 路径 |\n|------|------|\n| macOS | `~/.config/zed/settings.json` |\n| Linux | `~/.config/zed/settings.json` |\n\n> **注意**：Zed 目前支持 macOS 和 Linux。Windows 支持正在开发中。\n\n### 步骤 1: 打开 Zed 设置\n\n1. 打开 Zed 编辑器\n2. 按 `Cmd+,`（macOS）或 `Ctrl+,`（Linux）打开设置\n3. 点击设置面板右下角的 \"Open settings.json\"\n\n或者，您可以直接编辑 `~/.config/zed/settings.json` 文件。\n\n### 步骤 2: 添加 MCP 服务器配置\n\n使用 `context_servers` 键将 Universal Database MCP Server 配置添加到您的 `settings.json` 文件中：\n\n#### 基本配置\n\n```json\n{\n  \"context_servers\": {\n    \"universal-db-mcp\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### 步骤 3: 重启 Zed\n\n保存配置文件后，重启 Zed 编辑器以使更改生效。您也可以使用 `Cmd+Shift+P`（macOS）或 `Ctrl+Shift+P`（Linux）并搜索 \"Reload\" 来重新加载配置。\n\n## 配置示例\n\n### MySQL\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### PostgreSQL\n\n```json\n{\n  \"context_servers\": {\n    \"postgres-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"postgres\",\n          \"--host\", \"localhost\",\n          \"--port\", \"5432\",\n          \"--user\", \"postgres\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### SQLite\n\n```json\n{\n  \"context_servers\": {\n    \"sqlite-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"sqlite\",\n          \"--file\", \"/path/to/your/database.db\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### SQL Server\n\n```json\n{\n  \"context_servers\": {\n    \"sqlserver-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"sqlserver\",\n          \"--host\", \"localhost\",\n          \"--port\", \"1433\",\n          \"--user\", \"sa\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Oracle\n\n```json\n{\n  \"context_servers\": {\n    \"oracle-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"oracle\",\n          \"--host\", \"localhost\",\n          \"--port\", \"1521\",\n          \"--user\", \"system\",\n          \"--password\", \"your_password\",\n          \"--database\", \"ORCL\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### MongoDB\n\n```json\n{\n  \"context_servers\": {\n    \"mongodb\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mongodb\",\n          \"--host\", \"localhost\",\n          \"--port\", \"27017\",\n          \"--user\", \"admin\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### Redis\n\n```json\n{\n  \"context_servers\": {\n    \"redis\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"redis\",\n          \"--host\", \"localhost\",\n          \"--port\", \"6379\",\n          \"--password\", \"your_password\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### 达梦数据库\n\n```json\n{\n  \"context_servers\": {\n    \"dm-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"dm\",\n          \"--host\", \"localhost\",\n          \"--port\", \"5236\",\n          \"--user\", \"SYSDBA\",\n          \"--password\", \"your_password\",\n          \"--database\", \"DAMENG\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### 人大金仓\n\n```json\n{\n  \"context_servers\": {\n    \"kingbase-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"kingbase\",\n          \"--host\", \"localhost\",\n          \"--port\", \"54321\",\n          \"--user\", \"system\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### 多数据库配置\n\n您可以配置多个数据库连接：\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-production\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"prod-db.example.com\",\n          \"--port\", \"3306\",\n          \"--user\", \"readonly_user\",\n          \"--password\", \"prod_password\",\n          \"--database\", \"production_db\"\n        ]\n      }\n    },\n    \"mysql-development\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"dev_password\",\n          \"--database\", \"development_db\"\n        ]\n      }\n    },\n    \"postgres-analytics\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"postgres\",\n          \"--host\", \"analytics-db.example.com\",\n          \"--port\", \"5432\",\n          \"--user\", \"analyst\",\n          \"--password\", \"analytics_password\",\n          \"--database\", \"analytics\"\n        ]\n      }\n    }\n  }\n}\n```\n\n### 启用写操作\n\n默认情况下，为安全起见禁用写操作。要启用写操作：\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db-writable\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\",\n          \"--allow-write\", \"true\"\n        ]\n      }\n    }\n  }\n}\n```\n\n> **警告**：启用写操作允许 AI 执行 INSERT、UPDATE、DELETE 和其他修改查询。请谨慎使用，尤其是在生产环境中。\n\n### 使用环境变量\n\n为了更好的安全性，您可以在配置中使用环境变量：\n\n```json\n{\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ],\n        \"env\": {\n          \"NODE_ENV\": \"production\"\n        }\n      }\n    }\n  }\n}\n```\n\n## 可用工具\n\n配置完成后，以下 MCP 工具将在 Zed 中可用：\n\n| 工具 | 描述 |\n|------|------|\n| `execute_query` | 对数据库执行 SQL 查询 |\n| `get_schema` | 获取数据库结构信息（表、列、类型） |\n| `get_table_info` | 获取特定表的详细信息 |\n| `clear_cache` | 清除 Schema 缓存 |\n| `get_enum_values` | 获取指定列的所有唯一值 |\n| `get_sample_data` | 获取表的示例数据（自动脱敏） |\n| `connect_database` | 动态连接数据库（支持全部 17 种类型） |\n| `disconnect_database` | 断开当前数据库连接 |\n| `get_connection_status` | 获取当前数据库连接状态 |\n\n## 使用示例\n\n### 示例 1: 探索数据库结构\n\n在 Zed 的 AI 助手面板中，您可以询问：\n\n```\n我的数据库中有哪些表？\n```\n\nAI 将使用 `get_schema` 工具检索并显示您的数据库结构。\n\n### 示例 2: 查询数据\n\n让 AI 查询您的数据：\n\n```\n显示 orders 表中最近的 10 条订单\n```\n\nAI 将生成并执行适当的 SQL 查询：\n\n```sql\nSELECT * FROM orders ORDER BY created_at DESC LIMIT 10\n```\n\n### 示例 3: 编写 SQL 查询\n\n获取编写复杂查询的帮助：\n\n```\n编写一个查询，找出按总订单金额排名前 5 的客户\n```\n\nAI 将分析您的结构并生成：\n\n```sql\nSELECT\n  c.id,\n  c.name,\n  SUM(o.total_amount) as total_value\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.name\nORDER BY total_value DESC\nLIMIT 5\n```\n\n### 示例 4: 调试查询\n\n分享有问题的查询并寻求帮助：\n\n```\n这个查询很慢，你能帮我优化吗？\n\nSELECT * FROM users u\nWHERE u.id IN (SELECT user_id FROM orders WHERE created_at > '2024-01-01')\n```\n\nAI 将分析并建议优化方案。\n\n### 示例 5: 生成代码\n\n让 AI 生成数据库相关代码：\n\n```\n生成一个 TypeScript 函数，用于向 users 表插入新用户\n```\n\nAI 将检查您的结构并生成适当的代码。\n\n## 命令行参数\n\n| 参数 | 必填 | 描述 |\n|------|------|------|\n| `--type` | 是 | 数据库类型：mysql、postgres、sqlite、sqlserver、oracle、mongodb、redis、dm、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb |\n| `--host` | 是* | 数据库主机 |\n| `--port` | 否 | 数据库端口（不指定则使用默认端口） |\n| `--user` | 是* | 数据库用户名 |\n| `--password` | 是* | 数据库密码 |\n| `--database` | 是* | 数据库名称 |\n| `--file` | 是* | SQLite 文件路径（仅 sqlite 类型） |\n| `--allow-write` | 否 | 启用写操作（默认：false） |\n| `--oracle-client-path` | 否 | Oracle Instant Client 路径（用于 Oracle 11g） |\n\n*必填字段取决于数据库类型\n\n## 最佳实践\n\n### 1. 安全性\n\n- **使用只读数据库用户**访问生产数据库\n- **切勿将**包含真实凭据的 `settings.json` 提交到版本控制\n- **尽可能使用环境变量**存储敏感数据\n- **限制数据库权限**仅授予必要的权限\n\n### 2. 性能\n\n- 使用具体查询而非 `SELECT *`\n- 添加 `LIMIT` 子句以防止大结果集\n- 考虑使用只读副本进行大量查询\n\n### 3. 开发工作流\n\n- 为开发和生产配置单独的连接\n- 为多个数据库连接使用描述性名称\n- 除非特别需要，否则保持禁用写操作\n\n## 故障排除\n\n### 问题：MCP 服务器未连接\n\n**症状**：Zed 无法识别数据库工具\n\n**解决方案**：\n1. 验证 `settings.json` 文件位于正确位置（`~/.config/zed/settings.json`）\n2. 检查 JSON 语法是否有效（无尾随逗号、正确的引号）\n3. 更改配置后重启 Zed\n4. 确保 Node.js 已安装并可从 PATH 访问\n\n### 问题：连接被拒绝\n\n**症状**：关于连接被拒绝的错误消息\n\n**解决方案**：\n1. 验证数据库主机和端口是否正确\n2. 检查数据库服务器是否正在运行\n3. 确保防火墙允许连接到数据库端口\n4. 验证到数据库主机的网络连接\n\n### 问题：认证失败\n\n**症状**：关于无效凭据的错误消息\n\n**解决方案**：\n1. 仔细检查用户名和密码\n2. 验证用户是否有权访问指定的数据库\n3. 检查数据库是否需要 SSL/TLS 连接\n4. 确保用户可以从您的 IP 地址连接\n\n### 问题：权限被拒绝\n\n**症状**：查询因权限错误而失败\n\n**解决方案**：\n1. 验证数据库用户是否具有 SELECT 权限\n2. 检查特定表是否需要额外权限\n3. 对于写操作，确保设置了 `--allow-write` 且用户具有写权限\n\n### 问题：查询缓慢\n\n**症状**：查询执行时间过长\n\n**解决方案**：\n1. 为数据库表添加适当的索引\n2. 使用 `LIMIT` 子句限制结果集\n3. 优化复杂查询\n4. 考虑使用只读副本\n\n### 问题：找不到 npx 命令\n\n**症状**：错误提示 npx 未被识别\n\n**解决方案**：\n1. 安装 Node.js（版本 18 或更高）\n2. 确保 Node.js bin 目录在系统 PATH 中\n3. 尝试使用 npx 的完整路径（例如 `/usr/local/bin/npx`）\n4. 使用 `which npx` 或 `npx --version` 验证安装\n\n### 问题：上下文服务器无法启动\n\n**症状**：Zed 显示上下文服务器启动失败的错误\n\n**解决方案**：\n1. 检查 Zed 的日志文件以获取详细错误信息\n2. 验证命令路径是否正确（使用 `which npx` 查找完整路径）\n3. 在终端中手动测试 MCP 服务器：\n   ```bash\n   npx universal-db-mcp --type mysql --host localhost --port 3306 --user root --password your_password --database your_database\n   ```\n4. 确保提供了所有必需的参数\n\n## 高级配置\n\n### 与 Docker 配合使用\n\n如果您的数据库在 Docker 中运行，确保容器可访问：\n\n```json\n{\n  \"context_servers\": {\n    \"docker-mysql\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"127.0.0.1\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"root_password\",\n          \"--database\", \"app_db\"\n        ]\n      }\n    }\n  }\n}\n```\n\n> **注意**：在某些系统上连接 Docker 容器时，使用 `127.0.0.1` 而非 `localhost`。\n\n### 完整设置示例\n\n以下是一个完整的 `settings.json` 示例，包含数据库 MCP 服务器以及其他 Zed 设置：\n\n```json\n{\n  \"theme\": \"One Dark\",\n  \"buffer_font_size\": 14,\n  \"format_on_save\": \"on\",\n  \"context_servers\": {\n    \"mysql-db\": {\n      \"command\": {\n        \"path\": \"npx\",\n        \"args\": [\n          \"universal-db-mcp\",\n          \"--type\", \"mysql\",\n          \"--host\", \"localhost\",\n          \"--port\", \"3306\",\n          \"--user\", \"root\",\n          \"--password\", \"your_password\",\n          \"--database\", \"your_database\"\n        ]\n      }\n    }\n  }\n}\n```\n\n## 资源\n\n- [Zed 编辑器官方网站](https://zed.dev/)\n- [Zed 文档](https://zed.dev/docs)\n- [Zed 上下文服务器文档](https://zed.dev/docs/context-servers)\n- [Universal Database MCP Server 文档](../README.zh-CN.md)\n- [MCP 协议规范](https://modelcontextprotocol.io/)\n\n## 支持\n\n如有集成问题：\n- GitHub Issues: https://github.com/Anarkh-Lee/universal-db-mcp/issues\n- Zed 社区: https://zed.dev/community\n- Zed Discord: https://discord.gg/zed-community\n"
  },
  {
    "path": "docs/operations/guide.md",
    "content": "# Universal DB MCP 运维管理指南\n\n## 📍 基础操作\n\n所有命令需要先进入项目目录：\n\n```bash\ncd /opt/universal-db-mcp\n```\n\n---\n\n## 🔄 启动 / 停止 / 重启\n\n```bash\n# 启动服务\ndocker compose up -d\n\n# 停止服务\ndocker compose down\n\n# 重启服务\ndocker compose restart\n\n# 停止但不删除容器\ndocker compose stop\n\n# 启动已停止的容器\ndocker compose start\n```\n\n---\n\n## 📊 查看状态\n\n```bash\n# 查看容器运行状态\ndocker compose ps\n\n# 查看所有容器（包括停止的）\ndocker ps -a | grep universal-db-mcp\n\n# 查看资源占用（CPU、内存）\ndocker stats universal-db-mcp\n```\n\n---\n\n## 📋 查看日志\n\n```bash\n# 查看实时日志\ndocker compose logs -f\n\n# 查看最近 100 行日志\ndocker compose logs --tail 100\n\n# 查看指定时间内的日志\ndocker compose logs --since 1h\n```\n\n---\n\n## 🔧 更新版本\n\n```bash\ncd /opt/universal-db-mcp\n\n# 停止服务\ndocker compose down\n\n# 重新构建（拉取最新 npm 包）\ndocker compose build --no-cache\n\n# 启动服务\ndocker compose up -d\n```\n\n---\n\n## 🩺 健康检查\n\n```bash\n# 本地检查\ncurl http://localhost:3001/api/health\n\n# 外网检查（使用您的服务器公网 IP）\ncurl http://YOUR_SERVER_IP:3001/api/health\n```\n\n---\n\n## 🧹 清理操作\n\n```bash\n# 停止并删除容器、网络\ndocker compose down\n\n# 停止并删除容器、网络、镜像\ndocker compose down --rmi all\n\n# 清理未使用的镜像（释放磁盘空间）\ndocker image prune -f\n```\n\n---\n\n## 📝 快速命令速查表\n\n| 操作 | 命令 |\n|------|------|\n| 启动 | `docker compose up -d` |\n| 停止 | `docker compose down` |\n| 重启 | `docker compose restart` |\n| 状态 | `docker compose ps` |\n| 日志 | `docker compose logs -f` |\n| 健康检查 | `curl http://localhost:3001/api/health` |\n\n---\n\n## 💡 设置开机自启\n\nDocker 服务默认开机自启，由于配置了 `restart: unless-stopped`，服务器重启后容器会自动启动。\n\n确认 Docker 开机自启：\n\n```bash\nsudo systemctl enable docker\n```\n\n---\n\n## 🔐 安全配置\n\n### 修改 API 密钥\n\n编辑 `.env` 文件：\n\n```bash\nnano /opt/universal-db-mcp/.env\n```\n\n修改 `API_KEYS` 为您自己的安全密钥：\n\n```env\nAPI_KEYS=your-secure-api-key\n```\n\n修改后重启服务：\n\n```bash\ndocker compose restart\n```\n\n---\n\n## 🌐 服务端点\n\n- **健康检查**: `GET /api/health`\n- **连接数据库**: `POST /api/connect`\n- **执行查询**: `POST /api/query`\n- **获取表结构**: `GET /api/schema`\n\n### 请求示例\n\n```bash\n# 连接数据库\ncurl -X POST http://localhost:3001/api/connect \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"mysql\",\n    \"host\": \"your-db-host\",\n    \"port\": 3306,\n    \"user\": \"your-user\",\n    \"password\": \"your-password\",\n    \"database\": \"your-database\"\n  }'\n\n# 执行查询\ncurl -X POST http://localhost:3001/api/query \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sql\": \"SELECT * FROM users LIMIT 10\"\n  }'\n```\n\n---\n\n## 🛠 故障排查\n\n### 容器无法启动\n\n```bash\n# 查看详细错误日志\ndocker compose logs\n\n# 检查配置文件\ncat /opt/universal-db-mcp/.env\ncat /opt/universal-db-mcp/docker-compose.yml\n```\n\n### 端口被占用\n\n```bash\n# 查看端口占用\nsudo lsof -i :3001\n\n# 修改端口后重启\ndocker compose down\ndocker compose up -d\n```\n\n### 内存不足\n\n```bash\n# 查看系统内存\nfree -h\n\n# 查看容器资源使用\ndocker stats\n```\n"
  },
  {
    "path": "docs/operations/troubleshooting.md",
    "content": "# 故障排查指南\n\n本文档介绍 Universal DB MCP 常见问题的排查方法。\n\n## 连接问题\n\n### 无法连接数据库\n\n**症状**：启动时报错 \"数据库连接失败\"\n\n**排查步骤**：\n\n1. **检查数据库服务是否运行**\n   ```bash\n   # MySQL\n   systemctl status mysql\n\n   # PostgreSQL\n   systemctl status postgresql\n\n   # Redis\n   systemctl status redis\n   ```\n\n2. **验证网络连接**\n   ```bash\n   # 测试端口连通性\n   telnet localhost 3306\n   nc -zv localhost 3306\n   ```\n\n3. **检查防火墙**\n   ```bash\n   # UFW\n   sudo ufw status\n\n   # iptables\n   sudo iptables -L\n   ```\n\n4. **验证用户名和密码**\n   ```bash\n   # MySQL\n   mysql -h localhost -u root -p\n\n   # PostgreSQL\n   psql -h localhost -U postgres\n   ```\n\n### 连接超时\n\n**症状**：连接长时间无响应\n\n**可能原因**：\n- 网络延迟\n- 数据库负载过高\n- 防火墙阻断\n\n**解决方案**：\n1. 检查网络延迟：`ping database-host`\n2. 检查数据库负载\n3. 增加连接超时时间\n\n### 权限不足\n\n**症状**：报错 \"Access denied\" 或 \"permission denied\"\n\n**解决方案**：\n\n```sql\n-- MySQL\nGRANT SELECT ON database.* TO 'user'@'host';\nFLUSH PRIVILEGES;\n\n-- PostgreSQL\nGRANT SELECT ON ALL TABLES IN SCHEMA public TO user;\n```\n\n## 查询问题\n\n### 查询被拒绝\n\n**症状**：报错 \"操作被拒绝：当前处于只读安全模式\"\n\n**原因**：默认只读模式，拒绝写入操作\n\n**解决方案**：\n- 根据需要使用 `--permission-mode readwrite` 或 `--permission-mode full`\n- 仅在开发环境使用\n\n### 查询超时\n\n**症状**：查询长时间无响应或超时\n\n**可能原因**：\n- 查询复杂度高\n- 缺少索引\n- 数据量大\n\n**解决方案**：\n1. 优化查询语句\n2. 添加适当索引\n3. 使用 LIMIT 限制结果集\n\n### 结果集过大\n\n**症状**：返回数据量过大，响应缓慢\n\n**解决方案**：\n1. 使用 LIMIT 限制返回行数\n2. 只选择需要的列\n3. 添加过滤条件\n\n## HTTP API 问题\n\n### 401 Unauthorized\n\n**症状**：API 返回 401 错误\n\n**原因**：API Key 无效或缺失\n\n**解决方案**：\n1. 检查请求头是否包含 `X-API-Key` 或 `Authorization: Bearer <key>`\n2. 确认 API Key 正确\n3. 检查 `.env` 文件中的 `API_KEYS` 配置\n\n### 429 Too Many Requests\n\n**症状**：API 返回 429 错误\n\n**原因**：超过速率限制\n\n**解决方案**：\n1. 减少请求频率\n2. 调整速率限制配置：\n   ```bash\n   RATE_LIMIT_MAX=200\n   RATE_LIMIT_WINDOW=1m\n   ```\n\n### 502 Bad Gateway\n\n**症状**：通过 Nginx 访问返回 502\n\n**可能原因**：\n- MCP 服务未运行\n- 端口配置错误\n\n**排查步骤**：\n```bash\n# 检查服务状态\ndocker ps | grep universal-db-mcp\n\n# 检查服务日志\ndocker logs universal-db-mcp\n\n# 直接测试服务\ncurl http://localhost:3000/api/health\n```\n\n## Docker 问题\n\n### 容器无法启动\n\n**排查步骤**：\n\n```bash\n# 查看容器日志\ndocker logs universal-db-mcp\n\n# 检查配置\ndocker compose config\n\n# 检查环境变量\ncat .env\n```\n\n### 无法连接宿主机数据库\n\n**解决方案**：\n\n使用 `host.docker.internal` 作为主机名：\n\n```bash\ndocker run -e DB_HOST=host.docker.internal ...\n```\n\n### 构建失败\n\n**解决方案**：\n\n```bash\n# 清理缓存重新构建\ndocker system prune -a\ndocker compose build --no-cache\n```\n\n## MCP 模式问题\n\n### stdio 模式退出后进程挂起\n\n**症状**：使用 Codex CLI 等 stdio MCP 客户端时，执行 `/exit` 后终端提示符不返回，需要手动 `Ctrl+C`\n\n**原因**：v2.12.0 之前版本未监听 stdin 关闭事件，且 `stop()` 未释放 transport 资源\n\n**解决方案**：\n1. 升级到 v2.12.0 或更高版本（已修复）\n2. 如果仍有问题，检查是否使用了自定义的进程包装器阻止了 stdin EOF 传递\n\n### Claude Desktop 无法连接\n\n**排查步骤**：\n\n1. **检查配置文件格式**\n   - 确保 JSON 语法正确\n   - 使用 JSON 验证工具检查\n\n2. **重启 Claude Desktop**\n\n3. **查看日志**\n   - macOS: `~/Library/Logs/Claude/`\n   - Windows: `%APPDATA%\\Claude\\logs\\`\n\n4. **手动测试命令**\n   ```bash\n   npx universal-db-mcp --type mysql --host localhost --port 3306 --user root --password xxx --database test\n   ```\n\n### 工具未显示\n\n**可能原因**：\n- 配置文件路径错误\n- 配置格式错误\n- 服务启动失败\n\n**解决方案**：\n1. 确认配置文件位置正确\n2. 检查 JSON 格式\n3. 查看启动日志\n\n## 性能问题\n\n### Schema 获取缓慢\n\n**原因**：表数量多，首次获取需要查询所有表\n\n**解决方案**：\n1. 使用 Schema 缓存（默认启用）\n2. 强制刷新时使用 `forceRefresh` 参数\n\n### 内存占用过高\n\n**解决方案**：\n\n1. 限制容器内存：\n   ```yaml\n   deploy:\n     resources:\n       limits:\n         memory: 512M\n   ```\n\n2. 使用 PM2 限制：\n   ```javascript\n   max_memory_restart: '500M'\n   ```\n\n## 日志查看\n\n### Docker 部署\n\n```bash\n# 实时日志\ndocker compose logs -f\n\n# 最近 100 行\ndocker compose logs --tail 100\n```\n\n### PM2 部署\n\n```bash\n# 实时日志\npm2 logs universal-db-mcp\n\n# 日志文件\ncat /var/log/universal-db-mcp/out.log\n```\n\n### systemd 部署\n\n```bash\n# 实时日志\nsudo journalctl -u universal-db-mcp -f\n\n# 最近 1 小时\nsudo journalctl -u universal-db-mcp --since \"1 hour ago\"\n```\n\n## 获取帮助\n\n如果以上方法无法解决问题：\n\n1. **查看文档**：[docs/](../)\n2. **提交 Issue**：https://github.com/yourusername/universal-db-mcp/issues\n3. **提供信息**：\n   - 错误信息\n   - 配置文件（隐藏敏感信息）\n   - 环境信息（操作系统、Node.js 版本、数据库版本）\n   - 复现步骤\n"
  },
  {
    "path": "docs/plan/dynamic-connection-in-mcp-mode.md",
    "content": "# MCP stdio 模式动态数据库连接方案 — 完整实施计划\n\n## 一、问题描述\n\n当前 MCP stdio 模式下，数据库连接参数必须在 Claude Desktop 的 `claude_desktop_config.json` 中写死。用户每次需要连接不同的数据库时，必须手动修改配置文件并重启 MCP 服务，无法在对话中动态切换。\n\n**Issue 来源**: 用户反馈\"数据库的连接方式能否通过自然语言指定而不是在配置 MCP 时写死\"\n\n**用户痛点**:\n1. dev 环境下需要对接多种多样的数据库，每次切换都要改配置、重启\n2. 一个 MCP 实例只能绑定一个数据库，无法在对话中灵活切换\n3. 希望 AI 能自己读取用户提供的连接信息，动态连接数据库\n\n---\n\n## 二、问题分析\n\n### 2.1 现状梳理\n\n项目有两种运行模式，连接方式完全不同：\n\n| 模式 | 连接方式 | 是否支持动态连接 |\n|------|---------|---------------|\n| MCP stdio | CLI 参数写死，`--type`为必填项 | 不支持 |\n| HTTP REST API | `POST /api/connect` body 传参 | 支持 |\n| HTTP SSE | `GET /sse?type=mysql&host=...` URL 传参 | 支持 |\n| HTTP Streamable | `POST /mcp` 请求头 `X-DB-*` 传参 | 支持 |\n\n### 2.2 问题根因\n\n问题集中在 **2 个文件**：\n\n#### 根因 1：`src/mcp/mcp-index.ts` — `--type` 是 requiredOption\n\n```typescript\nprogram\n  .requiredOption('--type <type>', '数据库类型 (mysql|postgres|...)')\n```\n\n不传 `--type` 就无法启动 MCP server，强制要求启动时就确定数据库。\n\n#### 根因 2：`src/mcp/mcp-server.ts` — 没有动态连接的 tool\n\n`DatabaseMCPServer` 类：\n- 构造函数 `constructor(config: DbConfig, ...)` 要求必传 `DbConfig`\n- `setupHandlers()` 中只注册了 6 个 tool（execute_query、get_schema、get_table_info、clear_cache、get_enum_values、get_sample_data），没有连接/断开/状态查询相关的 tool\n- 现有 tool 在未连接时的错误提示是\"请检查配置并重启服务\"，没有引导 AI 调用连接 tool\n\n### 2.3 为什么 HTTP 模式不受影响\n\nHTTP 模式通过 `ConnectionManager`（`src/core/connection-manager.ts`）管理多会话，每个请求可以携带不同的数据库配置。而 MCP stdio 是单进程单客户端模型，没有这层动态管理能力。\n\n### 2.4 影响范围\n\n- 所有 17 种数据库适配器均受影响（它们本身没有问题，问题在上层入口）\n- 仅影响 MCP stdio 模式，HTTP/SSE/Streamable 模式不受影响\n- 适配器列表：mysql、postgres、redis、oracle、dm、sqlserver、mongodb、sqlite、kingbase、gaussdb、oceanbase、tidb、clickhouse、polardb、vastbase、highgo、goldendb\n\n---\n\n## 三、解决了什么问题\n\n1. MCP stdio 模式下可以不写死数据库连接，启动时不需要指定 `--type`\n2. AI 可以在对话中通过 tool call 动态连接任意数据库\n3. 支持在对话中随时切换到不同的数据库（自动断开旧连接）\n4. 向后兼容：传了 `--type` 参数的用户行为完全不变\n\n---\n\n## 四、用户层面使用差异\n\n### 4.1 改动前（当前行为）\n\n用户必须在 `claude_desktop_config.json` 中写死数据库参数：\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"universal-db-mcp\",\n        \"--type\", \"mysql\",\n        \"--host\", \"192.168.1.100\",\n        \"--port\", \"3306\",\n        \"--user\", \"root\",\n        \"--password\", \"123456\",\n        \"--database\", \"order_db\"\n      ]\n    }\n  }\n}\n```\n\n想查另一个数据库？改配置，重启 Claude Desktop。\n\n### 4.2 改动后（新行为）\n\n**方式 A：零配置启动（新增能力）**\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\"universal-db-mcp\"]\n    }\n  }\n}\n```\n\n然后在对话中直接说：\n- \"帮我连接 192.168.1.100 的 MySQL，用户名 root，密码 123456，数据库 order_db\"\n- \"切换到 10.0.0.5 的 PostgreSQL，端口 5432，数据库 analytics\"\n- \"断开当前数据库连接\"\n- \"当前连的是哪个数据库？\"\n\nAI 会自动调用 `connect_database`、`disconnect_database`、`get_connection_status` tool。\n\n**方式 B：带默认连接启动（向后兼容，行为不变）**\n\n```json\n{\n  \"mcpServers\": {\n    \"universal-db\": {\n      \"command\": \"npx\",\n      \"args\": [\"universal-db-mcp\", \"--type\", \"mysql\", \"--host\", \"localhost\", ...]\n    }\n  }\n}\n```\n\n启动时自动连接指定数据库，对话中仍可通过 `connect_database` 切换到其他数据库。\n\n---\n\n## 五、用户使用指南\n\n### 5.1 MCP stdio 模式（Claude Desktop / Codex CLI）\n\n**场景 1：不知道要连哪个库，对话中再决定**\n\n配置：\n```json\n{ \"command\": \"npx\", \"args\": [\"universal-db-mcp\"] }\n```\n\n对话示例：\n```\n用户：帮我查一下测试环境 MySQL 里 orders 表最近 7 天的订单量\nAI：我需要先连接数据库，请提供连接信息（地址、端口、用户名、密码、数据库名）\n用户：192.168.1.100:3306，root/123456，数据库 test_db\nAI：[调用 connect_database] → 连接成功\nAI：[调用 get_schema] → 获取表结构\nAI：[调用 execute_query] → SELECT COUNT(*) FROM orders WHERE ...\n```\n\n**场景 2：对话中切换数据库**\n\n```\n用户：现在帮我看看生产环境 PostgreSQL 的 users 表\nAI：[调用 connect_database 切换到新数据库] → 已断开 MySQL，连接 PostgreSQL 成功\nAI：[调用 execute_query] → ...\n```\n\n**场景 3：查看当前连接状态**\n\n```\n用户：我现在连的是哪个库？\nAI：[调用 get_connection_status] → 当前连接：MySQL 192.168.1.100:3306/test_db，只读模式\n```\n\n### 5.2 HTTP / SSE / Streamable 模式\n\n这些模式不受本次改动影响，使用方式不变。\n\n---\n\n## 六、最佳最优解决方案\n\n### 6.1 改动文件清单\n\n| 文件 | 改动类型 | 改动说明 |\n|------|---------|---------|\n| `src/mcp/mcp-server.ts` | 修改 | 核心改动：新增 3 个 tool，构造函数支持无 config 启动 |\n| `src/mcp/mcp-index.ts` | 修改 | `--type` 从 requiredOption 改为 option，支持无参启动 |\n\n仅改 2 个文件，不涉及适配器层、HTTP 层、类型定义层的任何改动。\n\n### 6.2 详细改动方案\n\n#### 改动 1：`src/mcp/mcp-server.ts`\n\n**1a) 新增 import**\n\n```typescript\nimport { createAdapter, normalizeDbType } from '../utils/adapter-factory.js';\n```\n\n**1b) 构造函数 — config 改为可选**\n\n```typescript\n// 改前\nconstructor(config: DbConfig, cacheConfig?: Partial<SchemaCacheConfig>) {\n  this.config = config;\n  // ...\n}\n\n// 改后\nconstructor(config?: DbConfig, cacheConfig?: Partial<SchemaCacheConfig>) {\n  this.config = config || null;  // null 表示未配置，等待动态连接\n  // ...\n}\n```\n\n对应 `private config: DbConfig` 改为 `private config: DbConfig | null`。\n\n**1c) ListToolsRequestSchema — 新增 3 个 tool 定义**\n\n在现有 tools 数组中追加：\n\n```typescript\n{\n  name: 'connect_database',\n  description: '连接到数据库。支持动态指定数据库类型和连接参数，无需重启服务。' +\n    '如果当前已有连接，会自动断开旧连接再建立新连接。' +\n    '支持的数据库类型：mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, ' +\n    'kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb。',\n  inputSchema: {\n    type: 'object',\n    properties: {\n      type: {\n        type: 'string',\n        description: '数据库类型',\n        enum: [\n          'mysql', 'postgres', 'redis', 'oracle', 'dm', 'sqlserver',\n          'mongodb', 'sqlite', 'kingbase', 'gaussdb', 'oceanbase',\n          'tidb', 'clickhouse', 'polardb', 'vastbase', 'highgo', 'goldendb'\n        ],\n      },\n      host: { type: 'string', description: '数据库主机地址' },\n      port: { type: 'number', description: '数据库端口' },\n      user: { type: 'string', description: '用户名' },\n      password: { type: 'string', description: '密码' },\n      database: { type: 'string', description: '数据库名称' },\n      filePath: { type: 'string', description: 'SQLite 数据库文件路径' },\n      allowWrite: { type: 'boolean', description: '是否允许写操作（默认 false）' },\n      permissionMode: {\n        type: 'string',\n        description: '权限模式: safe(只读) | readwrite(读写不删) | full(完全控制)',\n        enum: ['safe', 'readwrite', 'full'],\n      },\n      authSource: { type: 'string', description: 'MongoDB 认证数据库（默认 admin）' },\n      oracleClientPath: { type: 'string', description: 'Oracle Instant Client 路径' },\n    },\n    required: ['type'],\n  },\n},\n{\n  name: 'disconnect_database',\n  description: '断开当前数据库连接。断开后需要重新调用 connect_database 才能执行查询。',\n  inputSchema: {\n    type: 'object',\n    properties: {},\n  },\n},\n{\n  name: 'get_connection_status',\n  description: '获取当前数据库连接状态。返回是否已连接、数据库类型、地址、数据库名、权限模式等信息。',\n  inputSchema: {\n    type: 'object',\n    properties: {},\n  },\n},\n```\n\n**1d) CallToolRequestSchema — 新增 3 个 case 实现**\n\n```typescript\ncase 'connect_database': {\n  const {\n    type, host, port, user, password, database,\n    filePath, allowWrite, permissionMode, authSource, oracleClientPath,\n  } = args as Record<string, any>;\n\n  // 构建新配置\n  const newConfig: DbConfig = {\n    type: normalizeDbType(type),\n    host,\n    port,\n    user,\n    password,\n    database,\n    filePath,\n    allowWrite: allowWrite || false,\n    permissionMode: permissionMode || 'safe',\n  };\n\n  // MongoDB 特殊配置\n  if (newConfig.type === 'mongodb' && authSource) {\n    (newConfig as any).authSource = authSource;\n  }\n\n  // Oracle 特殊配置\n  if (newConfig.type === 'oracle' && oracleClientPath) {\n    newConfig.oracleClientPath = oracleClientPath;\n  }\n\n  // 断开旧连接\n  if (this.adapter) {\n    console.error('🔄 断开旧数据库连接...');\n    if (this.databaseService) {\n      this.databaseService.clearSchemaCache();\n    }\n    await this.adapter.disconnect();\n    this.adapter = null;\n    this.databaseService = null;\n  }\n\n  // 建立新连接\n  console.error(`🔌 正在连接 ${newConfig.type} 数据库...`);\n  const adapter = createAdapter(newConfig);\n  await adapter.connect();\n\n  this.adapter = adapter;\n  this.config = newConfig;\n  this.databaseService = new DatabaseService(adapter, newConfig, this.cacheConfig);\n\n  const connInfo = newConfig.type === 'sqlite'\n    ? `SQLite: ${newConfig.filePath}`\n    : `${newConfig.type}: ${newConfig.host}:${newConfig.port}/${newConfig.database || '(default)'}`;\n\n  console.error(`✅ 数据库连接成功: ${connInfo}`);\n\n  return {\n    content: [{\n      type: 'text',\n      text: JSON.stringify({\n        success: true,\n        message: `已成功连接到 ${connInfo}`,\n        connection: {\n          type: newConfig.type,\n          host: newConfig.host,\n          port: newConfig.port,\n          database: newConfig.database,\n          permissionMode: newConfig.permissionMode || 'safe',\n        },\n      }, null, 2),\n    }],\n  };\n}\n\ncase 'disconnect_database': {\n  if (!this.adapter) {\n    return {\n      content: [{\n        type: 'text',\n        text: JSON.stringify({ success: true, message: '当前没有活跃的数据库连接' }, null, 2),\n      }],\n    };\n  }\n\n  if (this.databaseService) {\n    this.databaseService.clearSchemaCache();\n  }\n  await this.adapter.disconnect();\n\n  const oldType = this.config?.type;\n  this.adapter = null;\n  this.config = null;\n  this.databaseService = null;\n\n  console.error('👋 数据库连接已断开');\n\n  return {\n    content: [{\n      type: 'text',\n      text: JSON.stringify({\n        success: true,\n        message: `已断开 ${oldType || ''} 数据库连接`,\n      }, null, 2),\n    }],\n  };\n}\n\ncase 'get_connection_status': {\n  if (!this.adapter || !this.config) {\n    return {\n      content: [{\n        type: 'text',\n        text: JSON.stringify({\n          connected: false,\n          message: '当前未连接任何数据库。请使用 connect_database 工具连接。',\n        }, null, 2),\n      }],\n    };\n  }\n\n  const status: Record<string, any> = {\n    connected: true,\n    type: this.config.type,\n    permissionMode: this.config.permissionMode || 'safe',\n  };\n\n  if (this.config.type === 'sqlite') {\n    status.filePath = this.config.filePath;\n  } else {\n    status.host = this.config.host;\n    status.port = this.config.port;\n    status.database = this.config.database;\n  }\n\n  if (this.databaseService) {\n    const cacheStats = this.databaseService.getCacheStats();\n    status.schemaCache = {\n      cached: cacheStats.isCached,\n      hitRate: this.databaseService.getCacheHitRate() + '%',\n    };\n  }\n\n  return {\n    content: [{\n      type: 'text',\n      text: JSON.stringify(status, null, 2),\n    }],\n  };\n}\n```\n\n**1e) 现有 tool 的未连接提示优化**\n\n将现有的未连接判断：\n\n```typescript\n// 改前\nif (!this.databaseService) {\n  throw new Error('数据库未连接。请检查配置并重启服务。');\n}\n\n// 改后\nif (!this.databaseService) {\n  throw new Error('数据库未连接。请先使用 connect_database 工具连接数据库。');\n}\n```\n\n**1f) `start()` 方法 — 初始连接改为可选**\n\n```typescript\n// 改前\nasync start(): Promise<void> {\n  await this.connectDatabase();\n  const transport = new StdioServerTransport();\n  await this.server.connect(transport);\n  console.error('🚀 MCP 服务器已启动，等待 Claude Desktop 连接...');\n}\n\n// 改后\nasync start(): Promise<void> {\n  // 如果有初始配置和适配器，先连接；否则等待 AI 调用 connect_database\n  if (this.adapter) {\n    await this.connectDatabase();\n  } else {\n    console.error('📡 MCP 服务器以无连接模式启动，等待通过 connect_database 工具连接数据库...');\n  }\n  const transport = new StdioServerTransport();\n  await this.server.connect(transport);\n  console.error('🚀 MCP 服务器已启动，等待客户端连接...');\n}\n```\n\n#### 改动 2：`src/mcp/mcp-index.ts`\n\n**2a) `--type` 从 requiredOption 改为 option**\n\n```typescript\n// 改前\n.requiredOption('--type <type>', '数据库类型 (mysql|postgres|...)')\n\n// 改后\n.option('--type <type>', '数据库类型 (mysql|postgres|...)。不指定则以无连接模式启动，可在对话中通过 connect_database 动态连接。')\n```\n\n**2b) action 中处理无 type 的情况**\n\n```typescript\n.action(async (options) => {\n  try {\n    if (options.type) {\n      // === 有初始配置：和现在完全一样的逻辑 ===\n      const dbType = normalizeDbType(options.type);\n      const config: DbConfig = {\n        type: dbType as any,\n        host: options.host,\n        port: options.port,\n        // ... 其余不变\n      };\n\n      const server = new DatabaseMCPServer(config);\n      const adapter = createAdapter(config);\n      server.setAdapter(adapter);\n      await server.start();\n\n      // ... graceful shutdown 逻辑不变\n    } else {\n      // === 无初始配置：无连接模式启动 ===\n      console.error('📡 无连接模式：未指定数据库类型，等待通过 connect_database 工具动态连接...');\n      console.error('');\n\n      const server = new DatabaseMCPServer();  // 不传 config\n      await server.start();\n\n      // ... graceful shutdown 逻辑同上（复用）\n    }\n  } catch (error) {\n    // ... 不变\n  }\n});\n```\n\n### 6.3 不需要改动的文件\n\n以下文件完全不需要改动：\n\n| 文件/目录 | 原因 |\n|----------|------|\n| `src/adapters/*.ts`（全部 17 个适配器） | 适配器本身没有问题，`createAdapter()` 已能正确创建所有类型 |\n| `src/utils/adapter-factory.ts` | 工厂函数已完善，直接复用 |\n| `src/utils/safety.ts` | 权限校验逻辑不变 |\n| `src/core/connection-manager.ts` | 仅 HTTP 模式使用，不受影响 |\n| `src/core/database-service.ts` | 业务逻辑层不变 |\n| `src/http/**` | HTTP/SSE/Streamable 模式不受影响 |\n| `src/types/adapter.ts` | 类型定义不需要变更 |\n\n### 6.4 向后兼容性保证\n\n| 场景 | 改动前 | 改动后 |\n|------|-------|-------|\n| `--type mysql --host ...` 启动 | 正常连接 | 行为完全一致 |\n| 不传 `--type` 启动 | 报错退出 | 无连接模式启动，等待动态连接 |\n| HTTP 模式 `POST /api/connect` | 正常 | 不受影响 |\n| SSE 模式 `GET /sse?type=...` | 正常 | 不受影响 |\n| Streamable HTTP `POST /mcp` | 正常 | 不受影响 |\n\n### 6.5 17 种适配器兼容性\n\n所有适配器通过 `createAdapter()` 统一创建，`connect_database` tool 内部调用的就是同一个工厂函数，因此 17 种数据库全部自动支持：\n\n| 适配器 | 动态连接支持 | 说明 |\n|--------|------------|------|\n| mysql | ✅ | 通过 createAdapter 创建 MySQLAdapter |\n| postgres | ✅ | 通过 createAdapter 创建 PostgreSQLAdapter |\n| redis | ✅ | 通过 createAdapter 创建 RedisAdapter |\n| oracle | ✅ | 支持 oracleClientPath 参数 |\n| dm | ✅ | 达梦数据库 |\n| sqlserver | ✅ | 支持 mssql 别名 |\n| mongodb | ✅ | 支持 authSource 参数 |\n| sqlite | ✅ | 通过 filePath 参数指定文件 |\n| kingbase | ✅ | 人大金仓 |\n| gaussdb | ✅ | 华为 GaussDB，支持 opengauss 别名 |\n| oceanbase | ✅ | 蚂蚁 OceanBase |\n| tidb | ✅ | PingCAP TiDB |\n| clickhouse | ✅ | ClickHouse |\n| polardb | ✅ | 阿里云 PolarDB |\n| vastbase | ✅ | 海量数据 Vastbase |\n| highgo | ✅ | 瀚高数据库 |\n| goldendb | ✅ | 中兴 GoldenDB |\n\n### 6.6 四种传输模式兼容性\n\n| 传输模式 | 改动影响 | 动态连接方式 |\n|---------|---------|------------|\n| stdio（MCP） | 本次改动目标 | 通过 `connect_database` tool |\n| REST API（HTTP） | 不受影响 | 通过 `POST /api/connect` |\n| SSE | 不受影响 | 通过 URL query 参数 |\n| Streamable HTTP | 不受影响 | 通过 `X-DB-*` 请求头 |\n\n---\n\n## 七、实施步骤\n\n### Step 1：修改 `src/mcp/mcp-server.ts`\n\n1. 新增 `createAdapter` 和 `normalizeDbType` 的 import\n2. `config` 属性类型改为 `DbConfig | null`，构造函数参数改为可选\n3. `setupHandlers()` 中 `ListToolsRequestSchema` 追加 3 个 tool 定义\n4. `setupHandlers()` 中 `CallToolRequestSchema` 追加 3 个 case（connect_database、disconnect_database、get_connection_status）\n5. 现有 tool 的未连接错误提示改为引导使用 `connect_database`\n6. `start()` 方法中初始连接改为条件执行\n7. `stop()` 方法兼容 config 为 null 的情况\n\n### Step 2：修改 `src/mcp/mcp-index.ts`\n\n1. `--type` 从 `requiredOption` 改为 `option`\n2. action 中增加 `if (options.type)` 分支，无 type 时以无连接模式启动\n\n### Step 3：测试验证\n\n1. 有 `--type` 参数启动 → 行为与改动前一致\n2. 无参数启动 → 无连接模式，tool 列表包含 connect_database\n3. 调用 connect_database 连接 → 连接成功，后续 execute_query 等正常工作\n4. 调用 connect_database 切换 → 旧连接断开，新连接建立\n5. 调用 disconnect_database → 连接断开，execute_query 提示需要先连接\n6. 调用 get_connection_status → 正确返回当前状态\n7. HTTP/SSE/Streamable 模式 → 功能不受影响\n\n---\n\n## 八、改动量总结\n\n| 指标 | 数值 |\n|------|------|\n| 改动文件数 | 2 |\n| 新增代码行数（估算） | ~120 行 |\n| 删除代码行数 | ~3 行（requiredOption 改 option、错误提示文案） |\n| 涉及适配器改动 | 0（全部 17 种自动兼容） |\n| 涉及传输模式改动 | 0（4 种模式全部兼容） |\n| 破坏性变更 | 无 |\n"
  },
  {
    "path": "docs/plan/fix-stdio-graceful-shutdown.md",
    "content": "# Fix: stdio MCP Server 进程无法正常退出\n\n> Issue 来源: GitHub Issue — \"stdio MCP server does not exit cleanly when Codex CLI session closes\"\n\n---\n\n## 一、问题描述\n\n当 `universal-db-mcp` 作为 **stdio MCP server** 被 Codex CLI 调用时，数据库查询功能一切正常，但用户在 Codex 中执行 `/exit` 后：\n\n- Codex 打印了正常的会话结束信息（token 用量、resume 提示）\n- **终端提示符不返回**，进程挂起\n- 必须手动按 `Ctrl+C` 才能回到 shell\n\n用户已验证：移除 MCP 配置后 `/exit` 正常工作，说明问题出在 MCP server 的进程生命周期管理上。\n\n### 复现环境\n\n| 项目 | 值 |\n|------|-----|\n| universal-db-mcp | 2.9.0+（当前 2.12.0 仍存在） |\n| Codex CLI | 0.114.0+ |\n| OS | Windows |\n| 数据库 | PostgreSQL |\n| MCP 模式 | stdio |\n\n---\n\n## 二、问题分析\n\n### 2.1 代码审计结果\n\n#### 文件 1: `src/mcp/mcp-index.ts` (第 94-105 行)\n\n当前 graceful shutdown 仅处理了两种 POSIX 信号：\n\n```typescript\n// Graceful shutdown\nprocess.on('SIGINT', async () => {\n  console.error('\\n⏹️  收到退出信号，正在关闭服务器...');\n  await server.stop();\n  process.exit(0);\n});\n\nprocess.on('SIGTERM', async () => {\n  console.error('\\n⏹️  收到终止信号，正在关闭服务器...');\n  await server.stop();\n  process.exit(0);\n});\n```\n\n**缺失：** 没有监听 `process.stdin` 的 `end` / `close` 事件。\n\n#### 文件 2: `src/mcp/mcp-server.ts` (第 392-401 行)\n\n`stop()` 方法只清理了数据库层，没有关闭 MCP Server 本身：\n\n```typescript\nasync stop(): Promise<void> {\n  if (this.databaseService) {\n    this.databaseService.clearSchemaCache();\n  }\n  if (this.adapter) {\n    await this.adapter.disconnect();\n    console.error('👋 数据库连接已关闭');\n  }\n  // ❌ 缺少: await this.server.close()\n}\n```\n\n#### 文件 3: SDK `StdioServerTransport` (node_modules)\n\nSDK 的 stdio transport 只监听了 `data` 和 `error`，**没有监听 `end`/`close`**：\n\n```javascript\nasync start() {\n    this._stdin.on('data', this._ondata);\n    this._stdin.on('error', this._onerror);\n    // ❌ 没有监听 stdin 的 end/close\n}\n```\n\n### 2.2 根因链路\n\n```\nCodex CLI 执行 /exit\n  → Codex 关闭子进程的 stdin 管道（EOF）\n  → 但不一定发送 SIGINT/SIGTERM（尤其在 Windows 上）\n  → universal-db-mcp 没有监听 stdin.end / stdin.close\n  → MCP Server 实例未被 close()（transport 层仍持有 stdin/stdout 引用）\n  → 数据库连接池仍然活跃（pg.Pool keepAlive: true, idleTimeoutMillis: 60000）\n  → Node.js 事件循环中存在活跃 handle，无法自动退出\n  → 进程挂起 ❌\n```\n\n### 2.3 影响范围\n\n| 传输模式 | 是否受影响 | 原因 |\n|----------|-----------|------|\n| **stdio** | ✅ 受影响 | 直接命中：缺少 stdin 关闭监听 + stop() 不完整 |\n| **SSE** | ⚠️ 间接受影响 | `stop()` 不调用 `server.close()`，资源清理不完整 |\n| **Streamable HTTP** | ⚠️ 间接受影响 | 同上，`cleanupSession()` 调用 `stop()` 但 MCP Server 未关闭 |\n| **REST API** | ✅ 不受影响 | HTTP 模式有独立的 shutdown 逻辑（`fastify.close()`） |\n\n所有 17 种数据库适配器均受影响，因为问题出在传输层和进程生命周期管理，不在适配器层。\n\n---\n\n## 三、问题原因总结\n\n1. **stdin 生命周期未监听**：stdio 模式下没有监听 `process.stdin` 的 `end`/`close` 事件，当 MCP 客户端关闭 stdin 管道时服务器无感知\n2. **MCP Server 未正确关闭**：`stop()` 方法缺少 `this.server.close()` 调用，导致 transport 层资源（stdin/stdout 监听器）未被释放\n3. **无超时保护**：shutdown 过程中如果数据库断连或 `server.close()` 挂起，没有超时兜底机制\n4. **无重入保护**：多个退出信号可能同时触发（如 stdin close + SIGINT），导致 `stop()` 被重复执行\n5. **Windows 兼容性**：Windows 上 SIGTERM 支持有限，更依赖 stdin 关闭来检测父进程退出\n\n---\n\n## 四、最佳解决方案\n\n### 4.1 设计原则\n\n- 改动最小化：只修改必要的文件，不影响现有功能\n- 全模式兼容：stdio / SSE / Streamable HTTP / REST 四种传输模式均正常工作\n- 全适配器兼容：17 种数据库适配器无需任何修改\n- 超时兜底：防止 shutdown 过程本身挂起\n- 重入安全：多信号并发时只执行一次 shutdown\n- Windows 友好：不依赖 POSIX-only 的信号机制\n\n### 4.2 修改文件清单\n\n| 文件 | 修改内容 | 影响范围 |\n|------|---------|---------|\n| `src/mcp/mcp-server.ts` | `stop()` 中增加 `this.server.close()` | 所有模式（stdio/SSE/Streamable HTTP） |\n| `src/mcp/mcp-index.ts` | 添加统一 graceful shutdown + stdin 监听 | 仅 stdio 模式 |\n\n**不需要修改的文件：**\n- 17 个数据库适配器 — 问题不在适配器层\n- `src/http/http-index.ts` — HTTP 模式有独立的 shutdown 逻辑，已正常工作\n- `src/http/routes/mcp-sse.ts` — SSE/Streamable 的 `cleanupSession()` 调用 `stop()`，修复 `stop()` 后自动受益\n- `src/index.ts` — 入口文件无需修改\n\n### 4.3 具体修改方案\n\n#### 修改 1: `src/mcp/mcp-server.ts` — 完善 `stop()` 方法\n\n**修改位置：** 第 392-401 行\n\n**修改前：**\n```typescript\nasync stop(): Promise<void> {\n  if (this.databaseService) {\n    this.databaseService.clearSchemaCache();\n  }\n  if (this.adapter) {\n    await this.adapter.disconnect();\n    console.error('👋 数据库连接已关闭');\n  }\n}\n```\n\n**修改后：**\n```typescript\nasync stop(): Promise<void> {\n  // 1. 关闭 MCP Server（释放 transport 层资源：stdin/stdout 监听器等）\n  try {\n    await this.server.close();\n  } catch (err) {\n    console.error('关闭 MCP Server 时出错:', err instanceof Error ? err.message : String(err));\n  }\n\n  // 2. 清理 Schema 缓存\n  if (this.databaseService) {\n    this.databaseService.clearSchemaCache();\n  }\n\n  // 3. 断开数据库连接\n  if (this.adapter) {\n    await this.adapter.disconnect();\n    console.error('👋 数据库连接已关闭');\n  }\n}\n```\n\n**修改理由：**\n- 先关闭 MCP Server，释放 transport 层持有的 stdin/stdout 引用\n- `server.close()` 内部会调用 `transport.close()`，移除 stdin 上的 `data`/`error` 监听器并 pause stdin\n- 这使得 SSE 和 Streamable HTTP 模式的 `cleanupSession()` 也能正确释放 transport 资源\n- 用 try-catch 包裹，防止 close 失败阻塞后续的数据库断连\n\n#### 修改 2: `src/mcp/mcp-index.ts` — 统一 graceful shutdown + stdin 监听\n\n**修改位置：** 第 84-111 行（`action` 回调内部）\n\n**修改前：**\n```typescript\n// Set adapter and start server\nserver.setAdapter(adapter);\nawait server.start();\n\n// Graceful shutdown\nprocess.on('SIGINT', async () => {\n  console.error('\\n⏹️  收到退出信号，正在关闭服务器...');\n  await server.stop();\n  process.exit(0);\n});\n\nprocess.on('SIGTERM', async () => {\n  console.error('\\n⏹️  收到终止信号，正在关闭服务器...');\n  await server.stop();\n  process.exit(0);\n});\n```\n\n**修改后：**\n```typescript\n// Set adapter and start server\nserver.setAdapter(adapter);\nawait server.start();\n\n// 统一的 graceful shutdown（防重入 + 超时保护）\nlet shuttingDown = false;\n\nasync function gracefulShutdown(reason: string): Promise<void> {\n  if (shuttingDown) return;\n  shuttingDown = true;\n\n  console.error(`\\n⏹️  正在关闭服务器 (${reason})...`);\n\n  try {\n    await Promise.race([\n      server.stop(),\n      new Promise<void>((resolve) => setTimeout(() => {\n        console.error('⚠️  关闭超时，强制退出');\n        resolve();\n      }, 5000)),\n    ]);\n  } catch (err) {\n    console.error('关闭过程中出错:', err instanceof Error ? err.message : String(err));\n  } finally {\n    process.exit(0);\n  }\n}\n\n// 信号处理\nprocess.on('SIGINT', () => gracefulShutdown('SIGINT'));\nprocess.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n\n// stdin 关闭处理（核心修复）\n// 当 MCP 客户端（如 Codex CLI）关闭 stdin 管道时触发\nprocess.stdin.resume();\nprocess.stdin.on('end', () => gracefulShutdown('stdin-end'));\nprocess.stdin.on('close', () => gracefulShutdown('stdin-close'));\n```\n\n**修改理由：**\n\n1. **`process.stdin.resume()`**：确保 stdin 处于流动模式（flowing mode），否则 `end` 事件可能不会触发。虽然 `StdioServerTransport.start()` 内部会调用 `stdin.on('data', ...)` 使 stdin 进入流动模式，但显式调用 `resume()` 更安全，确保即使 SDK 行为变化也能正确工作。\n\n2. **`stdin.on('end', ...)`**：当 MCP 客户端关闭 stdin 管道（发送 EOF）时触发。这是 Codex CLI `/exit` 的主要退出路径。\n\n3. **`stdin.on('close', ...)`**：当 stdin 流被完全销毁时触发。作为 `end` 的补充保障。\n\n4. **`shuttingDown` 标志**：防止多个事件（如 `end` + `close` 同时触发，或 `stdin-end` + `SIGINT`）导致 `stop()` 被重复执行。\n\n5. **`Promise.race` 超时保护**：5 秒超时兜底。如果数据库连接池断连挂起（如远程数据库网络不可达），不会导致进程永远无法退出。\n\n### 4.4 修改后的调用链路\n\n```\n场景 A: Codex CLI /exit（stdin 关闭）\n  → process.stdin 'end' 事件触发\n  → gracefulShutdown('stdin-end')\n  → server.stop()\n    → this.server.close()        ← 释放 transport（移除 stdin 监听器）\n    → this.adapter.disconnect()  ← 关闭数据库连接池\n  → process.exit(0)\n  → 进程正常退出 ✅\n\n场景 B: Ctrl+C（SIGINT）\n  → process 'SIGINT' 事件触发\n  → gracefulShutdown('SIGINT')\n  → 同上 ✅\n\n场景 C: 系统终止（SIGTERM）\n  → process 'SIGTERM' 事件触发\n  → gracefulShutdown('SIGTERM')\n  → 同上 ✅\n\n场景 D: 数据库断连超时\n  → gracefulShutdown(任意原因)\n  → server.stop() 中 adapter.disconnect() 挂起\n  → 5 秒后超时保护触发\n  → process.exit(0)\n  → 进程强制退出 ✅\n```\n\n### 4.5 对各传输模式的影响\n\n| 传输模式 | 影响 | 说明 |\n|----------|------|------|\n| **stdio** | ✅ 直接修复 | 新增 stdin 监听 + 完善 stop() |\n| **SSE** | ✅ 间接受益 | `cleanupSession()` → `stop()` 现在会正确调用 `server.close()` |\n| **Streamable HTTP** | ✅ 间接受益 | 同上 |\n| **REST API** | ✅ 无影响 | HTTP 模式不经过 `mcp-server.ts`，有独立的 shutdown 逻辑 |\n\n### 4.6 对 17 种数据库适配器的影响\n\n**零影响。** 所有适配器的 `disconnect()` 方法签名和行为不变，修改仅在传输层和进程生命周期管理层。\n\n| 适配器 | disconnect() 实现 | 影响 |\n|--------|-------------------|------|\n| PostgreSQL | `pool.end()` | 无 |\n| MySQL | `pool.end()` | 无 |\n| SQLite | `db.close()` | 无 |\n| Redis | `client.quit()` | 无 |\n| Oracle | `pool.close(0)` | 无 |\n| SQL Server | `pool.close()` | 无 |\n| MongoDB | `client.close()` | 无 |\n| ClickHouse | `client.close()` | 无 |\n| 达梦 (DM) | `connection.close()` | 无 |\n| 人大金仓 (KingBase) | `pool.end()` | 无 |\n| 华为高斯 (GaussDB) | `pool.end()` | 无 |\n| OceanBase | `pool.end()` | 无 |\n| TiDB | `pool.end()` | 无 |\n| PolarDB | `pool.end()` | 无 |\n| 海量 (VastBase) | `pool.end()` | 无 |\n| 瀚高 (HighGo) | `pool.end()` | 无 |\n| 中兴 (GoldenDB) | `pool.end()` | 无 |\n\n---\n\n## 五、验证方案\n\n### 5.1 stdio 模式验证\n\n```bash\n# 1. 构建项目\nnpm run build\n\n# 2. 用 Codex CLI 注册并测试\ncodex mcp add test-pg -- universal-db-mcp --type postgres --host <host> --port 5432 --user <user> --password <pass> --database <db>\n\n# 3. 启动 Codex，执行查询，然后 /exit\n# 预期：进程正常退出，终端提示符立即返回\n```\n\n### 5.2 手动 stdin 关闭测试\n\n```bash\n# 模拟 stdin 关闭\necho '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"capabilities\":{}},\"id\":1}' | node dist/index.js --type sqlite --file test.db\n\n# 预期：stdin EOF 后进程在几秒内自动退出\n```\n\n### 5.3 SSE / Streamable HTTP 模式验证\n\n```bash\n# 启动 HTTP 模式\nMODE=http node dist/index.js\n\n# 建立 SSE 连接，执行操作，然后断开\n# 预期：cleanupSession 正确释放所有资源\n```\n\n---\n\n## 六、风险评估\n\n| 风险项 | 等级 | 缓解措施 |\n|--------|------|---------|\n| `server.close()` 抛异常 | 低 | 已用 try-catch 包裹 |\n| stdin end/close 在某些平台不触发 | 低 | 保留 SIGINT/SIGTERM 作为后备 |\n| 超时时间不够（大型连接池） | 低 | 5 秒对单连接池足够；可按需调整 |\n| `process.stdin.resume()` 副作用 | 极低 | SDK 的 `StdioServerTransport` 已经在监听 data 事件，stdin 本就处于流动模式 |\n\n---\n\n## 七、执行计划\n\n| 步骤 | 操作 | 文件 |\n|------|------|------|\n| 1 | 修改 `stop()` 方法，增加 `this.server.close()` | `src/mcp/mcp-server.ts` |\n| 2 | 重构 shutdown 逻辑，添加统一 gracefulShutdown + stdin 监听 | `src/mcp/mcp-index.ts` |\n| 3 | 执行 `npm run build` 验证编译通过 | — |\n| 4 | 运行现有测试 `npm test` | — |\n"
  },
  {
    "path": "docs/plan/multi-schema-support.md",
    "content": "# 多 Schema 支持方案 — 完整实施计划\n\n## 一、问题描述\n\n当数据库包含多个 Schema 时，`get_schema`、`get_table_info`、`list_tables`、`get_enum_values`、`get_sample_data` 等工具只能获取默认 Schema 下的表信息，无法访问其他 Schema 中的表。\n\n**Issue 来源**: [PostgreSQL 数据库中 get_table_info 无法获取非 public schema 的表信息](https://github.com)\n\n**复现步骤**:\n1. PostgreSQL 数据库中创建非 `public` schema（如 `analytics`）并在其中建表\n2. 调用 `get_schema` 或 `get_table_info` 工具\n3. 返回结果中仅包含 `public` schema 的表，非 `public` 的表不可见\n\n---\n\n## 二、问题分析\n\n### 2.1 问题根因\n\n问题分布在 **4 个层次**，形成完整的阻断链：\n\n#### 层次 1：Adapter 层 — SQL 查询硬编码默认 Schema（核心根因）\n\n各适配器的 `_getSchemaImpl()` 中，所有元数据查询 SQL 都硬编码了默认 Schema 过滤条件：\n\n| 数据库类型 | 硬编码过滤条件 | 默认 Schema |\n|-----------|--------------|------------|\n| PostgreSQL 系 | `nspname = 'public'` / `table_schema = 'public'` | `public` |\n| SQL Server | `SCHEMA_NAME()` / `SCHEMA_ID()` | `dbo` |\n| Oracle | `OWNER = USER` | 当前用户 |\n| 达梦 (DM) | `USER_*` 视图 | 当前用户 |\n\n每个受影响的适配器中有 **5 条 SQL 查询**被硬编码（列信息、主键、索引、行数/注释、外键）。\n\n#### 层次 2：类型定义层 — `TableInfo` 缺少 schema 字段\n\n`src/types/adapter.ts` 中 `TableInfo` 接口只有 `name: string`，没有 `schema` 字段：\n\n```typescript\nexport interface TableInfo {\n  name: string;       // 只有表名，无 schema\n  comment?: string;\n  columns: ColumnInfo[];\n  // ...\n}\n```\n\n即使适配器返回了多 Schema 的表，也无法区分 `public.users` 和 `analytics.users`。\n\n#### 层次 3：DatabaseService 层 — SQL 构建不支持 Schema 限定名\n\n`src/core/database-service.ts` 中的 `quoteIdentifier()` 将表名作为单一标识符处理：\n\n```typescript\nprivate quoteIdentifier(identifier: string): string {\n  return `\"${identifier}\"`;  // \"analytics.users\" 而非 \"analytics\".\"users\"\n}\n```\n\n`get_enum_values` 和 `get_sample_data` 构建的 SQL 均无法正确引用带 Schema 前缀的表名。\n\n#### 层次 4：工具/API 层 — 缺少 schema 参数\n\n- **MCP 工具**（`src/mcp/mcp-server.ts`）：`get_table_info`、`get_enum_values`、`get_sample_data` 的 inputSchema 中只有 `tableName`，无 `schema` 参数\n- **HTTP API**（`src/http/routes/schema.ts`）：`/api/schema/:table`、`/api/enum-values`、`/api/sample-data` 同样缺少 schema 参数\n\n### 2.2 影响链路\n\n```\n用户调用 get_table_info(\"analytics.users\")\n  → MCP/HTTP 层传递 tableName=\"analytics.users\"\n    → DatabaseService.getTableInfo() 调用 getSchema()\n      → Adapter.getSchema() 只查默认 Schema\n        → 返回的 tables[] 中不含 analytics schema 的表\n      → schema.tables.find(t.name === \"analytics.users\") → 找不到\n    → 抛出 \"表 analytics.users 不存在\"\n```\n\n### 2.3 传输模式影响\n\n所有传输模式共享同一条代码路径：\n\n```\n┌───────────────┐     ┌──────────────────┐     ┌──────────┐\n│ stdio (MCP)   │────→│                  │     │          │\n│ SSE (MCP)     │────→│ DatabaseService  │────→│ Adapter  │\n│ Streamable    │────→│ (核心业务层)      │     │ (数据库层)│\n│ REST (HTTP)   │────→│                  │     │          │\n└───────────────┘     └──────────────────┘     └──────────┘\n```\n\n因此，**修复 Adapter + DatabaseService 层即可覆盖全部 4 种传输模式**。\n\n---\n\n## 三、受影响的适配器\n\n### 3.1 存在问题的适配器（8 个）\n\n| # | 适配器文件 | 数据库类型 | 硬编码条件 | 严重程度 |\n|---|-----------|-----------|-----------|---------|\n| 1 | `src/adapters/postgres.ts` | PostgreSQL | `nspname = 'public'` | **高** |\n| 2 | `src/adapters/gaussdb.ts` | GaussDB/OpenGauss | `nspname = 'public'` | **高** |\n| 3 | `src/adapters/kingbase.ts` | KingbaseES | `nspname = 'public'` | **高** |\n| 4 | `src/adapters/vastbase.ts` | Vastbase | `nspname = 'public'` | **高** |\n| 5 | `src/adapters/highgo.ts` | HighGo | `nspname = 'public'` | **高** |\n| 6 | `src/adapters/sqlserver.ts` | SQL Server | `SCHEMA_NAME()` / `SCHEMA_ID()` | **高** |\n| 7 | `src/adapters/oracle.ts` | Oracle | `OWNER = USER` | **中** |\n| 8 | `src/adapters/dm.ts` | 达梦 | `USER_*` 视图 | **中** |\n\n### 3.2 不受影响的适配器（9 个）\n\n| # | 适配器文件 | 数据库类型 | 原因 |\n|---|-----------|-----------|------|\n| 9 | `src/adapters/mysql.ts` | MySQL | `DATABASE()` = schema，无多 schema 概念 |\n| 10 | `src/adapters/tidb.ts` | TiDB | MySQL 兼容，同上 |\n| 11 | `src/adapters/oceanbase.ts` | OceanBase | MySQL 兼容，同上 |\n| 12 | `src/adapters/polardb.ts` | PolarDB | MySQL 兼容，同上 |\n| 13 | `src/adapters/goldendb.ts` | GoldenDB | MySQL 兼容，同上 |\n| 14 | `src/adapters/clickhouse.ts` | ClickHouse | 按 database 隔离，无 schema 概念 |\n| 15 | `src/adapters/sqlite.ts` | SQLite | 单文件数据库，无 schema 概念 |\n| 16 | `src/adapters/mongodb.ts` | MongoDB | NoSQL，不适用 |\n| 17 | `src/adapters/redis.ts` | Redis | NoSQL，不适用 |\n\n### 3.3 各 SQL 查询硬编码位置汇总\n\n**PostgreSQL 系（5 个适配器 x 5 条 SQL = 25 处）**：\n\n| 查询 | postgres.ts | gaussdb.ts | kingbase.ts | vastbase.ts | highgo.ts |\n|------|:-----------:|:----------:|:-----------:|:-----------:|:---------:|\n| 列信息 | L185 | L175 | L181 | L182 | L187 |\n| 主键 | L200 | L190 | L196 | L197 | L202 |\n| 索引 | L217 | L207 | L213 | L214 | L219 |\n| 行数/注释 | L231 | L221 | L227 | L228 | L233 |\n| 外键 | L266 | L256 | L262 | L263 | L268 |\n\n**SQL Server（5 处）**：`sqlserver.ts` L205, L218, L235, L250, L271\n\n**Oracle（6 处）**：`oracle.ts` L211, L219, L230, L241, L251, L272\n\n**达梦（5 处）**：`dm.ts` L287-333（使用 `USER_*` 视图本身就是限制）\n\n---\n\n## 四、最佳最优解决方案\n\n### 4.1 设计原则\n\n1. **向后兼容**：public/dbo/当前用户 Schema 的表名保持不变，不影响现有用户\n2. **最小侵入**：核心改动集中在 Adapter SQL 和 DatabaseService，不改变整体架构\n3. **统一方案**：所有适配器遵循同一套 Schema 处理逻辑\n4. **安全可控**：使用排除系统 Schema 的方式，自动适配用户自定义 Schema\n5. **全模式兼容**：修复自动覆盖 stdio、SSE、Streamable、REST 全部传输模式\n\n### 4.2 修改概览\n\n```\n修改文件                            改动说明\n─────────────────────────────────────────────────────────────\nsrc/types/adapter.ts               TableInfo 增加 schema 可选字段\nsrc/core/database-service.ts       quoteIdentifier 支持 schema 限定名\n                                   getTableInfo 支持 schema.table 查找\nsrc/adapters/postgres.ts           SQL 去掉 public 硬编码，按 schema 分组\nsrc/adapters/gaussdb.ts            同上\nsrc/adapters/kingbase.ts           同上\nsrc/adapters/vastbase.ts           同上\nsrc/adapters/highgo.ts             同上\nsrc/adapters/sqlserver.ts          SQL 去掉 SCHEMA_NAME() 硬编码\nsrc/adapters/oracle.ts             SQL 改用 ALL_* + 排除系统用户\nsrc/adapters/dm.ts                 SQL 改用 ALL_* 视图 + 排除系统用户\nsrc/mcp/mcp-server.ts              MCP 工具增加可选 schema 参数\nsrc/http/routes/schema.ts          HTTP API 增加可选 schema 参数\n─────────────────────────────────────────────────────────────\n共 12 个文件\n```\n\n### 4.3 实施步骤\n\n---\n\n#### 步骤 1：修改 `src/types/adapter.ts` — TableInfo 增加 schema 字段\n\n**改动**：给 `TableInfo` 接口增加可选的 `schema` 字段。\n\n```typescript\nexport interface TableInfo {\n  /** 表名（非默认 schema 时格式为 schema.table_name） */\n  name: string;\n  /** 所属 Schema（可选，不同数据库含义不同：PG=schema, Oracle=owner, SQLServer=schema） */\n  schema?: string;\n  /** 表注释/描述 */\n  comment?: string;\n  // ... 其余字段不变\n}\n```\n\n**兼容性说明**：\n- `schema` 是可选字段，不影响不支持多 Schema 的适配器（MySQL 系、SQLite、ClickHouse、NoSQL）\n- 不支持多 Schema 的适配器无需任何改动，`schema` 字段自然为 `undefined`\n\n---\n\n#### 步骤 2：修改 `src/core/database-service.ts` — 核心服务层适配\n\n**改动 2a**：`quoteIdentifier()` 支持 Schema 限定名\n\n```typescript\nprivate quoteIdentifier(identifier: string): string {\n  const dbType = this.config.type;\n\n  // 检查是否包含 schema 限定（schema.table 格式）\n  const dotIndex = identifier.indexOf('.');\n  if (dotIndex > 0) {\n    const schema = identifier.substring(0, dotIndex);\n    const name = identifier.substring(dotIndex + 1);\n    return `${this.quoteSimpleIdentifier(schema)}.${this.quoteSimpleIdentifier(name)}`;\n  }\n\n  return this.quoteSimpleIdentifier(identifier);\n}\n\n/**\n * 引用单个标识符（不含 schema 前缀）\n */\nprivate quoteSimpleIdentifier(identifier: string): string {\n  const dbType = this.config.type;\n\n  switch (dbType) {\n    case 'mysql':\n    case 'tidb':\n    case 'oceanbase':\n    case 'polardb':\n    case 'goldendb':\n      return `\\`${identifier}\\``;\n    case 'sqlserver':\n      return `[${identifier}]`;\n    default:\n      return `\"${identifier}\"`;\n  }\n}\n```\n\n**改动 2b**：`getTableInfo()` 增强表名匹配逻辑\n\n```typescript\nasync getTableInfo(tableName: string, forceRefresh: boolean = false): Promise<TableInfo> {\n  const schema = await this.getSchema(forceRefresh);\n\n  // 优先精确匹配 name 字段（已包含 schema 前缀）\n  let table = schema.tables.find(t =>\n    t.name === tableName ||\n    t.name.toLowerCase() === tableName.toLowerCase()\n  );\n\n  // 如果没找到，尝试用 schema + name 组合匹配\n  if (!table && tableName.includes('.')) {\n    const [schemaName, tblName] = tableName.split('.', 2);\n    table = schema.tables.find(t =>\n      t.schema?.toLowerCase() === schemaName.toLowerCase() &&\n      (t.name === tblName || t.name.toLowerCase() === tblName.toLowerCase() ||\n       t.name.toLowerCase() === tableName.toLowerCase())\n    );\n  }\n\n  // 如果还没找到，尝试只匹配表名部分（不含 schema 前缀）\n  if (!table) {\n    const baseName = tableName.includes('.') ? tableName.split('.').pop()! : tableName;\n    const matches = schema.tables.filter(t => {\n      const tBaseName = t.name.includes('.') ? t.name.split('.').pop()! : t.name;\n      return tBaseName.toLowerCase() === baseName.toLowerCase();\n    });\n    if (matches.length === 1) {\n      table = matches[0];\n    }\n    // 多个匹配时不自动选择，让用户明确指定 schema\n  }\n\n  if (!table) {\n    throw new Error(`表 \"${tableName}\" 不存在`);\n  }\n\n  return table;\n}\n```\n\n---\n\n#### 步骤 3：修改 PostgreSQL 系适配器（5 个文件）\n\n以 `src/adapters/postgres.ts` 为例（其余 4 个适配器做相同改动）：\n\n**改动 3a**：修改 `_getSchemaImpl()` 中的 5 条 SQL 查询\n\n将所有 `WHERE c.table_schema = 'public'` 和 `AND n.nspname = 'public'` 替换为排除系统 Schema：\n\n```sql\n-- 列信息查询（改前）\nWHERE c.table_schema = 'public'\n  AND t.table_type = 'BASE TABLE'\n\n-- 列信息查询（改后）\nWHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n  AND t.table_type = 'BASE TABLE'\n```\n\n```sql\n-- pg_catalog 查询（改前）\nAND n.nspname = 'public'\n\n-- pg_catalog 查询（改后）\nAND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n```\n\n**改动 3b**：修改列信息查询，额外返回 `table_schema` 列\n\n```sql\nSELECT\n  c.table_schema,    -- 新增\n  c.table_name,\n  c.column_name,\n  -- ... 其余列不变\nFROM information_schema.columns c\nJOIN information_schema.tables t\n  ON c.table_schema = t.table_schema AND c.table_name = t.table_name\nWHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n  AND t.table_type = 'BASE TABLE'\nORDER BY c.table_schema, c.table_name, c.ordinal_position\n```\n\n**改动 3c**：修改其余 4 条 pg_catalog 查询，额外返回 `nspname`\n\n```sql\n-- 主键、索引、行数、外键查询都需要额外 SELECT n.nspname as schema_name\nSELECT\n  n.nspname as schema_name,  -- 新增\n  t.relname as table_name,\n  -- ... 其余列不变\n```\n\n**改动 3d**：修改 `assembleSchema()` — 按 schema + table_name 分组\n\n核心逻辑：\n\n```typescript\n// 构建带 schema 前缀的表名键\n// 默认 schema (public) 的表：直接用表名，保持向后兼容\n// 非默认 schema 的表：使用 schema.table_name 格式\nfunction makeTableKey(schemaName: string, tableName: string): string {\n  return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n}\n```\n\n在 `assembleSchema` 中组装 `TableInfo` 时设置 `schema` 字段：\n\n```typescript\ntableInfos.push({\n  name: tableKey,       // public 的表: \"users\", 非 public 的表: \"analytics.users\"\n  schema: schemaName,   // \"public\" / \"analytics\" / ...\n  comment: ...,\n  columns,\n  // ... 其余不变\n});\n```\n\n---\n\n#### 步骤 4：修改 SQL Server 适配器\n\n**文件**：`src/adapters/sqlserver.ts`\n\n**改动 4a**：修改 5 条 SQL 查询，去掉 `SCHEMA_NAME()` / `SCHEMA_ID()` 限制\n\n```sql\n-- 列信息（改前）\nWHERE t.TABLE_TYPE = 'BASE TABLE'\n  AND t.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\n  AND t.TABLE_SCHEMA = SCHEMA_NAME()\n\n-- 列信息（改后）\nWHERE t.TABLE_TYPE = 'BASE TABLE'\n  AND t.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n```\n\n```sql\n-- 主键（改前）\nWHERE tc.TABLE_SCHEMA = SCHEMA_NAME()\n\n-- 主键（改后）\nWHERE tc.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n```\n\n```sql\n-- 索引（改前）\nWHERE t.schema_id = SCHEMA_ID()\n\n-- 索引（改后）\nWHERE t.schema_id NOT IN (SCHEMA_ID('sys'), SCHEMA_ID('INFORMATION_SCHEMA'), SCHEMA_ID('guest'))\n  AND SCHEMA_NAME(t.schema_id) IS NOT NULL\n```\n\n```sql\n-- 行数（改前）\nWHERE t.schema_id = SCHEMA_ID()\n\n-- 行数（改后）\nWHERE t.schema_id NOT IN (SCHEMA_ID('sys'), SCHEMA_ID('INFORMATION_SCHEMA'), SCHEMA_ID('guest'))\n  AND SCHEMA_NAME(t.schema_id) IS NOT NULL\n```\n\n```sql\n-- 外键（改前）\nWHERE t.schema_id = SCHEMA_ID()\n\n-- 外键（改后）\nWHERE t.schema_id NOT IN (SCHEMA_ID('sys'), SCHEMA_ID('INFORMATION_SCHEMA'), SCHEMA_ID('guest'))\n  AND SCHEMA_NAME(t.schema_id) IS NOT NULL\n```\n\n**改动 4b**：额外 SELECT schema 列\n\n```sql\n-- INFORMATION_SCHEMA 查询额外返回 TABLE_SCHEMA\nSELECT c.TABLE_SCHEMA, c.TABLE_NAME, ...\n\n-- sys 查询额外返回 SCHEMA_NAME(t.schema_id)\nSELECT SCHEMA_NAME(t.schema_id) AS table_schema, t.name AS table_name, ...\n```\n\n**改动 4c**：`assembleSchema()` 使用 `dbo` 作为默认 schema\n\n```typescript\nfunction makeTableKey(schemaName: string, tableName: string): string {\n  return schemaName === 'dbo' ? tableName : `${schemaName}.${tableName}`;\n}\n```\n\n---\n\n#### 步骤 5：修改 Oracle 适配器\n\n**文件**：`src/adapters/oracle.ts`\n\n**改动 5a**：将 `OWNER = USER` 改为排除系统用户，改用 `ALL_*` 视图的完整能力\n\n```sql\n-- 列信息（改前）\nFROM ALL_TAB_COLUMNS WHERE OWNER = USER\n\n-- 列信息（改后）\nFROM ALL_TAB_COLUMNS\nWHERE OWNER NOT IN (\n  'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n  'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n  'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n  'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n)\n```\n\n对 `ALL_COL_COMMENTS`、`ALL_CONSTRAINTS`、`ALL_INDEXES`、`ALL_TABLES` 查询做同样的改动，并额外 SELECT `OWNER` 列。\n\n**改动 5b**：`assembleSchema()` 使用当前用户名作为默认 schema\n\n```typescript\n// 当前用户的表直接用表名，其他用户的表加 owner 前缀\nfunction makeTableKey(owner: string, tableName: string, currentUser: string): string {\n  return owner === currentUser ? tableName : `${owner}.${tableName}`;\n}\n```\n\n---\n\n#### 步骤 6：修改达梦（DM）适配器\n\n**文件**：`src/adapters/dm.ts`\n\n**改动 6a**：将 `USER_*` 视图改为 `ALL_*` 视图 + 排除系统用户\n\n```sql\n-- 改前\nFROM USER_TAB_COLUMNS\n\n-- 改后\nFROM ALL_TAB_COLUMNS\nWHERE OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n```\n\n对 `USER_COL_COMMENTS`、`USER_CONSTRAINTS`、`USER_INDEXES`、`USER_TABLES` 做同样的改动。\n\n**改动 6b**：`assembleSchemaFromIndexedRows()` 使用当前用户作为默认 schema\n\n与 Oracle 适配器逻辑一致。\n\n---\n\n#### 步骤 7：修改 MCP 工具定义\n\n**文件**：`src/mcp/mcp-server.ts`\n\n为 `get_table_info`、`get_enum_values`、`get_sample_data` 的 `inputSchema` 更新 `tableName` 的描述，说明支持 `schema.table_name` 格式：\n\n```typescript\n// get_table_info\ntableName: {\n  type: 'string',\n  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。不指定 Schema 时查询默认 Schema。',\n},\n\n// get_enum_values\ntableName: {\n  type: 'string',\n  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。',\n},\n\n// get_sample_data\ntableName: {\n  type: 'string',\n  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。',\n},\n```\n\n同时更新 `get_schema` 的描述：\n\n```typescript\ndescription: '获取数据库结构信息，包括所有 Schema 中用户可访问的表名、列名、数据类型、主键、索引等元数据。...',\n```\n\n---\n\n#### 步骤 8：修改 HTTP API 路由\n\n**文件**：`src/http/routes/schema.ts`\n\n更新 API schema 描述中 `tableName` 的说明，与 MCP 工具保持一致。HTTP API 的 `tableName` 参数同样支持 `schema.table_name` 格式。（实际逻辑已在 DatabaseService 层处理，这里只需更新文档描述。）\n\n---\n\n### 4.4 表名规则总结\n\n| 数据库类型 | 默认 Schema | 默认 Schema 表名格式 | 非默认 Schema 表名格式 |\n|-----------|-----------|-------------------|---------------------|\n| PostgreSQL 系 | `public` | `users` | `analytics.users` |\n| SQL Server | `dbo` | `users` | `sales.orders` |\n| Oracle | 当前 USER | `users` | `other_owner.users` |\n| 达梦 | 当前 USER | `users` | `other_schema.users` |\n| MySQL 系 | N/A | `users`（不变） | N/A |\n| 其他 | N/A | `users`（不变） | N/A |\n\n---\n\n### 4.5 各适配器系统 Schema 排除清单\n\n| 数据库类型 | 需排除的系统 Schema |\n|-----------|-------------------|\n| PostgreSQL 系 | `pg_catalog`, `information_schema`, `pg_toast` |\n| SQL Server | `sys`, `INFORMATION_SCHEMA`, `guest` |\n| Oracle | `SYS`, `SYSTEM`, `DBSNMP`, `APPQOSSYS`, `DBSFWUSER`, `OUTLN`, `GSMADMIN_INTERNAL`, `GGSYS`, `XDB`, `WMSYS`, `MDSYS`, `ORDDATA`, `CTXSYS`, `ORDSYS`, `OLAPSYS`, `LBACSYS`, `DVSYS`, `AUDSYS`, `OJVMSYS`, `REMOTE_SCHEDULER_AGENT` |\n| 达梦 | `SYS`, `SYSTEM`, `SYSAUDITOR`, `SYSSSO`, `SYSDBA`, `CTISYS` |\n\n---\n\n## 五、修改文件清单\n\n| # | 文件路径 | 改动说明 | 预估改动量 |\n|---|---------|---------|----------|\n| 1 | `src/types/adapter.ts` | `TableInfo` 增加 `schema?: string` | 1 行 |\n| 2 | `src/core/database-service.ts` | `quoteIdentifier` 拆分 + `getTableInfo` 增强匹配 | ~30 行 |\n| 3 | `src/adapters/postgres.ts` | 5 条 SQL 改 + assembleSchema 适配 | ~50 行 |\n| 4 | `src/adapters/gaussdb.ts` | 同 postgres | ~50 行 |\n| 5 | `src/adapters/kingbase.ts` | 同 postgres | ~50 行 |\n| 6 | `src/adapters/vastbase.ts` | 同 postgres | ~50 行 |\n| 7 | `src/adapters/highgo.ts` | 同 postgres | ~50 行 |\n| 8 | `src/adapters/sqlserver.ts` | 5 条 SQL 改 + assembleSchema 适配 | ~60 行 |\n| 9 | `src/adapters/oracle.ts` | 6 条 SQL 改 + assembleSchema 适配 | ~60 行 |\n| 10 | `src/adapters/dm.ts` | 5 条 SQL 改 + assembleSchema 适配 | ~60 行 |\n| 11 | `src/mcp/mcp-server.ts` | 工具描述更新 | ~10 行 |\n| 12 | `src/http/routes/schema.ts` | API 描述更新 | ~5 行 |\n\n**总计**：12 个文件，约 476 行改动\n\n---\n\n## 六、执行顺序\n\n```\n阶段 1: 基础设施（无破坏性）\n  ├─ Step 1: 修改 types/adapter.ts（增加 schema 字段）\n  └─ Step 2: 修改 database-service.ts（quoteIdentifier + getTableInfo）\n\n阶段 2: 适配器修改（按数据库族分批）\n  ├─ Step 3: 修改 PostgreSQL 系 5 个适配器\n  │   ├─ postgres.ts\n  │   ├─ gaussdb.ts\n  │   ├─ kingbase.ts\n  │   ├─ vastbase.ts\n  │   └─ highgo.ts\n  ├─ Step 4: 修改 sqlserver.ts\n  ├─ Step 5: 修改 oracle.ts\n  └─ Step 6: 修改 dm.ts\n\n阶段 3: 工具/API 层（最后修改，依赖前两阶段）\n  ├─ Step 7: 修改 mcp-server.ts（MCP 工具描述）\n  └─ Step 8: 修改 schema.ts（HTTP API 描述）\n\n阶段 4: 验证\n  └─ Step 9: TypeScript 编译验证\n```\n\n---\n\n## 七、向后兼容性保障\n\n| 场景 | 兼容性 | 说明 |\n|------|:-----:|------|\n| 现有用户使用 `get_table_info(\"users\")` | **兼容** | 默认 Schema 的表名不变 |\n| 现有用户使用 `get_schema` | **兼容** | 返回结果新增非默认 Schema 表，但原有表不变 |\n| `TableInfo.schema` 字段 | **兼容** | 可选字段，不影响现有消费者 |\n| MySQL 系 / SQLite / ClickHouse / NoSQL | **兼容** | 这些适配器不涉及任何改动 |\n| MCP 工具参数 | **兼容** | `tableName` 参数不变，仅更新描述文字 |\n| HTTP API 参数 | **兼容** | 同上 |\n| `get_enum_values` / `get_sample_data` SQL | **兼容** | `quoteIdentifier` 自动处理有无 schema 前缀 |\n\n---\n\n## 八、风险评估\n\n| 风险 | 等级 | 缓解措施 |\n|------|:----:|---------|\n| Oracle 系统用户排除清单不完整 | 低 | 采用业界通用清单，遗漏的系统用户表不会影响业务功能，仅多返回一些无用表 |\n| 同名表在不同 Schema 中冲突 | 低 | `getTableInfo` 多匹配时不自动选择，要求用户用 `schema.table` 明确指定 |\n| 大量 Schema 导致返回数据过多 | 低 | 企业环境通常 Schema 数量有限（< 20），且返回的是元数据非实际数据 |\n| 达梦 `ALL_*` 视图兼容性 | 低 | 达梦官方文档明确支持 `ALL_TAB_COLUMNS` 等视图 |\n"
  },
  {
    "path": "fly.toml",
    "content": "app = \"universal-db-mcp\"\nprimary_region = \"hkg\"\nkill_signal = \"SIGINT\"\nkill_timeout = \"5s\"\n\n[experimental]\n  auto_rollback = true\n\n[build]\n\n[deploy]\n  release_command = \"npm run build\"\n\n[env]\n  MODE = \"http\"\n  HTTP_PORT = \"8080\"\n  HTTP_HOST = \"0.0.0.0\"\n  NODE_ENV = \"production\"\n\n[http_service]\n  internal_port = 8080\n  force_https = true\n  auto_stop_machines = true\n  auto_start_machines = true\n  min_machines_running = 0\n  processes = [\"app\"]\n\n[[http_service.checks]]\n  grace_period = \"10s\"\n  interval = \"30s\"\n  method = \"GET\"\n  timeout = \"5s\"\n  path = \"/api/health\"\n\n[http_service.concurrency]\n  type = \"connections\"\n  hard_limit = 25\n  soft_limit = 20\n\n[[services]]\n  protocol = \"tcp\"\n  internal_port = 8080\n  processes = [\"app\"]\n\n  [[services.ports]]\n    port = 80\n    handlers = [\"http\"]\n    force_https = true\n\n  [[services.ports]]\n    port = 443\n    handlers = [\"tls\", \"http\"]\n\n  [services.concurrency]\n    type = \"connections\"\n    hard_limit = 25\n    soft_limit = 20\n\n  [[services.tcp_checks]]\n    interval = \"15s\"\n    timeout = \"2s\"\n    grace_period = \"5s\"\n    restart_limit = 0\n\n[[vm]]\n  memory = \"512mb\"\n  cpu_kind = \"shared\"\n  cpus = 1\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"universal-db-mcp\",\n  \"version\": \"2.14.0\",\n  \"description\": \"MCP 数据库万能连接器 - 让 Claude Desktop 直接连接你的数据库\",\n  \"main\": \"dist/index.js\",\n  \"bin\": {\n    \"universal-db-mcp\": \"dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"dev\": \"tsc --watch\",\n    \"dev:http\": \"tsc && cross-env MODE=http node dist/index.js\",\n    \"dev:mcp\": \"tsc && cross-env MODE=mcp node dist/index.js\",\n    \"prepare\": \"npm run build\",\n    \"start\": \"node dist/index.js\",\n    \"start:http\": \"cross-env MODE=http node dist/index.js\",\n    \"start:mcp\": \"cross-env MODE=mcp node dist/index.js\",\n    \"test\": \"vitest\",\n    \"test:unit\": \"vitest run tests/unit\",\n    \"test:integration\": \"vitest run tests/integration\"\n  },\n  \"keywords\": [\n    \"mcp\",\n    \"model-context-protocol\",\n    \"claude\",\n    \"database\",\n    \"mysql\",\n    \"postgresql\",\n    \"redis\",\n    \"oracle\",\n    \"dameng\",\n    \"dm\",\n    \"sqlserver\",\n    \"mssql\",\n    \"sql-server\",\n    \"mongodb\",\n    \"mongo\",\n    \"sqlite\",\n    \"kingbase\",\n    \"kingbasees\",\n    \"gaussdb\",\n    \"opengauss\",\n    \"oceanbase\",\n    \"tidb\",\n    \"pingcap\",\n    \"clickhouse\",\n    \"olap\",\n    \"polardb\",\n    \"阿里云\",\n    \"vastbase\",\n    \"海量数据\",\n    \"highgo\",\n    \"瀚高\",\n    \"goldendb\",\n    \"中兴\",\n    \"列式数据库\",\n    \"蚂蚁金服\",\n    \"华为高斯\",\n    \"人大金仓\",\n    \"数据库\",\n    \"AI\"\n  ],\n  \"author\": \"Anarkh-Lee\",\n  \"license\": \"MIT\",\n  \"files\": [\n    \"dist/**/*.js\",\n    \"dist/**/*.d.ts\",\n    \"dist/**/*.js.map\",\n    \"dist/**/*.d.ts.map\",\n    \"!dist/test.*\",\n    \"README.md\",\n    \"EXAMPLES.md\",\n    \"DEPLOYMENT.md\",\n    \"CONTRIBUTING.md\",\n    \"LICENSE\"\n  ],\n  \"dependencies\": {\n    \"@clickhouse/client\": \"^1.16.0\",\n    \"@fastify/cors\": \"^9.0.1\",\n    \"@fastify/rate-limit\": \"^9.1.0\",\n    \"@modelcontextprotocol/sdk\": \"^1.0.4\",\n    \"better-sqlite3\": \"^11.8.1\",\n    \"commander\": \"^12.1.0\",\n    \"dotenv\": \"^16.4.1\",\n    \"fastify\": \"^4.26.0\",\n    \"ioredis\": \"^5.4.2\",\n    \"mongodb\": \"^5.9.2\",\n    \"mssql\": \"^12.2.0\",\n    \"mysql2\": \"^3.11.5\",\n    \"nanoid\": \"^5.0.4\",\n    \"oracledb\": \"^6.7.0\",\n    \"pg\": \"^8.13.1\",\n    \"zod\": \"^3.24.1\"\n  },\n  \"devDependencies\": {\n    \"@types/better-sqlite3\": \"^7.6.12\",\n    \"@types/mssql\": \"^9.1.5\",\n    \"@types/node\": \"^22.10.5\",\n    \"@types/oracledb\": \"^6.5.1\",\n    \"@types/pg\": \"^8.11.10\",\n    \"@vitest/ui\": \"^1.2.0\",\n    \"cross-env\": \"^7.0.3\",\n    \"typescript\": \"^5.7.3\",\n    \"vitest\": \"^1.2.0\"\n  },\n  \"optionalDependencies\": {\n    \"dmdb\": \"^1.0.46190\"\n  },\n  \"engines\": {\n    \"node\": \">=20.0.0\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/Anarkh-Lee/universal-db-mcp.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/Anarkh-Lee/universal-db-mcp/issues\"\n  },\n  \"homepage\": \"https://github.com/Anarkh-Lee/universal-db-mcp#readme\"\n}\n"
  },
  {
    "path": "railway.json",
    "content": "{\n  \"$schema\": \"https://railway.app/railway.schema.json\",\n  \"build\": {\n    \"builder\": \"NIXPACKS\",\n    \"buildCommand\": \"npm install && npm run build\"\n  },\n  \"deploy\": {\n    \"startCommand\": \"npm run start:http\",\n    \"restartPolicyType\": \"ON_FAILURE\",\n    \"restartPolicyMaxRetries\": 10,\n    \"healthcheckPath\": \"/api/health\",\n    \"healthcheckTimeout\": 100\n  },\n  \"env\": {\n    \"MODE\": {\n      \"default\": \"http\"\n    },\n    \"PORT\": {\n      \"default\": \"3000\"\n    },\n    \"HTTP_PORT\": {\n      \"default\": \"3000\"\n    },\n    \"HTTP_HOST\": {\n      \"default\": \"0.0.0.0\"\n    },\n    \"NODE_ENV\": {\n      \"default\": \"production\"\n    }\n  }\n}\n"
  },
  {
    "path": "render.yaml",
    "content": "services:\n  - type: web\n    name: universal-db-mcp\n    runtime: node\n    env: node\n    region: singapore\n    plan: free\n    buildCommand: npm install && npm run build\n    startCommand: npm run start:http\n    envVars:\n      - key: MODE\n        value: http\n      - key: HTTP_PORT\n        value: 3000\n      - key: HTTP_HOST\n        value: 0.0.0.0\n      - key: NODE_ENV\n        value: production\n      - key: API_KEYS\n        sync: false\n      - key: CORS_ORIGINS\n        value: '*'\n      - key: RATE_LIMIT_MAX\n        value: 100\n      - key: RATE_LIMIT_WINDOW\n        value: 1m\n      - key: LOG_LEVEL\n        value: info\n    healthCheckPath: /api/health\n    autoDeploy: true\n    # scaling:\n    #   minInstances: 1\n    #   maxInstances: 3\n    #   targetCPUPercent: 70\n"
  },
  {
    "path": "serverless/aliyun-fc/index.js",
    "content": "/**\n * Aliyun Function Compute Handler\n * Adapter for Universal Database MCP Server\n */\n\nconst { createHttpServer } = require('../../dist/http/server.js');\nconst { loadConfig } = require('../../dist/utils/config-loader.js');\n\nlet server;\n\n/**\n * Initialize server (lazy loading)\n */\nasync function initServer() {\n  if (!server) {\n    const config = loadConfig();\n    server = await createHttpServer(config);\n  }\n  return server;\n}\n\n/**\n * Function Compute HTTP Handler\n */\nexports.handler = async (req, resp, context) => {\n  try {\n    const fastify = await initServer();\n\n    // Convert FC request to Fastify request format\n    const response = await fastify.inject({\n      method: req.method,\n      url: req.path + (req.queries ? '?' + new URLSearchParams(req.queries).toString() : ''),\n      headers: req.headers,\n      payload: req.body,\n    });\n\n    // Set response\n    resp.setStatusCode(response.statusCode);\n    resp.setHeader('Content-Type', response.headers['content-type'] || 'application/json');\n\n    // Set CORS headers\n    resp.setHeader('Access-Control-Allow-Origin', '*');\n    resp.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n    resp.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key');\n\n    resp.send(response.body);\n  } catch (error) {\n    console.error('Handler error:', error);\n    resp.setStatusCode(500);\n    resp.send(JSON.stringify({\n      success: false,\n      error: {\n        code: 'INTERNAL_ERROR',\n        message: error.message\n      }\n    }));\n  }\n};\n"
  },
  {
    "path": "serverless/aliyun-fc/template.yml",
    "content": "ROSTemplateFormatVersion: '2015-09-01'\nTransform: 'Aliyun::Serverless-2018-04-03'\n\nResources:\n  universal-db-mcp:\n    Type: 'Aliyun::Serverless::Service'\n    Properties:\n      Description: 'Universal Database MCP Server - HTTP API Mode'\n      Role: 'acs:ram::${AccountId}:role/aliyunfcdefaultrole'\n      InternetAccess: true\n      LogConfig:\n        Project: 'universal-db-mcp-logs'\n        Logstore: 'function-logs'\n      VpcConfig:\n        VpcId: 'vpc-xxxxx'  # Optional: Your VPC ID\n        VSwitchIds:\n          - 'vsw-xxxxx'  # Optional: Your VSwitch ID\n        SecurityGroupId: 'sg-xxxxx'  # Optional: Your Security Group ID\n\n    universal-db-api:\n      Type: 'Aliyun::Serverless::Function'\n      Properties:\n        Description: 'Universal Database MCP API Handler'\n        Handler: index.handler\n        Runtime: nodejs20\n        CodeUri: './'\n        MemorySize: 512\n        Timeout: 60\n        InstanceConcurrency: 10\n        EnvironmentVariables:\n          MODE: 'http'\n          HTTP_PORT: '9000'\n          API_KEYS: '${ApiKeys}'\n          CORS_ORIGINS: '*'\n          RATE_LIMIT_MAX: '100'\n          RATE_LIMIT_WINDOW: '1m'\n          LOG_LEVEL: 'info'\n          NODE_ENV: 'production'\n\n        Events:\n          httpTrigger:\n            Type: HTTP\n            Properties:\n              AuthType: ANONYMOUS\n              Methods:\n                - GET\n                - POST\n                - PUT\n                - DELETE\n                - OPTIONS\n              Domains:\n                - Domain: 'auto'  # Auto-generated domain\n                  Protocol:\n                    - HTTP\n                    - HTTPS\n                  RouteConfig:\n                    Routes:\n                      - Path: '/*'\n                        Qualifier: 'LATEST'\n"
  },
  {
    "path": "serverless/aws-lambda/index.js",
    "content": "/**\n * AWS Lambda Handler\n * Adapter for Universal Database MCP Server\n */\n\nconst { createHttpServer } = require('../../dist/http/server.js');\nconst { loadConfig } = require('../../dist/utils/config-loader.js');\n\nlet server;\n\n/**\n * Initialize server (lazy loading)\n */\nasync function initServer() {\n  if (!server) {\n    const config = loadConfig();\n    server = await createHttpServer(config);\n  }\n  return server;\n}\n\n/**\n * Lambda Handler\n */\nexports.handler = async (event, context) => {\n  try {\n    const fastify = await initServer();\n\n    // Parse API Gateway event\n    const { httpMethod, path, queryStringParameters, headers, body, isBase64Encoded } = event;\n\n    // Build URL\n    let url = path;\n    if (queryStringParameters) {\n      const params = new URLSearchParams(queryStringParameters).toString();\n      url += '?' + params;\n    }\n\n    // Decode body if base64\n    let payload = body;\n    if (isBase64Encoded && body) {\n      payload = Buffer.from(body, 'base64').toString('utf-8');\n    }\n\n    // Convert to Fastify request\n    const response = await fastify.inject({\n      method: httpMethod,\n      url: url,\n      headers: headers || {},\n      payload: payload,\n    });\n\n    // Return API Gateway response format\n    return {\n      isBase64Encoded: false,\n      statusCode: response.statusCode,\n      headers: {\n        'Content-Type': response.headers['content-type'] || 'application/json',\n        'Access-Control-Allow-Origin': '*',\n        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n        'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',\n      },\n      body: response.body,\n    };\n  } catch (error) {\n    console.error('Handler error:', error);\n    return {\n      isBase64Encoded: false,\n      statusCode: 500,\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        success: false,\n        error: {\n          code: 'INTERNAL_ERROR',\n          message: error.message\n        }\n      }),\n    };\n  }\n};\n"
  },
  {
    "path": "serverless/aws-lambda/template.yaml",
    "content": "AWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: Universal Database MCP Server - HTTP API Mode\n\nGlobals:\n  Function:\n    Timeout: 60\n    MemorySize: 512\n    Runtime: nodejs20.x\n    Architectures:\n      - x86_64\n    Environment:\n      Variables:\n        MODE: http\n        HTTP_PORT: 9000\n        API_KEYS: !Ref ApiKeys\n        CORS_ORIGINS: '*'\n        RATE_LIMIT_MAX: 100\n        RATE_LIMIT_WINDOW: 1m\n        LOG_LEVEL: info\n        NODE_ENV: production\n\nParameters:\n  ApiKeys:\n    Type: String\n    Description: API Keys (comma-separated)\n    NoEcho: true\n\nResources:\n  UniversalDbMcpFunction:\n    Type: AWS::Serverless::Function\n    Properties:\n      FunctionName: universal-db-mcp-api\n      Description: Universal Database MCP API Handler\n      CodeUri: ./\n      Handler: index.handler\n      Events:\n        ApiEvent:\n          Type: Api\n          Properties:\n            Path: /{proxy+}\n            Method: ANY\n            RestApiId: !Ref UniversalDbMcpApi\n      Policies:\n        - AWSLambdaBasicExecutionRole\n        - AWSLambdaVPCAccessExecutionRole\n      VpcConfig:\n        SecurityGroupIds:\n          - !Ref LambdaSecurityGroup\n        SubnetIds:\n          - !Ref PrivateSubnet1\n          - !Ref PrivateSubnet2\n\n  UniversalDbMcpApi:\n    Type: AWS::Serverless::Api\n    Properties:\n      Name: universal-db-mcp-api\n      StageName: prod\n      Cors:\n        AllowMethods: \"'GET,POST,PUT,DELETE,OPTIONS'\"\n        AllowHeaders: \"'Content-Type,Authorization,X-API-Key'\"\n        AllowOrigin: \"'*'\"\n      DefinitionBody:\n        openapi: 3.0.0\n        info:\n          title: Universal Database MCP API\n          version: 1.0.0\n        paths:\n          /{proxy+}:\n            x-amazon-apigateway-any-method:\n              x-amazon-apigateway-integration:\n                type: aws_proxy\n                httpMethod: POST\n                uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UniversalDbMcpFunction.Arn}/invocations\n\n  LambdaSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n      GroupDescription: Security group for Lambda function\n      VpcId: !Ref VPC\n      SecurityGroupEgress:\n        - IpProtocol: -1\n          CidrIp: 0.0.0.0/0\n\n  VPC:\n    Type: AWS::EC2::VPC\n    Properties:\n      CidrBlock: 10.0.0.0/16\n      EnableDnsHostnames: true\n      EnableDnsSupport: true\n\n  PrivateSubnet1:\n    Type: AWS::EC2::Subnet\n    Properties:\n      VpcId: !Ref VPC\n      CidrBlock: 10.0.1.0/24\n      AvailabilityZone: !Select [0, !GetAZs '']\n\n  PrivateSubnet2:\n    Type: AWS::EC2::Subnet\n    Properties:\n      VpcId: !Ref VPC\n      CidrBlock: 10.0.2.0/24\n      AvailabilityZone: !Select [1, !GetAZs '']\n\nOutputs:\n  ApiUrl:\n    Description: API Gateway endpoint URL\n    Value: !Sub https://${UniversalDbMcpApi}.execute-api.${AWS::Region}.amazonaws.com/prod/\n\n  FunctionArn:\n    Description: Lambda Function ARN\n    Value: !GetAtt UniversalDbMcpFunction.Arn\n"
  },
  {
    "path": "serverless/tencent-scf/index.js",
    "content": "/**\n * Tencent Cloud SCF Handler\n * Adapter for Universal Database MCP Server\n */\n\nconst { createHttpServer } = require('../../dist/http/server.js');\nconst { loadConfig } = require('../../dist/utils/config-loader.js');\n\nlet server;\n\n/**\n * Initialize server (lazy loading)\n */\nasync function initServer() {\n  if (!server) {\n    const config = loadConfig();\n    server = await createHttpServer(config);\n  }\n  return server;\n}\n\n/**\n * SCF HTTP Handler\n */\nexports.handler = async (event, context) => {\n  try {\n    const fastify = await initServer();\n\n    // Parse event\n    const { httpMethod, path, queryString, headers, body, isBase64Encoded } = event;\n\n    // Build URL\n    let url = path;\n    if (queryString) {\n      const params = Object.entries(queryString)\n        .map(([key, value]) => `${key}=${value}`)\n        .join('&');\n      url += '?' + params;\n    }\n\n    // Decode body if base64\n    let payload = body;\n    if (isBase64Encoded && body) {\n      payload = Buffer.from(body, 'base64').toString('utf-8');\n    }\n\n    // Convert to Fastify request\n    const response = await fastify.inject({\n      method: httpMethod,\n      url: url,\n      headers: headers || {},\n      payload: payload,\n    });\n\n    // Return SCF response format\n    return {\n      isBase64Encoded: false,\n      statusCode: response.statusCode,\n      headers: {\n        'Content-Type': response.headers['content-type'] || 'application/json',\n        'Access-Control-Allow-Origin': '*',\n        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n        'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',\n      },\n      body: response.body,\n    };\n  } catch (error) {\n    console.error('Handler error:', error);\n    return {\n      isBase64Encoded: false,\n      statusCode: 500,\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        success: false,\n        error: {\n          code: 'INTERNAL_ERROR',\n          message: error.message\n        }\n      }),\n    };\n  }\n};\n"
  },
  {
    "path": "serverless/tencent-scf/serverless.yml",
    "content": "component: scf\nname: universal-db-mcp\n\ninputs:\n  name: universal-db-mcp-api\n  src: ./\n  handler: index.handler\n  runtime: Nodejs20.15\n  region: ap-guangzhou\n  description: Universal Database MCP Server - HTTP API Mode\n  memorySize: 512\n  timeout: 60\n  initTimeout: 3\n  retryNum: 2\n\n  environment:\n    variables:\n      MODE: http\n      HTTP_PORT: 9000\n      API_KEYS: ${env:API_KEYS}\n      CORS_ORIGINS: '*'\n      RATE_LIMIT_MAX: 100\n      RATE_LIMIT_WINDOW: 1m\n      LOG_LEVEL: info\n      NODE_ENV: production\n\n  events:\n    - apigw:\n        name: universal-db-mcp-apigw\n        parameters:\n          protocols:\n            - http\n            - https\n          environment: release\n          netTypes:\n            - OUTER\n          serviceName: universal-db-mcp-service\n          description: Universal Database MCP API Gateway\n          endpoints:\n            - path: /\n              method: ANY\n              function:\n                functionName: universal-db-mcp-api\n                isIntegratedResponse: true\n              enableCORS: true\n              responseType: JSON\n              serviceTimeout: 60\n\n  layers:\n    - name: universal-db-mcp-deps\n      version: 1\n\n  vpc:\n    vpcId: ${env:VPC_ID}\n    subnetId: ${env:SUBNET_ID}\n\n  tags:\n    app: universal-db-mcp\n    env: production\n"
  },
  {
    "path": "serverless/vercel/api/index.js",
    "content": "/**\n * Vercel Serverless Function Handler\n * Adapter for Universal Database MCP Server\n */\n\nconst { createHttpServer } = require('../../../dist/http/server.js');\nconst { loadConfig } = require('../../../dist/utils/config-loader.js');\n\nlet server;\n\n/**\n * Initialize server (lazy loading)\n */\nasync function initServer() {\n  if (!server) {\n    const config = loadConfig();\n    server = await createHttpServer(config);\n  }\n  return server;\n}\n\n/**\n * Vercel Handler\n */\nmodule.exports = async (req, res) => {\n  try {\n    const fastify = await initServer();\n\n    // Convert Vercel request to Fastify request\n    const response = await fastify.inject({\n      method: req.method,\n      url: req.url,\n      headers: req.headers,\n      payload: req.body,\n    });\n\n    // Set response headers\n    res.statusCode = response.statusCode;\n    Object.entries(response.headers).forEach(([key, value]) => {\n      res.setHeader(key, value);\n    });\n\n    // Set CORS headers\n    res.setHeader('Access-Control-Allow-Origin', '*');\n    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key');\n\n    // Send response\n    res.end(response.body);\n  } catch (error) {\n    console.error('Handler error:', error);\n    res.statusCode = 500;\n    res.setHeader('Content-Type', 'application/json');\n    res.end(JSON.stringify({\n      success: false,\n      error: {\n        code: 'INTERNAL_ERROR',\n        message: error.message\n      }\n    }));\n  }\n};\n"
  },
  {
    "path": "serverless/vercel/vercel.json",
    "content": "{\n  \"version\": 2,\n  \"name\": \"universal-db-mcp\",\n  \"builds\": [\n    {\n      \"src\": \"serverless/vercel/api/index.js\",\n      \"use\": \"@vercel/node\",\n      \"config\": {\n        \"maxDuration\": 60\n      }\n    }\n  ],\n  \"routes\": [\n    {\n      \"src\": \"/api/(.*)\",\n      \"dest\": \"/serverless/vercel/api/index.js\"\n    },\n    {\n      \"src\": \"/(.*)\",\n      \"dest\": \"/serverless/vercel/api/index.js\"\n    }\n  ],\n  \"env\": {\n    \"MODE\": \"http\",\n    \"HTTP_PORT\": \"9000\",\n    \"API_KEYS\": \"@api_keys\",\n    \"CORS_ORIGINS\": \"*\",\n    \"RATE_LIMIT_MAX\": \"100\",\n    \"RATE_LIMIT_WINDOW\": \"1m\",\n    \"LOG_LEVEL\": \"info\",\n    \"NODE_ENV\": \"production\"\n  },\n  \"regions\": [\"hkg1\"]\n}\n"
  },
  {
    "path": "src/adapters/clickhouse.ts",
    "content": "/**\n * ClickHouse 数据库适配器\n * 使用 @clickhouse/client 驱动实现 DbAdapter 接口\n * ClickHouse 是高性能列式 OLAP 数据库\n */\n\nimport { createClient, ClickHouseClient } from '@clickhouse/client';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class ClickHouseAdapter implements DbAdapter {\n  private client: ClickHouseClient | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 连接到 ClickHouse 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.client = createClient({\n        host: `http://${this.config.host}:${this.config.port}`,\n        username: this.config.user || 'default',\n        password: this.config.password,\n        database: this.config.database || 'default',\n      });\n\n      // 测试连接\n      await this.client.ping();\n    } catch (error) {\n      throw new Error(\n        `ClickHouse 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.client) {\n      await this.client.close();\n      this.client = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.client) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      // ClickHouse 使用命名参数或位置参数\n      const result = await this.client.query({\n        query,\n        query_params: params ? this.convertParams(params) : undefined,\n        format: 'JSONEachRow',\n      });\n\n      const data = await result.json();\n      const rows = Array.isArray(data) ? data as Record<string, unknown>[] : [];\n      const executionTime = Date.now() - startTime;\n\n      // 检查是否为写操作\n      const isWrite = this.isWriteOperation(query);\n\n      return {\n        rows: rows || [],\n        affectedRows: isWrite ? rows?.length || 0 : undefined,\n        executionTime,\n        metadata: {\n          query_id: result.query_id,\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 转换参数为 ClickHouse 格式\n   */\n  private convertParams(params: unknown[]): Record<string, unknown> {\n    const result: Record<string, unknown> = {};\n    params.forEach((param, index) => {\n      result[`param${index + 1}`] = param;\n    });\n    return result;\n  }\n\n  /**\n   * 获取数据库结构信息\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.client) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      // 获取数据库版本\n      const versionResult = await this.client.query({\n        query: 'SELECT version() as version',\n        format: 'JSONEachRow',\n      });\n      const versionData = await versionResult.json() as Array<{ version: string }>;\n      const version = (Array.isArray(versionData) && versionData.length > 0) ? versionData[0]?.version : 'unknown';\n\n      // 获取当前数据库名\n      const databaseName = this.config.database || 'default';\n\n      // 获取所有表\n      const tablesResult = await this.client.query({\n        query: `\n          SELECT name\n          FROM system.tables\n          WHERE database = {database:String}\n            AND engine NOT IN ('View', 'MaterializedView')\n          ORDER BY name\n        `,\n        query_params: {\n          database: databaseName,\n        },\n        format: 'JSONEachRow',\n      });\n\n      const tablesData = await tablesResult.json() as Array<{ name: string }>;\n      const tables = Array.isArray(tablesData) ? tablesData : [];\n      const tableInfos: TableInfo[] = [];\n\n      for (const table of tables) {\n        const tableInfo = await this.getTableInfo(table?.name);\n        tableInfos.push(tableInfo);\n      }\n\n      return {\n        databaseType: 'clickhouse',\n        databaseName,\n        tables: tableInfos,\n        version,\n      };\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取单个表的详细信息\n   */\n  private async getTableInfo(tableName: string): Promise<TableInfo> {\n    if (!this.client) {\n      throw new Error('数据库未连接');\n    }\n\n    const databaseName = this.config.database || 'default';\n\n    // 获取列信息\n    const columnsResult = await this.client.query({\n      query: `\n        SELECT\n          name,\n          type,\n          default_kind,\n          default_expression,\n          comment\n        FROM system.columns\n        WHERE database = {database:String}\n          AND table = {table:String}\n        ORDER BY position\n      `,\n      query_params: {\n        database: databaseName,\n        table: tableName,\n      },\n      format: 'JSONEachRow',\n    });\n\n    const columnsData = await columnsResult.json() as Array<{\n      name: string;\n      type: string;\n      default_kind: string;\n      default_expression: string;\n      comment: string;\n    }>;\n    const columns = Array.isArray(columnsData) ? columnsData : [];\n\n    const columnInfos: ColumnInfo[] = columns.map((col) => ({\n      name: col?.name,\n      type: col?.type,\n      nullable: col?.type?.includes('Nullable') || false,\n      defaultValue: col?.default_expression || undefined,\n      comment: col?.comment || undefined,\n    }));\n\n    // 获取主键信息\n    const primaryKeyResult = await this.client.query({\n      query: `\n        SELECT primary_key\n        FROM system.tables\n        WHERE database = {database:String}\n          AND name = {table:String}\n      `,\n      query_params: {\n        database: databaseName,\n        table: tableName,\n      },\n      format: 'JSONEachRow',\n    });\n\n    const pkData = await primaryKeyResult.json() as Array<{ primary_key: string }>;\n    const primaryKeyStr = (Array.isArray(pkData) && pkData.length > 0) ? pkData[0]?.primary_key : '';\n    const primaryKeys = primaryKeyStr\n      ? primaryKeyStr.split(',').map((k: string) => k.trim())\n      : [];\n\n    // 获取索引信息（ClickHouse 的索引称为 data skipping indexes）\n    const indexesResult = await this.client.query({\n      query: `\n        SELECT\n          name,\n          expr,\n          type\n        FROM system.data_skipping_indices\n        WHERE database = {database:String}\n          AND table = {table:String}\n      `,\n      query_params: {\n        database: databaseName,\n        table: tableName,\n      },\n      format: 'JSONEachRow',\n    });\n\n    const indexesData = await indexesResult.json() as Array<{\n      name: string;\n      expr: string;\n      type: string;\n    }>;\n    const indexes = Array.isArray(indexesData) ? indexesData : [];\n\n    const indexInfos: IndexInfo[] = indexes.map((idx) => ({\n      name: idx?.name,\n      columns: [idx?.expr], // ClickHouse 索引表达式\n      unique: false, // ClickHouse 索引不保证唯一性\n    }));\n\n    // 获取表行数估算和表注释\n    const countResult = await this.client.query({\n      query: `\n        SELECT total_rows, comment\n        FROM system.tables\n        WHERE database = {database:String}\n          AND name = {table:String}\n      `,\n      query_params: {\n        database: databaseName,\n        table: tableName,\n      },\n      format: 'JSONEachRow',\n    });\n\n    const countData = await countResult.json() as Array<{ total_rows: string; comment: string }>;\n    const estimatedRows = (Array.isArray(countData) && countData.length > 0)\n      ? parseInt(countData[0]?.total_rows || '0', 10)\n      : 0;\n    const tableComment = (Array.isArray(countData) && countData.length > 0)\n      ? countData[0]?.comment || undefined\n      : undefined;\n\n    return {\n      name: tableName,\n      comment: tableComment,\n      columns: columnInfos,\n      primaryKeys,\n      indexes: indexInfos,\n      estimatedRows,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/dm.ts",
    "content": "/**\n * 达梦数据库适配器\n * 达梦数据库高度兼容 Oracle，使用类似的 API 和系统视图\n *\n * dmdb 驱动会作为可选依赖自动安装\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n *\n * 连接管理：使用心跳保活 + 断线自动重连 + 操作自动重试，确保长连接稳定性\n */\n\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\n// 动态导入 dmdb，因为它是可选依赖\nlet dmdb: any = null;\n\nasync function loadDMDB() {\n  if (dmdb) {\n    return dmdb;\n  }\n\n  try {\n    // @ts-ignore - dmdb 是可选依赖，可能未安装\n    const module = await import('dmdb');\n    dmdb = module.default || module;\n    return dmdb;\n  } catch (error) {\n    throw new Error(\n      '达梦数据库驱动未安装。\\n' +\n      '请运行以下命令安装：npm install dmdb\\n' +\n      '或者全局安装：npm install -g dmdb'\n    );\n  }\n}\n\nexport class DMAdapter implements DbAdapter {\n  private connection: any = null;\n  private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n  private connectionConfig: any = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|网络|连接/.test(msg);\n  }\n\n  private async reconnect(): Promise<void> {\n    try {\n      if (this.connection) { try { await this.connection.close(); } catch {} this.connection = null; }\n      const DM = await loadDMDB();\n      this.connection = await DM.getConnection(this.connectionConfig);\n      console.error('达梦数据库重连成功');\n    } catch (error) {\n      console.error('达梦数据库重连失败:', error instanceof Error ? error.message : String(error));\n    }\n  }\n\n  private startHeartbeat(): void {\n    this.stopHeartbeat();\n    this.heartbeatTimer = setInterval(async () => {\n      try {\n        if (this.connection) { await this.connection.execute('SELECT 1 FROM DUAL', []); }\n      } catch {\n        await this.reconnect();\n      }\n    }, 30000);\n  }\n\n  private stopHeartbeat(): void {\n    if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; }\n  }\n\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try { return await fn(); } catch (error) {\n      if (this.isConnectionError(error)) { await this.reconnect(); return await fn(); }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到达梦数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      const DM = await loadDMDB();\n\n      // 达梦数据库连接配置\n      const connectionConfig = {\n        host: this.config.host,\n        port: this.config.port || 5236, // 达梦默认端口\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        // 禁用消息加密以避免 OpenSSL 3.0 兼容性问题\n        // 如果需要加密连接，请确保达梦数据库服务器配置了兼容的加密算法\n        cipherPath: '',\n        loginEncrypt: false,\n      };\n\n      this.connection = await DM.getConnection(connectionConfig);\n      this.connectionConfig = connectionConfig;\n\n      // 测试连接\n      await this.connection.execute('SELECT 1 FROM DUAL', []);\n      this.startHeartbeat();\n    } catch (error: any) {\n      // 翻译常见错误\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      if (errorMessage.includes('用户名') || errorMessage.includes('密码')) {\n        throw new Error('达梦数据库连接失败: 用户名或密码无效');\n      } else if (errorMessage.includes('连接') || errorMessage.includes('网络')) {\n        throw new Error('达梦数据库连接失败: 无法连接到数据库服务器，请检查主机地址和端口');\n      }\n\n      throw new Error(`达梦数据库连接失败: ${errorMessage}`);\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    this.stopHeartbeat();\n    if (this.connection) {\n      try {\n        await this.connection.close();\n      } catch (error) {\n        // 忽略关闭连接时的错误\n      }\n      this.connection = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.connection) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      // 达梦兼容 Oracle，不需要末尾的分号，移除它以避免语法错误\n      let cleanQuery = query.trim();\n      if (cleanQuery.endsWith(';')) {\n        cleanQuery = cleanQuery.slice(0, -1).trim();\n      }\n\n      // 执行查询\n      const result: any = await this.withRetry(() => this.connection.execute(cleanQuery, params || [], {\n        autoCommit: false,\n      }));\n\n      const executionTime = Date.now() - startTime;\n\n      // 处理查询结果\n      if (result.rows && result.rows.length > 0) {\n        // SELECT 查询 - 将列名转换为小写\n        const rows = result.rows.map((row: any) => {\n          const lowerCaseRow: Record<string, unknown> = {};\n          for (const [key, value] of Object.entries(row)) {\n            lowerCaseRow[key.toLowerCase()] = value;\n          }\n          return lowerCaseRow;\n        });\n\n        return {\n          rows,\n          executionTime,\n          metadata: {\n            columnCount: result.metaData?.length || 0,\n          },\n        };\n      } else if (result.rowsAffected !== undefined && result.rowsAffected > 0) {\n        // DML 操作 (INSERT/UPDATE/DELETE)\n        return {\n          rows: [],\n          affectedRows: result.rowsAffected,\n          executionTime,\n        };\n      } else {\n        // 其他操作或空结果\n        return {\n          rows: [],\n          executionTime,\n        };\n      }\n    } catch (error: any) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      if (errorMessage.includes('表') || errorMessage.includes('视图')) {\n        throw new Error('查询执行失败: 表或视图不存在');\n      } else if (errorMessage.includes('约束')) {\n        throw new Error('查询执行失败: 违反唯一约束');\n      }\n\n      throw new Error(`查询执行失败: ${errorMessage}`);\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   *\n   * 达梦数据库中：\n   * - database 是数据库实例名（如 DAMENG）\n   * - schema 是用户的命名空间（通常与用户名相同，如 SHOP）\n   * - 表存储在 schema 下，不是 database 下\n   *\n   * 注意：dmdb 驱动返回的列名是数字索引（\"0\", \"1\", ...），不是列名！\n   * 因此需要按索引位置访问数据。\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.connection) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n      // 获取达梦数据库版本\n      const versionResult = await this.connection.execute(\n        `SELECT BANNER FROM V$VERSION WHERE ROWNUM = 1`,\n        []\n      );\n      const version = versionResult.rows?.[0]\n        ? this.getValueByIndex(versionResult.rows[0], 0) as string\n        : 'unknown';\n\n      // 获取当前 schema（在达梦中，schema 通常与用户名相同）\n      const schemaResult = await this.connection.execute(\n        `SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') FROM DUAL`,\n        []\n      );\n      const currentSchema = schemaResult.rows?.[0]\n        ? this.getValueByIndex(schemaResult.rows[0], 0) as string\n        : '';\n\n      // 获取当前用户（作为备选）\n      const userResult = await this.connection.execute('SELECT USER FROM DUAL', []);\n      const currentUser = userResult.rows?.[0]\n        ? this.getValueByIndex(userResult.rows[0], 0) as string\n        : '';\n\n      // schema 名称：优先使用当前 schema，其次使用当前用户，最后使用配置的用户名\n      const schemaName = (currentSchema || currentUser || this.config.user || '').toUpperCase();\n      const databaseName = schemaName || 'unknown';\n\n      // 获取所有表的列信息\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=DATA_TYPE, 4=DATA_LENGTH,\n      //        5=DATA_PRECISION, 6=DATA_SCALE, 7=NULLABLE, 8=DATA_DEFAULT, 9=COLUMN_ID\n      const allColumnsResult = await this.connection.execute(\n        `SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION,\n                DATA_SCALE, NULLABLE, DATA_DEFAULT, COLUMN_ID\n         FROM ALL_TAB_COLUMNS\n         WHERE OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n         ORDER BY OWNER, TABLE_NAME, COLUMN_ID`,\n        []\n      );\n\n      // 获取所有列注释\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=COMMENTS\n      const allCommentsResult = await this.connection.execute(\n        `SELECT OWNER, TABLE_NAME, COLUMN_NAME, COMMENTS\n         FROM ALL_COL_COMMENTS\n         WHERE OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n           AND COMMENTS IS NOT NULL`,\n        []\n      );\n\n      // 获取所有主键信息\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=POSITION\n      const allPrimaryKeysResult = await this.connection.execute(\n        `SELECT cons.OWNER, cons.TABLE_NAME, cols.COLUMN_NAME, cols.POSITION\n         FROM ALL_CONSTRAINTS cons\n         JOIN ALL_CONS_COLUMNS cols\n           ON cons.CONSTRAINT_NAME = cols.CONSTRAINT_NAME AND cons.OWNER = cols.OWNER\n         WHERE cons.CONSTRAINT_TYPE = 'P'\n           AND cons.OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n         ORDER BY cons.OWNER, cons.TABLE_NAME, cols.POSITION`,\n        []\n      );\n\n      // 获取所有索引信息\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=INDEX_NAME, 3=UNIQUENESS, 4=COLUMN_NAME, 5=COLUMN_POSITION\n      const allIndexesResult = await this.connection.execute(\n        `SELECT i.OWNER, i.TABLE_NAME, i.INDEX_NAME, i.UNIQUENESS, ic.COLUMN_NAME, ic.COLUMN_POSITION\n         FROM ALL_INDEXES i\n         JOIN ALL_IND_COLUMNS ic\n           ON i.INDEX_NAME = ic.INDEX_NAME AND i.OWNER = ic.INDEX_OWNER\n         WHERE i.OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n         ORDER BY i.OWNER, i.TABLE_NAME, i.INDEX_NAME, ic.COLUMN_POSITION`,\n        []\n      );\n\n      // 获取所有表的行数估算和表注释\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=NUM_ROWS, 3=TABLE_COMMENT\n      const allStatsResult = await this.connection.execute(\n        `SELECT t.OWNER, t.TABLE_NAME, t.NUM_ROWS, c.COMMENTS AS TABLE_COMMENT\n         FROM ALL_TABLES t\n         LEFT JOIN ALL_TAB_COMMENTS c ON t.TABLE_NAME = c.TABLE_NAME AND t.OWNER = c.OWNER\n         WHERE t.OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')`,\n        []\n      );\n\n      // 获取所有外键信息\n      // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=CONSTRAINT_NAME, 3=COLUMN_NAME, 4=REFERENCED_TABLE,\n      //        5=REFERENCED_COLUMN, 6=DELETE_RULE, 7=REF_OWNER, 8=POSITION\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await this.connection.execute(\n          `SELECT\n            c.OWNER,\n            c.TABLE_NAME,\n            c.CONSTRAINT_NAME,\n            cc.COLUMN_NAME,\n            rc.TABLE_NAME AS REFERENCED_TABLE,\n            rcc.COLUMN_NAME AS REFERENCED_COLUMN,\n            c.DELETE_RULE,\n            rc.OWNER AS REF_OWNER,\n            cc.POSITION\n          FROM ALL_CONSTRAINTS c\n          JOIN ALL_CONS_COLUMNS cc ON c.CONSTRAINT_NAME = cc.CONSTRAINT_NAME AND c.OWNER = cc.OWNER\n          JOIN ALL_CONSTRAINTS rc ON c.R_CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND c.R_OWNER = rc.OWNER\n          JOIN ALL_CONS_COLUMNS rcc ON rc.CONSTRAINT_NAME = rcc.CONSTRAINT_NAME AND rc.OWNER = rcc.OWNER AND cc.POSITION = rcc.POSITION\n          WHERE c.CONSTRAINT_TYPE = 'R'\n            AND c.OWNER NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'SYSDBA', 'CTISYS')\n          ORDER BY c.OWNER, c.TABLE_NAME, c.CONSTRAINT_NAME, cc.POSITION`,\n          []\n        );\n        allForeignKeys = allForeignKeysResult.rows || [];\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchemaFromIndexedRows(\n        databaseName,\n        version,\n        allColumnsResult.rows || [],\n        allCommentsResult.rows || [],\n        allPrimaryKeysResult.rows || [],\n        allIndexesResult.rows || [],\n        allStatsResult.rows || [],\n        allForeignKeys,\n        schemaName\n      );\n  }\n\n  /**\n   * 按索引获取对象的值（dmdb 驱动返回的列名是数字索引）\n   */\n  private getValueByIndex(obj: any, index: number): unknown {\n    if (!obj || typeof obj !== 'object') {\n      return undefined;\n    }\n    // 尝试按数字索引访问\n    if (obj[index] !== undefined) {\n      return obj[index];\n    }\n    // 尝试按字符串索引访问\n    if (obj[String(index)] !== undefined) {\n      return obj[String(index)];\n    }\n    // 尝试按位置获取值\n    const values = Object.values(obj);\n    return values.length > index ? values[index] : undefined;\n  }\n\n  private makeTableKey(owner: string, tableName: string, currentUser: string): string {\n    return owner.toUpperCase() === currentUser.toUpperCase() ? tableName : `${owner}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息（处理 dmdb 驱动返回的数字索引列名）\n   */\n  private assembleSchemaFromIndexedRows(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allComments: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[],\n    currentUser: string\n  ): SchemaInfo {\n    // 按表名分组列信息\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=DATA_TYPE, 4=DATA_LENGTH,\n    //        5=DATA_PRECISION, 6=DATA_SCALE, 7=NULLABLE, 8=DATA_DEFAULT, 9=COLUMN_ID\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const owner = this.getValueByIndex(col, 0) as string;\n      const tableName = this.getValueByIndex(col, 1) as string;\n      const columnName = this.getValueByIndex(col, 2) as string;\n      const dataType = this.getValueByIndex(col, 3);\n      const dataLength = this.getValueByIndex(col, 4) as number;\n      const dataPrecision = this.getValueByIndex(col, 5) as number;\n      const dataScale = this.getValueByIndex(col, 6) as number;\n      const nullable = this.getValueByIndex(col, 7) as string;\n      const dataDefault = this.getValueByIndex(col, 8);\n\n      // 跳过无效数据\n      if (!tableName || !columnName) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, owner);\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: String(columnName).toLowerCase(),\n        type: this.formatDMType(\n          dataType as string | number | null | undefined,\n          dataLength,\n          dataPrecision,\n          dataScale\n        ),\n        nullable: nullable === 'Y',\n        defaultValue: dataDefault ? String(dataDefault).trim() : undefined,\n      });\n    }\n\n    // 按表名分组列注释\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=COMMENTS\n    const commentsByTable = new Map<string, Map<string, string>>();\n    for (const comment of allComments) {\n      const owner = this.getValueByIndex(comment, 0) as string;\n      const tableName = this.getValueByIndex(comment, 1) as string;\n      const columnName = this.getValueByIndex(comment, 2) as string;\n      const comments = this.getValueByIndex(comment, 3) as string;\n\n      // 跳过无效数据\n      if (!tableName || !columnName || !comments) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!commentsByTable.has(tableKey)) {\n        commentsByTable.set(tableKey, new Map());\n      }\n      commentsByTable.get(tableKey)!.set(\n        String(columnName).toLowerCase(),\n        String(comments)\n      );\n    }\n\n    // 将注释添加到列信息中\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableComments = commentsByTable.get(tableKey);\n      if (tableComments) {\n        for (const col of columns) {\n          if (tableComments.has(col.name)) {\n            col.comment = tableComments.get(col.name);\n          }\n        }\n      }\n    }\n\n    // 按表名分组主键信息\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=COLUMN_NAME, 3=POSITION\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const owner = this.getValueByIndex(pk, 0) as string;\n      const tableName = this.getValueByIndex(pk, 1) as string;\n      const columnName = this.getValueByIndex(pk, 2) as string;\n\n      // 跳过无效数据\n      if (!tableName || !columnName) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(String(columnName).toLowerCase());\n    }\n\n    // 按表名分组索引信息\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=INDEX_NAME, 3=UNIQUENESS, 4=COLUMN_NAME, 5=COLUMN_POSITION\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const owner = this.getValueByIndex(idx, 0) as string;\n      const tableName = this.getValueByIndex(idx, 1) as string;\n      const indexName = this.getValueByIndex(idx, 2) as string;\n      const uniqueness = this.getValueByIndex(idx, 3) as string;\n      const columnName = this.getValueByIndex(idx, 4) as string;\n\n      // 跳过无效数据\n      if (!tableName || !indexName || !columnName) {\n        continue;\n      }\n\n      // 跳过主键索引和系统索引\n      const idxNameStr = String(indexName);\n      if (idxNameStr.includes('PK_') || idxNameStr.startsWith('INDEX') || idxNameStr.includes('SYS_')) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: uniqueness === 'UNIQUE',\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(String(columnName).toLowerCase());\n    }\n\n    // 按表名分组行数统计\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=NUM_ROWS, 3=TABLE_COMMENT\n    const rowsByTable = new Map<string, number>();\n    const tableCommentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const owner = this.getValueByIndex(stat, 0) as string;\n      const tableName = this.getValueByIndex(stat, 1) as string;\n      const numRows = this.getValueByIndex(stat, 2);\n      const tableComment = this.getValueByIndex(stat, 3) as string;\n      if (tableName) {\n        const tableKey = this.makeTableKey(owner, tableName, currentUser);\n        rowsByTable.set(tableKey, Number(numRows) || 0);\n        if (tableComment) {\n          tableCommentsByTable.set(tableKey, tableComment);\n        }\n      }\n    }\n\n    // 按表名分组外键信息\n    // 列顺序: 0=OWNER, 1=TABLE_NAME, 2=CONSTRAINT_NAME, 3=COLUMN_NAME, 4=REFERENCED_TABLE,\n    //        5=REFERENCED_COLUMN, 6=DELETE_RULE, 7=REF_OWNER, 8=POSITION\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const owner = this.getValueByIndex(fk, 0) as string;\n      const tableName = this.getValueByIndex(fk, 1) as string;\n      const constraintName = this.getValueByIndex(fk, 2) as string;\n      const columnName = this.getValueByIndex(fk, 3) as string;\n      const referencedTable = this.getValueByIndex(fk, 4) as string;\n      const referencedColumn = this.getValueByIndex(fk, 5) as string;\n      const deleteRule = this.getValueByIndex(fk, 6) as string;\n      const refOwner = this.getValueByIndex(fk, 7) as string;\n\n      if (!tableName || !constraintName) continue;\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n      const refTableKey = this.makeTableKey(refOwner, referencedTable, currentUser);\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: String(refTableKey).toLowerCase(),\n          referencedColumns: [],\n          onDelete: deleteRule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(String(columnName).toLowerCase());\n      fkInfo.referencedColumns.push(String(referencedColumn).toLowerCase());\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: String(tableKey).toLowerCase(),\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: String(tableKey).toLowerCase(),\n        schema: schemaByTable.get(tableKey),\n        comment: tableCommentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'dm',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 格式化达梦数据类型\n   */\n  private formatDMType(\n    dataType: string | number | undefined | null,\n    length?: number,\n    precision?: number,\n    scale?: number\n  ): string {\n    // 处理空值\n    if (dataType === null || dataType === undefined) {\n      return 'UNKNOWN';\n    }\n\n    // 达梦的 TYPE$ 可能是数字类型代码，需要转换\n    const typeMap: Record<number, string> = {\n      0: 'CHAR',\n      1: 'VARCHAR',\n      2: 'VARCHAR2',\n      3: 'BIT',\n      4: 'TINYINT',\n      5: 'SMALLINT',\n      6: 'INT',\n      7: 'BIGINT',\n      8: 'DECIMAL',\n      9: 'FLOAT',\n      10: 'DOUBLE',\n      11: 'BLOB',\n      12: 'DATE',\n      13: 'TIME',\n      14: 'DATETIME',\n      15: 'TIMESTAMP',\n      17: 'BINARY',\n      18: 'VARBINARY',\n      19: 'CLOB',\n      21: 'TEXT',\n      22: 'IMAGE',\n      23: 'BFILE',\n    };\n\n    let typeName: string;\n    if (typeof dataType === 'number') {\n      typeName = typeMap[dataType] || `TYPE_${dataType}`;\n    } else {\n      typeName = String(dataType);\n    }\n\n    // 添加长度/精度信息\n    switch (typeName) {\n      case 'DECIMAL':\n      case 'NUMBER':\n      case 'NUMERIC':\n        if (precision && scale && scale > 0) {\n          return `${typeName}(${precision},${scale})`;\n        } else if (precision) {\n          return `${typeName}(${precision})`;\n        } else if (length) {\n          return `${typeName}(${length})`;\n        }\n        return typeName;\n\n      case 'VARCHAR':\n      case 'VARCHAR2':\n      case 'CHAR':\n        if (length) {\n          return `${typeName}(${length})`;\n        }\n        return typeName;\n\n      default:\n        return typeName;\n    }\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    // 首先使用通用的写操作检测\n    if (checkWriteOperation(query)) {\n      return true;\n    }\n\n    // 添加达梦特定的写操作检测（类似 Oracle）\n    const trimmedQuery = query.trim().toUpperCase();\n\n    // MERGE 语句（达梦支持）\n    if (trimmedQuery.startsWith('MERGE')) {\n      return true;\n    }\n\n    // PL/SQL 块（达梦兼容 Oracle PL/SQL）\n    if (trimmedQuery.startsWith('BEGIN') || trimmedQuery.startsWith('DECLARE')) {\n      return true;\n    }\n\n    // CALL 存储过程\n    if (trimmedQuery.startsWith('CALL')) {\n      return true;\n    }\n\n    // 事务控制语句\n    if (trimmedQuery.startsWith('COMMIT') || trimmedQuery.startsWith('ROLLBACK')) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "src/adapters/gaussdb.ts",
    "content": "/**\n * GaussDB / OpenGauss 数据库适配器\n * 使用 pg 驱动实现 DbAdapter 接口\n * GaussDB 和 OpenGauss 基于 PostgreSQL 开发，兼容 PostgreSQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport pg from 'pg';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nconst { Pool } = pg;\n\nexport class GaussDBAdapter implements DbAdapter {\n  private pool: pg.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    const code = String((error as any)?.code || '');\n    return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(msg + code);\n  }\n\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 GaussDB / OpenGauss 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = new Pool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        max: 3,\n        idleTimeoutMillis: 60000,\n        keepAlive: true,\n        keepAliveInitialDelayMillis: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `GaussDB 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const result = await this.withRetry(() => this.pool!.query(query, params));\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result.rows,\n        affectedRows: result.rowCount || 0,\n        executionTime,\n        metadata: {\n          command: result.command,\n          fields: result.fields?.map(f => ({\n            name: f.name,\n            dataTypeID: f.dataTypeID,\n          })),\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息的内部实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n      // 获取数据库版本\n      const versionResult = await this.pool!.query('SELECT version()');\n      const version = versionResult.rows[0]?.version || 'unknown';\n\n      // 获取当前数据库名\n      const dbResult = await this.pool!.query('SELECT current_database()');\n      const databaseName = dbResult.rows[0]?.current_database || this.config.database || 'unknown';\n\n      // 批量获取所有表的列信息\n      const allColumnsResult = await this.pool!.query(`\n        SELECT\n          c.table_schema,\n          c.table_name,\n          c.column_name,\n          c.data_type,\n          c.is_nullable,\n          c.column_default,\n          c.character_maximum_length,\n          c.numeric_precision,\n          c.numeric_scale,\n          c.ordinal_position\n        FROM information_schema.columns c\n        JOIN information_schema.tables t\n          ON c.table_schema = t.table_schema AND c.table_name = t.table_name\n        WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND t.table_type = 'BASE TABLE'\n        ORDER BY c.table_schema, c.table_name, c.ordinal_position\n      `);\n\n      // 批量获取所有表的主键信息\n      const allPrimaryKeysResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          a.attname as column_name\n        FROM pg_index i\n        JOIN pg_class t ON t.oid = i.indrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE i.indisprimary\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        ORDER BY n.nspname, t.relname, a.attnum\n      `);\n\n      // 批量获取所有表的索引信息\n      const allIndexesResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          i.relname as index_name,\n          a.attname as column_name,\n          ix.indisunique as is_unique\n        FROM pg_class t\n        JOIN pg_index ix ON t.oid = ix.indrelid\n        JOIN pg_class i ON i.oid = ix.indexrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE t.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND NOT ix.indisprimary\n        ORDER BY n.nspname, t.relname, i.relname, a.attnum\n      `);\n\n      // 批量获取所有表的行数估算和表注释\n      const allStatsResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          c.relname as table_name,\n          c.reltuples::bigint as estimated_rows,\n          obj_description(c.oid, 'pg_class') as table_comment\n        FROM pg_class c\n        JOIN pg_namespace n ON n.oid = c.relnamespace\n        WHERE c.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n      `);\n\n      // 批量获取所有外键信息\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await this.pool!.query(`\n          SELECT\n            n.nspname AS schema_name,\n            c.conname AS constraint_name,\n            t.relname AS table_name,\n            a.attname AS column_name,\n            rn.nspname AS ref_schema_name,\n            rt.relname AS referenced_table,\n            ra.attname AS referenced_column,\n            CASE c.confdeltype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS delete_rule,\n            CASE c.confupdtype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS update_rule,\n            array_position(c.conkey, a.attnum) AS column_position\n          FROM pg_constraint c\n          JOIN pg_class t ON t.oid = c.conrelid\n          JOIN pg_class rt ON rt.oid = c.confrelid\n          JOIN pg_namespace n ON n.oid = t.relnamespace\n          JOIN pg_namespace rn ON rn.oid = rt.relnamespace\n          JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)\n          JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = c.confkey[array_position(c.conkey, a.attnum)]\n          WHERE c.contype = 'f'\n            AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          ORDER BY n.nspname, t.relname, c.conname, array_position(c.conkey, a.attnum)\n        `);\n        allForeignKeys = allForeignKeysResult.rows;\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchema(\n        databaseName,\n        version,\n        allColumnsResult.rows,\n        allPrimaryKeysResult.rows,\n        allIndexesResult.rows,\n        allStatsResult.rows,\n        allForeignKeys\n      );\n  }\n\n  /**\n   * 构建带 schema 前缀的表名键\n   * 默认 schema (public) 的表直接用表名，保持向后兼容\n   */\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    // 按 schema.table 分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schemaName = col.table_schema || 'public';\n      const tableName = col.table_name;\n      const tableKey = this.makeTableKey(schemaName, tableName);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schemaName);\n      }\n\n      let dataType = col.data_type;\n      if (col.character_maximum_length) {\n        dataType += `(${col.character_maximum_length})`;\n      } else if (col.numeric_precision) {\n        dataType += `(${col.numeric_precision}${col.numeric_scale ? `,${col.numeric_scale}` : ''})`;\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.column_name,\n        type: dataType,\n        nullable: col.is_nullable === 'YES',\n        defaultValue: col.column_default || undefined,\n      });\n    }\n\n    // 按 schema.table 分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const tableKey = this.makeTableKey(pk.schema_name || 'public', pk.table_name);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.column_name);\n    }\n\n    // 按 schema.table 分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableKey = this.makeTableKey(idx.schema_name || 'public', idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name);\n    }\n\n    // 按 schema.table 分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const tableKey = this.makeTableKey(stat.schema_name || 'public', stat.table_name);\n      rowsByTable.set(tableKey, Number(stat.estimated_rows) || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, stat.table_comment);\n      }\n    }\n\n    // 按 schema.table 分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableKey = this.makeTableKey(fk.schema_name || 'public', fk.table_name);\n      const constraintName = fk.constraint_name;\n      const refTableKey = this.makeTableKey(fk.ref_schema_name || 'public', fk.referenced_table);\n\n      if (!tableKey || !constraintName) continue;\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name);\n      fkInfo.referencedColumns.push(fk.referenced_column);\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey,\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'gaussdb',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/goldendb.ts",
    "content": "/**\n * GoldenDB 数据库适配器\n * 使用 mysql2 驱动实现 DbAdapter 接口\n * GoldenDB 兼容 MySQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport mysql from 'mysql2/promise';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class GoldenDBAdapter implements DbAdapter {\n  private pool: mysql.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 GoldenDB 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = mysql.createPool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        multipleStatements: false,\n        waitForConnections: true,\n        connectionLimit: 3,\n        maxIdle: 1,\n        idleTimeout: 60000,\n        enableKeepAlive: true,\n        keepAliveInitialDelay: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `GoldenDB 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const [rows, fields] = await this.withRetry(() => this.pool!.execute(query, params));\n      const executionTime = Date.now() - startTime;\n\n      // 处理不同类型的查询结果\n      if (Array.isArray(rows)) {\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            fieldCount: fields?.length || 0,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const result = rows as mysql.ResultSetHeader;\n        return {\n          rows: [],\n          affectedRows: result.affectedRows,\n          executionTime,\n          metadata: {\n            insertId: result.insertId,\n            changedRows: result.changedRows,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    // 获取数据库版本\n    const [versionRows] = await this.pool!.query('SELECT VERSION() as version');\n    const version = (versionRows as any[])[0]?.version || 'unknown';\n\n    // 获取当前数据库名\n    const [dbRows] = await this.pool!.query('SELECT DATABASE() as db');\n    const databaseName = (dbRows as any[])[0]?.db || this.config.database || 'unknown';\n\n    // 批量获取所有表的列信息\n    const [allColumns] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        COLUMN_NAME,\n        COLUMN_TYPE,\n        IS_NULLABLE,\n        COLUMN_DEFAULT,\n        COLUMN_KEY,\n        COLUMN_COMMENT,\n        ORDINAL_POSITION\n      FROM INFORMATION_SCHEMA.COLUMNS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, ORDINAL_POSITION\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的索引信息\n    const [allIndexes] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        INDEX_NAME,\n        COLUMN_NAME,\n        NON_UNIQUE,\n        SEQ_IN_INDEX\n      FROM INFORMATION_SCHEMA.STATISTICS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的行数估算和表注释\n    const [allStats] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        TABLE_ROWS,\n        TABLE_COMMENT\n      FROM INFORMATION_SCHEMA.TABLES\n      WHERE TABLE_SCHEMA = DATABASE()\n        AND TABLE_TYPE = 'BASE TABLE'\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有外键信息\n    let allForeignKeys: mysql.RowDataPacket[] = [];\n    try {\n      const [fkRows] = await this.pool!.query(`\n        SELECT\n          kcu.TABLE_NAME,\n          kcu.CONSTRAINT_NAME,\n          kcu.COLUMN_NAME,\n          kcu.REFERENCED_TABLE_NAME,\n          kcu.REFERENCED_COLUMN_NAME,\n          kcu.ORDINAL_POSITION,\n          rc.DELETE_RULE,\n          rc.UPDATE_RULE\n        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n        JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n          ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n          AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA\n        WHERE kcu.TABLE_SCHEMA = DATABASE()\n          AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n        ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, kcu.ORDINAL_POSITION\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n      allForeignKeys = fkRows;\n    } catch (error) {\n      // 外键查询失败时忽略，返回空数组\n      console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n    }\n\n    // 在内存中组装数据\n    return this.assembleSchema(databaseName, version, allColumns, allIndexes, allStats, allForeignKeys);\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: mysql.RowDataPacket[],\n    allIndexes: mysql.RowDataPacket[],\n    allStats: mysql.RowDataPacket[],\n    allForeignKeys: mysql.RowDataPacket[]\n  ): SchemaInfo {\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const primaryKeysByTable = new Map<string, string[]>();\n\n    for (const col of allColumns) {\n      const tableName = col.TABLE_NAME;\n\n      if (!columnsByTable.has(tableName)) {\n        columnsByTable.set(tableName, []);\n        primaryKeysByTable.set(tableName, []);\n      }\n\n      columnsByTable.get(tableName)!.push({\n        name: col.COLUMN_NAME,\n        type: col.COLUMN_TYPE,\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT,\n        comment: col.COLUMN_COMMENT || undefined,\n      });\n\n      if (col.COLUMN_KEY === 'PRI') {\n        primaryKeysByTable.get(tableName)!.push(col.COLUMN_NAME);\n      }\n    }\n\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n\n      if (indexName === 'PRIMARY') continue;\n\n      if (!indexesByTable.has(tableName)) {\n        indexesByTable.set(tableName, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableName)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.NON_UNIQUE === 0,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.COLUMN_NAME);\n    }\n\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      rowsByTable.set(stat.TABLE_NAME, stat.TABLE_ROWS || 0);\n      if (stat.TABLE_COMMENT) {\n        commentsByTable.set(stat.TABLE_NAME, stat.TABLE_COMMENT);\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!foreignKeysByTable.has(tableName)) {\n        foreignKeysByTable.set(tableName, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableName)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: fk.REFERENCED_TABLE_NAME,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n          onUpdate: fk.UPDATE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.COLUMN_NAME);\n      fkInfo.referencedColumns.push(fk.REFERENCED_COLUMN_NAME);\n    }\n\n    // 生成全局关系视图\n    for (const [tableName, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableName,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableName, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableName);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableName);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableName,\n        comment: commentsByTable.get(tableName) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableName) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableName) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'goldendb',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/highgo.ts",
    "content": "/**\n * HighGo 数据库适配器\n * 使用 pg 驱动实现 DbAdapter 接口\n * HighGo（瀚高）基于 PostgreSQL 开发，兼容 PostgreSQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport pg from 'pg';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nconst { Pool } = pg;\n\nexport class HighGoAdapter implements DbAdapter {\n  private pool: pg.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 判断是否为连接类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    if (!(error instanceof Error)) return false;\n    const msg = error.message || '';\n    const code = (error as any).code || '';\n    return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(\n      msg + code\n    );\n  }\n\n  /**\n   * 带断线重试的执行包装器\n   */\n  private async withRetry<T>(fn: () => Promise<T>, retries = 2): Promise<T> {\n    for (let attempt = 0; ; attempt++) {\n      try {\n        return await fn();\n      } catch (error) {\n        if (attempt < retries && this.isConnectionError(error)) {\n          // 重建连接池后重试\n          await this.connect();\n          continue;\n        }\n        throw error;\n      }\n    }\n  }\n\n  /**\n   * 连接到 HighGo 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = new Pool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        max: 3,\n        idleTimeoutMillis: 60000,\n        keepAlive: true,\n        keepAliveInitialDelayMillis: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `HighGo 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const result = await this.withRetry(() => this.pool!.query(query, params));\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result.rows,\n        affectedRows: result.rowCount || 0,\n        executionTime,\n        metadata: {\n          command: result.command,\n          fields: result.fields?.map(f => ({\n            name: f.name,\n            dataTypeID: f.dataTypeID,\n          })),\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n      // 获取数据库版本\n      const versionResult = await this.pool!.query('SELECT version() as version');\n      const version = versionResult.rows[0]?.version || 'unknown';\n\n      // 获取当前数据库名\n      const databaseName = this.config.database || 'highgo';\n\n      // 批量获取所有表的列信息（支持多 schema）\n      const allColumnsResult = await this.pool!.query(`\n        SELECT\n          c.table_schema,\n          c.table_name,\n          c.column_name,\n          c.data_type,\n          c.is_nullable,\n          c.column_default,\n          c.character_maximum_length,\n          c.numeric_precision,\n          c.numeric_scale,\n          c.ordinal_position\n        FROM information_schema.columns c\n        JOIN information_schema.tables t\n          ON c.table_schema = t.table_schema AND c.table_name = t.table_name\n        WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND t.table_type = 'BASE TABLE'\n        ORDER BY c.table_schema, c.table_name, c.ordinal_position\n      `);\n\n      // 批量获取所有表的主键信息\n      const allPrimaryKeysResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          a.attname as column_name\n        FROM pg_index i\n        JOIN pg_class t ON t.oid = i.indrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE i.indisprimary\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        ORDER BY n.nspname, t.relname, a.attnum\n      `);\n\n      // 批量获取所有表的索引信息\n      const allIndexesResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          i.relname as index_name,\n          a.attname as column_name,\n          ix.indisunique as is_unique\n        FROM pg_class t\n        JOIN pg_index ix ON t.oid = ix.indrelid\n        JOIN pg_class i ON i.oid = ix.indexrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE t.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND NOT ix.indisprimary\n        ORDER BY n.nspname, t.relname, i.relname, a.attnum\n      `);\n\n      // 批量获取所有表的行数估算和表注释\n      const allStatsResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          c.relname as table_name,\n          c.reltuples::bigint as estimated_rows,\n          obj_description(c.oid, 'pg_class') as table_comment\n        FROM pg_class c\n        JOIN pg_namespace n ON n.oid = c.relnamespace\n        WHERE c.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n      `);\n\n      // 批量获取所有外键信息\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await this.pool!.query(`\n          SELECT\n            n.nspname AS schema_name,\n            c.conname AS constraint_name,\n            t.relname AS table_name,\n            a.attname AS column_name,\n            rn.nspname AS ref_schema_name,\n            rt.relname AS referenced_table,\n            ra.attname AS referenced_column,\n            CASE c.confdeltype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS delete_rule,\n            CASE c.confupdtype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS update_rule,\n            array_position(c.conkey, a.attnum) AS column_position\n          FROM pg_constraint c\n          JOIN pg_class t ON t.oid = c.conrelid\n          JOIN pg_class rt ON rt.oid = c.confrelid\n          JOIN pg_namespace n ON n.oid = t.relnamespace\n          JOIN pg_namespace rn ON rn.oid = rt.relnamespace\n          JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)\n          JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = c.confkey[array_position(c.conkey, a.attnum)]\n          WHERE c.contype = 'f'\n            AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          ORDER BY n.nspname, t.relname, c.conname, array_position(c.conkey, a.attnum)\n        `);\n        allForeignKeys = allForeignKeysResult.rows;\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchema(\n        databaseName,\n        version,\n        allColumnsResult.rows,\n        allPrimaryKeysResult.rows,\n        allIndexesResult.rows,\n        allStatsResult.rows,\n        allForeignKeys\n      );\n  }\n\n  /**\n   * 构建带 schema 前缀的表名键\n   * 默认 schema (public) 的表直接用表名，保持向后兼容\n   */\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    // 按 schema.table 分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schemaName = col.table_schema || 'public';\n      const tableName = col.table_name;\n      const tableKey = this.makeTableKey(schemaName, tableName);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schemaName);\n      }\n\n      let dataType = col.data_type;\n      if (col.character_maximum_length) {\n        dataType += `(${col.character_maximum_length})`;\n      } else if (col.numeric_precision) {\n        dataType += `(${col.numeric_precision}${col.numeric_scale ? `,${col.numeric_scale}` : ''})`;\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.column_name,\n        type: dataType,\n        nullable: col.is_nullable === 'YES',\n        defaultValue: col.column_default || undefined,\n      });\n    }\n\n    // 按 schema.table 分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const tableKey = this.makeTableKey(pk.schema_name || 'public', pk.table_name);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.column_name);\n    }\n\n    // 按 schema.table 分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableKey = this.makeTableKey(idx.schema_name || 'public', idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name);\n    }\n\n    // 按 schema.table 分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const tableKey = this.makeTableKey(stat.schema_name || 'public', stat.table_name);\n      rowsByTable.set(tableKey, Number(stat.estimated_rows) || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, stat.table_comment);\n      }\n    }\n\n    // 按 schema.table 分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableKey = this.makeTableKey(fk.schema_name || 'public', fk.table_name);\n      const constraintName = fk.constraint_name;\n      const refTableKey = this.makeTableKey(fk.ref_schema_name || 'public', fk.referenced_table);\n\n      if (!tableKey || !constraintName) continue;\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name);\n      fkInfo.referencedColumns.push(fk.referenced_column);\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey,\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'highgo',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/kingbase.ts",
    "content": "/**\n * KingbaseES（人大金仓）数据库适配器\n * 使用 pg 驱动实现 DbAdapter 接口\n * KingbaseES 基于 PostgreSQL 开发，兼容 PostgreSQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport pg from 'pg';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nconst { Pool } = pg;\n\nexport class KingbaseAdapter implements DbAdapter {\n  private pool: pg.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    const code = String((error as any)?.code || '');\n    return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(msg + code);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 KingbaseES 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = new Pool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        max: 3,\n        idleTimeoutMillis: 60000,\n        keepAlive: true,\n        keepAliveInitialDelayMillis: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `KingbaseES 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const result = await this.withRetry(() => this.pool!.query(query, params));\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result.rows,\n        affectedRows: result.rowCount || 0,\n        executionTime,\n        metadata: {\n          command: result.command,\n          fields: result.fields?.map(f => ({\n            name: f.name,\n            dataTypeID: f.dataTypeID,\n          })),\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * getSchema 内部实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    // 获取数据库版本\n    const versionResult = await this.pool!.query('SELECT version()');\n    const version = versionResult.rows[0]?.version || 'unknown';\n\n    // 获取当前数据库名\n    const dbResult = await this.pool!.query('SELECT current_database()');\n    const databaseName = dbResult.rows[0]?.current_database || this.config.database || 'unknown';\n\n    // 批量获取所有表的列信息（支持多 schema）\n    const allColumnsResult = await this.pool!.query(`\n      SELECT\n        c.table_schema,\n        c.table_name,\n        c.column_name,\n        c.data_type,\n        c.is_nullable,\n        c.column_default,\n        c.character_maximum_length,\n        c.numeric_precision,\n        c.numeric_scale,\n        c.ordinal_position\n      FROM information_schema.columns c\n      JOIN information_schema.tables t\n        ON c.table_schema = t.table_schema AND c.table_name = t.table_name\n      WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        AND t.table_type = 'BASE TABLE'\n      ORDER BY c.table_schema, c.table_name, c.ordinal_position\n    `);\n\n    // 批量获取所有表的主键信息\n    const allPrimaryKeysResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        t.relname as table_name,\n        a.attname as column_name\n      FROM pg_index i\n      JOIN pg_class t ON t.oid = i.indrelid\n      JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)\n      JOIN pg_namespace n ON n.oid = t.relnamespace\n      WHERE i.indisprimary\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n      ORDER BY n.nspname, t.relname, a.attnum\n    `);\n\n    // 批量获取所有表的索引信息\n    const allIndexesResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        t.relname as table_name,\n        i.relname as index_name,\n        a.attname as column_name,\n        ix.indisunique as is_unique\n      FROM pg_class t\n      JOIN pg_index ix ON t.oid = ix.indrelid\n      JOIN pg_class i ON i.oid = ix.indexrelid\n      JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n      JOIN pg_namespace n ON n.oid = t.relnamespace\n      WHERE t.relkind = 'r'\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        AND NOT ix.indisprimary\n      ORDER BY n.nspname, t.relname, i.relname, a.attnum\n    `);\n\n    // 批量获取所有表的行数估算和表注释\n    const allStatsResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        c.relname as table_name,\n        c.reltuples::bigint as estimated_rows,\n        obj_description(c.oid, 'pg_class') as table_comment\n      FROM pg_class c\n      JOIN pg_namespace n ON n.oid = c.relnamespace\n      WHERE c.relkind = 'r'\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n    `);\n\n    // 批量获取所有外键信息\n    let allForeignKeys: any[] = [];\n    try {\n      const allForeignKeysResult = await this.pool!.query(`\n        SELECT\n          n.nspname AS schema_name,\n          c.conname AS constraint_name,\n          t.relname AS table_name,\n          a.attname AS column_name,\n          rn.nspname AS ref_schema_name,\n          rt.relname AS referenced_table,\n          ra.attname AS referenced_column,\n          CASE c.confdeltype\n            WHEN 'a' THEN 'NO ACTION'\n            WHEN 'r' THEN 'RESTRICT'\n            WHEN 'c' THEN 'CASCADE'\n            WHEN 'n' THEN 'SET NULL'\n            WHEN 'd' THEN 'SET DEFAULT'\n          END AS delete_rule,\n          CASE c.confupdtype\n            WHEN 'a' THEN 'NO ACTION'\n            WHEN 'r' THEN 'RESTRICT'\n            WHEN 'c' THEN 'CASCADE'\n            WHEN 'n' THEN 'SET NULL'\n            WHEN 'd' THEN 'SET DEFAULT'\n          END AS update_rule,\n          array_position(c.conkey, a.attnum) AS column_position\n        FROM pg_constraint c\n        JOIN pg_class t ON t.oid = c.conrelid\n        JOIN pg_class rt ON rt.oid = c.confrelid\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        JOIN pg_namespace rn ON rn.oid = rt.relnamespace\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)\n        JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = c.confkey[array_position(c.conkey, a.attnum)]\n        WHERE c.contype = 'f'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        ORDER BY n.nspname, t.relname, c.conname, array_position(c.conkey, a.attnum)\n      `);\n      allForeignKeys = allForeignKeysResult.rows;\n    } catch (error) {\n      // 外键查询失败时忽略，返回空数组\n      console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n    }\n\n    return this.assembleSchema(\n      databaseName,\n      version,\n      allColumnsResult.rows,\n      allPrimaryKeysResult.rows,\n      allIndexesResult.rows,\n      allStatsResult.rows,\n      allForeignKeys\n    );\n  }\n\n  /**\n   * 构建带 schema 前缀的表名键\n   */\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    // 按 schema.table 分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schemaName = col.table_schema || 'public';\n      const tableName = col.table_name;\n      const tableKey = this.makeTableKey(schemaName, tableName);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schemaName);\n      }\n\n      let dataType = col.data_type;\n      if (col.character_maximum_length) {\n        dataType += `(${col.character_maximum_length})`;\n      } else if (col.numeric_precision) {\n        dataType += `(${col.numeric_precision}${col.numeric_scale ? `,${col.numeric_scale}` : ''})`;\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.column_name,\n        type: dataType,\n        nullable: col.is_nullable === 'YES',\n        defaultValue: col.column_default || undefined,\n      });\n    }\n\n    // 按 schema.table 分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const tableKey = this.makeTableKey(pk.schema_name || 'public', pk.table_name);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.column_name);\n    }\n\n    // 按 schema.table 分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableKey = this.makeTableKey(idx.schema_name || 'public', idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name);\n    }\n\n    // 按 schema.table 分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const tableKey = this.makeTableKey(stat.schema_name || 'public', stat.table_name);\n      rowsByTable.set(tableKey, Number(stat.estimated_rows) || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, stat.table_comment);\n      }\n    }\n\n    // 按 schema.table 分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableKey = this.makeTableKey(fk.schema_name || 'public', fk.table_name);\n      const constraintName = fk.constraint_name;\n      const refTableKey = this.makeTableKey(fk.ref_schema_name || 'public', fk.referenced_table);\n\n      if (!tableKey || !constraintName) continue;\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name);\n      fkInfo.referencedColumns.push(fk.referenced_column);\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey,\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'kingbase',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/mongodb.ts",
    "content": "/**\n * MongoDB 数据库适配器\n * 使用 mongodb 驱动实现 DbAdapter 接口\n *\n * 注意：MongoDB 是 NoSQL 文档数据库，没有固定的表结构\n * 本适配器提供集合操作和文档查询功能\n */\n\nimport { MongoClient, Db, Document } from 'mongodb';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n} from '../types/adapter.js';\n\nexport class MongoDBAdapter implements DbAdapter {\n  private client: MongoClient | null = null;\n  private db: Db | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n    authSource?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n    authSource?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 连接到 MongoDB 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      // 构建连接字符串\n      let uri = 'mongodb://';\n\n      if (this.config.user && this.config.password) {\n        uri += `${encodeURIComponent(this.config.user)}:${encodeURIComponent(this.config.password)}@`;\n      }\n\n      uri += `${this.config.host}:${this.config.port}`;\n\n      if (this.config.database) {\n        uri += `/${this.config.database}`;\n      }\n\n      // 添加认证源参数\n      const authSource = this.config.authSource || this.config.database || 'admin';\n      if (this.config.user) {\n        uri += `?authSource=${authSource}`;\n      }\n\n      this.client = new MongoClient(uri, {\n        serverSelectionTimeoutMS: 5000,\n        connectTimeoutMS: 10000,\n      });\n\n      await this.client.connect();\n\n      // 选择数据库\n      const dbName = this.config.database || 'test';\n      this.db = this.client.db(dbName);\n\n      // 测试连接 - 使用 command 方法代替 admin().ping()\n      await this.db.command({ ping: 1 });\n    } catch (error) {\n      throw new Error(\n        `MongoDB 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.client) {\n      await this.client.close();\n      this.client = null;\n      this.db = null;\n    }\n  }\n\n  /**\n   * 执行 MongoDB 查询\n   *\n   * 支持的查询格式：\n   * 1. JSON 格式的 MongoDB 查询：\n   *    {\"collection\": \"users\", \"operation\": \"find\", \"query\": {\"age\": {\"$gt\": 18}}}\n   * 2. 简化的命令格式：\n   *    db.users.find({\"age\": {\"$gt\": 18}})\n   * 3. 聚合管道：\n   *    {\"collection\": \"users\", \"operation\": \"aggregate\", \"pipeline\": [...]}\n   */\n  async executeQuery(query: string, _params?: unknown[]): Promise<QueryResult> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      // 解析查询\n      const parsedQuery = this.parseQuery(query);\n\n      // 执行操作\n      const result = await this.executeOperation(parsedQuery);\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result,\n        executionTime,\n        metadata: {\n          collection: parsedQuery.collection,\n          operation: parsedQuery.operation,\n          resultCount: result.length,\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `MongoDB 查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 解析查询字符串\n   */\n  private parseQuery(query: string): {\n    collection: string;\n    operation: string;\n    query?: Document;\n    update?: Document;\n    pipeline?: Document[];\n    options?: Document;\n  } {\n    const trimmed = query.trim();\n\n    // 尝试解析 JSON 格式\n    if (trimmed.startsWith('{')) {\n      try {\n        return JSON.parse(trimmed);\n      } catch (error) {\n        throw new Error('无效的 JSON 查询格式');\n      }\n    }\n\n    // 解析 db.collection.operation() 格式\n    const match = trimmed.match(/db\\.(\\w+)\\.(\\w+)\\((.*)\\)/s);\n    if (match) {\n      const [, collection, operation, argsStr] = match;\n\n      let args: Document = {};\n      if (argsStr.trim()) {\n        try {\n          args = JSON.parse(argsStr);\n        } catch (error) {\n          throw new Error('无效的查询参数格式');\n        }\n      }\n\n      return {\n        collection,\n        operation,\n        query: args,\n      };\n    }\n\n    throw new Error('不支持的查询格式。请使用 JSON 格式或 db.collection.operation() 格式');\n  }\n\n  /**\n   * 执行 MongoDB 操作\n   */\n  private async executeOperation(parsed: {\n    collection: string;\n    operation: string;\n    query?: Document;\n    update?: Document;\n    pipeline?: Document[];\n    options?: Document;\n  }): Promise<Document[]> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    const collection = this.db.collection(parsed.collection);\n    const operation = parsed.operation.toLowerCase();\n\n    switch (operation) {\n      case 'find': {\n        const cursor = collection.find(parsed.query || {}, parsed.options);\n        const results = await cursor.toArray();\n        return results.map(doc => this.formatDocument(doc));\n      }\n\n      case 'findone': {\n        const result = await collection.findOne(parsed.query || {}, parsed.options);\n        return result ? [this.formatDocument(result)] : [];\n      }\n\n      case 'count':\n      case 'countdocuments': {\n        const count = await collection.countDocuments(parsed.query || {});\n        return [{ count }];\n      }\n\n      case 'distinct': {\n        if (!parsed.options?.field) {\n          throw new Error('distinct 操作需要指定 field 参数');\n        }\n        const values = await collection.distinct(parsed.options.field, parsed.query || {});\n        return values.map((value, index) => ({ index, value }));\n      }\n\n      case 'aggregate': {\n        if (!parsed.pipeline) {\n          throw new Error('aggregate 操作需要指定 pipeline 参数');\n        }\n        const cursor = collection.aggregate(parsed.pipeline);\n        const results = await cursor.toArray();\n        return results.map(doc => this.formatDocument(doc));\n      }\n\n      case 'insert':\n      case 'insertone': {\n        if (!parsed.query) {\n          throw new Error('insert 操作需要指定文档数据');\n        }\n        const result = await collection.insertOne(parsed.query);\n        return [{ insertedId: result.insertedId.toString(), acknowledged: result.acknowledged }];\n      }\n\n      case 'insertmany': {\n        if (!parsed.query || !Array.isArray(parsed.query)) {\n          throw new Error('insertMany 操作需要指定文档数组');\n        }\n        const result = await collection.insertMany(parsed.query);\n        return [{\n          insertedCount: result.insertedCount,\n          insertedIds: Object.values(result.insertedIds).map(id => id.toString()),\n          acknowledged: result.acknowledged\n        }];\n      }\n\n      case 'update':\n      case 'updateone': {\n        if (!parsed.query || !parsed.update) {\n          throw new Error('update 操作需要指定 query 和 update 参数');\n        }\n        const result = await collection.updateOne(parsed.query, parsed.update);\n        return [{\n          matchedCount: result.matchedCount,\n          modifiedCount: result.modifiedCount,\n          acknowledged: result.acknowledged,\n        }];\n      }\n\n      case 'updatemany': {\n        if (!parsed.query || !parsed.update) {\n          throw new Error('updateMany 操作需要指定 query 和 update 参数');\n        }\n        const result = await collection.updateMany(parsed.query, parsed.update);\n        return [{\n          matchedCount: result.matchedCount,\n          modifiedCount: result.modifiedCount,\n          acknowledged: result.acknowledged,\n        }];\n      }\n\n      case 'delete':\n      case 'deleteone': {\n        if (!parsed.query) {\n          throw new Error('delete 操作需要指定查询条件');\n        }\n        const result = await collection.deleteOne(parsed.query);\n        return [{\n          deletedCount: result.deletedCount,\n          acknowledged: result.acknowledged,\n        }];\n      }\n\n      case 'deletemany': {\n        if (!parsed.query) {\n          throw new Error('deleteMany 操作需要指定查询条件');\n        }\n        const result = await collection.deleteMany(parsed.query);\n        return [{\n          deletedCount: result.deletedCount,\n          acknowledged: result.acknowledged,\n        }];\n      }\n\n      default:\n        throw new Error(`不支持的操作: ${operation}`);\n    }\n  }\n\n  /**\n   * 格式化 MongoDB 文档（将 ObjectId 转换为字符串）\n   */\n  private formatDocument(doc: Document): Document {\n    const formatted: Document = {};\n\n    for (const [key, value] of Object.entries(doc)) {\n      if (value && typeof value === 'object' && '_bsontype' in value) {\n        // 处理 BSON 类型（如 ObjectId）\n        formatted[key] = value.toString();\n      } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n        // 递归处理嵌套对象\n        formatted[key] = this.formatDocument(value);\n      } else if (Array.isArray(value)) {\n        // 处理数组\n        formatted[key] = value.map(item =>\n          item && typeof item === 'object' ? this.formatDocument(item) : item\n        );\n      } else {\n        formatted[key] = value;\n      }\n    }\n\n    return formatted;\n  }\n\n  /**\n   * 获取 MongoDB 数据库信息\n   *\n   * MongoDB 没有固定的表结构，这里通过采样文档来推断集合的字段\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      // 获取 MongoDB 版本 - 使用 buildInfo 命令代替 admin().serverInfo()\n      const buildInfo = await this.db.command({ buildInfo: 1 });\n      const version = buildInfo.version || 'unknown';\n\n      // 获取数据库名称\n      const databaseName = this.db.databaseName;\n\n      // 获取所有集合\n      const collections = await this.db.listCollections().toArray();\n\n      const tables: TableInfo[] = [];\n\n      for (const collInfo of collections) {\n        const collectionName = collInfo.name;\n\n        // 跳过系统集合\n        if (collectionName.startsWith('system.')) {\n          continue;\n        }\n\n        const collection = this.db.collection(collectionName);\n\n        // 获取集合统计信息\n        let estimatedRows = 0;\n        try {\n          const stats = await this.db.command({ collStats: collectionName });\n          estimatedRows = stats.count || 0;\n        } catch (error) {\n          // 如果获取统计失败，使用 countDocuments\n          estimatedRows = await collection.countDocuments();\n        }\n\n        // 采样文档以推断字段结构（最多采样 100 个文档）\n        const sampleDocs = await collection.find().limit(100).toArray();\n\n        // 分析字段\n        const fieldMap = new Map<string, { types: Set<string>; nullable: boolean }>();\n\n        for (const doc of sampleDocs) {\n          for (const [key, value] of Object.entries(doc)) {\n            if (!fieldMap.has(key)) {\n              fieldMap.set(key, { types: new Set(), nullable: false });\n            }\n\n            const fieldInfo = fieldMap.get(key)!;\n\n            if (value === null || value === undefined) {\n              fieldInfo.nullable = true;\n            } else {\n              const type = this.getMongoType(value);\n              fieldInfo.types.add(type);\n            }\n          }\n        }\n\n        // 转换为 ColumnInfo\n        const columns: ColumnInfo[] = Array.from(fieldMap.entries()).map(\n          ([name, info]) => ({\n            name,\n            type: Array.from(info.types).join(' | ') || 'unknown',\n            nullable: info.nullable || sampleDocs.length < estimatedRows,\n          })\n        );\n\n        // MongoDB 的 _id 字段通常是主键\n        const primaryKeys = columns.some(col => col.name === '_id') ? ['_id'] : [];\n\n        tables.push({\n          name: collectionName,\n          columns,\n          primaryKeys,\n          estimatedRows,\n        });\n      }\n\n      return {\n        databaseType: 'mongodb',\n        databaseName,\n        tables,\n        version,\n      };\n    } catch (error) {\n      throw new Error(\n        `获取 MongoDB 信息失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取 MongoDB 值的类型\n   */\n  private getMongoType(value: unknown): string {\n    if (value === null) return 'null';\n    if (value === undefined) return 'undefined';\n    if (Array.isArray(value)) return 'array';\n    if (value instanceof Date) return 'date';\n    if (typeof value === 'object' && '_bsontype' in (value as any)) {\n      return (value as any)._bsontype.toLowerCase();\n    }\n    if (typeof value === 'object') return 'object';\n    return typeof value;\n  }\n\n  /**\n   * 检查是否为写操作\n   *\n   * MongoDB 写操作包括：insert, update, delete, drop 等\n   */\n  isWriteOperation(query: string): boolean {\n    // 检查 JSON 格式的操作\n    if (query.trim().startsWith('{')) {\n      try {\n        const parsed = JSON.parse(query);\n        const operation = parsed.operation?.toLowerCase() || '';\n        return this.isWriteOperationName(operation);\n      } catch {\n        return false;\n      }\n    }\n\n    // 检查 db.collection.operation() 格式\n    const match = query.match(/db\\.\\w+\\.(\\w+)\\(/);\n    if (match) {\n      const operation = match[1].toLowerCase();\n      return this.isWriteOperationName(operation);\n    }\n\n    return false;\n  }\n\n  /**\n   * 检查操作名称是否为写操作\n   */\n  private isWriteOperationName(operation: string): boolean {\n    const writeOperations = [\n      'insert', 'insertone', 'insertmany',\n      'update', 'updateone', 'updatemany',\n      'replace', 'replaceone',\n      'delete', 'deleteone', 'deletemany',\n      'remove', 'removeone', 'removemany',\n      'drop', 'dropcollection', 'dropdatabase',\n      'create', 'createcollection', 'createindex',\n      'rename', 'renamecollection',\n    ];\n\n    return writeOperations.includes(operation);\n  }\n}\n"
  },
  {
    "path": "src/adapters/mysql.ts",
    "content": "/**\n * MySQL 数据库适配器\n * 使用 mysql2 驱动实现 DbAdapter 接口\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport mysql from 'mysql2/promise';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class MySQLAdapter implements DbAdapter {\n  private pool: mysql.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 MySQL 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = mysql.createPool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        multipleStatements: false,\n        // 连接池配置\n        waitForConnections: true,\n        connectionLimit: 3,\n        maxIdle: 1,\n        idleTimeout: 60000,\n        // TCP Keep-Alive：防止连接被服务端或中间件超时关闭\n        enableKeepAlive: true,\n        keepAliveInitialDelay: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `MySQL 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const [rows, fields] = await this.withRetry(() => this.pool!.execute(query, params));\n      const executionTime = Date.now() - startTime;\n\n      // 处理不同类型的查询结果\n      if (Array.isArray(rows)) {\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            fieldCount: fields?.length || 0,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const result = rows as mysql.ResultSetHeader;\n        return {\n          rows: [],\n          affectedRows: result.affectedRows,\n          executionTime,\n          metadata: {\n            insertId: result.insertId,\n            changedRows: result.changedRows,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   *\n   * 优化前：每个表需要 4 次查询（列、主键、索引、行数）\n   * 优化后：只需要 4 次查询获取所有表的信息\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * getSchema 内部实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    // 获取数据库版本\n    const [versionRows] = await this.pool!.query('SELECT VERSION() as version');\n    const version = (versionRows as any[])[0]?.version || 'unknown';\n\n    // 获取当前数据库名\n    const [dbRows] = await this.pool!.query('SELECT DATABASE() as db');\n    const databaseName = (dbRows as any[])[0]?.db || this.config.database || 'unknown';\n\n    // 批量获取所有表的列信息\n    const [allColumns] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        COLUMN_NAME,\n        COLUMN_TYPE,\n        IS_NULLABLE,\n        COLUMN_DEFAULT,\n        COLUMN_KEY,\n        COLUMN_COMMENT,\n        ORDINAL_POSITION\n      FROM INFORMATION_SCHEMA.COLUMNS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, ORDINAL_POSITION\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的索引信息\n    const [allIndexes] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        INDEX_NAME,\n        COLUMN_NAME,\n        NON_UNIQUE,\n        SEQ_IN_INDEX\n      FROM INFORMATION_SCHEMA.STATISTICS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的行数估算\n    const [allStats] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        TABLE_ROWS,\n        TABLE_COMMENT\n      FROM INFORMATION_SCHEMA.TABLES\n      WHERE TABLE_SCHEMA = DATABASE()\n        AND TABLE_TYPE = 'BASE TABLE'\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有外键信息\n    let allForeignKeys: mysql.RowDataPacket[] = [];\n    try {\n      const [fkRows] = await this.pool!.query(`\n        SELECT\n          kcu.TABLE_NAME,\n          kcu.CONSTRAINT_NAME,\n          kcu.COLUMN_NAME,\n          kcu.REFERENCED_TABLE_NAME,\n          kcu.REFERENCED_COLUMN_NAME,\n          kcu.ORDINAL_POSITION,\n          rc.DELETE_RULE,\n          rc.UPDATE_RULE\n        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n        JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n          ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n          AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA\n        WHERE kcu.TABLE_SCHEMA = DATABASE()\n          AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n        ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, kcu.ORDINAL_POSITION\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n      allForeignKeys = fkRows;\n    } catch (error) {\n      // 外键查询失败时忽略，返回空数组\n      console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n    }\n\n    // 在内存中组装数据\n    return this.assembleSchema(databaseName, version, allColumns, allIndexes, allStats, allForeignKeys);\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: mysql.RowDataPacket[],\n    allIndexes: mysql.RowDataPacket[],\n    allStats: mysql.RowDataPacket[],\n    allForeignKeys: mysql.RowDataPacket[]\n  ): SchemaInfo {\n    // 按表名分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const primaryKeysByTable = new Map<string, string[]>();\n\n    for (const col of allColumns) {\n      const tableName = col.TABLE_NAME;\n\n      if (!columnsByTable.has(tableName)) {\n        columnsByTable.set(tableName, []);\n        primaryKeysByTable.set(tableName, []);\n      }\n\n      columnsByTable.get(tableName)!.push({\n        name: col.COLUMN_NAME,\n        type: col.COLUMN_TYPE,\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT,\n        comment: col.COLUMN_COMMENT || undefined,\n      });\n\n      // 收集主键\n      if (col.COLUMN_KEY === 'PRI') {\n        primaryKeysByTable.get(tableName)!.push(col.COLUMN_NAME);\n      }\n    }\n\n    // 按表名分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n\n      if (indexName === 'PRIMARY') continue; // 跳过主键索引\n\n      if (!indexesByTable.has(tableName)) {\n        indexesByTable.set(tableName, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableName)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.NON_UNIQUE === 0,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.COLUMN_NAME);\n    }\n\n    // 按表名分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      rowsByTable.set(stat.TABLE_NAME, stat.TABLE_ROWS || 0);\n      if (stat.TABLE_COMMENT) {\n        commentsByTable.set(stat.TABLE_NAME, stat.TABLE_COMMENT);\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!foreignKeysByTable.has(tableName)) {\n        foreignKeysByTable.set(tableName, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableName)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: fk.REFERENCED_TABLE_NAME,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n          onUpdate: fk.UPDATE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.COLUMN_NAME);\n      fkInfo.referencedColumns.push(fk.REFERENCED_COLUMN_NAME);\n    }\n\n    // 生成全局关系视图\n    for (const [tableName, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableName,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableName, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableName);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableName);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableName,\n        comment: commentsByTable.get(tableName) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableName) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableName) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'mysql',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/oceanbase.ts",
    "content": "/**\n * OceanBase 数据库适配器\n * 使用 mysql2 驱动实现 DbAdapter 接口\n * OceanBase 兼容 MySQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport mysql from 'mysql2/promise';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class OceanBaseAdapter implements DbAdapter {\n  private pool: mysql.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 OceanBase 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = mysql.createPool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        multipleStatements: false,\n        waitForConnections: true,\n        connectionLimit: 3,\n        maxIdle: 1,\n        idleTimeout: 60000,\n        enableKeepAlive: true,\n        keepAliveInitialDelay: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `OceanBase 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const [rows, fields] = await this.withRetry(() => this.pool!.execute(query, params));\n      const executionTime = Date.now() - startTime;\n\n      // 处理不同类型的查询结果\n      if (Array.isArray(rows)) {\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            fieldCount: fields?.length || 0,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const result = rows as mysql.ResultSetHeader;\n        return {\n          rows: [],\n          affectedRows: result.affectedRows,\n          executionTime,\n          metadata: {\n            insertId: result.insertId,\n            changedRows: result.changedRows,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    // 获取数据库版本\n    const [versionRows] = await this.pool!.query('SELECT VERSION() as version');\n    const version = (versionRows as any[])[0]?.version || 'unknown';\n\n    // 获取当前数据库名\n    const [dbRows] = await this.pool!.query('SELECT DATABASE() as db');\n    const databaseName = (dbRows as any[])[0]?.db || this.config.database || 'unknown';\n\n    // 批量获取所有表的列信息\n    const [allColumns] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        COLUMN_NAME,\n        COLUMN_TYPE,\n        IS_NULLABLE,\n        COLUMN_DEFAULT,\n        COLUMN_KEY,\n        COLUMN_COMMENT,\n        ORDINAL_POSITION\n      FROM INFORMATION_SCHEMA.COLUMNS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, ORDINAL_POSITION\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的索引信息\n    const [allIndexes] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        INDEX_NAME,\n        COLUMN_NAME,\n        NON_UNIQUE,\n        SEQ_IN_INDEX\n      FROM INFORMATION_SCHEMA.STATISTICS\n      WHERE TABLE_SCHEMA = DATABASE()\n      ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有表的行数估算和表注释\n    const [allStats] = await this.pool!.query(`\n      SELECT\n        TABLE_NAME,\n        TABLE_ROWS,\n        TABLE_COMMENT\n      FROM INFORMATION_SCHEMA.TABLES\n      WHERE TABLE_SCHEMA = DATABASE()\n        AND TABLE_TYPE = 'BASE TABLE'\n    `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n    // 批量获取所有外键信息\n    let allForeignKeys: mysql.RowDataPacket[] = [];\n    try {\n      const [fkRows] = await this.pool!.query(`\n        SELECT\n          kcu.TABLE_NAME,\n          kcu.CONSTRAINT_NAME,\n          kcu.COLUMN_NAME,\n          kcu.REFERENCED_TABLE_NAME,\n          kcu.REFERENCED_COLUMN_NAME,\n          kcu.ORDINAL_POSITION,\n          rc.DELETE_RULE,\n          rc.UPDATE_RULE\n        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n        JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n          ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n          AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA\n        WHERE kcu.TABLE_SCHEMA = DATABASE()\n          AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n        ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, kcu.ORDINAL_POSITION\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n      allForeignKeys = fkRows;\n    } catch (error) {\n      // 外键查询失败时忽略，返回空数组\n      console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n    }\n\n    // 在内存中组装数据\n    return this.assembleSchema(databaseName, version, allColumns, allIndexes, allStats, allForeignKeys);\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: mysql.RowDataPacket[],\n    allIndexes: mysql.RowDataPacket[],\n    allStats: mysql.RowDataPacket[],\n    allForeignKeys: mysql.RowDataPacket[]\n  ): SchemaInfo {\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const primaryKeysByTable = new Map<string, string[]>();\n\n    for (const col of allColumns) {\n      const tableName = col.TABLE_NAME;\n\n      if (!columnsByTable.has(tableName)) {\n        columnsByTable.set(tableName, []);\n        primaryKeysByTable.set(tableName, []);\n      }\n\n      columnsByTable.get(tableName)!.push({\n        name: col.COLUMN_NAME,\n        type: col.COLUMN_TYPE,\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT,\n        comment: col.COLUMN_COMMENT || undefined,\n      });\n\n      if (col.COLUMN_KEY === 'PRI') {\n        primaryKeysByTable.get(tableName)!.push(col.COLUMN_NAME);\n      }\n    }\n\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n\n      if (indexName === 'PRIMARY') continue;\n\n      if (!indexesByTable.has(tableName)) {\n        indexesByTable.set(tableName, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableName)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.NON_UNIQUE === 0,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.COLUMN_NAME);\n    }\n\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      rowsByTable.set(stat.TABLE_NAME, stat.TABLE_ROWS || 0);\n      if (stat.TABLE_COMMENT) {\n        commentsByTable.set(stat.TABLE_NAME, stat.TABLE_COMMENT);\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!foreignKeysByTable.has(tableName)) {\n        foreignKeysByTable.set(tableName, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableName)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: fk.REFERENCED_TABLE_NAME,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n          onUpdate: fk.UPDATE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.COLUMN_NAME);\n      fkInfo.referencedColumns.push(fk.REFERENCED_COLUMN_NAME);\n    }\n\n    // 生成全局关系视图\n    for (const [tableName, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableName,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableName, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableName);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableName);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableName,\n        comment: commentsByTable.get(tableName) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableName) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableName) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'oceanbase',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/oracle.ts",
    "content": "/**\n * Oracle 数据库适配器\n * 使用 oracledb 驱动实现 DbAdapter 接口\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + 连接健康检测 + 断线自动重试，确保长连接稳定性\n */\n\nimport oracledb from 'oracledb';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class OracleAdapter implements DbAdapter {\n  private pool: oracledb.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n    serviceName?: string;\n    sid?: string;\n    connectString?: string;\n    oracleClientPath?: string;\n  };\n  private static thickModeInitialized = false;\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n    serviceName?: string;\n    sid?: string;\n    connectString?: string;\n    oracleClientPath?: string;\n  }) {\n    this.config = config;\n\n    // 如果提供了 Oracle Client 路径，启用 Thick 模式（支持 11g）\n    if (config.oracleClientPath && !OracleAdapter.thickModeInitialized) {\n      try {\n        oracledb.initOracleClient({ libDir: config.oracleClientPath });\n        OracleAdapter.thickModeInitialized = true;\n        console.error(`🔧 Oracle Thick 模式已启用，Client 路径: ${config.oracleClientPath}`);\n      } catch (error: any) {\n        // 如果已经初始化过，忽略错误\n        if (error.message && error.message.includes('already initialized')) {\n          OracleAdapter.thickModeInitialized = true;\n        } else {\n          throw new Error(`Oracle Client 初始化失败: ${error.message || String(error)}`);\n        }\n      }\n    }\n\n    // 配置 oracledb 全局设置\n    oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;\n    oracledb.fetchAsString = [oracledb.CLOB];\n  }\n\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    const errNum = (error as any)?.errorNum;\n    return /NJS-003|NJS-500|NJS-521|DPI-1010|DPI-1080|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED/.test(msg) ||\n      [3113, 3114, 3135, 12170, 12571, 28547].includes(errNum);\n  }\n\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try { return await fn(); } catch (error) { if (this.isConnectionError(error)) { return await fn(); } throw error; }\n  }\n\n  private async withConnection<T>(fn: (conn: oracledb.Connection) => Promise<T>): Promise<T> {\n    const connection = await this.pool!.getConnection();\n    try { return await fn(connection); } finally { await connection.close(); }\n  }\n\n  /**\n   * 构建 Oracle 连接字符串\n   */\n  private buildConnectionString(): string {\n    // 优先级: connectString > serviceName > sid > database\n    if (this.config.connectString) {\n      return this.config.connectString;\n    }\n\n    const host = this.config.host;\n    const port = this.config.port || 1521;\n    const service = this.config.serviceName || this.config.sid || this.config.database;\n\n    if (!service) {\n      throw new Error('必须提供 database、serviceName 或 sid');\n    }\n\n    // 构建 Easy Connect 字符串\n    return `${host}:${port}/${service}`;\n  }\n\n  /**\n   * 连接到 Oracle 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      const connectionString = this.buildConnectionString();\n      this.pool = await oracledb.createPool({\n        user: this.config.user,\n        password: this.config.password,\n        connectString: connectionString,\n        poolMin: 1,\n        poolMax: 3,\n        poolTimeout: 60,\n        poolPingInterval: 30,\n      });\n      // 测试连接\n      const connection = await this.pool.getConnection();\n      try { await connection.execute('SELECT 1 FROM DUAL'); } finally { await connection.close(); }\n    } catch (error: any) {\n      if (error.errorNum === 1017) throw new Error('Oracle 连接失败: 用户名或密码无效');\n      else if (error.errorNum === 12154) throw new Error('Oracle 连接失败: 无法解析连接标识符，请检查 TNS 配置');\n      else if (error.errorNum === 12541) throw new Error('Oracle 连接失败: TNS 无监听程序');\n      throw new Error(`Oracle 连接失败: ${error instanceof Error ? error.message : String(error)}`);\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      try { await this.pool.close(0); } catch {}\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) throw new Error('数据库未连接');\n    const startTime = Date.now();\n    try {\n      return await this.withRetry(() => this.withConnection(async (connection) => {\n        let cleanQuery = query.trim();\n        if (cleanQuery.endsWith(';')) cleanQuery = cleanQuery.slice(0, -1).trim();\n        const result = await connection.execute(cleanQuery, params || [], { autoCommit: false, outFormat: oracledb.OUT_FORMAT_OBJECT });\n        const executionTime = Date.now() - startTime;\n        if (result.rows && result.rows.length > 0) {\n          const rows = result.rows.map((row: any) => { const r: Record<string, unknown> = {}; for (const [k, v] of Object.entries(row)) { r[k.toLowerCase()] = v; } return r; });\n          return { rows, executionTime, metadata: { columnCount: result.metaData?.length || 0 } };\n        } else if (result.rowsAffected !== undefined && result.rowsAffected > 0) {\n          return { rows: [], affectedRows: result.rowsAffected, executionTime };\n        } else {\n          return { rows: [], executionTime };\n        }\n      }));\n    } catch (error: any) {\n      if (error.errorNum === 942) throw new Error('查询执行失败: 表或视图不存在');\n      else if (error.errorNum === 1) throw new Error('查询执行失败: 违反唯一约束');\n      throw new Error(`查询执行失败: ${error instanceof Error ? error.message : String(error)}`);\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    return this.withConnection(async (connection) => {\n      // 获取 Oracle 版本\n      const versionResult = await connection.execute(\n        `SELECT banner FROM v$version WHERE banner LIKE 'Oracle%'`\n      );\n      const version = versionResult.rows?.[0]\n        ? Object.values(versionResult.rows[0])[0] as string\n        : 'unknown';\n\n      // 获取当前用户\n      const userResult = await connection.execute('SELECT USER FROM DUAL');\n      const currentUser = userResult.rows?.[0]\n        ? Object.values(userResult.rows[0])[0] as string\n        : 'unknown';\n      const databaseName = currentUser;\n\n      // 批量获取所有表的列信息\n      const allColumnsResult = await connection.execute(\n        `SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION,\n                DATA_SCALE, NULLABLE, DATA_DEFAULT, COLUMN_ID\n         FROM ALL_TAB_COLUMNS\n         WHERE OWNER NOT IN (\n           'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n           'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n           'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n           'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n         )\n         ORDER BY TABLE_NAME, COLUMN_ID`\n      );\n\n      // 批量获取所有列注释\n      const allCommentsResult = await connection.execute(\n        `SELECT OWNER, TABLE_NAME, COLUMN_NAME, COMMENTS\n         FROM ALL_COL_COMMENTS\n         WHERE OWNER NOT IN (\n           'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n           'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n           'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n           'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n         )\n           AND COMMENTS IS NOT NULL`\n      );\n\n      // 批量获取所有主键信息\n      const allPrimaryKeysResult = await connection.execute(\n        `SELECT cons.OWNER, cons.TABLE_NAME, cols.COLUMN_NAME, cols.POSITION\n         FROM ALL_CONSTRAINTS cons\n         JOIN ALL_CONS_COLUMNS cols\n           ON cons.CONSTRAINT_NAME = cols.CONSTRAINT_NAME\n           AND cons.OWNER = cols.OWNER\n         WHERE cons.CONSTRAINT_TYPE = 'P'\n           AND cons.OWNER NOT IN (\n             'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n             'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n             'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n             'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n           )\n         ORDER BY cons.TABLE_NAME, cols.POSITION`\n      );\n\n      // 批量获取所有索引信息\n      const allIndexesResult = await connection.execute(\n        `SELECT i.TABLE_OWNER AS OWNER, i.TABLE_NAME, i.INDEX_NAME, i.UNIQUENESS, ic.COLUMN_NAME, ic.COLUMN_POSITION\n         FROM ALL_INDEXES i\n         JOIN ALL_IND_COLUMNS ic\n           ON i.INDEX_NAME = ic.INDEX_NAME\n           AND i.OWNER = ic.INDEX_OWNER\n         WHERE i.OWNER NOT IN (\n           'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n           'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n           'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n           'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n         )\n           AND i.INDEX_TYPE != 'LOB'\n         ORDER BY i.TABLE_NAME, i.INDEX_NAME, ic.COLUMN_POSITION`\n      );\n\n      // 批量获取所有表的行数估算和表注释\n      const allStatsResult = await connection.execute(\n        `SELECT t.OWNER, t.TABLE_NAME, t.NUM_ROWS, c.COMMENTS AS TABLE_COMMENT\n         FROM ALL_TABLES t\n         LEFT JOIN ALL_TAB_COMMENTS c ON t.TABLE_NAME = c.TABLE_NAME AND t.OWNER = c.OWNER\n         WHERE t.OWNER NOT IN (\n           'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n           'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n           'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n           'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n         )\n           AND t.TEMPORARY = 'N'`\n      );\n\n      // 批量获取所有外键信息\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await connection.execute(\n          `SELECT\n            c.OWNER,\n            c.TABLE_NAME,\n            c.CONSTRAINT_NAME,\n            cc.COLUMN_NAME,\n            rc.OWNER AS REF_OWNER,\n            rc.TABLE_NAME AS REFERENCED_TABLE,\n            rcc.COLUMN_NAME AS REFERENCED_COLUMN,\n            c.DELETE_RULE,\n            cc.POSITION\n          FROM ALL_CONSTRAINTS c\n          JOIN ALL_CONS_COLUMNS cc ON c.CONSTRAINT_NAME = cc.CONSTRAINT_NAME AND c.OWNER = cc.OWNER\n          JOIN ALL_CONSTRAINTS rc ON c.R_CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND c.R_OWNER = rc.OWNER\n          JOIN ALL_CONS_COLUMNS rcc ON rc.CONSTRAINT_NAME = rcc.CONSTRAINT_NAME AND rc.OWNER = rcc.OWNER AND cc.POSITION = rcc.POSITION\n          WHERE c.CONSTRAINT_TYPE = 'R'\n            AND c.OWNER NOT IN (\n              'SYS', 'SYSTEM', 'DBSNMP', 'APPQOSSYS', 'DBSFWUSER',\n              'OUTLN', 'GSMADMIN_INTERNAL', 'GGSYS', 'XDB', 'WMSYS',\n              'MDSYS', 'ORDDATA', 'CTXSYS', 'ORDSYS', 'OLAPSYS',\n              'LBACSYS', 'DVSYS', 'AUDSYS', 'OJVMSYS', 'REMOTE_SCHEDULER_AGENT'\n            )\n          ORDER BY c.TABLE_NAME, c.CONSTRAINT_NAME, cc.POSITION`\n        );\n        allForeignKeys = allForeignKeysResult.rows || [];\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchema(\n        databaseName,\n        version,\n        allColumnsResult.rows || [],\n        allCommentsResult.rows || [],\n        allPrimaryKeysResult.rows || [],\n        allIndexesResult.rows || [],\n        allStatsResult.rows || [],\n        allForeignKeys,\n        currentUser\n      );\n    });\n  }\n\n  private makeTableKey(owner: string, tableName: string, currentUser: string): string {\n    return owner === currentUser ? tableName : `${owner}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allComments: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[],\n    currentUser: string\n  ): SchemaInfo {\n    // 按表名分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const owner = col.OWNER;\n      const tableName = col.TABLE_NAME;\n      const columnName = col.COLUMN_NAME;\n\n      // 跳过无效数据\n      if (!tableName || !columnName) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, owner);\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: columnName.toLowerCase(),\n        type: this.formatOracleType(\n          col.DATA_TYPE,\n          col.DATA_LENGTH,\n          col.DATA_PRECISION,\n          col.DATA_SCALE\n        ),\n        nullable: col.NULLABLE === 'Y',\n        defaultValue: col.DATA_DEFAULT?.trim() || undefined,\n      });\n    }\n\n    // 按表名分组列注释\n    const commentsByTable = new Map<string, Map<string, string>>();\n    for (const comment of allComments) {\n      const owner = comment.OWNER;\n      const tableName = comment.TABLE_NAME;\n      const columnName = comment.COLUMN_NAME;\n      const comments = comment.COMMENTS;\n\n      // 跳过无效数据\n      if (!tableName || !columnName || !comments) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!commentsByTable.has(tableKey)) {\n        commentsByTable.set(tableKey, new Map());\n      }\n      commentsByTable.get(tableKey)!.set(\n        columnName.toLowerCase(),\n        comments\n      );\n    }\n\n    // 将注释添加到列信息中\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableComments = commentsByTable.get(tableKey);\n      if (tableComments) {\n        for (const col of columns) {\n          if (tableComments.has(col.name)) {\n            col.comment = tableComments.get(col.name);\n          }\n        }\n      }\n    }\n\n    // 按表名分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const owner = pk.OWNER;\n      const tableName = pk.TABLE_NAME;\n      const columnName = pk.COLUMN_NAME;\n\n      // 跳过无效数据\n      if (!tableName || !columnName) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(columnName.toLowerCase());\n    }\n\n    // 按表名分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const owner = idx.OWNER;\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n      const columnName = idx.COLUMN_NAME;\n\n      // 跳过无效数据\n      if (!tableName || !indexName || !columnName) {\n        continue;\n      }\n\n      // 跳过主键索引\n      if (indexName.includes('PK_') || indexName.includes('SYS_')) {\n        continue;\n      }\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.UNIQUENESS === 'UNIQUE',\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(columnName.toLowerCase());\n    }\n\n    // 按表名分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const tableCommentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const owner = stat.OWNER;\n      const tableName = stat.TABLE_NAME;\n      if (tableName) {\n        const tableKey = this.makeTableKey(owner, tableName, currentUser);\n        rowsByTable.set(tableKey, stat.NUM_ROWS || 0);\n        if (stat.TABLE_COMMENT) {\n          tableCommentsByTable.set(tableKey, stat.TABLE_COMMENT);\n        }\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const owner = fk.OWNER;\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!tableName || !constraintName) continue;\n\n      const tableKey = this.makeTableKey(owner, tableName, currentUser);\n      const refOwner = fk.REF_OWNER;\n      const refTableKey = this.makeTableKey(refOwner, fk.REFERENCED_TABLE, currentUser);\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(String(fk.COLUMN_NAME).toLowerCase());\n      fkInfo.referencedColumns.push(String(fk.REFERENCED_COLUMN).toLowerCase());\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey.toLowerCase(),\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable.toLowerCase(),\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息（基于列信息构建，不依赖 ALL_TABLES 的结果）\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable.toLowerCase(),\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey.toLowerCase(),\n        schema: schemaByTable.get(tableKey),\n        comment: tableCommentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'oracle',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 格式化 Oracle 数据类型\n   */\n  private formatOracleType(\n    dataType: string | undefined | null,\n    length?: number,\n    precision?: number,\n    scale?: number\n  ): string {\n    // 处理空值\n    if (!dataType) {\n      return 'UNKNOWN';\n    }\n\n    switch (dataType) {\n      case 'NUMBER':\n        if (precision !== null && precision !== undefined) {\n          if (scale !== null && scale !== undefined && scale > 0) {\n            return `NUMBER(${precision},${scale})`;\n          }\n          return `NUMBER(${precision})`;\n        }\n        return 'NUMBER';\n\n      case 'VARCHAR2':\n      case 'CHAR':\n        if (length) {\n          return `${dataType}(${length})`;\n        }\n        return dataType;\n\n      case 'TIMESTAMP':\n        if (scale !== null && scale !== undefined) {\n          return `TIMESTAMP(${scale})`;\n        }\n        return 'TIMESTAMP';\n\n      default:\n        return dataType;\n    }\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    // 首先使用通用的写操作检测\n    if (checkWriteOperation(query)) {\n      return true;\n    }\n\n    // 添加 Oracle 特定的写操作检测\n    const trimmedQuery = query.trim().toUpperCase();\n\n    // MERGE 语句（Oracle 的 upsert 操作）\n    if (trimmedQuery.startsWith('MERGE')) {\n      return true;\n    }\n\n    // PL/SQL 块（可能包含写操作）\n    if (trimmedQuery.startsWith('BEGIN') || trimmedQuery.startsWith('DECLARE')) {\n      return true;\n    }\n\n    // CALL 存储过程（可能包含写操作）\n    if (trimmedQuery.startsWith('CALL')) {\n      return true;\n    }\n\n    // 事务控制语句\n    if (trimmedQuery.startsWith('COMMIT') || trimmedQuery.startsWith('ROLLBACK')) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "src/adapters/polardb.ts",
    "content": "/**\n * PolarDB 数据库适配器\n * 使用 mysql2 驱动实现 DbAdapter 接口\n * PolarDB for MySQL 完全兼容 MySQL 5.6/5.7/8.0 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport mysql from 'mysql2/promise';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class PolarDBAdapter implements DbAdapter {\n  private pool: mysql.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 PolarDB 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = mysql.createPool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        multipleStatements: false,\n        waitForConnections: true,\n        connectionLimit: 3,\n        maxIdle: 1,\n        idleTimeout: 60000,\n        enableKeepAlive: true,\n        keepAliveInitialDelay: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `PolarDB 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const [rows, fields] = await this.withRetry(() => this.pool!.execute(query, params));\n      const executionTime = Date.now() - startTime;\n\n      // 处理不同类型的查询结果\n      if (Array.isArray(rows)) {\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            fieldCount: fields?.length || 0,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const result = rows as mysql.ResultSetHeader;\n        return {\n          rows: [],\n          affectedRows: result.affectedRows,\n          executionTime,\n          metadata: {\n            insertId: result.insertId,\n            changedRows: result.changedRows,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n      // 获取数据库版本\n      const [versionRows] = await this.pool!.query('SELECT VERSION() as version');\n      const version = (versionRows as any[])[0]?.version || 'unknown';\n\n      // 获取当前数据库名\n      const [dbRows] = await this.pool!.query('SELECT DATABASE() as db');\n      const databaseName = (dbRows as any[])[0]?.db || this.config.database || 'unknown';\n\n      // 批量获取所有表的列信息\n      const [allColumns] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          COLUMN_NAME,\n          COLUMN_TYPE,\n          IS_NULLABLE,\n          COLUMN_DEFAULT,\n          COLUMN_KEY,\n          COLUMN_COMMENT,\n          ORDINAL_POSITION\n        FROM INFORMATION_SCHEMA.COLUMNS\n        WHERE TABLE_SCHEMA = DATABASE()\n        ORDER BY TABLE_NAME, ORDINAL_POSITION\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有表的索引信息\n      const [allIndexes] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          INDEX_NAME,\n          COLUMN_NAME,\n          NON_UNIQUE,\n          SEQ_IN_INDEX\n        FROM INFORMATION_SCHEMA.STATISTICS\n        WHERE TABLE_SCHEMA = DATABASE()\n        ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有表的行数估算和表注释\n      const [allStats] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          TABLE_ROWS,\n          TABLE_COMMENT\n        FROM INFORMATION_SCHEMA.TABLES\n        WHERE TABLE_SCHEMA = DATABASE()\n          AND TABLE_TYPE = 'BASE TABLE'\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有外键信息\n      let allForeignKeys: mysql.RowDataPacket[] = [];\n      try {\n        const [fkRows] = await this.pool!.query(`\n          SELECT\n            kcu.TABLE_NAME,\n            kcu.CONSTRAINT_NAME,\n            kcu.COLUMN_NAME,\n            kcu.REFERENCED_TABLE_NAME,\n            kcu.REFERENCED_COLUMN_NAME,\n            kcu.ORDINAL_POSITION,\n            rc.DELETE_RULE,\n            rc.UPDATE_RULE\n          FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n          JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n            ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n            AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA\n          WHERE kcu.TABLE_SCHEMA = DATABASE()\n            AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n          ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, kcu.ORDINAL_POSITION\n        `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n        allForeignKeys = fkRows;\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      // 在内存中组装数据\n      return this.assembleSchema(databaseName, version, allColumns, allIndexes, allStats, allForeignKeys);\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: mysql.RowDataPacket[],\n    allIndexes: mysql.RowDataPacket[],\n    allStats: mysql.RowDataPacket[],\n    allForeignKeys: mysql.RowDataPacket[]\n  ): SchemaInfo {\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const primaryKeysByTable = new Map<string, string[]>();\n\n    for (const col of allColumns) {\n      const tableName = col.TABLE_NAME;\n\n      if (!columnsByTable.has(tableName)) {\n        columnsByTable.set(tableName, []);\n        primaryKeysByTable.set(tableName, []);\n      }\n\n      columnsByTable.get(tableName)!.push({\n        name: col.COLUMN_NAME,\n        type: col.COLUMN_TYPE,\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT,\n        comment: col.COLUMN_COMMENT || undefined,\n      });\n\n      if (col.COLUMN_KEY === 'PRI') {\n        primaryKeysByTable.get(tableName)!.push(col.COLUMN_NAME);\n      }\n    }\n\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n\n      if (indexName === 'PRIMARY') continue;\n\n      if (!indexesByTable.has(tableName)) {\n        indexesByTable.set(tableName, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableName)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.NON_UNIQUE === 0,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.COLUMN_NAME);\n    }\n\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      rowsByTable.set(stat.TABLE_NAME, stat.TABLE_ROWS || 0);\n      if (stat.TABLE_COMMENT) {\n        commentsByTable.set(stat.TABLE_NAME, stat.TABLE_COMMENT);\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!foreignKeysByTable.has(tableName)) {\n        foreignKeysByTable.set(tableName, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableName)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: fk.REFERENCED_TABLE_NAME,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n          onUpdate: fk.UPDATE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.COLUMN_NAME);\n      fkInfo.referencedColumns.push(fk.REFERENCED_COLUMN_NAME);\n    }\n\n    // 生成全局关系视图\n    for (const [tableName, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableName,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableName, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableName);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableName);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableName,\n        comment: commentsByTable.get(tableName) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableName) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableName) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'polardb',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/postgres.ts",
    "content": "/**\n * PostgreSQL 数据库适配器\n * 使用 pg 驱动实现 DbAdapter 接口\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport pg from 'pg';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nconst { Pool } = pg;\n\nexport class PostgreSQLAdapter implements DbAdapter {\n  private pool: pg.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    const code = String((error as any)?.code || '');\n    return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(msg + code);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 PostgreSQL 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = new Pool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        // 连接池配置\n        max: 3,\n        idleTimeoutMillis: 60000,\n        // TCP Keep-Alive：防止连接被服务端或中间件超时关闭\n        keepAlive: true,\n        keepAliveInitialDelayMillis: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `PostgreSQL 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const result = await this.withRetry(() => this.pool!.query(query, params));\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result.rows,\n        affectedRows: result.rowCount || 0,\n        executionTime,\n        metadata: {\n          command: result.command,\n          fields: result.fields?.map(f => ({\n            name: f.name,\n            dataTypeID: f.dataTypeID,\n          })),\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   *\n   * 优化前：每个表需要 4 次查询（列、主键、索引、行数）\n   * 优化后：只需要 4 次查询获取所有表的信息\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * getSchema 内部实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    // 获取数据库版本\n    const versionResult = await this.pool!.query('SELECT version()');\n    const version = versionResult.rows[0]?.version || 'unknown';\n\n    // 获取当前数据库名\n    const dbResult = await this.pool!.query('SELECT current_database()');\n    const databaseName = dbResult.rows[0]?.current_database || this.config.database || 'unknown';\n\n    // 批量获取所有表的列信息（支持多 schema）\n    const allColumnsResult = await this.pool!.query(`\n      SELECT\n        c.table_schema,\n        c.table_name,\n        c.column_name,\n        c.data_type,\n        c.is_nullable,\n        c.column_default,\n        c.character_maximum_length,\n        c.numeric_precision,\n        c.numeric_scale,\n        c.ordinal_position\n      FROM information_schema.columns c\n      JOIN information_schema.tables t\n        ON c.table_schema = t.table_schema AND c.table_name = t.table_name\n      WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        AND t.table_type = 'BASE TABLE'\n      ORDER BY c.table_schema, c.table_name, c.ordinal_position\n    `);\n\n    // 批量获取所有表的主键信息\n    const allPrimaryKeysResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        t.relname as table_name,\n        a.attname as column_name\n      FROM pg_index i\n      JOIN pg_class t ON t.oid = i.indrelid\n      JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)\n      JOIN pg_namespace n ON n.oid = t.relnamespace\n      WHERE i.indisprimary\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n      ORDER BY n.nspname, t.relname, a.attnum\n    `);\n\n    // 批量获取所有表的索引信息（排除主键）\n    const allIndexesResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        t.relname as table_name,\n        i.relname as index_name,\n        a.attname as column_name,\n        ix.indisunique as is_unique\n      FROM pg_class t\n      JOIN pg_index ix ON t.oid = ix.indrelid\n      JOIN pg_class i ON i.oid = ix.indexrelid\n      JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n      JOIN pg_namespace n ON n.oid = t.relnamespace\n      WHERE t.relkind = 'r'\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        AND NOT ix.indisprimary\n      ORDER BY n.nspname, t.relname, i.relname, a.attnum\n    `);\n\n    // 批量获取所有表的行数估算\n    const allStatsResult = await this.pool!.query(`\n      SELECT\n        n.nspname as schema_name,\n        c.relname as table_name,\n        c.reltuples::bigint as estimated_rows,\n        obj_description(c.oid, 'pg_class') as table_comment\n      FROM pg_class c\n      JOIN pg_namespace n ON n.oid = c.relnamespace\n      WHERE c.relkind = 'r'\n        AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n    `);\n\n    // 批量获取所有外键信息\n    let allForeignKeys: any[] = [];\n    try {\n      const allForeignKeysResult = await this.pool!.query(`\n        SELECT\n          n.nspname AS schema_name,\n          c.conname AS constraint_name,\n          t.relname AS table_name,\n          a.attname AS column_name,\n          rn.nspname AS ref_schema_name,\n          rt.relname AS referenced_table,\n          ra.attname AS referenced_column,\n          CASE c.confdeltype\n            WHEN 'a' THEN 'NO ACTION'\n            WHEN 'r' THEN 'RESTRICT'\n            WHEN 'c' THEN 'CASCADE'\n            WHEN 'n' THEN 'SET NULL'\n            WHEN 'd' THEN 'SET DEFAULT'\n          END AS delete_rule,\n          CASE c.confupdtype\n            WHEN 'a' THEN 'NO ACTION'\n            WHEN 'r' THEN 'RESTRICT'\n            WHEN 'c' THEN 'CASCADE'\n            WHEN 'n' THEN 'SET NULL'\n            WHEN 'd' THEN 'SET DEFAULT'\n          END AS update_rule,\n          array_position(c.conkey, a.attnum) AS column_position\n        FROM pg_constraint c\n        JOIN pg_class t ON t.oid = c.conrelid\n        JOIN pg_class rt ON rt.oid = c.confrelid\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        JOIN pg_namespace rn ON rn.oid = rt.relnamespace\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)\n        JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = c.confkey[array_position(c.conkey, a.attnum)]\n        WHERE c.contype = 'f'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        ORDER BY n.nspname, t.relname, c.conname, array_position(c.conkey, a.attnum)\n      `);\n      allForeignKeys = allForeignKeysResult.rows;\n    } catch (error) {\n      // 外键查询失败时忽略，返回空数组\n      console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n    }\n\n    // 在内存中组装数据\n    return this.assembleSchema(\n      databaseName,\n      version,\n      allColumnsResult.rows,\n      allPrimaryKeysResult.rows,\n      allIndexesResult.rows,\n      allStatsResult.rows,\n      allForeignKeys\n    );\n  }\n\n  /**\n   * 构建带 schema 前缀的表名键\n   * 默认 schema (public) 的表直接用表名，保持向后兼容\n   */\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    // 按 schema.table 分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schemaName = col.table_schema || 'public';\n      const tableName = col.table_name;\n      const tableKey = this.makeTableKey(schemaName, tableName);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schemaName);\n      }\n\n      let dataType = col.data_type;\n      // 添加长度/精度信息\n      if (col.character_maximum_length) {\n        dataType += `(${col.character_maximum_length})`;\n      } else if (col.numeric_precision) {\n        dataType += `(${col.numeric_precision}${col.numeric_scale ? `,${col.numeric_scale}` : ''})`;\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.column_name,\n        type: dataType,\n        nullable: col.is_nullable === 'YES',\n        defaultValue: col.column_default || undefined,\n      });\n    }\n\n    // 按 schema.table 分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const tableKey = this.makeTableKey(pk.schema_name || 'public', pk.table_name);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.column_name);\n    }\n\n    // 按 schema.table 分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableKey = this.makeTableKey(idx.schema_name || 'public', idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name);\n    }\n\n    // 按 schema.table 分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const tableKey = this.makeTableKey(stat.schema_name || 'public', stat.table_name);\n      rowsByTable.set(tableKey, Number(stat.estimated_rows) || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, stat.table_comment);\n      }\n    }\n\n    // 按 schema.table 分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableKey = this.makeTableKey(fk.schema_name || 'public', fk.table_name);\n      const constraintName = fk.constraint_name;\n      const refTableKey = this.makeTableKey(fk.ref_schema_name || 'public', fk.referenced_table);\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name);\n      fkInfo.referencedColumns.push(fk.referenced_column);\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey,\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'postgres',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/redis.ts",
    "content": "/**\n * Redis 数据库适配器\n * 使用 ioredis 驱动实现 DbAdapter 接口\n *\n * 注意：Redis 是 NoSQL 键值存储，没有传统的表结构\n * 本适配器提供基本的键值操作和信息查询功能\n */\n\nimport { Redis } from 'ioredis';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n} from '../types/adapter.js';\n\nexport class RedisAdapter implements DbAdapter {\n  private client: Redis | null = null;\n  private config: {\n    host: string;\n    port: number;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 连接到 Redis 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.client = new Redis({\n        host: this.config.host,\n        port: this.config.port,\n        password: this.config.password,\n        db: this.config.database ? parseInt(this.config.database) : 0,\n        retryStrategy: (times: number) => {\n          if (times > 3) {\n            return null; // 停止重试\n          }\n          return Math.min(times * 100, 2000);\n        },\n      });\n\n      // 测试连接\n      await this.client.ping();\n    } catch (error) {\n      throw new Error(\n        `Redis 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.client) {\n      await this.client.quit();\n      this.client = null;\n    }\n  }\n\n  /**\n   * 执行 Redis 命令\n   *\n   * 支持的命令格式示例：\n   * - \"GET mykey\"\n   * - \"SET mykey myvalue\"\n   * - \"HGETALL myhash\"\n   * - \"KEYS pattern*\"\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.client) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      // 解析命令和参数\n      const parts = query.trim().split(/\\s+/);\n      const command = parts[0].toLowerCase();\n      const args = parts.slice(1);\n\n      // 如果提供了额外参数，追加到参数列表\n      if (params && params.length > 0) {\n        args.push(...params.map(p => String(p)));\n      }\n\n      // 执行 Redis 命令\n      const result = await this.client.call(command, ...args);\n      const executionTime = Date.now() - startTime;\n\n      // 格式化结果\n      const formattedResult = this.formatRedisResult(command, result);\n\n      return {\n        rows: formattedResult,\n        executionTime,\n        metadata: {\n          command: command.toUpperCase(),\n          rawResult: result,\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `Redis 命令执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 格式化 Redis 命令结果为统一的行格式\n   */\n  private formatRedisResult(command: string, result: unknown): Record<string, unknown>[] {\n    // 处理 null/undefined\n    if (result === null || result === undefined) {\n      return [{ result: null }];\n    }\n\n    // 处理数组结果（如 KEYS, MGET 等）\n    if (Array.isArray(result)) {\n      // 如果是 HGETALL 返回的数组，转换为键值对\n      if (command === 'hgetall' && result.length % 2 === 0) {\n        const obj: Record<string, unknown> = {};\n        for (let i = 0; i < result.length; i += 2) {\n          obj[result[i]] = result[i + 1];\n        }\n        return [obj];\n      }\n\n      // 其他数组结果，每个元素作为一行\n      return result.map((item, index) => ({\n        index,\n        value: item,\n      }));\n    }\n\n    // 处理简单值\n    return [{ result }];\n  }\n\n  /**\n   * 获取 Redis 数据库信息\n   *\n   * Redis 没有传统的表结构，这里返回数据库统计信息\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.client) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      // 获取 Redis 服务器信息\n      const info = await this.client.info();\n      const lines = info.split('\\r\\n');\n\n      let version = 'unknown';\n\n      for (const line of lines) {\n        if (line.startsWith('redis_version:')) {\n          version = line.split(':')[1];\n        }\n      }\n\n      // 获取当前数据库编号\n      const dbIndex = this.config.database || '0';\n\n      // 获取键的样本（最多 100 个）\n      const keys = await this.client.keys('*');\n      const sampleKeys = keys.slice(0, 100);\n\n      // 分析键的类型分布\n      const typeMap = new Map<string, string[]>();\n\n      for (const key of sampleKeys) {\n        const type = await this.client.type(key);\n        if (!typeMap.has(type)) {\n          typeMap.set(type, []);\n        }\n        typeMap.get(type)!.push(key);\n      }\n\n      // 为每种类型创建一个\"虚拟表\"\n      const tables: TableInfo[] = [];\n\n      // 添加概览表\n      tables.push({\n        name: '_overview',\n        columns: [\n          { name: 'metric', type: 'string', nullable: false },\n          { name: 'value', type: 'string', nullable: false },\n        ],\n        primaryKeys: [],\n        estimatedRows: 5,\n      });\n\n      // 为每种数据类型添加表\n      for (const [type, keyList] of typeMap.entries()) {\n        const columns: ColumnInfo[] = [\n          { name: 'key', type: 'string', nullable: false },\n          { name: 'type', type: 'string', nullable: false },\n        ];\n\n        // 根据类型添加特定列\n        switch (type) {\n          case 'string':\n            columns.push({ name: 'value', type: 'string', nullable: true });\n            break;\n          case 'list':\n            columns.push({ name: 'length', type: 'number', nullable: false });\n            break;\n          case 'set':\n            columns.push({ name: 'cardinality', type: 'number', nullable: false });\n            break;\n          case 'zset':\n            columns.push({ name: 'cardinality', type: 'number', nullable: false });\n            break;\n          case 'hash':\n            columns.push({ name: 'field_count', type: 'number', nullable: false });\n            break;\n        }\n\n        tables.push({\n          name: `keys_${type}`,\n          columns,\n          primaryKeys: ['key'],\n          estimatedRows: keyList.length,\n        });\n      }\n\n      return {\n        databaseType: 'redis',\n        databaseName: `db${dbIndex}`,\n        tables,\n        version,\n      };\n    } catch (error) {\n      throw new Error(\n        `获取 Redis 信息失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 检查是否为写操作\n   *\n   * Redis 写操作包括：SET, DEL, FLUSHDB, FLUSHALL 等\n   */\n  isWriteOperation(query: string): boolean {\n    const upperQuery = query.trim().toUpperCase();\n    const writeCommands = [\n      'SET', 'SETEX', 'SETNX', 'MSET', 'MSETNX',\n      'DEL', 'UNLINK',\n      'FLUSHDB', 'FLUSHALL',\n      'LPUSH', 'RPUSH', 'LPOP', 'RPOP', 'LSET', 'LREM',\n      'SADD', 'SREM', 'SPOP',\n      'ZADD', 'ZREM', 'ZPOPMIN', 'ZPOPMAX',\n      'HSET', 'HMSET', 'HDEL',\n      'INCR', 'DECR', 'INCRBY', 'DECRBY',\n      'APPEND', 'SETRANGE',\n      'EXPIRE', 'EXPIREAT', 'PERSIST',\n      'RENAME', 'RENAMENX',\n    ];\n\n    const command = upperQuery.split(/\\s+/)[0];\n    return writeCommands.includes(command);\n  }\n}\n"
  },
  {
    "path": "src/adapters/sqlite.ts",
    "content": "/**\n * SQLite 数据库适配器\n * 使用 better-sqlite3 驱动实现 DbAdapter 接口\n */\n\nimport Database from 'better-sqlite3';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class SQLiteAdapter implements DbAdapter {\n  private db: Database.Database | null = null;\n  private config: {\n    filePath: string;\n    readonly?: boolean;\n  };\n\n  constructor(config: {\n    filePath: string;\n    readonly?: boolean;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 连接到 SQLite 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.db = new Database(this.config.filePath, {\n        readonly: this.config.readonly,\n        fileMustExist: false, // 如果文件不存在则创建\n      });\n\n      // 启用外键约束\n      this.db.pragma('foreign_keys = ON');\n    } catch (error) {\n      throw new Error(\n        `SQLite 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.db) {\n      this.db.close();\n      this.db = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      // 清理查询语句\n      const trimmedQuery = query.trim().toUpperCase();\n\n      // 判断是否为查询操作\n      if (trimmedQuery.startsWith('SELECT') || trimmedQuery.startsWith('PRAGMA')) {\n        // SELECT 查询\n        const stmt = this.db.prepare(query);\n        const rows = params ? stmt.all(...params) : stmt.all();\n        const executionTime = Date.now() - startTime;\n\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            rowCount: rows.length,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const stmt = this.db.prepare(query);\n        const info = params ? stmt.run(...params) : stmt.run();\n        const executionTime = Date.now() - startTime;\n\n        return {\n          rows: [],\n          affectedRows: info.changes,\n          executionTime,\n          metadata: {\n            lastInsertRowid: info.lastInsertRowid,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      // 获取 SQLite 版本\n      const versionRow = this.db.prepare('SELECT sqlite_version() as version').get() as { version: string };\n      const version = versionRow.version;\n\n      // 获取数据库文件名作为数据库名\n      const databaseName = this.config.filePath.split(/[\\\\/]/).pop() || 'unknown';\n\n      // 获取所有表（排除 sqlite 内部表）\n      const tables = this.db\n        .prepare(\n          `SELECT name FROM sqlite_master\n           WHERE type='table' AND name NOT LIKE 'sqlite_%'\n           ORDER BY name`\n        )\n        .all() as { name: string }[];\n\n      const tableInfos: TableInfo[] = [];\n      const relationships: RelationshipInfo[] = [];\n\n      for (const table of tables) {\n        const { tableInfo, tableForeignKeys } = await this.getTableInfo(table.name);\n        tableInfos.push(tableInfo);\n\n        // 收集全局关系\n        for (const fk of tableForeignKeys) {\n          relationships.push({\n            fromTable: table.name,\n            fromColumns: fk.columns,\n            toTable: fk.referencedTable,\n            toColumns: fk.referencedColumns,\n            type: 'many-to-one',\n            constraintName: fk.name,\n          });\n        }\n      }\n\n      return {\n        databaseType: 'sqlite',\n        databaseName,\n        tables: tableInfos,\n        version,\n        relationships: relationships.length > 0 ? relationships : undefined,\n      };\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取单个表的详细信息\n   */\n  private async getTableInfo(tableName: string): Promise<{ tableInfo: TableInfo; tableForeignKeys: ForeignKeyInfo[] }> {\n    if (!this.db) {\n      throw new Error('数据库未连接');\n    }\n\n    // 获取列信息\n    const columns = this.db\n      .prepare(`PRAGMA table_info(${tableName})`)\n      .all() as Array<{\n        cid: number;\n        name: string;\n        type: string;\n        notnull: number;\n        dflt_value: string | null;\n        pk: number;\n      }>;\n\n    const columnInfos: ColumnInfo[] = columns.map((col) => ({\n      name: col.name,\n      type: col.type,\n      nullable: col.notnull === 0,\n      defaultValue: col.dflt_value || undefined,\n    }));\n\n    // 获取主键\n    const primaryKeys = columns\n      .filter((col) => col.pk > 0)\n      .sort((a, b) => a.pk - b.pk)\n      .map((col) => col.name);\n\n    // 获取索引信息\n    const indexes = this.db\n      .prepare(`PRAGMA index_list(${tableName})`)\n      .all() as Array<{\n        seq: number;\n        name: string;\n        unique: number;\n        origin: string;\n        partial: number;\n      }>;\n\n    const indexInfos: IndexInfo[] = [];\n\n    for (const idx of indexes) {\n      // 跳过自动创建的主键索引\n      if (idx.origin === 'pk') continue;\n\n      // 获取索引的列信息\n      const indexColumns = this.db\n        .prepare(`PRAGMA index_info(${idx.name})`)\n        .all() as Array<{\n          seqno: number;\n          cid: number;\n          name: string;\n        }>;\n\n      indexInfos.push({\n        name: idx.name,\n        columns: indexColumns.map((col) => col.name),\n        unique: idx.unique === 1,\n      });\n    }\n\n    // 获取外键信息\n    const foreignKeys = this.db\n      .prepare(`PRAGMA foreign_key_list(${tableName})`)\n      .all() as Array<{\n        id: number;\n        seq: number;\n        table: string;\n        from: string;\n        to: string;\n        on_update: string;\n        on_delete: string;\n        match: string;\n      }>;\n\n    // 按外键 ID 分组（一个外键可能包含多列）\n    const fkMap = new Map<number, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>();\n\n    for (const fk of foreignKeys) {\n      if (!fkMap.has(fk.id)) {\n        fkMap.set(fk.id, {\n          columns: [],\n          referencedTable: fk.table,\n          referencedColumns: [],\n          onDelete: fk.on_delete !== 'NO ACTION' ? fk.on_delete : undefined,\n          onUpdate: fk.on_update !== 'NO ACTION' ? fk.on_update : undefined,\n        });\n      }\n      const fkInfo = fkMap.get(fk.id)!;\n      fkInfo.columns.push(fk.from);\n      fkInfo.referencedColumns.push(fk.to);\n    }\n\n    const foreignKeyInfos: ForeignKeyInfo[] = [];\n    for (const [id, fkData] of fkMap.entries()) {\n      foreignKeyInfos.push({\n        name: `fk_${tableName}_${id}`,\n        columns: fkData.columns,\n        referencedTable: fkData.referencedTable,\n        referencedColumns: fkData.referencedColumns,\n        onDelete: fkData.onDelete,\n        onUpdate: fkData.onUpdate,\n      });\n    }\n\n    // 获取表行数\n    const countRow = this.db\n      .prepare(`SELECT COUNT(*) as count FROM ${tableName}`)\n      .get() as { count: number };\n    const estimatedRows = countRow.count;\n\n    return {\n      tableInfo: {\n        name: tableName,\n        columns: columnInfos,\n        primaryKeys,\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows,\n      },\n      tableForeignKeys: foreignKeyInfos,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/sqlserver.ts",
    "content": "/**\n * SQL Server 数据库适配器\n * 使用 mssql 驱动实现 DbAdapter 接口\n * 支持 SQL Server 2012+ 和 Azure SQL Database\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n */\n\nimport sql from 'mssql';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class SQLServerAdapter implements DbAdapter {\n  private pool: sql.ConnectionPool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 连接到 SQL Server 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      // 检测是否为 Azure SQL Database\n      const isAzure = this.config.host.includes('.database.windows.net');\n\n      const poolConfig: sql.config = {\n        server: this.config.host,\n        port: this.config.port || 1433,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        options: {\n          encrypt: isAzure,  // Azure SQL 需要加密\n          trustServerCertificate: !isAzure,  // 仅本地开发信任证书\n          enableArithAbort: true,\n        },\n        pool: {\n          max: 10,\n          min: 0,\n          idleTimeoutMillis: 30000,\n        },\n      };\n\n      this.pool = await sql.connect(poolConfig);\n\n      // 测试连接\n      await this.pool.request().query('SELECT 1');\n    } catch (error: any) {\n      // 翻译常见错误\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      if (error.number === 18456) {\n        throw new Error('SQL Server 连接失败: 身份验证失败，请检查用户名和密码');\n      } else if (errorMessage.includes('ECONNREFUSED') || errorMessage.includes('ETIMEDOUT')) {\n        throw new Error('SQL Server 连接失败: 无法连接到数据库服务器，请检查主机地址和端口');\n      } else if (errorMessage.includes('database') && errorMessage.includes('does not exist')) {\n        throw new Error('SQL Server 连接失败: 数据库不存在');\n      }\n\n      throw new Error(`SQL Server 连接失败: ${errorMessage}`);\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      try {\n        await this.pool.close();  // 正确关闭连接池，排空所有连接\n      } catch (error) {\n        console.error('关闭连接池时出错:', error);\n      }\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const request = this.pool.request();\n\n      // 处理参数 - SQL Server 使用 @param0, @param1 语法\n      if (params && params.length > 0) {\n        params.forEach((param, index) => {\n          request.input(`param${index}`, param);\n        });\n\n        // 替换 ? 占位符为 @param0, @param1, ...\n        let paramIndex = 0;\n        query = query.replace(/\\?/g, () => `@param${paramIndex++}`);\n      }\n\n      const result = await request.query(query);\n      const executionTime = Date.now() - startTime;\n\n      // 处理 SELECT 查询\n      if (result.recordset && result.recordset.length > 0) {\n        return {\n          rows: result.recordset,\n          executionTime,\n          metadata: {\n            columnCount: Object.keys(result.recordset[0]).length,\n          },\n        };\n      }\n\n      // 处理 DML 操作 (INSERT/UPDATE/DELETE)\n      if (result.rowsAffected && result.rowsAffected.length > 0) {\n        const affectedRows = result.rowsAffected.reduce((sum, count) => sum + count, 0);\n        return {\n          rows: [],\n          affectedRows,\n          executionTime,\n        };\n      }\n\n      // 其他操作或空结果\n      return {\n        rows: [],\n        executionTime,\n      };\n    } catch (error: any) {\n      // 翻译常见 SQL Server 错误\n      if (error.number === 208) {\n        throw new Error('查询执行失败: 表或视图不存在');\n      } else if (error.number === 2627 || error.number === 2601) {\n        throw new Error('查询执行失败: 违反唯一约束');\n      } else if (error.number === 547) {\n        throw new Error('查询执行失败: 违反外键约束');\n      } else if (error.number === 18456) {\n        throw new Error('查询执行失败: 身份验证失败');\n      }\n\n      throw new Error(`查询执行失败: ${error.message || String(error)}`);\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      // 获取 SQL Server 版本\n      const versionResult = await this.pool.request().query('SELECT @@VERSION AS version');\n      const version = versionResult.recordset?.[0]?.version || 'unknown';\n\n      // 获取数据库名\n      const dbNameResult = await this.pool.request().query('SELECT DB_NAME() AS database_name');\n      const databaseName = dbNameResult.recordset?.[0]?.database_name || 'unknown';\n\n      // 批量获取所有表的列信息\n      const allColumnsResult = await this.pool.request().query(`\n        SELECT\n          c.TABLE_SCHEMA,\n          c.TABLE_NAME,\n          c.COLUMN_NAME,\n          c.DATA_TYPE,\n          c.CHARACTER_MAXIMUM_LENGTH,\n          c.NUMERIC_PRECISION,\n          c.NUMERIC_SCALE,\n          c.IS_NULLABLE,\n          c.COLUMN_DEFAULT,\n          c.ORDINAL_POSITION\n        FROM INFORMATION_SCHEMA.COLUMNS c\n        JOIN INFORMATION_SCHEMA.TABLES t\n          ON c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME\n        WHERE t.TABLE_TYPE = 'BASE TABLE'\n          AND t.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\n        ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION\n      `);\n\n      // 批量获取所有表的主键信息\n      const allPrimaryKeysResult = await this.pool.request().query(`\n        SELECT\n          tc.TABLE_SCHEMA,\n          tc.TABLE_NAME,\n          c.COLUMN_NAME\n        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n        JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c\n          ON tc.CONSTRAINT_NAME = c.CONSTRAINT_NAME\n        WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n          AND tc.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n        ORDER BY tc.TABLE_NAME\n      `);\n\n      // 批量获取所有表的索引信息\n      const allIndexesResult = await this.pool.request().query(`\n        SELECT\n          SCHEMA_NAME(t.schema_id) AS table_schema,\n          t.name AS table_name,\n          i.name AS index_name,\n          c.name AS column_name,\n          i.is_unique\n        FROM sys.indexes i\n        INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\n        INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\n        INNER JOIN sys.tables t ON i.object_id = t.object_id\n        WHERE i.is_primary_key = 0\n          AND i.type > 0\n          AND SCHEMA_NAME(t.schema_id) NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n        ORDER BY t.name, i.name, ic.key_ordinal\n      `);\n\n      // 批量获取所有表的行数估算\n      const allStatsResult = await this.pool.request().query(`\n        SELECT\n          SCHEMA_NAME(t.schema_id) AS table_schema,\n          t.name AS table_name,\n          SUM(p.rows) AS row_count,\n          ep.value AS table_comment\n        FROM sys.partitions p\n        JOIN sys.tables t ON p.object_id = t.object_id\n        LEFT JOIN sys.extended_properties ep ON ep.major_id = t.object_id\n          AND ep.minor_id = 0\n          AND ep.name = 'MS_Description'\n        WHERE SCHEMA_NAME(t.schema_id) NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n          AND p.index_id IN (0, 1)\n        GROUP BY SCHEMA_NAME(t.schema_id), t.name, ep.value\n      `);\n\n      // 批量获取所有外键信息\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await this.pool.request().query(`\n          SELECT\n            SCHEMA_NAME(t.schema_id) AS table_schema,\n            OBJECT_NAME(fk.parent_object_id) AS table_name,\n            fk.name AS constraint_name,\n            COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS column_name,\n            SCHEMA_NAME(OBJECT_SCHEMA_ID(fk.referenced_object_id)) AS ref_table_schema,\n            OBJECT_NAME(fk.referenced_object_id) AS referenced_table,\n            COL_NAME(fkc.referenced_object_id, fkc.referenced_column_id) AS referenced_column,\n            fk.delete_referential_action_desc AS delete_rule,\n            fk.update_referential_action_desc AS update_rule,\n            fkc.constraint_column_id AS column_position\n          FROM sys.foreign_keys fk\n          JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\n          JOIN sys.tables t ON fk.parent_object_id = t.object_id\n          WHERE SCHEMA_NAME(t.schema_id) NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')\n          ORDER BY OBJECT_NAME(fk.parent_object_id), fk.name, fkc.constraint_column_id\n        `);\n        allForeignKeys = allForeignKeysResult.recordset || [];\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchema(\n        databaseName,\n        version,\n        allColumnsResult.recordset || [],\n        allPrimaryKeysResult.recordset || [],\n        allIndexesResult.recordset || [],\n        allStatsResult.recordset || [],\n        allForeignKeys\n      );\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'dbo' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schema = col.TABLE_SCHEMA || 'dbo';\n      const tableKey = this.makeTableKey(schema, col.TABLE_NAME);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schema);\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.COLUMN_NAME.toLowerCase(),\n        type: this.formatSQLServerType(\n          col.DATA_TYPE,\n          col.CHARACTER_MAXIMUM_LENGTH,\n          col.NUMERIC_PRECISION,\n          col.NUMERIC_SCALE\n        ),\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT?.trim() || undefined,\n      });\n    }\n\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const schema = pk.TABLE_SCHEMA || 'dbo';\n      const tableKey = this.makeTableKey(schema, pk.TABLE_NAME);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.COLUMN_NAME.toLowerCase());\n    }\n\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const schema = idx.table_schema || 'dbo';\n      const tableKey = this.makeTableKey(schema, idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name.toLowerCase());\n    }\n\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const schema = stat.table_schema || 'dbo';\n      const tableKey = this.makeTableKey(schema, stat.table_name);\n      rowsByTable.set(tableKey, stat.row_count || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, String(stat.table_comment));\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const schema = fk.table_schema || 'dbo';\n      const tableKey = this.makeTableKey(schema, fk.table_name);\n      const constraintName = fk.constraint_name;\n\n      if (!fk.table_name || !constraintName) continue;\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const refSchema = fk.ref_table_schema || 'dbo';\n      const refTableKey = this.makeTableKey(refSchema, fk.referenced_table);\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name.toLowerCase());\n      fkInfo.referencedColumns.push(fk.referenced_column.toLowerCase());\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey.toLowerCase(),\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable.toLowerCase(),\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable.toLowerCase(),\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey.toLowerCase(),\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'sqlserver',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 格式化 SQL Server 数据类型\n   */\n  private formatSQLServerType(\n    dataType: string,\n    length?: number,\n    precision?: number,\n    scale?: number\n  ): string {\n    switch (dataType.toUpperCase()) {\n      case 'NVARCHAR':\n      case 'VARCHAR':\n      case 'NCHAR':\n      case 'CHAR':\n        if (length === -1) return `${dataType}(MAX)`;\n        if (length) return `${dataType}(${length})`;\n        return dataType;\n\n      case 'DECIMAL':\n      case 'NUMERIC':\n        if (precision && scale !== undefined && scale !== null) {\n          return `${dataType}(${precision},${scale})`;\n        }\n        if (precision) return `${dataType}(${precision})`;\n        return dataType;\n\n      case 'DATETIME2':\n      case 'DATETIMEOFFSET':\n      case 'TIME':\n        if (scale !== undefined && scale !== null) {\n          return `${dataType}(${scale})`;\n        }\n        return dataType;\n\n      case 'VARBINARY':\n      case 'BINARY':\n        if (length === -1) return `${dataType}(MAX)`;\n        if (length) return `${dataType}(${length})`;\n        return dataType;\n\n      default:\n        return dataType;\n    }\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    // 首先使用通用的写操作检测\n    if (checkWriteOperation(query)) {\n      return true;\n    }\n\n    // SQL Server 特定的写操作检测\n    const trimmedQuery = query.trim().toUpperCase();\n\n    // MERGE 语句（SQL Server 的 upsert 操作）\n    if (trimmedQuery.startsWith('MERGE')) {\n      return true;\n    }\n\n    // 存储过程执行\n    if (trimmedQuery.startsWith('EXEC') || trimmedQuery.startsWith('EXECUTE')) {\n      return true;\n    }\n\n    // 事务控制语句\n    if (trimmedQuery.startsWith('BEGIN TRANSACTION') ||\n        trimmedQuery.startsWith('BEGIN TRAN') ||\n        trimmedQuery.startsWith('COMMIT') ||\n        trimmedQuery.startsWith('ROLLBACK')) {\n      return true;\n    }\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "src/adapters/tidb.ts",
    "content": "/**\n * TiDB 数据库适配器\n * 使用 mysql2 驱动实现 DbAdapter 接口\n * TiDB 兼容 MySQL 5.7 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport mysql from 'mysql2/promise';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nexport class TiDBAdapter implements DbAdapter {\n  private pool: mysql.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 检测是否为连接断开类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    const msg = String((error as any)?.message || '');\n    return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n  }\n\n  /**\n   * 带断线重试的操作包装器（连接池会自动提供新连接）\n   */\n  private async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n    try {\n      return await fn();\n    } catch (error) {\n      if (this.isConnectionError(error)) {\n        return await fn();\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * 连接到 TiDB 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = mysql.createPool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        multipleStatements: false,\n        waitForConnections: true,\n        connectionLimit: 3,\n        maxIdle: 1,\n        idleTimeout: 60000,\n        enableKeepAlive: true,\n        keepAliveInitialDelay: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `TiDB 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const [rows, fields] = await this.withRetry(() => this.pool!.execute(query, params));\n      const executionTime = Date.now() - startTime;\n\n      // 处理不同类型的查询结果\n      if (Array.isArray(rows)) {\n        return {\n          rows: rows as Record<string, unknown>[],\n          executionTime,\n          metadata: {\n            fieldCount: fields?.length || 0,\n          },\n        };\n      } else {\n        // INSERT/UPDATE/DELETE 等操作\n        const result = rows as mysql.ResultSetHeader;\n        return {\n          rows: [],\n          affectedRows: result.affectedRows,\n          executionTime,\n          metadata: {\n            insertId: result.insertId,\n            changedRows: result.changedRows,\n          },\n        };\n      }\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    try {\n      return await this.withRetry(() => this._getSchemaImpl());\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * getSchema 的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n      // 获取数据库版本\n      const [versionRows] = await this.pool!.query('SELECT VERSION() as version');\n      const version = (versionRows as any[])[0]?.version || 'unknown';\n\n      // 获取当前数据库名\n      const [dbRows] = await this.pool!.query('SELECT DATABASE() as db');\n      const databaseName = (dbRows as any[])[0]?.db || this.config.database || 'unknown';\n\n      // 批量获取所有表的列信息\n      const [allColumns] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          COLUMN_NAME,\n          COLUMN_TYPE,\n          IS_NULLABLE,\n          COLUMN_DEFAULT,\n          COLUMN_KEY,\n          COLUMN_COMMENT,\n          ORDINAL_POSITION\n        FROM INFORMATION_SCHEMA.COLUMNS\n        WHERE TABLE_SCHEMA = DATABASE()\n        ORDER BY TABLE_NAME, ORDINAL_POSITION\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有表的索引信息\n      const [allIndexes] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          INDEX_NAME,\n          COLUMN_NAME,\n          NON_UNIQUE,\n          SEQ_IN_INDEX\n        FROM INFORMATION_SCHEMA.STATISTICS\n        WHERE TABLE_SCHEMA = DATABASE()\n        ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有表的行数估算\n      const [allStats] = await this.pool!.query(`\n        SELECT\n          TABLE_NAME,\n          TABLE_ROWS,\n          TABLE_COMMENT\n        FROM INFORMATION_SCHEMA.TABLES\n        WHERE TABLE_SCHEMA = DATABASE()\n          AND TABLE_TYPE = 'BASE TABLE'\n      `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n\n      // 批量获取所有外键信息\n      let allForeignKeys: mysql.RowDataPacket[] = [];\n      try {\n        const [fkRows] = await this.pool!.query(`\n          SELECT\n            kcu.TABLE_NAME,\n            kcu.CONSTRAINT_NAME,\n            kcu.COLUMN_NAME,\n            kcu.REFERENCED_TABLE_NAME,\n            kcu.REFERENCED_COLUMN_NAME,\n            kcu.ORDINAL_POSITION,\n            rc.DELETE_RULE,\n            rc.UPDATE_RULE\n          FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n          JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n            ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n            AND kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA\n          WHERE kcu.TABLE_SCHEMA = DATABASE()\n            AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n          ORDER BY kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, kcu.ORDINAL_POSITION\n        `) as [mysql.RowDataPacket[], mysql.FieldPacket[]];\n        allForeignKeys = fkRows;\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      // 在内存中组装数据\n      return this.assembleSchema(databaseName, version, allColumns, allIndexes, allStats, allForeignKeys);\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: mysql.RowDataPacket[],\n    allIndexes: mysql.RowDataPacket[],\n    allStats: mysql.RowDataPacket[],\n    allForeignKeys: mysql.RowDataPacket[]\n  ): SchemaInfo {\n    // 按表名分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const primaryKeysByTable = new Map<string, string[]>();\n\n    for (const col of allColumns) {\n      const tableName = col.TABLE_NAME;\n\n      if (!columnsByTable.has(tableName)) {\n        columnsByTable.set(tableName, []);\n        primaryKeysByTable.set(tableName, []);\n      }\n\n      columnsByTable.get(tableName)!.push({\n        name: col.COLUMN_NAME,\n        type: col.COLUMN_TYPE,\n        nullable: col.IS_NULLABLE === 'YES',\n        defaultValue: col.COLUMN_DEFAULT,\n        comment: col.COLUMN_COMMENT || undefined,\n      });\n\n      // 收集主键\n      if (col.COLUMN_KEY === 'PRI') {\n        primaryKeysByTable.get(tableName)!.push(col.COLUMN_NAME);\n      }\n    }\n\n    // 按表名分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableName = idx.TABLE_NAME;\n      const indexName = idx.INDEX_NAME;\n\n      if (indexName === 'PRIMARY') continue;\n\n      if (!indexesByTable.has(tableName)) {\n        indexesByTable.set(tableName, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableName)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.NON_UNIQUE === 0,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.COLUMN_NAME);\n    }\n\n    // 按表名分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      rowsByTable.set(stat.TABLE_NAME, stat.TABLE_ROWS || 0);\n      if (stat.TABLE_COMMENT) {\n        commentsByTable.set(stat.TABLE_NAME, stat.TABLE_COMMENT);\n      }\n    }\n\n    // 按表名分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableName = fk.TABLE_NAME;\n      const constraintName = fk.CONSTRAINT_NAME;\n\n      if (!foreignKeysByTable.has(tableName)) {\n        foreignKeysByTable.set(tableName, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableName)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: fk.REFERENCED_TABLE_NAME,\n          referencedColumns: [],\n          onDelete: fk.DELETE_RULE,\n          onUpdate: fk.UPDATE_RULE,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.COLUMN_NAME);\n      fkInfo.referencedColumns.push(fk.REFERENCED_COLUMN_NAME);\n    }\n\n    // 生成全局关系视图\n    for (const [tableName, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableName,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableName, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableName);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableName);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableName,\n        comment: commentsByTable.get(tableName) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableName) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableName) || 0,\n      });\n    }\n\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'tidb',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/adapters/vastbase.ts",
    "content": "/**\n * Vastbase 数据库适配器\n * 使用 pg 驱动实现 DbAdapter 接口\n * Vastbase 基于 PostgreSQL 开发，兼容 PostgreSQL 协议\n *\n * 性能优化：使用批量查询获取 Schema 信息，避免 N+1 查询问题\n * 连接管理：使用连接池 + TCP Keep-Alive + 断线自动重试，确保长连接稳定性\n */\n\nimport pg from 'pg';\nimport type {\n  DbAdapter,\n  QueryResult,\n  SchemaInfo,\n  TableInfo,\n  ColumnInfo,\n  IndexInfo,\n  ForeignKeyInfo,\n  RelationshipInfo,\n} from '../types/adapter.js';\nimport { isWriteOperation as checkWriteOperation } from '../utils/safety.js';\n\nconst { Pool } = pg;\n\nexport class VastbaseAdapter implements DbAdapter {\n  private pool: pg.Pool | null = null;\n  private config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  };\n\n  constructor(config: {\n    host: string;\n    port: number;\n    user?: string;\n    password?: string;\n    database?: string;\n  }) {\n    this.config = config;\n  }\n\n  /**\n   * 判断是否为连接类错误\n   */\n  private isConnectionError(error: unknown): boolean {\n    if (!(error instanceof Error)) return false;\n    const msg = error.message || '';\n    const code = (error as any).code || '';\n    return /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/.test(\n      msg + code\n    );\n  }\n\n  /**\n   * 带断线重试的执行包装器\n   */\n  private async withRetry<T>(fn: () => Promise<T>, retries = 2): Promise<T> {\n    for (let attempt = 0; ; attempt++) {\n      try {\n        return await fn();\n      } catch (error) {\n        if (attempt < retries && this.isConnectionError(error)) {\n          // 等待一小段时间后重试\n          await new Promise(resolve => setTimeout(resolve, 500 * (attempt + 1)));\n          continue;\n        }\n        throw error;\n      }\n    }\n  }\n\n  /**\n   * 连接到 Vastbase 数据库\n   */\n  async connect(): Promise<void> {\n    try {\n      this.pool = new Pool({\n        host: this.config.host,\n        port: this.config.port,\n        user: this.config.user,\n        password: this.config.password,\n        database: this.config.database,\n        max: 3,\n        idleTimeoutMillis: 60000,\n        keepAlive: true,\n        keepAliveInitialDelayMillis: 30000,\n      });\n\n      // 测试连接\n      await this.pool.query('SELECT 1');\n    } catch (error) {\n      throw new Error(\n        `Vastbase 连接失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 断开数据库连接\n   */\n  async disconnect(): Promise<void> {\n    if (this.pool) {\n      await this.pool.end();\n      this.pool = null;\n    }\n  }\n\n  /**\n   * 执行 SQL 查询\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    const startTime = Date.now();\n\n    try {\n      const result = await this.withRetry(() => this.pool!.query(query, params));\n      const executionTime = Date.now() - startTime;\n\n      return {\n        rows: result.rows,\n        affectedRows: result.rowCount || 0,\n        executionTime,\n        metadata: {\n          command: result.command,\n          fields: result.fields?.map(f => ({\n            name: f.name,\n            dataTypeID: f.dataTypeID,\n          })),\n        },\n      };\n    } catch (error) {\n      throw new Error(\n        `查询执行失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 获取数据库结构信息（批量查询优化版本）\n   */\n  async getSchema(): Promise<SchemaInfo> {\n    if (!this.pool) {\n      throw new Error('数据库未连接');\n    }\n\n    return this.withRetry(() => this._getSchemaImpl());\n  }\n\n  /**\n   * 获取数据库结构信息的实际实现\n   */\n  private async _getSchemaImpl(): Promise<SchemaInfo> {\n    try {\n      // 获取数据库版本\n      const versionResult = await this.pool!.query('SELECT version() as version');\n      const version = versionResult.rows[0]?.version || 'unknown';\n\n      // 获取当前数据库名\n      const databaseName = this.config.database || 'postgres';\n\n      // 批量获取所有表的列信息（支持多 schema）\n      const allColumnsResult = await this.pool!.query(`\n        SELECT\n          c.table_schema,\n          c.table_name,\n          c.column_name,\n          c.data_type,\n          c.is_nullable,\n          c.column_default,\n          c.character_maximum_length,\n          c.numeric_precision,\n          c.numeric_scale,\n          c.ordinal_position\n        FROM information_schema.columns c\n        JOIN information_schema.tables t\n          ON c.table_schema = t.table_schema AND c.table_name = t.table_name\n        WHERE c.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND t.table_type = 'BASE TABLE'\n        ORDER BY c.table_schema, c.table_name, c.ordinal_position\n      `);\n\n      // 批量获取所有表的主键信息\n      const allPrimaryKeysResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          a.attname as column_name\n        FROM pg_index i\n        JOIN pg_class t ON t.oid = i.indrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE i.indisprimary\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n        ORDER BY n.nspname, t.relname, a.attnum\n      `);\n\n      // 批量获取所有表的索引信息（排除主键）\n      const allIndexesResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          t.relname as table_name,\n          i.relname as index_name,\n          a.attname as column_name,\n          ix.indisunique as is_unique\n        FROM pg_class t\n        JOIN pg_index ix ON t.oid = ix.indrelid\n        JOIN pg_class i ON i.oid = ix.indexrelid\n        JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n        JOIN pg_namespace n ON n.oid = t.relnamespace\n        WHERE t.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          AND NOT ix.indisprimary\n        ORDER BY n.nspname, t.relname, i.relname, a.attnum\n      `);\n\n      // 批量获取所有表的行数估算和表注释\n      const allStatsResult = await this.pool!.query(`\n        SELECT\n          n.nspname as schema_name,\n          c.relname as table_name,\n          c.reltuples::bigint as estimated_rows,\n          obj_description(c.oid, 'pg_class') as table_comment\n        FROM pg_class c\n        JOIN pg_namespace n ON n.oid = c.relnamespace\n        WHERE c.relkind = 'r'\n          AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n      `);\n\n      // 批量获取所有外键信息\n      let allForeignKeys: any[] = [];\n      try {\n        const allForeignKeysResult = await this.pool!.query(`\n          SELECT\n            n.nspname AS schema_name,\n            c.conname AS constraint_name,\n            t.relname AS table_name,\n            a.attname AS column_name,\n            rn.nspname AS ref_schema_name,\n            rt.relname AS referenced_table,\n            ra.attname AS referenced_column,\n            CASE c.confdeltype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS delete_rule,\n            CASE c.confupdtype\n              WHEN 'a' THEN 'NO ACTION'\n              WHEN 'r' THEN 'RESTRICT'\n              WHEN 'c' THEN 'CASCADE'\n              WHEN 'n' THEN 'SET NULL'\n              WHEN 'd' THEN 'SET DEFAULT'\n            END AS update_rule,\n            array_position(c.conkey, a.attnum) AS column_position\n          FROM pg_constraint c\n          JOIN pg_class t ON t.oid = c.conrelid\n          JOIN pg_class rt ON rt.oid = c.confrelid\n          JOIN pg_namespace n ON n.oid = t.relnamespace\n          JOIN pg_namespace rn ON rn.oid = rt.relnamespace\n          JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)\n          JOIN pg_attribute ra ON ra.attrelid = rt.oid AND ra.attnum = c.confkey[array_position(c.conkey, a.attnum)]\n          WHERE c.contype = 'f'\n            AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n          ORDER BY n.nspname, t.relname, c.conname, array_position(c.conkey, a.attnum)\n        `);\n        allForeignKeys = allForeignKeysResult.rows;\n      } catch (error) {\n        // 外键查询失败时忽略，返回空数组\n        console.error('获取外键信息失败，跳过:', error instanceof Error ? error.message : String(error));\n      }\n\n      return this.assembleSchema(\n        databaseName,\n        version,\n        allColumnsResult.rows,\n        allPrimaryKeysResult.rows,\n        allIndexesResult.rows,\n        allStatsResult.rows,\n        allForeignKeys\n      );\n    } catch (error) {\n      throw new Error(\n        `获取数据库结构失败: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * 构建带 schema 前缀的表名键\n   * 默认 schema (public) 的表直接用表名，保持向后兼容\n   */\n  private makeTableKey(schemaName: string, tableName: string): string {\n    return schemaName === 'public' ? tableName : `${schemaName}.${tableName}`;\n  }\n\n  /**\n   * 组装 Schema 信息\n   */\n  private assembleSchema(\n    databaseName: string,\n    version: string,\n    allColumns: any[],\n    allPrimaryKeys: any[],\n    allIndexes: any[],\n    allStats: any[],\n    allForeignKeys: any[]\n  ): SchemaInfo {\n    // 按 schema.table 分组列信息\n    const columnsByTable = new Map<string, ColumnInfo[]>();\n    const schemaByTable = new Map<string, string>();\n\n    for (const col of allColumns) {\n      const schemaName = col.table_schema || 'public';\n      const tableName = col.table_name;\n      const tableKey = this.makeTableKey(schemaName, tableName);\n\n      if (!columnsByTable.has(tableKey)) {\n        columnsByTable.set(tableKey, []);\n        schemaByTable.set(tableKey, schemaName);\n      }\n\n      let dataType = col.data_type;\n      if (col.character_maximum_length) {\n        dataType += `(${col.character_maximum_length})`;\n      } else if (col.numeric_precision) {\n        dataType += `(${col.numeric_precision}${col.numeric_scale ? `,${col.numeric_scale}` : ''})`;\n      }\n\n      columnsByTable.get(tableKey)!.push({\n        name: col.column_name,\n        type: dataType,\n        nullable: col.is_nullable === 'YES',\n        defaultValue: col.column_default || undefined,\n      });\n    }\n\n    // 按 schema.table 分组主键信息\n    const primaryKeysByTable = new Map<string, string[]>();\n    for (const pk of allPrimaryKeys) {\n      const tableKey = this.makeTableKey(pk.schema_name || 'public', pk.table_name);\n      if (!primaryKeysByTable.has(tableKey)) {\n        primaryKeysByTable.set(tableKey, []);\n      }\n      primaryKeysByTable.get(tableKey)!.push(pk.column_name);\n    }\n\n    // 按 schema.table 分组索引信息\n    const indexesByTable = new Map<string, Map<string, { columns: string[]; unique: boolean }>>();\n\n    for (const idx of allIndexes) {\n      const tableKey = this.makeTableKey(idx.schema_name || 'public', idx.table_name);\n      const indexName = idx.index_name;\n\n      if (!indexesByTable.has(tableKey)) {\n        indexesByTable.set(tableKey, new Map());\n      }\n\n      const tableIndexes = indexesByTable.get(tableKey)!;\n\n      if (!tableIndexes.has(indexName)) {\n        tableIndexes.set(indexName, {\n          columns: [],\n          unique: idx.is_unique,\n        });\n      }\n\n      tableIndexes.get(indexName)!.columns.push(idx.column_name);\n    }\n\n    // 按 schema.table 分组行数统计\n    const rowsByTable = new Map<string, number>();\n    const commentsByTable = new Map<string, string>();\n    for (const stat of allStats) {\n      const tableKey = this.makeTableKey(stat.schema_name || 'public', stat.table_name);\n      rowsByTable.set(tableKey, Number(stat.estimated_rows) || 0);\n      if (stat.table_comment) {\n        commentsByTable.set(tableKey, stat.table_comment);\n      }\n    }\n\n    // 按 schema.table 分组外键信息\n    const foreignKeysByTable = new Map<string, Map<string, { columns: string[]; referencedTable: string; referencedColumns: string[]; onDelete?: string; onUpdate?: string }>>();\n    const relationships: RelationshipInfo[] = [];\n\n    for (const fk of allForeignKeys) {\n      const tableKey = this.makeTableKey(fk.schema_name || 'public', fk.table_name);\n      const constraintName = fk.constraint_name;\n      const refTableKey = this.makeTableKey(fk.ref_schema_name || 'public', fk.referenced_table);\n\n      if (!tableKey || !constraintName) continue;\n\n      if (!foreignKeysByTable.has(tableKey)) {\n        foreignKeysByTable.set(tableKey, new Map());\n      }\n\n      const tableForeignKeys = foreignKeysByTable.get(tableKey)!;\n\n      if (!tableForeignKeys.has(constraintName)) {\n        tableForeignKeys.set(constraintName, {\n          columns: [],\n          referencedTable: refTableKey,\n          referencedColumns: [],\n          onDelete: fk.delete_rule,\n          onUpdate: fk.update_rule,\n        });\n      }\n\n      const fkInfo = tableForeignKeys.get(constraintName)!;\n      fkInfo.columns.push(fk.column_name);\n      fkInfo.referencedColumns.push(fk.referenced_column);\n    }\n\n    // 生成全局关系视图\n    for (const [tableKey, tableForeignKeys] of foreignKeysByTable.entries()) {\n      for (const [constraintName, fkInfo] of tableForeignKeys.entries()) {\n        relationships.push({\n          fromTable: tableKey,\n          fromColumns: fkInfo.columns,\n          toTable: fkInfo.referencedTable,\n          toColumns: fkInfo.referencedColumns,\n          type: 'many-to-one',\n          constraintName,\n        });\n      }\n    }\n\n    // 组装表信息\n    const tableInfos: TableInfo[] = [];\n\n    for (const [tableKey, columns] of columnsByTable.entries()) {\n      const tableIndexes = indexesByTable.get(tableKey);\n      const indexInfos: IndexInfo[] = [];\n\n      if (tableIndexes) {\n        for (const [indexName, indexData] of tableIndexes.entries()) {\n          indexInfos.push({\n            name: indexName,\n            columns: indexData.columns,\n            unique: indexData.unique,\n          });\n        }\n      }\n\n      // 组装外键信息\n      const tableForeignKeys = foreignKeysByTable.get(tableKey);\n      const foreignKeyInfos: ForeignKeyInfo[] = [];\n\n      if (tableForeignKeys) {\n        for (const [constraintName, fkData] of tableForeignKeys.entries()) {\n          foreignKeyInfos.push({\n            name: constraintName,\n            columns: fkData.columns,\n            referencedTable: fkData.referencedTable,\n            referencedColumns: fkData.referencedColumns,\n            onDelete: fkData.onDelete,\n            onUpdate: fkData.onUpdate,\n          });\n        }\n      }\n\n      tableInfos.push({\n        name: tableKey,\n        schema: schemaByTable.get(tableKey),\n        comment: commentsByTable.get(tableKey) || undefined,\n        columns,\n        primaryKeys: primaryKeysByTable.get(tableKey) || [],\n        indexes: indexInfos,\n        foreignKeys: foreignKeyInfos.length > 0 ? foreignKeyInfos : undefined,\n        estimatedRows: rowsByTable.get(tableKey) || 0,\n      });\n    }\n\n    // 按表名排序\n    tableInfos.sort((a, b) => a.name.localeCompare(b.name));\n\n    return {\n      databaseType: 'vastbase',\n      databaseName,\n      tables: tableInfos,\n      version,\n      relationships: relationships.length > 0 ? relationships : undefined,\n    };\n  }\n\n  /**\n   * 检查是否为写操作\n   */\n  isWriteOperation(query: string): boolean {\n    return checkWriteOperation(query);\n  }\n}\n"
  },
  {
    "path": "src/core/connection-manager.ts",
    "content": "/**\n * Connection Manager\n * Manages database connections and sessions\n * Supports both single-connection (MCP) and multi-session (HTTP) modes\n */\n\nimport { nanoid } from 'nanoid';\nimport type { DbAdapter, DbConfig } from '../types/adapter.js';\nimport type { Session } from '../types/http.js';\nimport { createAdapter } from '../utils/adapter-factory.js';\nimport { DatabaseService, SchemaCacheConfig } from './database-service.js';\n\n/**\n * 扩展的会话接口，包含 DatabaseService 实例\n */\ninterface ExtendedSession extends Session {\n  /** DatabaseService 实例（带缓存） */\n  service: DatabaseService;\n}\n\n/**\n * Connection Manager Class\n */\nexport class ConnectionManager {\n  private sessions: Map<string, ExtendedSession> = new Map();\n  private cleanupInterval?: NodeJS.Timeout;\n  private sessionTimeout: number;\n  private defaultCacheConfig: Partial<SchemaCacheConfig>;\n\n  constructor(\n    sessionTimeout: number = 3600000,\n    cleanupInterval: number = 300000,\n    defaultCacheConfig?: Partial<SchemaCacheConfig>\n  ) {\n    this.sessionTimeout = sessionTimeout;\n    this.defaultCacheConfig = defaultCacheConfig || {};\n\n    // Start cleanup interval\n    if (cleanupInterval > 0) {\n      this.cleanupInterval = setInterval(() => {\n        this.cleanupExpiredSessions();\n      }, cleanupInterval);\n    }\n  }\n\n  /**\n   * Create a new connection and return session ID\n   */\n  async connect(config: DbConfig): Promise<string> {\n    // Create adapter\n    const adapter = createAdapter(config);\n\n    // Connect to database\n    await adapter.connect();\n\n    // Generate session ID\n    const sessionId = nanoid();\n\n    // Create DatabaseService with cache support\n    const service = new DatabaseService(adapter, config, this.defaultCacheConfig);\n\n    // Store session with service\n    const session: ExtendedSession = {\n      id: sessionId,\n      adapter,\n      config,\n      service,\n      createdAt: new Date(),\n      lastAccessedAt: new Date(),\n    };\n\n    this.sessions.set(sessionId, session);\n\n    return sessionId;\n  }\n\n  /**\n   * Disconnect a session\n   */\n  async disconnect(sessionId: string): Promise<void> {\n    const session = this.sessions.get(sessionId);\n\n    if (!session) {\n      throw new Error(`会话 ${sessionId} 不存在`);\n    }\n\n    // Clear schema cache before disconnecting\n    session.service.clearSchemaCache();\n\n    // Disconnect adapter\n    await session.adapter.disconnect();\n\n    // Remove session\n    this.sessions.delete(sessionId);\n  }\n\n  /**\n   * Get adapter for a session\n   */\n  getAdapter(sessionId: string): DbAdapter {\n    const session = this.sessions.get(sessionId);\n\n    if (!session) {\n      throw new Error(`会话 ${sessionId} 不存在或已过期`);\n    }\n\n    // Update last accessed time\n    session.lastAccessedAt = new Date();\n\n    return session.adapter;\n  }\n\n  /**\n   * Get database service for a session\n   * Returns the cached DatabaseService instance to preserve schema cache\n   */\n  getService(sessionId: string): DatabaseService {\n    const session = this.sessions.get(sessionId);\n\n    if (!session) {\n      throw new Error(`会话 ${sessionId} 不存在或已过期`);\n    }\n\n    // Update last accessed time\n    session.lastAccessedAt = new Date();\n\n    // Return the existing service instance (preserves cache)\n    return session.service;\n  }\n\n  /**\n   * Check if session exists\n   */\n  hasSession(sessionId: string): boolean {\n    return this.sessions.has(sessionId);\n  }\n\n  /**\n   * Get session count\n   */\n  getSessionCount(): number {\n    return this.sessions.size;\n  }\n\n  /**\n   * Get all session IDs\n   */\n  getSessionIds(): string[] {\n    return Array.from(this.sessions.keys());\n  }\n\n  /**\n   * Clear schema cache for a specific session\n   */\n  clearSessionCache(sessionId: string): void {\n    const session = this.sessions.get(sessionId);\n    if (session) {\n      session.service.clearSchemaCache();\n    }\n  }\n\n  /**\n   * Clear schema cache for all sessions\n   */\n  clearAllCaches(): void {\n    for (const session of this.sessions.values()) {\n      session.service.clearSchemaCache();\n    }\n    console.error(`🗑️ 已清除所有会话的 Schema 缓存 (共 ${this.sessions.size} 个会话)`);\n  }\n\n  /**\n   * Cleanup expired sessions\n   */\n  private cleanupExpiredSessions(): void {\n    const now = Date.now();\n\n    for (const [sessionId, session] of this.sessions.entries()) {\n      const lastAccessed = session.lastAccessedAt.getTime();\n      const elapsed = now - lastAccessed;\n\n      if (elapsed > this.sessionTimeout) {\n        // Clear cache and disconnect\n        session.service.clearSchemaCache();\n        session.adapter.disconnect().catch((err: Error) => {\n          console.error(`清理会话 ${sessionId} 时出错:`, err);\n        });\n\n        this.sessions.delete(sessionId);\n        console.log(`🧹 清理过期会话: ${sessionId}`);\n      }\n    }\n  }\n\n  /**\n   * Disconnect all sessions and stop cleanup\n   */\n  async disconnectAll(): Promise<void> {\n    // Stop cleanup interval\n    if (this.cleanupInterval) {\n      clearInterval(this.cleanupInterval);\n    }\n\n    // Clear all caches and disconnect all sessions\n    const disconnectPromises = Array.from(this.sessions.values()).map(session => {\n      session.service.clearSchemaCache();\n      return session.adapter.disconnect().catch((err: Error) => {\n        console.error(`断开会话 ${session.id} 时出错:`, err);\n      });\n    });\n\n    await Promise.all(disconnectPromises);\n\n    // Clear sessions\n    this.sessions.clear();\n  }\n}\n"
  },
  {
    "path": "src/core/database-service.ts",
    "content": "/**\n * Database Service\n * Core business logic for database operations\n * Shared between MCP and HTTP modes\n */\n\nimport type { DbAdapter, DbConfig, QueryResult, SchemaInfo, TableInfo, EnumValuesResult, SampleDataResult } from '../types/adapter.js';\nimport { validateQuery } from '../utils/safety.js';\nimport { SchemaEnhancer, SchemaEnhancerConfig } from '../utils/schema-enhancer.js';\nimport { DataMasker, createDataMasker } from '../utils/data-masking.js';\n\n/**\n * Schema 缓存配置\n */\nexport interface SchemaCacheConfig {\n  /** 缓存过期时间（毫秒），默认 5 分钟 */\n  ttl: number;\n  /** 是否启用缓存，默认 true */\n  enabled: boolean;\n}\n\n/**\n * Schema 增强配置（导出供外部使用）\n */\nexport type { SchemaEnhancerConfig };\n\n/**\n * Schema 缓存统计信息\n */\nexport interface SchemaCacheStats {\n  /** 缓存是否有效 */\n  isCached: boolean;\n  /** 缓存时间 */\n  cachedAt: Date | null;\n  /** 缓存过期时间 */\n  expiresAt: Date | null;\n  /** 缓存命中次数 */\n  hitCount: number;\n  /** 缓存未命中次数 */\n  missCount: number;\n}\n\n/**\n * 默认缓存配置\n */\nconst DEFAULT_CACHE_CONFIG: SchemaCacheConfig = {\n  ttl: 5 * 60 * 1000, // 5 分钟\n  enabled: true,\n};\n\n/**\n * Database Service Class\n * Encapsulates all database operations with validation and error handling\n */\nexport class DatabaseService {\n  private adapter: DbAdapter;\n  private config: DbConfig;\n\n  // Schema 缓存相关\n  private schemaCache: SchemaInfo | null = null;\n  private schemaCacheTime: number = 0;\n  private cacheConfig: SchemaCacheConfig;\n  private cacheHitCount: number = 0;\n  private cacheMissCount: number = 0;\n\n  // Schema 增强器\n  private schemaEnhancer: SchemaEnhancer;\n\n  // 数据脱敏器\n  private dataMasker: DataMasker;\n\n  constructor(\n    adapter: DbAdapter,\n    config: DbConfig,\n    cacheConfig?: Partial<SchemaCacheConfig>,\n    enhancerConfig?: Partial<SchemaEnhancerConfig>\n  ) {\n    this.adapter = adapter;\n    this.config = config;\n    this.cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig };\n    this.schemaEnhancer = new SchemaEnhancer(enhancerConfig);\n    this.dataMasker = createDataMasker(true);\n  }\n\n  /**\n   * Execute a query with validation\n   */\n  async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {\n    // Validate query safety\n    this.validateQuery(query);\n\n    // Execute query\n    const result = await this.adapter.executeQuery(query, params);\n\n    return result;\n  }\n\n  /**\n   * Get complete database schema\n   * @param forceRefresh - 是否强制刷新缓存，忽略现有缓存\n   */\n  async getSchema(forceRefresh: boolean = false): Promise<SchemaInfo> {\n    const now = Date.now();\n\n    // 检查是否可以使用缓存\n    if (\n      !forceRefresh &&\n      this.cacheConfig.enabled &&\n      this.schemaCache &&\n      (now - this.schemaCacheTime) < this.cacheConfig.ttl\n    ) {\n      this.cacheHitCount++;\n      console.error(`📦 Schema 缓存命中 (命中率: ${this.getCacheHitRate()}%)`);\n      return this.schemaCache;\n    }\n\n    // 缓存未命中或已过期，重新获取\n    this.cacheMissCount++;\n    console.error(`🔄 正在获取数据库 Schema${forceRefresh ? ' (强制刷新)' : this.schemaCache ? ' (缓存已过期)' : ' (首次加载)'}...`);\n\n    const startTime = Date.now();\n    const schema = await this.adapter.getSchema();\n    const elapsed = Date.now() - startTime;\n\n    // 增强 Schema 信息（隐式关系推断、关系类型细化）\n    const enhancedSchema = this.enhanceSchema(schema);\n\n    // 更新缓存\n    if (this.cacheConfig.enabled) {\n      this.schemaCache = enhancedSchema;\n      this.schemaCacheTime = now;\n\n      // 统计增强信息\n      const explicitRelCount = schema.relationships?.length || 0;\n      const totalRelCount = enhancedSchema.relationships?.length || 0;\n      const inferredRelCount = totalRelCount - explicitRelCount;\n\n      console.error(`✅ Schema 已缓存 (获取耗时: ${elapsed}ms, 表数量: ${enhancedSchema.tables.length}, 显式关系: ${explicitRelCount}, 推断关系: ${inferredRelCount}, 缓存有效期: ${this.cacheConfig.ttl / 1000}秒)`);\n    }\n\n    return enhancedSchema;\n  }\n\n  /**\n   * 增强 Schema 信息\n   * - 为现有外键关系添加 source 标记\n   * - 推断隐式关系\n   * - 细化关系类型\n   */\n  private enhanceSchema(schema: SchemaInfo): SchemaInfo {\n    // 对于 NoSQL 数据库（Redis、MongoDB），不进行关系增强\n    if (schema.databaseType === 'redis' || schema.databaseType === 'mongodb') {\n      return schema;\n    }\n\n    // 增强关系信息\n    const existingRelationships = schema.relationships || [];\n    const enhancedRelationships = this.schemaEnhancer.enhanceRelationships(\n      schema.tables,\n      existingRelationships\n    );\n\n    return {\n      ...schema,\n      relationships: enhancedRelationships.length > 0 ? enhancedRelationships : undefined,\n    };\n  }\n\n  /**\n   * Get information about a specific table\n   * @param tableName - 表名（支持 schema.table_name 格式）\n   * @param forceRefresh - 是否强制刷新缓存\n   */\n  async getTableInfo(tableName: string, forceRefresh: boolean = false): Promise<TableInfo> {\n    const schema = await this.getSchema(forceRefresh);\n\n    // 1. 精确匹配 name 字段（已包含 schema 前缀）\n    let table = schema.tables.find(t =>\n      t.name === tableName ||\n      t.name.toLowerCase() === tableName.toLowerCase()\n    );\n\n    // 2. 如果没找到且包含点号，尝试用 schema + 表名组合匹配\n    if (!table && tableName.includes('.')) {\n      const dotIndex = tableName.indexOf('.');\n      const schemaName = tableName.substring(0, dotIndex);\n      const tblName = tableName.substring(dotIndex + 1);\n      table = schema.tables.find(t =>\n        t.schema?.toLowerCase() === schemaName.toLowerCase() &&\n        (t.name === tblName || t.name.toLowerCase() === tblName.toLowerCase() ||\n         t.name.toLowerCase() === tableName.toLowerCase())\n      );\n    }\n\n    // 3. 如果还没找到，尝试只匹配表名部分（不含 schema 前缀）\n    if (!table) {\n      const baseName = tableName.includes('.') ? tableName.substring(tableName.indexOf('.') + 1) : tableName;\n      const matches = schema.tables.filter(t => {\n        const tBaseName = t.name.includes('.') ? t.name.substring(t.name.indexOf('.') + 1) : t.name;\n        return tBaseName.toLowerCase() === baseName.toLowerCase();\n      });\n      if (matches.length === 1) {\n        table = matches[0];\n      }\n    }\n\n    if (!table) {\n      throw new Error(`表 \"${tableName}\" 不存在`);\n    }\n\n    return table;\n  }\n\n  /**\n   * List all tables in the database\n   * @param forceRefresh - 是否强制刷新缓存\n   */\n  async listTables(forceRefresh: boolean = false): Promise<string[]> {\n    const schema = await this.getSchema(forceRefresh);\n    return schema.tables.map(t => t.name);\n  }\n\n  /**\n   * Test database connection\n   */\n  async testConnection(): Promise<boolean> {\n    try {\n      // Try a simple query to test connection\n      await this.adapter.executeQuery('SELECT 1');\n      return true;\n    } catch (error) {\n      return false;\n    }\n  }\n\n  /**\n   * 清除 Schema 缓存\n   */\n  clearSchemaCache(): void {\n    this.schemaCache = null;\n    this.schemaCacheTime = 0;\n    console.error('🗑️ Schema 缓存已清除');\n  }\n\n  /**\n   * 获取缓存统计信息\n   */\n  getCacheStats(): SchemaCacheStats {\n    const now = Date.now();\n    const isCached = this.schemaCache !== null && (now - this.schemaCacheTime) < this.cacheConfig.ttl;\n\n    return {\n      isCached,\n      cachedAt: this.schemaCacheTime > 0 ? new Date(this.schemaCacheTime) : null,\n      expiresAt: this.schemaCacheTime > 0 ? new Date(this.schemaCacheTime + this.cacheConfig.ttl) : null,\n      hitCount: this.cacheHitCount,\n      missCount: this.cacheMissCount,\n    };\n  }\n\n  /**\n   * 获取缓存命中率\n   */\n  getCacheHitRate(): string {\n    const total = this.cacheHitCount + this.cacheMissCount;\n    if (total === 0) return '0.00';\n    return ((this.cacheHitCount / total) * 100).toFixed(2);\n  }\n\n  /**\n   * 更新缓存配置\n   */\n  updateCacheConfig(config: Partial<SchemaCacheConfig>): void {\n    this.cacheConfig = { ...this.cacheConfig, ...config };\n    console.error(`⚙️ 缓存配置已更新: TTL=${this.cacheConfig.ttl}ms, 启用=${this.cacheConfig.enabled}`);\n  }\n\n  /**\n   * 更新 Schema 增强配置\n   */\n  updateEnhancerConfig(config: Partial<SchemaEnhancerConfig>): void {\n    this.schemaEnhancer.updateConfig(config);\n    // 清除缓存以便下次获取时应用新配置\n    this.clearSchemaCache();\n    console.error(`⚙️ Schema 增强配置已更新`);\n  }\n\n  /**\n   * 获取 Schema 增强配置\n   */\n  getEnhancerConfig(): SchemaEnhancerConfig {\n    return this.schemaEnhancer.getConfig();\n  }\n\n  /**\n   * Validate query against write permissions\n   */\n  private validateQuery(query: string): void {\n    validateQuery(query, this.config);\n  }\n\n  /**\n   * Get the underlying adapter\n   */\n  getAdapter(): DbAdapter {\n    return this.adapter;\n  }\n\n  /**\n   * Get the configuration\n   */\n  getConfig(): DbConfig {\n    return this.config;\n  }\n\n  /**\n   * 获取指定列的枚举值\n   * 用于帮助 LLM 了解 status、type 等枚举列的所有可能值\n   *\n   * @param tableName - 表名\n   * @param columnName - 列名\n   * @param limit - 最大返回数量（默认 50，最大 100）\n   * @param includeCount - 是否包含每个值的出现次数（默认 false）\n   * @returns 枚举值查询结果\n   */\n  async getEnumValues(\n    tableName: string,\n    columnName: string,\n    limit: number = 50,\n    includeCount: boolean = false\n  ): Promise<EnumValuesResult> {\n    // 检查是否为 NoSQL 数据库\n    if (this.config.type === 'redis' || this.config.type === 'mongodb') {\n      throw new Error(\n        `${this.config.type} 是 NoSQL 数据库，不支持 get_enum_values 工具。` +\n        `请使用 execute_query 工具直接查询。`\n      );\n    }\n\n    // 1. 验证表和列是否存在\n    const tableInfo = await this.getTableInfo(tableName);\n    const column = tableInfo.columns.find(\n      c => c.name.toLowerCase() === columnName.toLowerCase()\n    );\n\n    if (!column) {\n      throw new Error(\n        `列 \"${columnName}\" 在表 \"${tableName}\" 中不存在。` +\n        `该表的列有: ${tableInfo.columns.map(c => c.name).join(', ')}`\n      );\n    }\n\n    // 使用实际的列名（保持原始大小写）\n    const actualColumnName = column.name;\n    const actualTableName = tableInfo.name;\n\n    // 2. 限制返回数量（安全限制）\n    const safeLimit = Math.min(Math.max(1, limit), 100);\n\n    // 3. 构建查询 SQL\n    let query: string;\n    if (includeCount) {\n      query = this.buildEnumValuesQueryWithCount(actualTableName, actualColumnName, safeLimit + 1);\n    } else {\n      query = this.buildEnumValuesQuery(actualTableName, actualColumnName, safeLimit + 1);\n    }\n\n    // 4. 执行查询\n    const result = await this.adapter.executeQuery(query);\n\n    // 5. 处理结果\n    const hasMore = result.rows.length > safeLimit;\n    const rows = hasMore ? result.rows.slice(0, safeLimit) : result.rows;\n\n    const values = rows.map(row => row.value as string | number | null);\n    const valueCounts = includeCount\n      ? Object.fromEntries(rows.map(row => [String(row.value), Number(row.count)]))\n      : undefined;\n\n    return {\n      tableName: actualTableName,\n      columnName: actualColumnName,\n      values,\n      totalCount: values.length,\n      isEnum: !hasMore,\n      valueCounts,\n      columnType: column.type,\n    };\n  }\n\n  /**\n   * 获取表的示例数据（已脱敏）\n   * 用于帮助 LLM 理解数据格式（日期格式、ID 格式等）\n   *\n   * @param tableName - 表名\n   * @param columns - 要查看的列（可选，默认全部）\n   * @param limit - 返回行数（默认 3，最大 10）\n   * @returns 示例数据查询结果\n   */\n  async getSampleData(\n    tableName: string,\n    columns?: string[],\n    limit: number = 3\n  ): Promise<SampleDataResult> {\n    // 检查是否为 NoSQL 数据库\n    if (this.config.type === 'redis' || this.config.type === 'mongodb') {\n      throw new Error(\n        `${this.config.type} 是 NoSQL 数据库，不支持 get_sample_data 工具。` +\n        `请使用 execute_query 工具直接查询。`\n      );\n    }\n\n    // 1. 验证表是否存在\n    const tableInfo = await this.getTableInfo(tableName);\n    const actualTableName = tableInfo.name;\n\n    // 2. 验证并确定要查询的列\n    let selectedColumns: string[];\n    if (columns && columns.length > 0) {\n      const validColumns = tableInfo.columns.map(c => c.name.toLowerCase());\n      const invalidColumns = columns.filter(c => !validColumns.includes(c.toLowerCase()));\n      if (invalidColumns.length > 0) {\n        throw new Error(\n          `列 \"${invalidColumns.join(', ')}\" 在表 \"${tableName}\" 中不存在。` +\n          `该表的列有: ${tableInfo.columns.map(c => c.name).join(', ')}`\n        );\n      }\n      // 使用实际的列名（保持原始大小写）\n      selectedColumns = columns.map(c => {\n        const found = tableInfo.columns.find(col => col.name.toLowerCase() === c.toLowerCase());\n        return found ? found.name : c;\n      });\n    } else {\n      // 默认查询所有列\n      selectedColumns = tableInfo.columns.map(c => c.name);\n    }\n\n    // 3. 限制返回行数（安全限制）\n    const safeLimit = Math.min(Math.max(1, limit), 10);\n\n    // 4. 构建查询 SQL\n    const query = this.buildSampleDataQuery(actualTableName, selectedColumns, safeLimit);\n\n    // 5. 执行查询\n    const result = await this.adapter.executeQuery(query);\n\n    // 6. 脱敏处理\n    const { maskedRows, maskedColumns } = this.dataMasker.maskRows(result.rows);\n\n    return {\n      tableName: actualTableName,\n      columns: selectedColumns,\n      rows: maskedRows,\n      rowCount: maskedRows.length,\n      masked: maskedColumns.length > 0,\n      maskedColumns: maskedColumns.length > 0 ? maskedColumns : undefined,\n    };\n  }\n\n  /**\n   * 构建枚举值查询 SQL（不含计数）\n   */\n  private buildEnumValuesQuery(tableName: string, columnName: string, limit: number): string {\n    const quotedTable = this.quoteIdentifier(tableName);\n    const quotedColumn = this.quoteIdentifier(columnName);\n\n    const baseQuery = `SELECT DISTINCT ${quotedColumn} as value FROM ${quotedTable} WHERE ${quotedColumn} IS NOT NULL`;\n\n    return this.appendLimit(baseQuery, limit);\n  }\n\n  /**\n   * 构建枚举值查询 SQL（含计数）\n   */\n  private buildEnumValuesQueryWithCount(tableName: string, columnName: string, limit: number): string {\n    const quotedTable = this.quoteIdentifier(tableName);\n    const quotedColumn = this.quoteIdentifier(columnName);\n\n    const baseQuery = `SELECT ${quotedColumn} as value, COUNT(*) as count FROM ${quotedTable} WHERE ${quotedColumn} IS NOT NULL GROUP BY ${quotedColumn} ORDER BY count DESC`;\n\n    return this.appendLimit(baseQuery, limit);\n  }\n\n  /**\n   * 构建示例数据查询 SQL\n   */\n  private buildSampleDataQuery(tableName: string, columns: string[], limit: number): string {\n    const quotedTable = this.quoteIdentifier(tableName);\n    const quotedColumns = columns.map(c => this.quoteIdentifier(c)).join(', ');\n\n    const baseQuery = `SELECT ${quotedColumns} FROM ${quotedTable}`;\n\n    return this.appendLimit(baseQuery, limit);\n  }\n\n  /**\n   * 引用标识符（表名、列名）\n   * 根据数据库类型使用不同的引号\n   * 支持 schema.table 格式：自动拆分并分别引用\n   */\n  private quoteIdentifier(identifier: string): string {\n    // 检查是否包含 schema 限定（schema.table 格式）\n    const dotIndex = identifier.indexOf('.');\n    if (dotIndex > 0) {\n      const schema = identifier.substring(0, dotIndex);\n      const name = identifier.substring(dotIndex + 1);\n      return `${this.quoteSimpleIdentifier(schema)}.${this.quoteSimpleIdentifier(name)}`;\n    }\n\n    return this.quoteSimpleIdentifier(identifier);\n  }\n\n  /**\n   * 引用单个标识符（不含 schema 前缀）\n   */\n  private quoteSimpleIdentifier(identifier: string): string {\n    const dbType = this.config.type;\n\n    switch (dbType) {\n      case 'mysql':\n      case 'tidb':\n      case 'oceanbase':\n      case 'polardb':\n      case 'goldendb':\n        // MySQL 系使用反引号\n        return `\\`${identifier}\\``;\n\n      case 'sqlserver':\n        // SQL Server 使用方括号\n        return `[${identifier}]`;\n\n      default:\n        // PostgreSQL, Oracle, SQLite, 达梦, KingbaseES, GaussDB, Vastbase, HighGo, ClickHouse 等使用双引号\n        return `\"${identifier}\"`;\n    }\n  }\n\n  /**\n   * 添加 LIMIT 子句\n   * 根据数据库类型使用不同的语法\n   */\n  private appendLimit(query: string, limit: number): string {\n    const dbType = this.config.type;\n\n    switch (dbType) {\n      case 'oracle':\n      case 'dm':\n        // Oracle/达梦 使用 FETCH FIRST\n        return `${query} FETCH FIRST ${limit} ROWS ONLY`;\n\n      case 'sqlserver':\n        // SQL Server 使用 TOP（需要插入到 SELECT 后面）\n        return query.replace(/^SELECT/i, `SELECT TOP ${limit}`);\n\n      default:\n        // MySQL, PostgreSQL, SQLite, TiDB, ClickHouse 等使用 LIMIT\n        return `${query} LIMIT ${limit}`;\n    }\n  }\n}\n"
  },
  {
    "path": "src/http/http-index.ts",
    "content": "/**\n * HTTP Server Entry Point\n * Starts the HTTP API server\n */\n\nimport type { AppConfig } from '../types/http.js';\nimport { createHttpServer } from './server.js';\n\n/**\n * Start HTTP server\n */\nexport async function startHttpServer(config: AppConfig): Promise<void> {\n  try {\n    // Create server\n    const server = await createHttpServer(config);\n\n    // Get configuration\n    const port = config.http?.port || 3000;\n    const host = config.http?.host || '0.0.0.0';\n\n    // Start listening\n    await server.listen({ port, host });\n\n    console.log('');\n    console.log('🚀 HTTP API Server started successfully!');\n    console.log('');\n    console.log(`📍 Server URL: http://${host}:${port}`);\n    console.log(`📊 Supported databases: 17 types`);\n    console.log(`🛡️  Security: API Key authentication ${config.http?.apiKeys.length ? 'enabled' : 'disabled (WARNING!)'}`);\n    console.log(`⚡ Rate limiting: ${config.http?.rateLimit.max} requests per ${config.http?.rateLimit.window}`);\n    console.log('');\n    console.log('📖 API Endpoints:');\n    console.log('   GET  /api/health          - Health check');\n    console.log('   GET  /api/info            - Service information');\n    console.log('   POST /api/connect         - Connect to database');\n    console.log('   POST /api/disconnect      - Disconnect from database');\n    console.log('   POST /api/query           - Execute query');\n    console.log('   POST /api/execute         - Execute write operation');\n    console.log('   GET  /api/tables          - List tables');\n    console.log('   GET  /api/schema          - Get database schema');\n    console.log('   GET  /api/schema/:table   - Get table information');\n    console.log('');\n\n    // Graceful shutdown\n    const signals = ['SIGINT', 'SIGTERM'];\n    signals.forEach(signal => {\n      process.on(signal, async () => {\n        console.log(`\\n⏹️  Received ${signal}, shutting down gracefully...`);\n        await server.close();\n        console.log('👋 Server closed');\n        process.exit(0);\n      });\n    });\n\n  } catch (error) {\n    console.error('❌ Failed to start HTTP server:', error instanceof Error ? error.message : String(error));\n    process.exit(1);\n  }\n}\n"
  },
  {
    "path": "src/http/middleware/auth.ts",
    "content": "/**\n * Authentication Middleware\n * API Key authentication for HTTP API\n */\n\nimport type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { AppConfig } from '../../types/http.js';\n\n/**\n * API Key authentication hook\n */\nexport async function authMiddleware(\n  request: FastifyRequest,\n  reply: FastifyReply,\n  config: AppConfig\n): Promise<void> {\n  // Skip auth for health and info endpoints\n  if (request.url === '/api/health' || request.url === '/api/info') {\n    return;\n  }\n\n  // Get API key from header (supports both X-API-Key and Authorization Bearer)\n  const apiKey =\n    request.headers['x-api-key'] ||\n    (request.headers.authorization?.startsWith('Bearer ')\n      ? request.headers.authorization.substring(7)\n      : null);\n\n  // Check if API keys are configured\n  const validKeys = config.http?.apiKeys || [];\n\n  // If no API keys configured, skip authentication (development mode)\n  if (validKeys.length === 0) {\n    return;\n  }\n\n  if (!apiKey) {\n    reply.code(401).send({\n      success: false,\n      error: {\n        code: 'UNAUTHORIZED',\n        message: 'API key required. Provide X-API-Key header or Authorization: Bearer <key>',\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    });\n    return;\n  }\n\n  // Validate API key\n  if (!validKeys.includes(apiKey as string)) {\n    reply.code(403).send({\n      success: false,\n      error: {\n        code: 'FORBIDDEN',\n        message: 'Invalid API key',\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    });\n    return;\n  }\n\n  // Store API key in request for later use\n  (request as any).apiKey = apiKey;\n}\n"
  },
  {
    "path": "src/http/middleware/error-handler.ts",
    "content": "/**\n * Error Handler Middleware\n * Centralized error handling for HTTP API\n */\n\nimport type { FastifyError, FastifyRequest, FastifyReply } from 'fastify';\n\n/**\n * Global error handler\n */\nexport function setupErrorHandler(fastify: any): void {\n  fastify.setErrorHandler((error: FastifyError, request: FastifyRequest, reply: FastifyReply) => {\n    // Log error\n    request.log.error(error);\n\n    // Determine status code\n    const statusCode = error.statusCode || 500;\n    const errorCode = error.code || 'INTERNAL_ERROR';\n\n    // Send error response\n    reply.code(statusCode).send({\n      success: false,\n      error: {\n        code: errorCode,\n        message: error.message,\n        details: process.env.NODE_ENV === 'development' ? error.stack : undefined,\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    });\n  });\n}\n"
  },
  {
    "path": "src/http/middleware/index.ts",
    "content": "/**\n * Middleware Index\n * Exports all middleware setup functions\n */\n\nexport { authMiddleware } from './auth.js';\nexport { setupErrorHandler } from './error-handler.js';\n"
  },
  {
    "path": "src/http/routes/connection.ts",
    "content": "/**\n * Connection Routes\n * Database connection and disconnection endpoints\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type {\n  ConnectRequest,\n  ConnectResponse,\n  DisconnectRequest,\n  DisconnectResponse,\n  ApiResponse,\n} from '../../types/http.js';\nimport { ConnectionManager } from '../../core/connection-manager.js';\n\nexport async function setupConnectionRoutes(\n  fastify: FastifyInstance,\n  connectionManager: ConnectionManager\n): Promise<void> {\n  /**\n   * POST /api/connect\n   * Connect to a database\n   */\n  fastify.post<{\n    Body: ConnectRequest;\n    Reply: ApiResponse<ConnectResponse>;\n  }>('/api/connect', {\n    schema: {\n      body: {\n        type: 'object',\n        required: ['type'],\n        properties: {\n          type: { type: 'string' },\n          host: { type: 'string' },\n          port: { type: 'number' },\n          user: { type: 'string' },\n          password: { type: 'string' },\n          database: { type: 'string' },\n          filePath: { type: 'string' },\n          authSource: { type: 'string' },\n          allowWrite: { type: 'boolean', default: false },\n          permissionMode: { type: 'string', enum: ['safe', 'readwrite', 'full', 'custom'] },\n          permissions: { type: 'array', items: { type: 'string', enum: ['read', 'insert', 'update', 'delete', 'ddl'] } },\n          oracleClientPath: { type: 'string' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const config = request.body;\n\n      // Connect to database\n      const sessionId = await connectionManager.connect(config as any);\n\n      return {\n        success: true,\n        data: {\n          sessionId,\n          databaseType: config.type,\n          connected: true,\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'CONNECTION_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to connect to database',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * POST /api/disconnect\n   * Disconnect from a database\n   */\n  fastify.post<{\n    Body: DisconnectRequest;\n    Reply: ApiResponse<DisconnectResponse>;\n  }>('/api/disconnect', {\n    schema: {\n      body: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId } = request.body;\n\n      // Disconnect from database\n      await connectionManager.disconnect(sessionId);\n\n      return {\n        success: true,\n        data: {\n          disconnected: true,\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'DISCONNECTION_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to disconnect from database',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n}\n"
  },
  {
    "path": "src/http/routes/health.ts",
    "content": "/**\n * Health and Info Routes\n * System health check and service information endpoints\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { HealthResponse, InfoResponse, ApiResponse } from '../../types/http.js';\n\nexport async function setupHealthRoutes(fastify: FastifyInstance): Promise<void> {\n  /**\n   * GET /api/health\n   * Health check endpoint\n   */\n  fastify.get<{ Reply: ApiResponse<HealthResponse> }>('/api/health', async (request) => {\n    return {\n      success: true,\n      data: {\n        status: 'healthy',\n        uptime: process.uptime(),\n        timestamp: new Date().toISOString(),\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    };\n  });\n\n  /**\n   * GET /api/info\n   * Service information endpoint\n   */\n  fastify.get<{ Reply: ApiResponse<InfoResponse> }>('/api/info', async (request) => {\n    return {\n      success: true,\n      data: {\n        name: 'universal-db-mcp',\n        version: '1.0.0',\n        mode: 'http',\n        supportedDatabases: [\n          'mysql',\n          'postgres',\n          'redis',\n          'oracle',\n          'dm',\n          'sqlserver',\n          'mongodb',\n          'sqlite',\n          'kingbase',\n          'gaussdb',\n          'oceanbase',\n          'tidb',\n          'clickhouse',\n          'polardb',\n          'vastbase',\n          'highgo',\n          'goldendb',\n        ],\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    };\n  });\n}\n"
  },
  {
    "path": "src/http/routes/index.ts",
    "content": "/**\n * Routes Index\n * Aggregates all route setup functions\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { ConnectionManager } from '../../core/connection-manager.js';\nimport { setupHealthRoutes } from './health.js';\nimport { setupConnectionRoutes } from './connection.js';\nimport { setupQueryRoutes } from './query.js';\nimport { setupSchemaRoutes } from './schema.js';\nimport { setupMcpSseRoutes } from './mcp-sse.js';\n\n/**\n * Setup all routes\n */\nexport async function setupRoutes(\n  fastify: FastifyInstance,\n  connectionManager: ConnectionManager\n): Promise<void> {\n  // Health and info routes (no auth required)\n  await setupHealthRoutes(fastify);\n\n  // MCP SSE routes (no auth required, uses its own session management)\n  await setupMcpSseRoutes(fastify);\n\n  // Connection routes\n  await setupConnectionRoutes(fastify, connectionManager);\n\n  // Query routes\n  await setupQueryRoutes(fastify, connectionManager);\n\n  // Schema routes\n  await setupSchemaRoutes(fastify, connectionManager);\n}\n"
  },
  {
    "path": "src/http/routes/mcp-sse.ts",
    "content": "/**\n * MCP SSE Routes\n * 提供 MCP over SSE/Streamable HTTP 传输支持\n * 使 Dify 等平台可以通过 MCP 协议直接调用\n */\n\nimport type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';\nimport { randomUUID } from 'node:crypto';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\nimport { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';\nimport { DatabaseMCPServer } from '../../mcp/mcp-server.js';\nimport type { DbConfig, PermissionType, PermissionMode } from '../../types/adapter.js';\nimport { createAdapter } from '../../utils/adapter-factory.js';\n\n// 支持的数据库类型\ntype DbType = DbConfig['type'];\nconst SUPPORTED_DB_TYPES: DbType[] = [\n  'mysql', 'postgres', 'redis', 'oracle', 'dm', 'sqlserver', 'mongodb', 'sqlite',\n  'kingbase', 'gaussdb', 'oceanbase', 'tidb', 'clickhouse', 'polardb', 'vastbase', 'highgo', 'goldendb'\n];\n\n// 存储活跃的 SSE 传输实例（按 sessionId）\nconst sseTransports: Map<string, SSEServerTransport> = new Map();\n\n// 存储活跃的 Streamable HTTP 传输实例（按 sessionId）\nconst streamableTransports: Map<string, StreamableHTTPServerTransport> = new Map();\n\n// 存储 MCP 服务器实例（按 sessionId）\nconst mcpServers: Map<string, DatabaseMCPServer> = new Map();\n\n/**\n * 验证数据库类型\n */\nfunction isValidDbType(type: string): type is DbType {\n  return SUPPORTED_DB_TYPES.includes(type as DbType);\n}\n\n/**\n * 从请求中解析数据库配置\n */\nfunction parseDbConfigFromQuery(query: Record<string, unknown>): DbConfig | null {\n  const type = query.type as string;\n  if (!type || !isValidDbType(type)) return null;\n\n  // 解析 permissions 数组\n  const permissionsStr = query.permissions as string;\n  const permissions = permissionsStr\n    ? permissionsStr.split(',').map(p => p.trim()) as PermissionType[]\n    : undefined;\n\n  return {\n    type,\n    host: query.host as string,\n    port: query.port ? parseInt(query.port as string, 10) : undefined,\n    user: query.user as string,\n    password: query.password as string,\n    database: query.database as string,\n    filePath: query.filePath as string,\n    allowWrite: query.allowWrite === 'true',\n    permissionMode: query.permissionMode as PermissionMode,\n    permissions,\n    oracleClientPath: query.oracleClientPath as string,\n  };\n}\n\n/**\n * 创建并初始化 MCP 服务器\n */\nasync function createMcpServer(config: DbConfig): Promise<DatabaseMCPServer> {\n  const mcpServer = new DatabaseMCPServer(config);\n  const adapter = createAdapter(config);\n  mcpServer.setAdapter(adapter);\n  await mcpServer.connectDatabase();\n  return mcpServer;\n}\n\n/**\n * 清理会话资源\n */\nasync function cleanupSession(sessionId: string): Promise<void> {\n  const mcpServer = mcpServers.get(sessionId);\n  if (mcpServer) {\n    await mcpServer.stop();\n    mcpServers.delete(sessionId);\n  }\n  sseTransports.delete(sessionId);\n  streamableTransports.delete(sessionId);\n}\n\n/**\n * 设置 MCP SSE 路由\n */\nexport async function setupMcpSseRoutes(fastify: FastifyInstance): Promise<void> {\n  /**\n   * SSE 端点 - 用于建立 SSE 连接（传统 SSE 模式）\n   * GET /sse?type=mysql&host=localhost&port=3306&user=root&password=xxx&database=mydb\n   */\n  fastify.get('/sse', async (request: FastifyRequest, reply: FastifyReply) => {\n    const query = request.query as Record<string, unknown>;\n    const config = parseDbConfigFromQuery(query);\n\n    if (!config) {\n      return reply.code(400).send({\n        success: false,\n        error: {\n          code: 'INVALID_CONFIG',\n          message: 'Missing required database configuration. Please provide at least \"type\" parameter.',\n        },\n      });\n    }\n\n    try {\n      // 创建 MCP 服务器\n      const mcpServer = await createMcpServer(config);\n\n      // 获取原始的 Node.js response 对象\n      const res = reply.raw;\n\n      // 创建 SSE 传输\n      const transport = new SSEServerTransport('/sse/message', res);\n      const sessionId = transport.sessionId;\n\n      // 存储实例\n      sseTransports.set(sessionId, transport);\n      mcpServers.set(sessionId, mcpServer);\n\n      // 设置关闭处理\n      transport.onclose = async () => {\n        console.error(`SSE session ${sessionId} closed`);\n        await cleanupSession(sessionId);\n      };\n\n      // 连接 MCP 服务器到传输层（connect 会自动调用 transport.start()）\n      await mcpServer.getServer().connect(transport);\n\n      console.error(`🔗 SSE session started: ${sessionId}`);\n\n      // SSE 连接需要保持打开，不返回任何内容\n      // Fastify 会自动处理，因为 response 已经被 SSE transport 接管\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      console.error(`❌ SSE connection error: ${errorMessage}`);\n      // 只有在 headers 还没发送时才返回错误\n      if (!reply.raw.headersSent) {\n        return reply.code(500).send({\n          success: false,\n          error: {\n            code: 'CONNECTION_ERROR',\n            message: errorMessage,\n          },\n        });\n      }\n    }\n  });\n\n  /**\n   * SSE 消息端点 - 接收客户端发送的消息（传统 SSE 模式）\n   * POST /sse/message?sessionId=xxx\n   */\n  fastify.post('/sse/message', async (request: FastifyRequest, reply: FastifyReply) => {\n    const query = request.query as Record<string, unknown>;\n    const sessionId = query.sessionId as string;\n\n    if (!sessionId) {\n      return reply.code(400).send({\n        success: false,\n        error: {\n          code: 'MISSING_SESSION_ID',\n          message: 'Session ID is required',\n        },\n      });\n    }\n\n    const transport = sseTransports.get(sessionId);\n    if (!transport) {\n      return reply.code(404).send({\n        success: false,\n        error: {\n          code: 'SESSION_NOT_FOUND',\n          message: 'Session not found or expired',\n        },\n      });\n    }\n\n    try {\n      // 获取原始的 Node.js request/response 对象\n      const req = request.raw;\n      const res = reply.raw;\n\n      await transport.handlePostMessage(req, res, request.body);\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      console.error(`❌ SSE message error: ${errorMessage}`);\n      return reply.code(500).send({\n        success: false,\n        error: {\n          code: 'MESSAGE_ERROR',\n          message: errorMessage,\n        },\n      });\n    }\n  });\n\n  /**\n   * Streamable HTTP 端点 - MCP 2025 新规范\n   * POST /mcp\n   *\n   * 数据库配置通过请求头传递：\n   * X-DB-Type, X-DB-Host, X-DB-Port, X-DB-User, X-DB-Password, X-DB-Database, X-DB-Allow-Write\n   */\n  fastify.post('/mcp', async (request: FastifyRequest, reply: FastifyReply) => {\n    const headers = request.headers;\n    const body = request.body;\n\n    // 从请求头解析数据库类型\n    const dbType = headers['x-db-type'] as string;\n\n    try {\n      // 检查是否有现有会话\n      const sessionId = headers['mcp-session-id'] as string;\n      let transport: StreamableHTTPServerTransport;\n\n      if (sessionId && streamableTransports.has(sessionId)) {\n        // 复用现有传输\n        transport = streamableTransports.get(sessionId)!;\n      } else if (!sessionId && isInitializeRequest(body)) {\n        // 新的初始化请求\n        if (!dbType || !isValidDbType(dbType)) {\n          return reply.code(400).send({\n            jsonrpc: '2.0',\n            error: {\n              code: -32000,\n              message: 'Missing or invalid database configuration. Please provide valid X-DB-Type header.',\n            },\n            id: null,\n          });\n        }\n\n        // 构建数据库配置\n        const permissionsHeader = headers['x-db-permissions'] as string;\n        const config: DbConfig = {\n          type: dbType,\n          host: headers['x-db-host'] as string,\n          port: headers['x-db-port'] ? parseInt(headers['x-db-port'] as string, 10) : undefined,\n          user: headers['x-db-user'] as string,\n          password: headers['x-db-password'] as string,\n          database: headers['x-db-database'] as string,\n          filePath: headers['x-db-filepath'] as string,\n          allowWrite: headers['x-db-allow-write'] === 'true',\n          permissionMode: headers['x-db-permission-mode'] as PermissionMode,\n          permissions: permissionsHeader ? permissionsHeader.split(',').map(p => p.trim()) as PermissionType[] : undefined,\n          oracleClientPath: headers['x-db-oracle-client-path'] as string,\n        };\n\n        // 创建 MCP 服务器\n        const mcpServer = await createMcpServer(config);\n\n        // 创建 Streamable HTTP 传输\n        transport = new StreamableHTTPServerTransport({\n          sessionIdGenerator: () => randomUUID(),\n          onsessioninitialized: (newSessionId) => {\n            console.error(`🔗 MCP session initialized: ${newSessionId}`);\n            streamableTransports.set(newSessionId, transport);\n            mcpServers.set(newSessionId, mcpServer);\n          },\n        });\n\n        // 连接 MCP 服务器到传输层（使用 getServer() 避免重复调用 start）\n        await mcpServer.getServer().connect(transport);\n\n        // 处理请求\n        await transport.handleRequest(request.raw, reply.raw, body);\n        return;\n      } else {\n        // 无效请求\n        return reply.code(400).send({\n          jsonrpc: '2.0',\n          error: {\n            code: -32000,\n            message: 'Bad Request: No valid session ID provided',\n          },\n          id: null,\n        });\n      }\n\n      // 使用现有传输处理请求\n      await transport.handleRequest(request.raw, reply.raw, body);\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      console.error(`❌ MCP request error: ${errorMessage}`);\n      if (!reply.sent) {\n        return reply.code(500).send({\n          jsonrpc: '2.0',\n          error: {\n            code: -32603,\n            message: errorMessage,\n          },\n          id: null,\n        });\n      }\n    }\n  });\n\n  /**\n   * Streamable HTTP GET 端点 - 用于 SSE 流\n   * GET /mcp\n   */\n  fastify.get('/mcp', async (request: FastifyRequest, reply: FastifyReply) => {\n    const sessionId = request.headers['mcp-session-id'] as string;\n\n    if (!sessionId || !streamableTransports.has(sessionId)) {\n      return reply.code(400).send({\n        jsonrpc: '2.0',\n        error: {\n          code: -32000,\n          message: 'Bad Request: No valid session ID provided',\n        },\n        id: null,\n      });\n    }\n\n    const transport = streamableTransports.get(sessionId)!;\n    await transport.handleRequest(request.raw, reply.raw);\n  });\n\n  /**\n   * 删除会话端点\n   * DELETE /mcp?sessionId=xxx\n   */\n  fastify.delete('/mcp', async (request: FastifyRequest, reply: FastifyReply) => {\n    const query = request.query as Record<string, unknown>;\n    const sessionId = query.sessionId as string || request.headers['mcp-session-id'] as string;\n\n    if (!sessionId) {\n      return reply.code(400).send({\n        success: false,\n        error: {\n          code: 'MISSING_SESSION_ID',\n          message: 'Session ID is required',\n        },\n      });\n    }\n\n    await cleanupSession(sessionId);\n\n    return reply.send({\n      success: true,\n      message: 'Session closed',\n    });\n  });\n\n  console.error('📡 MCP SSE/Streamable HTTP routes registered');\n}\n"
  },
  {
    "path": "src/http/routes/query.ts",
    "content": "/**\n * Query Routes\n * Query execution endpoints\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { QueryRequest, ExecuteRequest, ApiResponse, HttpQueryResult } from '../../types/http.js';\nimport type { QueryResult } from '../../types/adapter.js';\nimport { ConnectionManager } from '../../core/connection-manager.js';\n\nexport async function setupQueryRoutes(\n  fastify: FastifyInstance,\n  connectionManager: ConnectionManager\n): Promise<void> {\n  /**\n   * POST /api/query\n   * Execute a query (read operations)\n   */\n  fastify.post<{\n    Body: QueryRequest;\n    Reply: ApiResponse<HttpQueryResult>;\n  }>('/api/query', {\n    schema: {\n      body: {\n        type: 'object',\n        required: ['sessionId', 'query'],\n        properties: {\n          sessionId: { type: 'string' },\n          query: { type: 'string' },\n          params: { type: 'array' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, query, params } = request.body;\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Execute query\n      const result = await service.executeQuery(query, params);\n\n      // Convert rows to JSON string for Coze compatibility\n      const httpResult: HttpQueryResult = {\n        rows: JSON.stringify(result.rows),\n        affectedRows: result.affectedRows,\n        executionTime: result.executionTime,\n        metadata: result.metadata,\n      };\n\n      return {\n        success: true,\n        data: httpResult,\n        metadata: {\n          executionTime: result.executionTime,\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'QUERY_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to execute query',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * POST /api/execute\n   * Execute a write operation (INSERT, UPDATE, DELETE, etc.)\n   */\n  fastify.post<{\n    Body: ExecuteRequest;\n    Reply: ApiResponse<QueryResult>;\n  }>('/api/execute', {\n    schema: {\n      body: {\n        type: 'object',\n        required: ['sessionId', 'query'],\n        properties: {\n          sessionId: { type: 'string' },\n          query: { type: 'string' },\n          params: { type: 'array' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, query, params } = request.body;\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Execute query (validation happens in service)\n      const result = await service.executeQuery(query, params);\n\n      return {\n        success: true,\n        data: result,\n        metadata: {\n          executionTime: result.executionTime,\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'EXECUTE_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to execute operation',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n}\n"
  },
  {
    "path": "src/http/routes/schema.ts",
    "content": "/**\n * Schema Routes\n * Database schema and table information endpoints\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport type { TablesResponse, ApiResponse } from '../../types/http.js';\nimport type { SchemaInfo, TableInfo, EnumValuesResult, SampleDataResult } from '../../types/adapter.js';\nimport { ConnectionManager } from '../../core/connection-manager.js';\nimport type { SchemaCacheStats } from '../../core/database-service.js';\n\n/**\n * Schema 响应（包含缓存信息）\n */\ninterface SchemaWithCacheInfo extends SchemaInfo {\n  _cacheInfo?: {\n    cached: boolean;\n    cachedAt?: string;\n    hitRate: string;\n  };\n}\n\n/**\n * 缓存状态响应\n */\ninterface CacheStatusResponse {\n  sessionId: string;\n  cache: SchemaCacheStats;\n  hitRate: string;\n}\n\nexport async function setupSchemaRoutes(\n  fastify: FastifyInstance,\n  connectionManager: ConnectionManager\n): Promise<void> {\n  /**\n   * GET /api/tables\n   * List all tables in the database\n   */\n  fastify.get<{\n    Querystring: { sessionId: string; forceRefresh?: string };\n    Reply: ApiResponse<TablesResponse>;\n  }>('/api/tables', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n          forceRefresh: { type: 'string', description: '是否强制刷新缓存 (true/false)' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, forceRefresh } = request.query;\n      const shouldRefresh = forceRefresh === 'true';\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // List tables\n      const tables = await service.listTables(shouldRefresh);\n\n      return {\n        success: true,\n        data: { tables },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'LIST_TABLES_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to list tables',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * GET /api/schema\n   * Get complete database schema\n   */\n  fastify.get<{\n    Querystring: { sessionId: string; forceRefresh?: string };\n    Reply: ApiResponse<SchemaWithCacheInfo>;\n  }>('/api/schema', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n          forceRefresh: { type: 'string', description: '是否强制刷新缓存 (true/false)' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, forceRefresh } = request.query;\n      const shouldRefresh = forceRefresh === 'true';\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Get schema\n      const schema = await service.getSchema(shouldRefresh);\n\n      // Add cache info\n      const cacheStats = service.getCacheStats();\n      const response: SchemaWithCacheInfo = {\n        ...schema,\n        _cacheInfo: {\n          cached: cacheStats.isCached,\n          cachedAt: cacheStats.cachedAt?.toISOString(),\n          hitRate: service.getCacheHitRate() + '%',\n        },\n      };\n\n      return {\n        success: true,\n        data: response,\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'GET_SCHEMA_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to get schema',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * GET /api/schema/:table\n   * Get information about a specific table\n   */\n  fastify.get<{\n    Params: { table: string };\n    Querystring: { sessionId: string; forceRefresh?: string };\n    Reply: ApiResponse<TableInfo>;\n  }>('/api/schema/:table', {\n    schema: {\n      params: {\n        type: 'object',\n        properties: {\n          table: { type: 'string' },\n        },\n      },\n      querystring: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n          forceRefresh: { type: 'string', description: '是否强制刷新缓存 (true/false)' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { table } = request.params;\n      const { sessionId, forceRefresh } = request.query;\n      const shouldRefresh = forceRefresh === 'true';\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Get table info\n      const tableInfo = await service.getTableInfo(table, shouldRefresh);\n\n      return {\n        success: true,\n        data: tableInfo,\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'GET_TABLE_INFO_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to get table information',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * DELETE /api/cache\n   * Clear schema cache for a session\n   */\n  fastify.delete<{\n    Querystring: { sessionId: string };\n    Reply: ApiResponse<{ cleared: boolean; message: string }>;\n  }>('/api/cache', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId } = request.query;\n\n      // Get database service and clear cache\n      const service = connectionManager.getService(sessionId);\n      service.clearSchemaCache();\n\n      return {\n        success: true,\n        data: {\n          cleared: true,\n          message: 'Schema 缓存已清除',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'CLEAR_CACHE_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to clear cache',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * GET /api/cache/status\n   * Get cache status for a session\n   */\n  fastify.get<{\n    Querystring: { sessionId: string };\n    Reply: ApiResponse<CacheStatusResponse>;\n  }>('/api/cache/status', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId'],\n        properties: {\n          sessionId: { type: 'string' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId } = request.query;\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n      const cacheStats = service.getCacheStats();\n\n      return {\n        success: true,\n        data: {\n          sessionId,\n          cache: cacheStats,\n          hitRate: service.getCacheHitRate() + '%',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'GET_CACHE_STATUS_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to get cache status',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * GET /api/enum-values\n   * Get all unique values for a column (for enum-type columns)\n   */\n  fastify.get<{\n    Querystring: {\n      sessionId: string;\n      tableName: string;\n      columnName: string;\n      limit?: string;\n      includeCount?: string;\n    };\n    Reply: ApiResponse<EnumValuesResult>;\n  }>('/api/enum-values', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId', 'tableName', 'columnName'],\n        properties: {\n          sessionId: { type: 'string' },\n          tableName: { type: 'string', description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。' },\n          columnName: { type: 'string', description: '列名' },\n          limit: { type: 'string', description: '最大返回数量（默认 50，最大 100）' },\n          includeCount: { type: 'string', description: '是否包含每个值的出现次数 (true/false)' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, tableName, columnName, limit, includeCount } = request.query;\n      const limitNum = limit ? parseInt(limit, 10) : undefined;\n      const shouldIncludeCount = includeCount === 'true';\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Get enum values\n      const result = await service.getEnumValues(\n        tableName,\n        columnName,\n        limitNum,\n        shouldIncludeCount\n      );\n\n      return {\n        success: true,\n        data: result,\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'GET_ENUM_VALUES_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to get enum values',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n\n  /**\n   * GET /api/sample-data\n   * Get sample data from a table (with automatic data masking)\n   */\n  fastify.get<{\n    Querystring: {\n      sessionId: string;\n      tableName: string;\n      columns?: string;\n      limit?: string;\n    };\n    Reply: ApiResponse<SampleDataResult>;\n  }>('/api/sample-data', {\n    schema: {\n      querystring: {\n        type: 'object',\n        required: ['sessionId', 'tableName'],\n        properties: {\n          sessionId: { type: 'string' },\n          tableName: { type: 'string', description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。' },\n          columns: { type: 'string', description: '要查看的列（逗号分隔，可选）' },\n          limit: { type: 'string', description: '返回行数（默认 3，最大 10）' },\n        },\n      },\n    },\n  }, async (request, reply) => {\n    try {\n      const { sessionId, tableName, columns, limit } = request.query;\n      const limitNum = limit ? parseInt(limit, 10) : undefined;\n      const columnList = columns ? columns.split(',').map(c => c.trim()) : undefined;\n\n      // Get database service\n      const service = connectionManager.getService(sessionId);\n\n      // Get sample data\n      const result = await service.getSampleData(\n        tableName,\n        columnList,\n        limitNum\n      );\n\n      return {\n        success: true,\n        data: result,\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    } catch (error) {\n      reply.code(500);\n      return {\n        success: false,\n        error: {\n          code: 'GET_SAMPLE_DATA_FAILED',\n          message: error instanceof Error ? error.message : 'Failed to get sample data',\n        },\n        metadata: {\n          timestamp: new Date().toISOString(),\n          requestId: request.id,\n        },\n      };\n    }\n  });\n}\n"
  },
  {
    "path": "src/http/server.ts",
    "content": "/**\n * HTTP Server Setup\n * Fastify server configuration with middleware and routes\n */\n\nimport Fastify from 'fastify';\nimport cors from '@fastify/cors';\nimport rateLimit from '@fastify/rate-limit';\nimport type { AppConfig } from '../types/http.js';\nimport { ConnectionManager } from '../core/connection-manager.js';\nimport { authMiddleware, setupErrorHandler } from './middleware/index.js';\nimport { setupRoutes } from './routes/index.js';\n\n/**\n * Create and configure HTTP server\n */\nexport async function createHttpServer(config: AppConfig) {\n  // Create Fastify instance\n  const fastify = Fastify({\n    logger: {\n      level: config.http?.logging.level || 'info',\n      transport: config.http?.logging.pretty\n        ? {\n            target: 'pino-pretty',\n            options: {\n              translateTime: 'HH:MM:ss Z',\n              ignore: 'pid,hostname',\n            },\n          }\n        : undefined,\n    },\n    requestIdHeader: 'x-request-id',\n    trustProxy: true,\n  });\n\n  // Setup CORS\n  await fastify.register(cors, {\n    origin: config.http?.cors.origins || '*',\n    credentials: config.http?.cors.credentials || false,\n    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n    allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key', 'X-Request-ID'],\n  });\n\n  // Setup rate limiting\n  await fastify.register(rateLimit, {\n    max: config.http?.rateLimit.max || 100,\n    timeWindow: config.http?.rateLimit.window || '1m',\n    keyGenerator: (request) => {\n      // Use API key if available, otherwise use IP\n      return (request as any).apiKey || request.ip;\n    },\n    errorResponseBuilder: (request) => ({\n      success: false,\n      error: {\n        code: 'RATE_LIMIT_EXCEEDED',\n        message: 'Too many requests, please try again later',\n      },\n      metadata: {\n        timestamp: new Date().toISOString(),\n        requestId: request.id,\n      },\n    }),\n  });\n\n  // Setup authentication middleware\n  fastify.addHook('onRequest', async (request, reply) => {\n    await authMiddleware(request, reply, config);\n  });\n\n  // Create connection manager\n  const connectionManager = new ConnectionManager(\n    config.http?.session.timeout || 3600000,\n    config.http?.session.cleanupInterval || 300000\n  );\n\n  // Store connection manager in fastify instance for access in routes\n  fastify.decorate('connectionManager', connectionManager);\n\n  // Setup routes\n  await setupRoutes(fastify, connectionManager);\n\n  // Setup error handler\n  setupErrorHandler(fastify);\n\n  // Graceful shutdown handler\n  fastify.addHook('onClose', async () => {\n    await connectionManager.disconnectAll();\n  });\n\n  return fastify;\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "#!/usr/bin/env node\n\n/**\n * Universal Database MCP Server - Main Entry Point\n * Mode selector: MCP (stdio) or HTTP (REST API)\n */\n\nimport { loadConfig, validateConfig } from './utils/config-loader.js';\n\nasync function main() {\n  try {\n    // Load configuration from environment variables\n    const config = loadConfig();\n\n    // Validate configuration\n    validateConfig(config);\n\n    // Select mode based on configuration\n    if (config.mode === 'http') {\n      // HTTP API mode\n      console.log('🌐 Starting HTTP API mode...');\n      const { startHttpServer } = await import('./http/http-index.js');\n      await startHttpServer(config);\n    } else {\n      // MCP mode (default)\n      console.error('🔌 Starting MCP mode...');\n      const { startMcpServer } = await import('./mcp/mcp-index.js');\n      await startMcpServer();\n    }\n  } catch (error) {\n    console.error('❌ Failed to start server:', error instanceof Error ? error.message : String(error));\n    process.exit(1);\n  }\n}\n\nmain();\n"
  },
  {
    "path": "src/mcp/mcp-index.ts",
    "content": "#!/usr/bin/env node\n\n/**\n * MCP 数据库万能连接器 - MCP 模式入口\n */\n\nimport { Command } from 'commander';\nimport { DatabaseMCPServer } from './mcp-server.js';\nimport type { DbConfig, PermissionType, PermissionMode } from '../types/adapter.js';\nimport { createAdapter, normalizeDbType } from '../utils/adapter-factory.js';\nimport { resolvePermissions, formatPermissions } from '../utils/safety.js';\n\n/**\n * Start MCP server\n */\nexport async function startMcpServer(): Promise<void> {\n  const program = new Command();\n\n  program\n    .name('universal-db-mcp')\n    .description('MCP 数据库万能连接器 - 让 Claude Desktop 直接连接你的数据库')\n    .version('1.0.0')\n    .option('--type <type>', '数据库类型 (mysql|postgres|redis|oracle|dm|sqlserver|mssql|mongodb|sqlite|kingbase|gaussdb|opengauss|oceanbase|tidb|clickhouse|polardb|vastbase|highgo|goldendb)。不指定则以无连接模式启动，可在对话中通过 connect_database 动态连接。')\n    .option('--host <host>', '数据库主机地址')\n    .option('--port <port>', '数据库端口', parseInt)\n    .option('--user <user>', '用户名')\n    .option('--password <password>', '密码')\n    .option('--database <database>', '数据库名称')\n    .option('--file <file>', 'SQLite 数据库文件路径')\n    .option('--auth-source <authSource>', 'MongoDB 认证数据库（默认为 admin）')\n    .option('--oracle-client-path <path>', 'Oracle Instant Client 路径（启用 Thick 模式以支持 11g）')\n    .option('--danger-allow-write', '启用完全写入模式（危险！等价于 --permission-mode=full）', false)\n    .option('--permission-mode <mode>', '权限模式: safe(只读) | readwrite(读写不删) | full(完全控制)', 'safe')\n    .option('--permissions <list>', '自定义权限列表，逗号分隔: read,insert,update,delete,ddl')\n    .action(async (options) => {\n      try {\n        // 提取 graceful shutdown 逻辑为复用函数\n        function setupGracefulShutdown(server: DatabaseMCPServer): void {\n          let shuttingDown = false;\n\n          async function gracefulShutdown(reason: string): Promise<void> {\n            if (shuttingDown) return;\n            shuttingDown = true;\n\n            console.error(`\\n⏹️  正在关闭服务器 (${reason})...`);\n\n            try {\n              await Promise.race([\n                server.stop(),\n                new Promise<void>((resolve) => setTimeout(() => {\n                  console.error('⚠️  关闭超时，强制退出');\n                  resolve();\n                }, 5000)),\n              ]);\n            } catch (err) {\n              console.error('关闭过程中出错:', err instanceof Error ? err.message : String(err));\n            } finally {\n              process.exit(0);\n            }\n          }\n\n          // 信号处理\n          process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n          process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n\n          // stdin 关闭处理（核心修复）\n          // 当 MCP 客户端（如 Codex CLI）关闭 stdin 管道时触发\n          process.stdin.resume();\n          process.stdin.on('end', () => gracefulShutdown('stdin-end'));\n          process.stdin.on('close', () => gracefulShutdown('stdin-close'));\n        }\n\n        if (options.type) {\n          // === 有初始配置：和原来完全一样的逻辑 ===\n          // Normalize database type\n          const dbType = normalizeDbType(options.type);\n\n          // Parse permissions from command line\n          const parsedPermissions = options.permissions\n            ? options.permissions.split(',').map((p: string) => p.trim()) as PermissionType[]\n            : undefined;\n\n          // Build configuration\n          const config: DbConfig = {\n            type: dbType as any,\n            host: options.host,\n            port: options.port,\n            user: options.user,\n            password: options.password,\n            database: options.database,\n            filePath: options.file,\n            allowWrite: options.dangerAllowWrite,\n            permissionMode: options.dangerAllowWrite ? 'full' : options.permissionMode as PermissionMode,\n            permissions: parsedPermissions,\n          };\n\n          // Add MongoDB-specific config\n          if (dbType === 'mongodb' && options.authSource) {\n            (config as any).authSource = options.authSource;\n          }\n\n          // Add Oracle-specific config\n          if (dbType === 'oracle' && options.oracleClientPath) {\n            config.oracleClientPath = options.oracleClientPath;\n          }\n\n          // Resolve and display permissions\n          const permissions = resolvePermissions(config);\n          const isSafeMode = permissions.length === 1 && permissions[0] === 'read';\n\n          console.error('🔧 配置信息:');\n          console.error(`   数据库类型: ${config.type}`);\n          if (config.type === 'sqlite') {\n            console.error(`   数据库文件: ${config.filePath}`);\n          } else {\n            console.error(`   主机地址: ${config.host}:${config.port}`);\n            console.error(`   数据库名: ${config.database || '(默认)'}`);\n          }\n          console.error(`   权限模式: ${isSafeMode ? '✅ 只读模式' : '⚠️  ' + formatPermissions(permissions)}`);\n          console.error('');\n\n          // Create server\n          const server = new DatabaseMCPServer(config);\n\n          // Create adapter using factory\n          const adapter = createAdapter(config);\n\n          // Set adapter and start server\n          server.setAdapter(adapter);\n          await server.start();\n\n          setupGracefulShutdown(server);\n        } else {\n          // === 无初始配置：无连接模式启动 ===\n          console.error('📡 无连接模式：未指定数据库类型，等待通过 connect_database 工具动态连接...');\n          console.error('');\n\n          const server = new DatabaseMCPServer();\n          await server.start();\n\n          setupGracefulShutdown(server);\n        }\n      } catch (error) {\n        console.error('❌ 启动失败:', error instanceof Error ? error.message : String(error));\n        process.exit(1);\n      }\n    });\n\n  program.parse();\n}\n\n// If running directly (not imported)\nif (import.meta.url === `file://${process.argv[1]}`) {\n  startMcpServer();\n}\n"
  },
  {
    "path": "src/mcp/mcp-server.ts",
    "content": "#!/usr/bin/env node\n\n/**\n * MCP 数据库万能连接器 - 主服务器\n * 通过 Model Context Protocol 让 Claude Desktop 连接数据库\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n  CallToolRequestSchema,\n  ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { DbAdapter, DbConfig } from '../types/adapter.js';\nimport { DatabaseService, SchemaCacheConfig } from '../core/database-service.js';\nimport { createAdapter, normalizeDbType } from '../utils/adapter-factory.js';\n\n/**\n * 数据库 MCP 服务器类\n */\nexport class DatabaseMCPServer {\n  private server: Server;\n  private adapter: DbAdapter | null = null;\n  private config: DbConfig | null;\n  private databaseService: DatabaseService | null = null;\n  private cacheConfig: Partial<SchemaCacheConfig>;\n\n  constructor(config?: DbConfig, cacheConfig?: Partial<SchemaCacheConfig>) {\n    this.config = config || null;\n    this.cacheConfig = cacheConfig || {};\n    this.server = new Server(\n      {\n        name: 'universal-db-mcp',\n        version: '1.0.0',\n      },\n      {\n        capabilities: {\n          tools: {},\n        },\n      }\n    );\n\n    this.setupHandlers();\n  }\n\n  /**\n   * 设置 MCP 协议处理器\n   */\n  private setupHandlers(): void {\n    // 列出可用工具\n    this.server.setRequestHandler(ListToolsRequestSchema, async () => {\n      return {\n        tools: [\n          {\n            name: 'execute_query',\n            description: '执行 SQL 查询或数据库命令。支持 SELECT、JOIN、聚合等查询操作。如果启用了写入模式，也可以执行 INSERT、UPDATE、DELETE 等操作。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                query: {\n                  type: 'string',\n                  description: '要执行的 SQL 语句或数据库命令',\n                },\n                params: {\n                  type: 'array',\n                  description: '查询参数（可选，用于参数化查询防止 SQL 注入）',\n                  items: {\n                    type: 'string',\n                  },\n                },\n              },\n              required: ['query'],\n            },\n          },\n          {\n            name: 'get_schema',\n            description: '获取数据库结构信息，包括所有 Schema 中用户可访问的表名、列名、数据类型、主键、索引等元数据。在执行查询前调用此工具可以帮助理解数据库结构。结果会被缓存以提高性能。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                forceRefresh: {\n                  type: 'boolean',\n                  description: '是否强制刷新缓存（可选，默认 false）。设为 true 可获取最新的数据库结构。',\n                },\n              },\n            },\n          },\n          {\n            name: 'get_table_info',\n            description: '获取指定表的详细信息，包括列定义、索引、预估行数等。用于深入了解某个表的结构。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                tableName: {\n                  type: 'string',\n                  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。不指定 Schema 时查询默认 Schema。',\n                },\n                forceRefresh: {\n                  type: 'boolean',\n                  description: '是否强制刷新缓存（可选，默认 false）',\n                },\n              },\n              required: ['tableName'],\n            },\n          },\n          {\n            name: 'clear_cache',\n            description: '清除 Schema 缓存。当数据库结构发生变化（如新增表、修改列）时，可以调用此工具清除缓存。',\n            inputSchema: {\n              type: 'object',\n              properties: {},\n            },\n          },\n          {\n            name: 'get_enum_values',\n            description: '获取指定列的所有唯一值。用于了解 status、type、category 等枚举类型列的所有可能值，帮助生成准确的 WHERE 条件。例如：获取 orders.status 列的所有状态值（pending, shipped, delivered 等）。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                tableName: {\n                  type: 'string',\n                  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。',\n                },\n                columnName: {\n                  type: 'string',\n                  description: '列名（通常是 status、type、category 等枚举类型的列）',\n                },\n                limit: {\n                  type: 'number',\n                  description: '最大返回数量（可选，默认 50，最大 100）。如果唯一值超过此数量，说明该列可能不是枚举类型。',\n                },\n                includeCount: {\n                  type: 'boolean',\n                  description: '是否包含每个值的出现次数（可选，默认 false）。设为 true 可了解数据分布。',\n                },\n              },\n              required: ['tableName', 'columnName'],\n            },\n          },\n          {\n            name: 'get_sample_data',\n            description: '获取表的示例数据（已自动脱敏）。用于了解数据格式，如日期格式（2024-01-01 vs 20240101）、ID格式（UUID vs 自增）、金额精度等。敏感数据（手机号、邮箱、身份证等）会自动脱敏保护隐私。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                tableName: {\n                  type: 'string',\n                  description: '表名。支持 schema.table_name 格式指定 Schema（如 analytics.users）。',\n                },\n                columns: {\n                  type: 'array',\n                  items: { type: 'string' },\n                  description: '要查看的列（可选，默认全部列）',\n                },\n                limit: {\n                  type: 'number',\n                  description: '返回行数（可选，默认 3，最大 10）',\n                },\n              },\n              required: ['tableName'],\n            },\n          },\n          {\n            name: 'connect_database',\n            description: '连接到数据库。支持动态指定数据库类型和连接参数，无需重启服务。如果当前已有连接，会自动断开旧连接再建立新连接。支持的数据库类型：mysql, postgres, redis, oracle, dm, sqlserver, mongodb, sqlite, kingbase, gaussdb, oceanbase, tidb, clickhouse, polardb, vastbase, highgo, goldendb。',\n            inputSchema: {\n              type: 'object',\n              properties: {\n                type: {\n                  type: 'string',\n                  description: '数据库类型',\n                  enum: [\n                    'mysql', 'postgres', 'redis', 'oracle', 'dm', 'sqlserver',\n                    'mongodb', 'sqlite', 'kingbase', 'gaussdb', 'oceanbase',\n                    'tidb', 'clickhouse', 'polardb', 'vastbase', 'highgo', 'goldendb',\n                  ],\n                },\n                host: { type: 'string', description: '数据库主机地址' },\n                port: { type: 'number', description: '数据库端口' },\n                user: { type: 'string', description: '用户名' },\n                password: { type: 'string', description: '密码' },\n                database: { type: 'string', description: '数据库名称' },\n                filePath: { type: 'string', description: 'SQLite 数据库文件路径' },\n                allowWrite: { type: 'boolean', description: '是否允许写操作（默认 false）' },\n                permissionMode: {\n                  type: 'string',\n                  description: '权限模式: safe(只读) | readwrite(读写不删) | full(完全控制)',\n                  enum: ['safe', 'readwrite', 'full'],\n                },\n                authSource: { type: 'string', description: 'MongoDB 认证数据库（默认 admin）' },\n                oracleClientPath: { type: 'string', description: 'Oracle Instant Client 路径' },\n              },\n              required: ['type'],\n            },\n          },\n          {\n            name: 'disconnect_database',\n            description: '断开当前数据库连接。断开后需要重新调用 connect_database 才能执行查询。',\n            inputSchema: {\n              type: 'object',\n              properties: {},\n            },\n          },\n          {\n            name: 'get_connection_status',\n            description: '获取当前数据库连接状态。返回是否已连接、数据库类型、地址、数据库名、权限模式等信息。',\n            inputSchema: {\n              type: 'object',\n              properties: {},\n            },\n          },\n        ],\n      };\n    });\n\n    // 处理工具调用\n    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n      const { name, arguments: args } = request.params;\n\n      try {\n        // 连接管理类 tool 不需要检查数据库连接\n        switch (name) {\n          case 'connect_database': {\n            const {\n              type, host, port, user, password, database,\n              filePath, allowWrite, permissionMode, authSource, oracleClientPath,\n            } = args as Record<string, any>;\n\n            // 构建新配置\n            const newConfig: DbConfig = {\n              type: normalizeDbType(type),\n              host,\n              port,\n              user,\n              password,\n              database,\n              filePath,\n              allowWrite: allowWrite || false,\n              permissionMode: permissionMode || 'safe',\n            };\n\n            // MongoDB 特殊配置\n            if (newConfig.type === 'mongodb' && authSource) {\n              (newConfig as any).authSource = authSource;\n            }\n\n            // Oracle 特殊配置\n            if (newConfig.type === 'oracle' && oracleClientPath) {\n              newConfig.oracleClientPath = oracleClientPath;\n            }\n\n            // 断开旧连接\n            if (this.adapter) {\n              console.error('🔄 断开旧数据库连接...');\n              if (this.databaseService) {\n                this.databaseService.clearSchemaCache();\n              }\n              await this.adapter.disconnect();\n              this.adapter = null;\n              this.databaseService = null;\n            }\n\n            // 建立新连接\n            console.error(`🔌 正在连接 ${newConfig.type} 数据库...`);\n            const newAdapter = createAdapter(newConfig);\n            await newAdapter.connect();\n\n            this.adapter = newAdapter;\n            this.config = newConfig;\n            this.databaseService = new DatabaseService(newAdapter, newConfig, this.cacheConfig);\n\n            const connInfo = newConfig.type === 'sqlite'\n              ? `SQLite: ${newConfig.filePath}`\n              : `${newConfig.type}: ${newConfig.host}:${newConfig.port}/${newConfig.database || '(default)'}`;\n\n            console.error(`✅ 数据库连接成功: ${connInfo}`);\n\n            return {\n              content: [{\n                type: 'text',\n                text: JSON.stringify({\n                  success: true,\n                  message: `已成功连接到 ${connInfo}`,\n                  connection: {\n                    type: newConfig.type,\n                    host: newConfig.host,\n                    port: newConfig.port,\n                    database: newConfig.database,\n                    permissionMode: newConfig.permissionMode || 'safe',\n                  },\n                }, null, 2),\n              }],\n            };\n          }\n\n          case 'disconnect_database': {\n            if (!this.adapter) {\n              return {\n                content: [{\n                  type: 'text',\n                  text: JSON.stringify({ success: true, message: '当前没有活跃的数据库连接' }, null, 2),\n                }],\n              };\n            }\n\n            if (this.databaseService) {\n              this.databaseService.clearSchemaCache();\n            }\n            await this.adapter.disconnect();\n\n            const oldType = this.config?.type;\n            this.adapter = null;\n            this.config = null;\n            this.databaseService = null;\n\n            console.error('👋 数据库连接已断开');\n\n            return {\n              content: [{\n                type: 'text',\n                text: JSON.stringify({\n                  success: true,\n                  message: `已断开 ${oldType || ''} 数据库连接`,\n                }, null, 2),\n              }],\n            };\n          }\n\n          case 'get_connection_status': {\n            if (!this.adapter || !this.config) {\n              return {\n                content: [{\n                  type: 'text',\n                  text: JSON.stringify({\n                    connected: false,\n                    message: '当前未连接任何数据库。请使用 connect_database 工具连接。',\n                  }, null, 2),\n                }],\n              };\n            }\n\n            const status: Record<string, any> = {\n              connected: true,\n              type: this.config.type,\n              permissionMode: this.config.permissionMode || 'safe',\n            };\n\n            if (this.config.type === 'sqlite') {\n              status.filePath = this.config.filePath;\n            } else {\n              status.host = this.config.host;\n              status.port = this.config.port;\n              status.database = this.config.database;\n            }\n\n            if (this.databaseService) {\n              const cacheStats = this.databaseService.getCacheStats();\n              status.schemaCache = {\n                cached: cacheStats.isCached,\n                hitRate: this.databaseService.getCacheHitRate() + '%',\n              };\n            }\n\n            return {\n              content: [{\n                type: 'text',\n                text: JSON.stringify(status, null, 2),\n              }],\n            };\n          }\n\n          default:\n            break;\n        }\n\n        // 以下 tool 需要数据库已连接\n        if (!this.databaseService) {\n          throw new Error('数据库未连接。请先使用 connect_database 工具连接数据库。');\n        }\n\n        switch (name) {\n          case 'execute_query': {\n            const { query, params } = args as { query: string; params?: unknown[] };\n\n            console.error(`📊 执行查询: ${query.substring(0, 100)}...`);\n\n            const result = await this.databaseService.executeQuery(query, params);\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify(result, null, 2),\n                },\n              ],\n            };\n          }\n\n          case 'get_schema': {\n            const { forceRefresh } = (args as { forceRefresh?: boolean }) || {};\n\n            console.error('📋 获取数据库结构...');\n\n            const schema = await this.databaseService.getSchema(forceRefresh);\n\n            // 添加缓存状态信息\n            const cacheStats = this.databaseService.getCacheStats();\n            const response = {\n              ...schema,\n              _cacheInfo: {\n                cached: cacheStats.isCached,\n                cachedAt: cacheStats.cachedAt?.toISOString(),\n                hitRate: this.databaseService.getCacheHitRate() + '%',\n              },\n            };\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify(response, null, 2),\n                },\n              ],\n            };\n          }\n\n          case 'get_table_info': {\n            const { tableName, forceRefresh } = args as { tableName: string; forceRefresh?: boolean };\n\n            console.error(`📄 获取表信息: ${tableName}`);\n\n            const table = await this.databaseService.getTableInfo(tableName, forceRefresh);\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify(table, null, 2),\n                },\n              ],\n            };\n          }\n\n          case 'clear_cache': {\n            console.error('🗑️ 清除 Schema 缓存...');\n\n            this.databaseService.clearSchemaCache();\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify({\n                    success: true,\n                    message: 'Schema 缓存已清除',\n                  }, null, 2),\n                },\n              ],\n            };\n          }\n\n          case 'get_enum_values': {\n            const { tableName, columnName, limit, includeCount } = args as {\n              tableName: string;\n              columnName: string;\n              limit?: number;\n              includeCount?: boolean;\n            };\n\n            console.error(`🔢 获取枚举值: ${tableName}.${columnName}`);\n\n            const result = await this.databaseService.getEnumValues(\n              tableName,\n              columnName,\n              limit,\n              includeCount\n            );\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify(result, null, 2),\n                },\n              ],\n            };\n          }\n\n          case 'get_sample_data': {\n            const { tableName, columns, limit } = args as {\n              tableName: string;\n              columns?: string[];\n              limit?: number;\n            };\n\n            console.error(`📝 获取示例数据: ${tableName}`);\n\n            const result = await this.databaseService.getSampleData(\n              tableName,\n              columns,\n              limit\n            );\n\n            return {\n              content: [\n                {\n                  type: 'text',\n                  text: JSON.stringify(result, null, 2),\n                },\n              ],\n            };\n          }\n\n          default:\n            throw new Error(`未知工具: ${name}`);\n        }\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        console.error(`❌ 错误: ${errorMessage}`);\n\n        return {\n          content: [\n            {\n              type: 'text',\n              text: `执行失败: ${errorMessage}`,\n            },\n          ],\n          isError: true,\n        };\n      }\n    });\n  }\n\n  /**\n   * 设置数据库适配器\n   */\n  setAdapter(adapter: DbAdapter): void {\n    this.adapter = adapter;\n    if (this.config) {\n      this.databaseService = new DatabaseService(adapter, this.config, this.cacheConfig);\n    }\n  }\n\n  /**\n   * 获取 MCP Server 实例（用于 SSE/HTTP 传输）\n   */\n  getServer(): Server {\n    return this.server;\n  }\n\n  /**\n   * 连接数据库（不启动传输层）\n   */\n  async connectDatabase(): Promise<void> {\n    if (!this.adapter) {\n      throw new Error('必须先设置数据库适配器才能连接数据库');\n    }\n\n    // 连接数据库\n    console.error('🔌 正在连接数据库...');\n    await this.adapter.connect();\n    console.error('✅ 数据库连接成功');\n\n    // 显示安全模式状态\n    if (this.config?.allowWrite) {\n      console.error('⚠️  警告: 写入模式已启用，请谨慎操作！');\n    } else {\n      console.error('🛡️  安全模式: 只读模式（推荐）');\n    }\n\n    // 显示缓存配置\n    console.error('📦 Schema 缓存已启用 (默认 TTL: 5 分钟)');\n  }\n\n  /**\n   * 使用指定的传输层连接 MCP 服务器\n   */\n  async connect(transport: Transport): Promise<void> {\n    await this.server.connect(transport);\n  }\n\n  /**\n   * 启动服务器（使用 stdio 传输，用于 Claude Desktop）\n   */\n  async start(): Promise<void> {\n    // 如果有初始配置和适配器，先连接；否则等待 AI 调用 connect_database\n    if (this.adapter) {\n      await this.connectDatabase();\n    } else {\n      console.error('📡 MCP 服务器以无连接模式启动，等待通过 connect_database 工具连接数据库...');\n    }\n\n    // 启动 MCP 服务器（stdio 模式）\n    const transport = new StdioServerTransport();\n    await this.server.connect(transport);\n\n    console.error('🚀 MCP 服务器已启动，等待客户端连接...');\n  }\n\n  /**\n   * 停止服务器\n   */\n  async stop(): Promise<void> {\n    // 1. 关闭 MCP Server（释放 transport 层资源：stdin/stdout 监听器等）\n    try {\n      await this.server.close();\n    } catch (err) {\n      console.error('关闭 MCP Server 时出错:', err instanceof Error ? err.message : String(err));\n    }\n\n    // 2. 清理 Schema 缓存\n    if (this.databaseService) {\n      this.databaseService.clearSchemaCache();\n    }\n\n    // 3. 断开数据库连接\n    if (this.adapter) {\n      await this.adapter.disconnect();\n      console.error('👋 数据库连接已关闭');\n    }\n  }\n}\n"
  },
  {
    "path": "src/server.ts",
    "content": "/**\n * Backward Compatibility Shim\n * Re-exports DatabaseMCPServer from mcp/mcp-server.ts\n * This maintains compatibility with any external code that imports from server.ts\n */\n\nexport { DatabaseMCPServer } from './mcp/mcp-server.js';\n"
  },
  {
    "path": "src/test.ts",
    "content": "#!/usr/bin/env node\n\n/**\n * 测试脚本 - 验证各个适配器的基本功能\n * 注意：此脚本仅用于开发测试，不会包含在最终发布中\n */\n\nimport { MySQLAdapter } from './adapters/mysql.js';\nimport { PostgreSQLAdapter } from './adapters/postgres.js';\nimport { RedisAdapter } from './adapters/redis.js';\nimport { OracleAdapter } from './adapters/oracle.js';\nimport { DMAdapter } from './adapters/dm.js';\n\nasync function testMySQL() {\n  console.log('\\n=== 测试 MySQL 适配器 ===\\n');\n\n  const adapter = new MySQLAdapter({\n    host: 'localhost',\n    port: 3306,\n    user: 'root',\n    password: 'password',\n    database: 'test',\n  });\n\n  try {\n    console.log('1. 连接数据库...');\n    await adapter.connect();\n    console.log('✅ 连接成功');\n\n    console.log('\\n2. 获取数据库结构...');\n    const schema = await adapter.getSchema();\n    console.log(`✅ 数据库: ${schema.databaseName}`);\n    console.log(`✅ 版本: ${schema.version}`);\n    console.log(`✅ 表数量: ${schema.tables.length}`);\n\n    if (schema.tables.length > 0) {\n      console.log(`\\n3. 查看第一个表: ${schema.tables[0].name}`);\n      console.log(`   列数: ${schema.tables[0].columns.length}`);\n      console.log(`   主键: ${schema.tables[0].primaryKeys.join(', ')}`);\n    }\n\n    console.log('\\n4. 执行简单查询...');\n    const result = await adapter.executeQuery('SELECT 1 as test');\n    console.log(`✅ 查询成功，返回 ${result.rows.length} 行`);\n    console.log(`   执行时间: ${result.executionTime}ms`);\n\n    console.log('\\n5. 测试写操作检测...');\n    console.log(`   SELECT 是写操作? ${adapter.isWriteOperation('SELECT * FROM users')}`);\n    console.log(`   DELETE 是写操作? ${adapter.isWriteOperation('DELETE FROM users')}`);\n\n    await adapter.disconnect();\n    console.log('\\n✅ MySQL 测试完成');\n  } catch (error) {\n    console.error('❌ MySQL 测试失败:', error instanceof Error ? error.message : String(error));\n  }\n}\n\nasync function testPostgreSQL() {\n  console.log('\\n=== 测试 PostgreSQL 适配器 ===\\n');\n\n  const adapter = new PostgreSQLAdapter({\n    host: 'localhost',\n    port: 5432,\n    user: 'postgres',\n    password: 'password',\n    database: 'test',\n  });\n\n  try {\n    console.log('1. 连接数据库...');\n    await adapter.connect();\n    console.log('✅ 连接成功');\n\n    console.log('\\n2. 获取数据库结构...');\n    const schema = await adapter.getSchema();\n    console.log(`✅ 数据库: ${schema.databaseName}`);\n    console.log(`✅ 版本: ${schema.version}`);\n    console.log(`✅ 表数量: ${schema.tables.length}`);\n\n    console.log('\\n3. 执行简单查询...');\n    const result = await adapter.executeQuery('SELECT 1 as test');\n    console.log(`✅ 查询成功，返回 ${result.rows.length} 行`);\n    console.log(`   执行时间: ${result.executionTime}ms`);\n\n    await adapter.disconnect();\n    console.log('\\n✅ PostgreSQL 测试完成');\n  } catch (error) {\n    console.error('❌ PostgreSQL 测试失败:', error instanceof Error ? error.message : String(error));\n  }\n}\n\nasync function testRedis() {\n  console.log('\\n=== 测试 Redis 适配器 ===\\n');\n\n  const adapter = new RedisAdapter({\n    host: 'localhost',\n    port: 6379,\n  });\n\n  try {\n    console.log('1. 连接数据库...');\n    await adapter.connect();\n    console.log('✅ 连接成功');\n\n    console.log('\\n2. 获取数据库信息...');\n    const schema = await adapter.getSchema();\n    console.log(`✅ 数据库: ${schema.databaseName}`);\n    console.log(`✅ 版本: ${schema.version}`);\n    console.log(`✅ 键类型数量: ${schema.tables.length}`);\n\n    console.log('\\n3. 执行 PING 命令...');\n    const result = await adapter.executeQuery('PING');\n    console.log(`✅ 命令成功，结果:`, result.rows);\n\n    console.log('\\n4. 测试写操作检测...');\n    console.log(`   GET 是写操作? ${adapter.isWriteOperation('GET mykey')}`);\n    console.log(`   SET 是写操作? ${adapter.isWriteOperation('SET mykey value')}`);\n    console.log(`   DEL 是写操作? ${adapter.isWriteOperation('DEL mykey')}`);\n\n    await adapter.disconnect();\n    console.log('\\n✅ Redis 测试完成');\n  } catch (error) {\n    console.error('❌ Redis 测试失败:', error instanceof Error ? error.message : String(error));\n  }\n}\n\nasync function testOracle() {\n  console.log('\\n=== 测试 Oracle 适配器 ===\\n');\n\n  const adapter = new OracleAdapter({\n    host: 'localhost',\n    port: 1521,\n    user: 'system',\n    password: 'password',\n    database: 'XEPDB1',\n  });\n\n  try {\n    console.log('1. 连接数据库...');\n    await adapter.connect();\n    console.log('✅ 连接成功');\n\n    console.log('\\n2. 获取数据库结构...');\n    const schema = await adapter.getSchema();\n    console.log(`✅ 数据库: ${schema.databaseName}`);\n    console.log(`✅ 版本: ${schema.version}`);\n    console.log(`✅ 表数量: ${schema.tables.length}`);\n\n    if (schema.tables.length > 0) {\n      console.log(`\\n3. 查看第一个表: ${schema.tables[0].name}`);\n      console.log(`   列数: ${schema.tables[0].columns.length}`);\n      console.log(`   主键: ${schema.tables[0].primaryKeys.join(', ')}`);\n    }\n\n    console.log('\\n4. 执行简单查询...');\n    const result = await adapter.executeQuery('SELECT 1 FROM DUAL');\n    console.log(`✅ 查询成功，返回 ${result.rows.length} 行`);\n    console.log(`   执行时间: ${result.executionTime}ms`);\n\n    console.log('\\n5. 测试写操作检测...');\n    console.log(`   SELECT 是写操作? ${adapter.isWriteOperation('SELECT * FROM users')}`);\n    console.log(`   DELETE 是写操作? ${adapter.isWriteOperation('DELETE FROM users')}`);\n    console.log(`   MERGE 是写操作? ${adapter.isWriteOperation('MERGE INTO users...')}`);\n\n    await adapter.disconnect();\n    console.log('\\n✅ Oracle 测试完成');\n  } catch (error) {\n    console.error('❌ Oracle 测试失败:', error instanceof Error ? error.message : String(error));\n  }\n}\n\nasync function testDM() {\n  console.log('\\n=== 测试达梦数据库适配器 ===\\n');\n\n  const adapter = new DMAdapter({\n    host: 'localhost',\n    port: 5236,\n    user: 'SYSDBA',\n    password: 'SYSDBA',\n    database: 'DAMENG',\n  });\n\n  try {\n    console.log('1. 连接数据库...');\n    await adapter.connect();\n    console.log('✅ 连接成功');\n\n    console.log('\\n2. 获取数据库结构...');\n    const schema = await adapter.getSchema();\n    console.log(`✅ 数据库: ${schema.databaseName}`);\n    console.log(`✅ 版本: ${schema.version}`);\n    console.log(`✅ 表数量: ${schema.tables.length}`);\n\n    if (schema.tables.length > 0) {\n      console.log(`\\n3. 查看第一个表: ${schema.tables[0].name}`);\n      console.log(`   列数: ${schema.tables[0].columns.length}`);\n      console.log(`   主键: ${schema.tables[0].primaryKeys.join(', ')}`);\n    }\n\n    console.log('\\n4. 执行简单查询...');\n    const result = await adapter.executeQuery('SELECT 1 FROM DUAL');\n    console.log(`✅ 查询成功，返回 ${result.rows.length} 行`);\n    console.log(`   执行时间: ${result.executionTime}ms`);\n\n    console.log('\\n5. 测试写操作检测...');\n    console.log(`   SELECT 是写操作? ${adapter.isWriteOperation('SELECT * FROM users')}`);\n    console.log(`   DELETE 是写操作? ${adapter.isWriteOperation('DELETE FROM users')}`);\n    console.log(`   MERGE 是写操作? ${adapter.isWriteOperation('MERGE INTO users...')}`);\n\n    await adapter.disconnect();\n    console.log('\\n✅ 达梦数据库测试完成');\n  } catch (error) {\n    console.error('❌ 达梦数据库测试失败:', error instanceof Error ? error.message : String(error));\n  }\n}\n\n// 主函数\nasync function main() {\n  console.log('🧪 MCP 数据库万能连接器 - 适配器测试\\n');\n  console.log('注意：此测试需要本地运行相应的数据库服务\\n');\n\n  const args = process.argv.slice(2);\n\n  if (args.length === 0 || args.includes('mysql')) {\n    await testMySQL();\n  }\n\n  if (args.length === 0 || args.includes('postgres')) {\n    await testPostgreSQL();\n  }\n\n  if (args.length === 0 || args.includes('redis')) {\n    await testRedis();\n  }\n\n  if (args.length === 0 || args.includes('oracle')) {\n    await testOracle();\n  }\n\n  if (args.length === 0 || args.includes('dm')) {\n    await testDM();\n  }\n\n  console.log('\\n✅ 所有测试完成\\n');\n}\n\nmain().catch(error => {\n  console.error('❌ 测试失败:', error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "src/types/adapter.ts",
    "content": "/**\n * 数据库适配器接口\n * 所有数据库实现都必须遵循此接口，确保统一的调用方式\n */\n\nexport interface DbAdapter {\n  /**\n   * 连接到数据库\n   * @throws 连接失败时抛出错误\n   */\n  connect(): Promise<void>;\n\n  /**\n   * 断开数据库连接\n   */\n  disconnect(): Promise<void>;\n\n  /**\n   * 执行查询语句\n   * @param query - SQL 查询语句、Redis 命令或 MongoDB 查询\n   * @param params - 查询参数（用于防止 SQL 注入）\n   * @returns 查询结果\n   */\n  executeQuery(query: string, params?: unknown[]): Promise<QueryResult>;\n\n  /**\n   * 获取数据库结构信息\n   * @returns 数据库的表结构、索引等元数据\n   */\n  getSchema(): Promise<SchemaInfo>;\n\n  /**\n   * 检查查询是否为写操作\n   * @param query - 待检查的查询语句\n   * @returns 如果是写操作返回 true\n   */\n  isWriteOperation(query: string): boolean;\n}\n\n/**\n * 查询结果接口\n */\nexport interface QueryResult {\n  /** 查询返回的行数据 */\n  rows: Record<string, unknown>[];\n  /** 受影响的行数（用于 INSERT/UPDATE/DELETE） */\n  affectedRows?: number;\n  /** 执行时间（毫秒） */\n  executionTime?: number;\n  /** 额外的元数据 */\n  metadata?: Record<string, unknown>;\n}\n\n/**\n * 数据库结构信息\n */\nexport interface SchemaInfo {\n  /** 数据库类型 */\n  databaseType: 'mysql' | 'postgres' | 'redis' | 'oracle' | 'dm' | 'sqlserver' | 'mongodb' | 'sqlite' | 'kingbase' | 'gaussdb' | 'oceanbase' | 'tidb' | 'clickhouse' | 'polardb' | 'vastbase' | 'highgo' | 'goldendb';\n  /** 数据库名称 */\n  databaseName: string;\n  /** 表信息列表 */\n  tables: TableInfo[];\n  /** 数据库版本 */\n  version?: string;\n  /** 表间关系（全局视图，方便 LLM 理解表关联） */\n  relationships?: RelationshipInfo[];\n}\n\n/**\n * 表结构信息\n */\nexport interface TableInfo {\n  /** 表名（非默认 schema 时格式为 schema.table_name） */\n  name: string;\n  /** 所属 Schema（PG=schema, Oracle/DM=owner, SQLServer=schema） */\n  schema?: string;\n  /** 表注释/描述 */\n  comment?: string;\n  /** 列信息 */\n  columns: ColumnInfo[];\n  /** 主键列名 */\n  primaryKeys: string[];\n  /** 索引信息 */\n  indexes?: IndexInfo[];\n  /** 外键信息 */\n  foreignKeys?: ForeignKeyInfo[];\n  /** 预估行数 */\n  estimatedRows?: number;\n}\n\n/**\n * 列信息\n */\nexport interface ColumnInfo {\n  /** 列名 */\n  name: string;\n  /** 数据类型 */\n  type: string;\n  /** 是否可为空 */\n  nullable: boolean;\n  /** 默认值 */\n  defaultValue?: string;\n  /** 注释说明 */\n  comment?: string;\n}\n\n/**\n * 索引信息\n */\nexport interface IndexInfo {\n  /** 索引名称 */\n  name: string;\n  /** 索引列 */\n  columns: string[];\n  /** 是否唯一索引 */\n  unique: boolean;\n}\n\n/**\n * 外键信息\n */\nexport interface ForeignKeyInfo {\n  /** 外键约束名称 */\n  name: string;\n  /** 本表的外键列 */\n  columns: string[];\n  /** 引用的表名 */\n  referencedTable: string;\n  /** 引用的列名 */\n  referencedColumns: string[];\n  /** 删除时的动作 (CASCADE, SET NULL, NO ACTION, RESTRICT) */\n  onDelete?: string;\n  /** 更新时的动作 (CASCADE, SET NULL, NO ACTION, RESTRICT) */\n  onUpdate?: string;\n}\n\n/**\n * 表间关系信息（全局视图）\n */\nexport interface RelationshipInfo {\n  /** 源表名 */\n  fromTable: string;\n  /** 源表的外键列 */\n  fromColumns: string[];\n  /** 目标表名 */\n  toTable: string;\n  /** 目标表的被引用列 */\n  toColumns: string[];\n  /** 关系类型 */\n  type: 'one-to-one' | 'one-to-many' | 'many-to-one';\n  /** 外键约束名称 */\n  constraintName?: string;\n  /** 关系来源：foreign_key=显式外键约束, inferred=基于命名规则推断 */\n  source?: 'foreign_key' | 'inferred';\n  /** 推断置信度 (0-1)，仅当 source='inferred' 时有效 */\n  confidence?: number;\n}\n\n/**\n * 权限类型\n */\nexport type PermissionType = 'read' | 'insert' | 'update' | 'delete' | 'ddl';\n\n/**\n * 权限模式\n */\nexport type PermissionMode = 'safe' | 'readwrite' | 'full' | 'custom';\n\n/**\n * 数据库连接配置\n */\nexport interface DbConfig {\n  type: 'mysql' | 'postgres' | 'redis' | 'oracle' | 'dm' | 'sqlserver' | 'mongodb' | 'sqlite' | 'kingbase' | 'gaussdb' | 'oceanbase' | 'tidb' | 'clickhouse' | 'polardb' | 'vastbase' | 'highgo' | 'goldendb';\n  host?: string;\n  port?: number;\n  user?: string;\n  password?: string;\n  database?: string;\n  /** SQLite 数据库文件路径 */\n  filePath?: string;\n  /** 是否允许写操作（默认 false，只读模式）- 向后兼容，推荐使用 permissionMode */\n  allowWrite?: boolean;\n  /** 权限模式：safe=只读, readwrite=读写不删, full=完全控制, custom=自定义 */\n  permissionMode?: PermissionMode;\n  /** 自定义权限列表，当 permissionMode='custom' 或直接指定时生效 */\n  permissions?: PermissionType[];\n  /** Oracle Instant Client 路径（启用 Thick 模式以支持 11g） */\n  oracleClientPath?: string;\n}\n\n/**\n * 枚举值查询结果\n * 用于 get_enum_values 工具返回\n */\nexport interface EnumValuesResult {\n  /** 表名 */\n  tableName: string;\n  /** 列名 */\n  columnName: string;\n  /** 所有唯一值 */\n  values: (string | number | null)[];\n  /** 唯一值总数 */\n  totalCount: number;\n  /** 是否适合作为枚举（唯一值数量 < limit，说明值是有限的） */\n  isEnum: boolean;\n  /** 每个值的出现次数（可选，当 includeCount=true 时返回） */\n  valueCounts?: Record<string, number>;\n  /** 列的数据类型 */\n  columnType?: string;\n}\n\n/**\n * 示例数据查询结果\n * 用于 get_sample_data 工具返回\n */\nexport interface SampleDataResult {\n  /** 表名 */\n  tableName: string;\n  /** 返回的列 */\n  columns: string[];\n  /** 示例数据行（已脱敏） */\n  rows: Record<string, unknown>[];\n  /** 返回行数 */\n  rowCount: number;\n  /** 是否已脱敏 */\n  masked: boolean;\n  /** 脱敏的列（仅当有列被脱敏时返回） */\n  maskedColumns?: string[];\n}\n"
  },
  {
    "path": "src/types/http.ts",
    "content": "/**\n * HTTP API Type Definitions\n * Types specific to HTTP API mode\n */\n\nimport type { DbConfig } from './adapter.js';\n\n/**\n * HTTP Server Configuration\n */\nexport interface HttpConfig {\n  port: number;\n  host: string;\n  apiKeys: string[];\n  cors: CorsConfig;\n  rateLimit: RateLimitConfig;\n  logging: LoggingConfig;\n  session: SessionConfig;\n}\n\n/**\n * CORS Configuration\n */\nexport interface CorsConfig {\n  origins: string | string[];\n  credentials: boolean;\n}\n\n/**\n * Rate Limiting Configuration\n */\nexport interface RateLimitConfig {\n  max: number;\n  window: string;\n}\n\n/**\n * Logging Configuration\n */\nexport interface LoggingConfig {\n  level: 'debug' | 'info' | 'warn' | 'error';\n  pretty: boolean;\n}\n\n/**\n * Session Configuration\n */\nexport interface SessionConfig {\n  timeout: number;\n  cleanupInterval: number;\n}\n\n/**\n * Application Configuration\n */\nexport interface AppConfig {\n  mode: 'mcp' | 'http';\n  database?: DbConfig;\n  http?: HttpConfig;\n}\n\n/**\n * Connect Request\n */\nexport interface ConnectRequest {\n  type: string;\n  host?: string;\n  port?: number;\n  user?: string;\n  password?: string;\n  database?: string;\n  filePath?: string;\n  authSource?: string;\n  allowWrite?: boolean;\n  /** Oracle Instant Client 路径（启用 Thick 模式以支持 11g） */\n  oracleClientPath?: string;\n}\n\n/**\n * Connect Response\n */\nexport interface ConnectResponse {\n  sessionId: string;\n  databaseType: string;\n  connected: boolean;\n}\n\n/**\n * Disconnect Request\n */\nexport interface DisconnectRequest {\n  sessionId: string;\n}\n\n/**\n * Disconnect Response\n */\nexport interface DisconnectResponse {\n  disconnected: boolean;\n}\n\n/**\n * Query Request\n */\nexport interface QueryRequest {\n  sessionId: string;\n  query: string;\n  params?: unknown[];\n}\n\n/**\n * Execute Request (for write operations)\n */\nexport interface ExecuteRequest {\n  sessionId: string;\n  query: string;\n  params?: unknown[];\n}\n\n/**\n * Tables Request\n */\nexport interface TablesRequest {\n  sessionId: string;\n}\n\n/**\n * Tables Response\n */\nexport interface TablesResponse {\n  tables: string[];\n}\n\n/**\n * Schema Request\n */\nexport interface SchemaRequest {\n  sessionId: string;\n  tableName?: string;\n}\n\n/**\n * API Error\n */\nexport interface ApiError {\n  code: string;\n  message: string;\n  details?: unknown;\n}\n\n/**\n * Response Metadata\n */\nexport interface ResponseMetadata {\n  executionTime?: number;\n  timestamp: string;\n  requestId: string;\n}\n\n/**\n * Generic API Response\n */\nexport interface ApiResponse<T = unknown> {\n  success: boolean;\n  data?: T;\n  error?: ApiError;\n  metadata?: ResponseMetadata;\n}\n\n/**\n * Health Response\n */\nexport interface HealthResponse {\n  status: 'healthy' | 'unhealthy';\n  uptime: number;\n  timestamp: string;\n}\n\n/**\n * Info Response\n */\nexport interface InfoResponse {\n  name: string;\n  version: string;\n  mode: string;\n  supportedDatabases: string[];\n}\n\n/**\n * Session\n */\nexport interface Session {\n  id: string;\n  adapter: any;\n  config: DbConfig;\n  createdAt: Date;\n  lastAccessedAt: Date;\n}\n\n/**\n * HTTP Query Result (rows as JSON string for Coze compatibility)\n */\nexport interface HttpQueryResult {\n  /** 查询返回的行数据（JSON字符串格式） */\n  rows: string;\n  /** 受影响的行数（用于 INSERT/UPDATE/DELETE） */\n  affectedRows?: number;\n  /** 执行时间（毫秒） */\n  executionTime?: number;\n  /** 额外的元数据 */\n  metadata?: Record<string, unknown>;\n}\n\n/**\n * Fastify Request with API Key\n */\nexport interface AuthenticatedRequest {\n  apiKey?: string;\n}\n"
  },
  {
    "path": "src/utils/adapter-factory.ts",
    "content": "/**\n * Adapter Factory - Centralized database adapter creation\n * Extracts adapter creation logic for reuse across MCP and HTTP modes\n */\n\nimport type { DbAdapter, DbConfig } from '../types/adapter.js';\nimport { MySQLAdapter } from '../adapters/mysql.js';\nimport { PostgreSQLAdapter } from '../adapters/postgres.js';\nimport { RedisAdapter } from '../adapters/redis.js';\nimport { OracleAdapter } from '../adapters/oracle.js';\nimport { DMAdapter } from '../adapters/dm.js';\nimport { SQLServerAdapter } from '../adapters/sqlserver.js';\nimport { MongoDBAdapter } from '../adapters/mongodb.js';\nimport { SQLiteAdapter } from '../adapters/sqlite.js';\nimport { KingbaseAdapter } from '../adapters/kingbase.js';\nimport { GaussDBAdapter } from '../adapters/gaussdb.js';\nimport { OceanBaseAdapter } from '../adapters/oceanbase.js';\nimport { TiDBAdapter } from '../adapters/tidb.js';\nimport { ClickHouseAdapter } from '../adapters/clickhouse.js';\nimport { PolarDBAdapter } from '../adapters/polardb.js';\nimport { VastbaseAdapter } from '../adapters/vastbase.js';\nimport { HighGoAdapter } from '../adapters/highgo.js';\nimport { GoldenDBAdapter } from '../adapters/goldendb.js';\n\n/**\n * Supported database types\n */\nexport type DbType =\n  | 'mysql'\n  | 'postgres'\n  | 'redis'\n  | 'oracle'\n  | 'dm'\n  | 'sqlserver'\n  | 'mongodb'\n  | 'sqlite'\n  | 'kingbase'\n  | 'gaussdb'\n  | 'oceanbase'\n  | 'tidb'\n  | 'clickhouse'\n  | 'polardb'\n  | 'vastbase'\n  | 'highgo'\n  | 'goldendb';\n\n/**\n * Normalize database type aliases to canonical names\n */\nexport function normalizeDbType(type: string): DbType {\n  const normalized = type.toLowerCase();\n\n  // Handle aliases\n  if (normalized === 'mssql') {\n    return 'sqlserver';\n  }\n  if (normalized === 'opengauss') {\n    return 'gaussdb';\n  }\n\n  // Validate type\n  const validTypes: DbType[] = [\n    'mysql',\n    'postgres',\n    'redis',\n    'oracle',\n    'dm',\n    'sqlserver',\n    'mongodb',\n    'sqlite',\n    'kingbase',\n    'gaussdb',\n    'oceanbase',\n    'tidb',\n    'clickhouse',\n    'polardb',\n    'vastbase',\n    'highgo',\n    'goldendb',\n  ];\n\n  if (!validTypes.includes(normalized as DbType)) {\n    throw new Error(\n      `不支持的数据库类型: ${type}。支持的类型: ${validTypes.join(', ')}`\n    );\n  }\n\n  return normalized as DbType;\n}\n\n/**\n * Validate database configuration\n */\nexport function validateDbConfig(config: DbConfig): void {\n  // Normalize type\n  const dbType = normalizeDbType(config.type);\n\n  // SQLite special validation\n  if (dbType === 'sqlite') {\n    if (!config.filePath) {\n      throw new Error('SQLite 数据库需要指定 filePath 参数');\n    }\n    return;\n  }\n\n  // Other databases need host and port\n  if (!config.host || !config.port) {\n    throw new Error(`${dbType} 数据库需要指定 host 和 port 参数`);\n  }\n}\n\n/**\n * Create database adapter based on configuration\n */\nexport function createAdapter(config: DbConfig): DbAdapter {\n  // Validate configuration\n  validateDbConfig(config);\n\n  // Normalize type\n  const dbType = normalizeDbType(config.type);\n\n  // Create adapter based on type\n  switch (dbType) {\n    case 'mysql':\n      return new MySQLAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'postgres':\n      return new PostgreSQLAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'redis':\n      return new RedisAdapter({\n        host: config.host!,\n        port: config.port!,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'oracle':\n      return new OracleAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n        oracleClientPath: config.oracleClientPath,\n      });\n\n    case 'dm':\n      return new DMAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'sqlserver':\n      return new SQLServerAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'mongodb':\n      return new MongoDBAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n        authSource: (config as any).authSource,\n      });\n\n    case 'sqlite':\n      return new SQLiteAdapter({\n        filePath: config.filePath!,\n        readonly: !config.allowWrite,\n      });\n\n    case 'kingbase':\n      return new KingbaseAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'gaussdb':\n      return new GaussDBAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'oceanbase':\n      return new OceanBaseAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'tidb':\n      return new TiDBAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'clickhouse':\n      return new ClickHouseAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'polardb':\n      return new PolarDBAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'vastbase':\n      return new VastbaseAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'highgo':\n      return new HighGoAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    case 'goldendb':\n      return new GoldenDBAdapter({\n        host: config.host!,\n        port: config.port!,\n        user: config.user,\n        password: config.password,\n        database: config.database,\n      });\n\n    default:\n      throw new Error(`不支持的数据库类型: ${dbType}`);\n  }\n}\n"
  },
  {
    "path": "src/utils/config-loader.ts",
    "content": "/**\n * Configuration Loader\n * Unified configuration loading from multiple sources with priority:\n * CLI args > Environment variables > Config file > Defaults\n */\n\nimport { config as dotenvConfig } from 'dotenv';\nimport type { AppConfig, HttpConfig } from '../types/http.js';\n\n// Load environment variables from .env file\ndotenvConfig();\n\n/**\n * Default HTTP configuration\n */\nconst DEFAULT_HTTP_CONFIG: HttpConfig = {\n  port: 3000,\n  host: '0.0.0.0',\n  apiKeys: [],\n  cors: {\n    origins: '*',\n    credentials: false,\n  },\n  rateLimit: {\n    max: 100,\n    window: '1m',\n  },\n  logging: {\n    level: 'info',\n    pretty: false,\n  },\n  session: {\n    timeout: 3600000, // 1 hour\n    cleanupInterval: 300000, // 5 minutes\n  },\n};\n\n/**\n * Load configuration from environment variables\n */\nexport function loadFromEnv(): Partial<AppConfig> {\n  const config: Partial<AppConfig> = {};\n\n  // Mode\n  if (process.env.MODE) {\n    config.mode = process.env.MODE as 'mcp' | 'http';\n  }\n\n  // HTTP configuration\n  if (process.env.HTTP_PORT || process.env.HTTP_HOST || process.env.API_KEYS) {\n    config.http = {\n      ...DEFAULT_HTTP_CONFIG,\n      port: process.env.HTTP_PORT ? parseInt(process.env.HTTP_PORT, 10) : DEFAULT_HTTP_CONFIG.port,\n      host: process.env.HTTP_HOST || DEFAULT_HTTP_CONFIG.host,\n      apiKeys: process.env.API_KEYS ? process.env.API_KEYS.split(',').map(k => k.trim()) : [],\n      cors: {\n        origins: process.env.CORS_ORIGINS || DEFAULT_HTTP_CONFIG.cors.origins,\n        credentials: process.env.CORS_CREDENTIALS === 'true',\n      },\n      rateLimit: {\n        max: process.env.RATE_LIMIT_MAX ? parseInt(process.env.RATE_LIMIT_MAX, 10) : DEFAULT_HTTP_CONFIG.rateLimit.max,\n        window: process.env.RATE_LIMIT_WINDOW || DEFAULT_HTTP_CONFIG.rateLimit.window,\n      },\n      logging: {\n        level: (process.env.LOG_LEVEL as any) || DEFAULT_HTTP_CONFIG.logging.level,\n        pretty: process.env.LOG_PRETTY === 'true',\n      },\n      session: {\n        timeout: process.env.SESSION_TIMEOUT ? parseInt(process.env.SESSION_TIMEOUT, 10) : DEFAULT_HTTP_CONFIG.session.timeout,\n        cleanupInterval: process.env.SESSION_CLEANUP_INTERVAL ? parseInt(process.env.SESSION_CLEANUP_INTERVAL, 10) : DEFAULT_HTTP_CONFIG.session.cleanupInterval,\n      },\n    };\n  }\n\n  // Database configuration (for single-connection mode)\n  if (process.env.DB_TYPE) {\n    config.database = {\n      type: process.env.DB_TYPE as any,\n      host: process.env.DB_HOST,\n      port: process.env.DB_PORT ? parseInt(process.env.DB_PORT, 10) : undefined,\n      user: process.env.DB_USER,\n      password: process.env.DB_PASSWORD,\n      database: process.env.DB_DATABASE,\n      filePath: process.env.DB_FILE_PATH,\n      allowWrite: process.env.DB_ALLOW_WRITE === 'true',\n    };\n  }\n\n  return config;\n}\n\n/**\n * Merge multiple configuration objects with priority\n */\nexport function mergeConfigs(...configs: Partial<AppConfig>[]): AppConfig {\n  const merged: AppConfig = {\n    mode: 'mcp', // Default mode\n  };\n\n  for (const config of configs) {\n    if (config.mode) {\n      merged.mode = config.mode;\n    }\n    if (config.database) {\n      merged.database = { ...merged.database, ...config.database };\n    }\n    if (config.http) {\n      merged.http = { ...merged.http, ...config.http };\n    }\n  }\n\n  // Ensure HTTP config exists if in HTTP mode\n  if (merged.mode === 'http' && !merged.http) {\n    merged.http = DEFAULT_HTTP_CONFIG;\n  }\n\n  return merged;\n}\n\n/**\n * Load complete configuration\n */\nexport function loadConfig(): AppConfig {\n  // Load from environment variables\n  const envConfig = loadFromEnv();\n\n  // Merge with defaults\n  const config = mergeConfigs(\n    {\n      mode: 'mcp',\n      http: DEFAULT_HTTP_CONFIG,\n    },\n    envConfig\n  );\n\n  return config;\n}\n\n/**\n * Validate configuration\n */\nexport function validateConfig(config: AppConfig): void {\n  if (config.mode === 'http') {\n    if (!config.http) {\n      throw new Error('HTTP 模式需要 HTTP 配置');\n    }\n    if (config.http.apiKeys.length === 0) {\n      console.warn('⚠️  警告: 未配置 API Keys，建议设置 API_KEYS 环境变量');\n    }\n  }\n}\n"
  },
  {
    "path": "src/utils/data-masking.ts",
    "content": "/**\n * 数据脱敏工具\n * 用于保护敏感数据，支持多种脱敏策略\n *\n * 支持的脱敏类型：\n * - phone: 手机号（138****1234）\n * - email: 邮箱（z***@example.com）\n * - idcard: 身份证（110***********1234）\n * - bankcard: 银行卡（************1234）\n * - password: 密码（******）\n * - partial: 部分隐藏（张*明）\n * - full: 完全隐藏（******）\n */\n\n/**\n * 脱敏类型\n */\nexport type MaskType = 'phone' | 'email' | 'idcard' | 'bankcard' | 'password' | 'partial' | 'full';\n\n/**\n * 脱敏规则\n */\nexport interface MaskingRule {\n  /** 匹配模式（列名正则） */\n  pattern: RegExp;\n  /** 脱敏类型 */\n  type: MaskType;\n}\n\n/**\n * 默认脱敏规则（按优先级排序）\n */\nconst DEFAULT_MASKING_RULES: MaskingRule[] = [\n  // 密码类 - 完全隐藏\n  { pattern: /^(password|passwd|pwd|secret|token|api_key|apikey|access_token|refresh_token)$/i, type: 'full' },\n\n  // 手机号\n  { pattern: /^(phone|mobile|tel|telephone|cellphone|phone_number|mobile_number|contact_phone|user_phone)$/i, type: 'phone' },\n\n  // 邮箱\n  { pattern: /^(email|mail|e_mail|email_address|user_email|contact_email)$/i, type: 'email' },\n\n  // 身份证\n  { pattern: /^(id_card|idcard|id_number|identity|citizen_id|ssn|social_security|identity_card|id_no)$/i, type: 'idcard' },\n\n  // 银行卡\n  { pattern: /^(bank_card|bankcard|card_number|card_no|account_number|account_no|bank_account)$/i, type: 'bankcard' },\n\n  // 地址类 - 部分隐藏\n  { pattern: /^(address|addr|home_address|work_address|detail_address)$/i, type: 'partial' },\n\n  // 姓名类 - 部分隐藏\n  { pattern: /^(real_name|realname|full_name|fullname|true_name|user_name|username|nick_name|nickname)$/i, type: 'partial' },\n];\n\n/**\n * 数据脱敏器类\n */\nexport class DataMasker {\n  private rules: MaskingRule[];\n  private enabled: boolean;\n\n  constructor(enabled: boolean = true, customRules?: MaskingRule[]) {\n    this.enabled = enabled;\n    this.rules = customRules\n      ? [...customRules, ...DEFAULT_MASKING_RULES]\n      : DEFAULT_MASKING_RULES;\n  }\n\n  /**\n   * 脱敏单个值\n   * @param columnName - 列名\n   * @param value - 原始值\n   * @returns 脱敏后的值\n   */\n  maskValue(columnName: string, value: unknown): unknown {\n    if (!this.enabled || value === null || value === undefined) {\n      return value;\n    }\n\n    const stringValue = String(value);\n\n    // 空字符串不处理\n    if (stringValue.trim() === '') {\n      return value;\n    }\n\n    // 根据列名匹配规则\n    const rule = this.findMatchingRule(columnName);\n\n    if (rule) {\n      return this.applyMask(stringValue, rule.type);\n    }\n\n    // 自动检测敏感数据格式\n    const maskedValue = this.autoDetectAndMask(stringValue);\n\n    // 如果没有被脱敏，返回原始值（保持类型）\n    if (maskedValue === stringValue) {\n      return value;\n    }\n\n    return maskedValue;\n  }\n\n  /**\n   * 脱敏一行数据\n   * @param row - 原始行数据\n   * @returns 脱敏后的行数据和被脱敏的列名\n   */\n  maskRow(row: Record<string, unknown>): {\n    maskedRow: Record<string, unknown>;\n    maskedColumns: string[];\n  } {\n    const maskedRow: Record<string, unknown> = {};\n    const maskedColumns: string[] = [];\n\n    for (const [key, value] of Object.entries(row)) {\n      const maskedValue = this.maskValue(key, value);\n      maskedRow[key] = maskedValue;\n\n      if (maskedValue !== value) {\n        maskedColumns.push(key);\n      }\n    }\n\n    return { maskedRow, maskedColumns };\n  }\n\n  /**\n   * 脱敏多行数据\n   * @param rows - 原始行数据数组\n   * @returns 脱敏后的行数据数组和被脱敏的列名\n   */\n  maskRows(rows: Record<string, unknown>[]): {\n    maskedRows: Record<string, unknown>[];\n    maskedColumns: string[];\n  } {\n    const allMaskedColumns = new Set<string>();\n    const maskedRows = rows.map(row => {\n      const { maskedRow, maskedColumns } = this.maskRow(row);\n      maskedColumns.forEach(col => allMaskedColumns.add(col));\n      return maskedRow;\n    });\n\n    return {\n      maskedRows,\n      maskedColumns: Array.from(allMaskedColumns),\n    };\n  }\n\n  /**\n   * 查找匹配的脱敏规则\n   * @param columnName - 列名\n   * @returns 匹配的规则或 undefined\n   */\n  private findMatchingRule(columnName: string): MaskingRule | undefined {\n    return this.rules.find(rule => rule.pattern.test(columnName));\n  }\n\n  /**\n   * 自动检测并脱敏（基于值的格式）\n   * @param value - 原始值\n   * @returns 脱敏后的值\n   */\n  private autoDetectAndMask(value: string): string {\n    // 检测手机号格式（中国大陆）\n    if (/^1[3-9]\\d{9}$/.test(value)) {\n      return this.applyMask(value, 'phone');\n    }\n\n    // 检测邮箱格式\n    if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n      return this.applyMask(value, 'email');\n    }\n\n    // 检测身份证格式（18位）\n    if (/^\\d{17}[\\dXx]$/.test(value)) {\n      return this.applyMask(value, 'idcard');\n    }\n\n    // 检测银行卡格式（16-19位数字）\n    if (/^\\d{16,19}$/.test(value)) {\n      return this.applyMask(value, 'bankcard');\n    }\n\n    return value;\n  }\n\n  /**\n   * 应用脱敏\n   * @param value - 原始值\n   * @param type - 脱敏类型\n   * @returns 脱敏后的值\n   */\n  private applyMask(value: string, type: MaskType): string {\n    switch (type) {\n      case 'phone':\n        // 138****1234\n        return value.length >= 11\n          ? value.slice(0, 3) + '****' + value.slice(-4)\n          : '****';\n\n      case 'email':\n        // z***@example.com\n        const atIndex = value.indexOf('@');\n        if (atIndex > 0) {\n          const prefix = value.slice(0, 1);\n          const domain = value.slice(atIndex);\n          return prefix + '***' + domain;\n        }\n        return '***@***';\n\n      case 'idcard':\n        // 110***********1234\n        return value.length >= 18\n          ? value.slice(0, 3) + '***********' + value.slice(-4)\n          : '***';\n\n      case 'bankcard':\n        // ************1234\n        return value.length >= 4\n          ? '************' + value.slice(-4)\n          : '****';\n\n      case 'password':\n      case 'full':\n        return '******';\n\n      case 'partial':\n        // 保留首尾，中间用 * 替换\n        if (value.length <= 1) {\n          return '*';\n        }\n        if (value.length === 2) {\n          return value.slice(0, 1) + '*';\n        }\n        // 对于较长的字符串，保留首尾各1个字符\n        const maskLength = value.length - 2;\n        return value.slice(0, 1) + '*'.repeat(Math.min(maskLength, 6)) + value.slice(-1);\n\n      default:\n        return value;\n    }\n  }\n\n  /**\n   * 检查是否启用脱敏\n   */\n  isEnabled(): boolean {\n    return this.enabled;\n  }\n\n  /**\n   * 设置是否启用脱敏\n   */\n  setEnabled(enabled: boolean): void {\n    this.enabled = enabled;\n  }\n\n  /**\n   * 添加自定义脱敏规则\n   * @param rule - 脱敏规则\n   */\n  addRule(rule: MaskingRule): void {\n    // 添加到规则列表开头，优先级最高\n    this.rules.unshift(rule);\n  }\n}\n\n/**\n * 创建默认的数据脱敏器\n * @param enabled - 是否启用脱敏，默认 true\n * @returns DataMasker 实例\n */\nexport function createDataMasker(enabled: boolean = true): DataMasker {\n  return new DataMasker(enabled);\n}\n"
  },
  {
    "path": "src/utils/safety.ts",
    "content": "/**\n * 安全检查工具\n * 用于防止误操作删库等危险行为\n */\n\nimport type { DbConfig, PermissionType } from '../types/adapter.js';\n\n/**\n * 操作类型到 SQL 关键字的映射\n */\nconst OPERATION_KEYWORDS: Record<Exclude<PermissionType, 'read'>, readonly string[]> = {\n  insert: ['INSERT', 'REPLACE'],\n  update: ['UPDATE'],\n  delete: ['DELETE', 'TRUNCATE'],\n  ddl: ['CREATE', 'ALTER', 'DROP', 'RENAME'],\n} as const;\n\n/**\n * 预设权限模式\n */\nconst PERMISSION_PRESETS: Record<string, readonly PermissionType[]> = {\n  safe: ['read'],\n  readwrite: ['read', 'insert', 'update'],\n  full: ['read', 'insert', 'update', 'delete', 'ddl'],\n} as const;\n\n/**\n * 解析配置得到最终权限列表\n */\nexport function resolvePermissions(config: DbConfig): PermissionType[] {\n  // 向后兼容：allowWrite=true 且未设置新参数时，等价于 full\n  if (config.allowWrite === true && !config.permissionMode && !config.permissions) {\n    return [...PERMISSION_PRESETS.full];\n  }\n\n  // 直接指定 permissions 数组（优先级最高）\n  if (config.permissions?.length) {\n    const perms = new Set<PermissionType>(['read', ...config.permissions]);\n    return Array.from(perms);\n  }\n\n  // 使用预设模式\n  if (config.permissionMode && config.permissionMode !== 'custom') {\n    return [...PERMISSION_PRESETS[config.permissionMode]];\n  }\n\n  // 默认安全模式\n  return [...PERMISSION_PRESETS.safe];\n}\n\n/**\n * 检查 SQL 语句是否以指定关键字开头\n */\nfunction startsWithKeyword(query: string, keyword: string): boolean {\n  const pattern = new RegExp(`^(\\\\s|--.*|/\\\\*.*?\\\\*/)*${keyword}\\\\b`, 'i');\n  return pattern.test(query);\n}\n\n/**\n * 检查 SQL 语句是否包含写操作\n * @param query - 待检查的 SQL 语句\n * @returns 如果包含写操作返回 true\n */\nexport function isWriteOperation(query: string): boolean {\n  const upperQuery = query.trim().toUpperCase();\n  for (const keywords of Object.values(OPERATION_KEYWORDS)) {\n    for (const keyword of keywords) {\n      if (startsWithKeyword(upperQuery, keyword)) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n/**\n * 检测查询的操作类型\n */\nfunction detectOperationType(query: string): { type: Exclude<PermissionType, 'read'>; keyword: string } | null {\n  const upperQuery = query.trim().toUpperCase();\n  for (const [opType, keywords] of Object.entries(OPERATION_KEYWORDS)) {\n    for (const keyword of keywords) {\n      if (startsWithKeyword(upperQuery, keyword)) {\n        return { type: opType as Exclude<PermissionType, 'read'>, keyword };\n      }\n    }\n  }\n  return null;\n}\n\n/**\n * 验证查询是否允许执行\n * @param query - 待执行的查询\n * @param configOrAllowWrite - DbConfig 对象或 allowWrite 布尔值（向后兼容）\n * @throws 如果查询被拒绝，抛出带有中文提示的错误\n */\nexport function validateQuery(query: string, configOrAllowWrite: DbConfig | boolean): void {\n  // 向后兼容：支持旧的 boolean 参数\n  let permissions: PermissionType[];\n  if (typeof configOrAllowWrite === 'boolean') {\n    permissions = configOrAllowWrite ? [...PERMISSION_PRESETS.full] : [...PERMISSION_PRESETS.safe];\n  } else {\n    permissions = resolvePermissions(configOrAllowWrite);\n  }\n\n  const detected = detectOperationType(query);\n  if (detected && !permissions.includes(detected.type)) {\n    const permissionLabels: Record<string, string> = {\n      insert: '插入(insert)',\n      update: '更新(update)',\n      delete: '删除(delete)',\n      ddl: 'DDL(ddl)',\n    };\n    throw new Error(\n      `❌ 操作被拒绝：当前权限不允许 ${detected.keyword} 操作。\\n` +\n      `需要的权限：${permissionLabels[detected.type]}\\n` +\n      `当前权限：${permissions.join(', ')}\\n` +\n      `如需更多权限，请使用 --permission-mode 或 --permissions 参数。`\n    );\n  }\n}\n\n/**\n * 获取查询中的危险关键字（用于日志记录）\n * @param query - SQL 查询语句\n * @returns 找到的危险关键字数组\n */\nexport function getDangerousKeywords(query: string): string[] {\n  const upperQuery = query.trim().toUpperCase();\n  const allKeywords = Object.values(OPERATION_KEYWORDS).flat();\n  return allKeywords.filter(keyword => upperQuery.includes(keyword));\n}\n\n/**\n * 格式化权限列表用于显示\n */\nexport function formatPermissions(permissions: PermissionType[]): string {\n  const labels: Record<PermissionType, string> = {\n    read: '读取',\n    insert: '插入',\n    update: '更新',\n    delete: '删除',\n    ddl: 'DDL',\n  };\n  return permissions.map(p => `${labels[p]}(${p})`).join(', ');\n}\n"
  },
  {
    "path": "src/utils/schema-enhancer.ts",
    "content": "/**\n * Schema 增强工具\n * 提供隐式关系推断、关系类型细化等功能\n * 用于提升 LLM 对数据库结构的理解，提高 Text2SQL 准确性\n */\n\nimport type { TableInfo, RelationshipInfo } from '../types/adapter.js';\n\n/**\n * Schema 增强配置\n */\nexport interface SchemaEnhancerConfig {\n  /** 是否启用隐式关系推断，默认 true */\n  enableInferredRelationships: boolean;\n  /** 是否启用关系类型细化，默认 true */\n  enableRelationshipTypeRefinement: boolean;\n  /** 推断关系的最小置信度阈值，低于此值的推断将被过滤，默认 0.7 */\n  minConfidenceThreshold: number;\n}\n\n/**\n * 默认配置\n */\nconst DEFAULT_CONFIG: SchemaEnhancerConfig = {\n  enableInferredRelationships: true,\n  enableRelationshipTypeRefinement: true,\n  minConfidenceThreshold: 0.7,\n};\n\n/**\n * Schema 增强器类\n */\nexport class SchemaEnhancer {\n  private config: SchemaEnhancerConfig;\n\n  constructor(config?: Partial<SchemaEnhancerConfig>) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n  }\n\n  /**\n   * 增强关系信息\n   * 1. 为现有外键关系添加 source='foreign_key' 标记\n   * 2. 推断隐式关系并添加 source='inferred' 标记\n   * 3. 细化关系类型（区分 one-to-one 和 many-to-one）\n   */\n  enhanceRelationships(\n    tables: TableInfo[],\n    existingRelationships: RelationshipInfo[]\n  ): RelationshipInfo[] {\n    // 1. 标记现有外键关系\n    const markedRelationships: RelationshipInfo[] = existingRelationships.map(rel => ({\n      ...rel,\n      source: 'foreign_key' as const,\n      confidence: 1.0,\n    }));\n\n    // 2. 推断隐式关系\n    let allRelationships: RelationshipInfo[] = [...markedRelationships];\n    if (this.config.enableInferredRelationships) {\n      const inferredRelationships = this.inferRelationships(tables, markedRelationships);\n      allRelationships = [...markedRelationships, ...inferredRelationships];\n    }\n\n    // 3. 细化关系类型\n    if (this.config.enableRelationshipTypeRefinement) {\n      allRelationships = this.refineRelationshipTypes(tables, allRelationships);\n    }\n\n    return allRelationships;\n  }\n\n  /**\n   * 推断隐式关系\n   * 基于列命名规则推断表间关系，支持以下模式：\n   * - xxx_id → xxxs.id 或 xxx.id\n   * - xxxId → xxxs.id 或 xxx.id (驼峰命名)\n   * - xxx_code → xxxs.code 或 xxx.code\n   */\n  private inferRelationships(\n    tables: TableInfo[],\n    existingRelationships: RelationshipInfo[]\n  ): RelationshipInfo[] {\n    const inferred: RelationshipInfo[] = [];\n\n    // 构建表名集合（小写）用于快速查找\n    const tableNameSet = new Set(tables.map(t => t.name.toLowerCase()));\n\n    // 构建表名到表信息的映射\n    const tableMap = new Map(tables.map(t => [t.name.toLowerCase(), t]));\n\n    // 构建已有关系的集合，避免重复推断\n    const existingPairs = new Set(\n      existingRelationships.map(r => `${r.fromTable.toLowerCase()}.${r.fromColumns[0].toLowerCase()}`)\n    );\n\n    for (const table of tables) {\n      const tableName = table.name.toLowerCase();\n\n      for (const column of table.columns) {\n        const columnName = column.name.toLowerCase();\n\n        // 跳过已有外键的列\n        if (existingPairs.has(`${tableName}.${columnName}`)) {\n          continue;\n        }\n\n        // 跳过主键列（主键通常不是外键）\n        if (table.primaryKeys.map(pk => pk.toLowerCase()).includes(columnName)) {\n          continue;\n        }\n\n        // 尝试推断关系\n        const inferredRelation = this.tryInferRelation(\n          tableName,\n          columnName,\n          tableNameSet,\n          tableMap\n        );\n\n        if (inferredRelation && (inferredRelation.confidence ?? 0) >= this.config.minConfidenceThreshold) {\n          inferred.push(inferredRelation);\n        }\n      }\n    }\n\n    return inferred;\n  }\n\n  /**\n   * 尝试为单个列推断关系\n   */\n  private tryInferRelation(\n    tableName: string,\n    columnName: string,\n    tableNameSet: Set<string>,\n    tableMap: Map<string, TableInfo>\n  ): RelationshipInfo | null {\n    // 规则1: xxx_id → xxxs.id 或 xxx.id\n    if (columnName.endsWith('_id') && columnName !== 'id') {\n      const baseName = columnName.slice(0, -3); // 去掉 _id\n      return this.findTargetTable(tableName, columnName, baseName, 'id', tableNameSet, tableMap);\n    }\n\n    // 规则2: xxxId → xxxs.id 或 xxx.id (驼峰命名)\n    const camelCaseMatch = columnName.match(/^(.+)Id$/);\n    if (camelCaseMatch && columnName !== 'id') {\n      const baseName = camelCaseMatch[1].toLowerCase();\n      const relation = this.findTargetTable(tableName, columnName, baseName, 'id', tableNameSet, tableMap);\n      if (relation) {\n        // 驼峰命名的置信度稍低\n        relation.confidence = Math.max(0, (relation.confidence || 0) - 0.05);\n      }\n      return relation;\n    }\n\n    // 规则3: xxx_code → xxxs.code 或 xxx.code\n    if (columnName.endsWith('_code') && columnName !== 'code') {\n      const baseName = columnName.slice(0, -5); // 去掉 _code\n      return this.findTargetTable(tableName, columnName, baseName, 'code', tableNameSet, tableMap);\n    }\n\n    // 规则4: xxx_no → xxxs.xxx_no 或 xxx.xxx_no\n    if (columnName.endsWith('_no') && columnName !== 'no') {\n      const baseName = columnName.slice(0, -3); // 去掉 _no\n      // 对于 _no 后缀，目标列名通常是完整的列名\n      return this.findTargetTable(tableName, columnName, baseName, columnName, tableNameSet, tableMap, 0.75);\n    }\n\n    return null;\n  }\n\n  /**\n   * 查找目标表\n   */\n  private findTargetTable(\n    fromTable: string,\n    fromColumn: string,\n    baseName: string,\n    targetColumn: string,\n    tableNameSet: Set<string>,\n    tableMap: Map<string, TableInfo>,\n    baseConfidence: number = 0.95\n  ): RelationshipInfo | null {\n    // 尝试匹配的表名变体（按优先级排序）\n    const candidates = [\n      { name: baseName + 's', confidence: baseConfidence },      // 复数形式 users\n      { name: baseName + 'es', confidence: baseConfidence },     // 复数形式 boxes\n      { name: baseName, confidence: baseConfidence - 0.05 },     // 单数形式 user\n      { name: baseName + '_info', confidence: baseConfidence - 0.10 },  // xxx_info 形式\n      { name: baseName + '_list', confidence: baseConfidence - 0.10 },  // xxx_list 形式\n    ];\n\n    for (const candidate of candidates) {\n      if (tableNameSet.has(candidate.name) && candidate.name !== fromTable) {\n        const targetTable = tableMap.get(candidate.name);\n        if (targetTable) {\n          // 验证目标表有对应的列\n          const hasTargetColumn = targetTable.columns.some(\n            col => col.name.toLowerCase() === targetColumn.toLowerCase()\n          );\n          // 或者目标列是主键\n          const isTargetPrimaryKey = targetTable.primaryKeys\n            .map(pk => pk.toLowerCase())\n            .includes(targetColumn.toLowerCase());\n\n          if (hasTargetColumn || isTargetPrimaryKey) {\n            return {\n              fromTable,\n              fromColumns: [fromColumn],\n              toTable: candidate.name,\n              toColumns: [targetColumn],\n              type: 'many-to-one',\n              source: 'inferred',\n              confidence: candidate.confidence,\n            };\n          }\n        }\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * 细化关系类型\n   * 通过检查外键列是否有唯一约束来区分 one-to-one 和 many-to-one\n   */\n  private refineRelationshipTypes(\n    tables: TableInfo[],\n    relationships: RelationshipInfo[]\n  ): RelationshipInfo[] {\n    // 构建表名到表信息的映射\n    const tableMap = new Map(tables.map(t => [t.name.toLowerCase(), t]));\n\n    return relationships.map(rel => {\n      const fromTable = tableMap.get(rel.fromTable.toLowerCase());\n      if (!fromTable) {\n        return rel;\n      }\n\n      // 检查外键列是否有唯一约束\n      const isOneToOne = this.hasUniqueConstraint(fromTable, rel.fromColumns);\n\n      return {\n        ...rel,\n        type: isOneToOne ? 'one-to-one' : rel.type,\n      };\n    });\n  }\n\n  /**\n   * 检查列是否有唯一约束\n   */\n  private hasUniqueConstraint(table: TableInfo, columns: string[]): boolean {\n    if (!table.indexes || columns.length === 0) {\n      return false;\n    }\n\n    const normalizedColumns = columns.map(c => c.toLowerCase()).sort();\n\n    // 检查是否有唯一索引覆盖这些列\n    return table.indexes.some(idx => {\n      if (!idx.unique) {\n        return false;\n      }\n\n      const indexColumns = idx.columns.map(c => c.toLowerCase()).sort();\n\n      // 索引列必须完全匹配外键列\n      return (\n        indexColumns.length === normalizedColumns.length &&\n        indexColumns.every((col, i) => col === normalizedColumns[i])\n      );\n    });\n  }\n\n  /**\n   * 更新配置\n   */\n  updateConfig(config: Partial<SchemaEnhancerConfig>): void {\n    this.config = { ...this.config, ...config };\n  }\n\n  /**\n   * 获取当前配置\n   */\n  getConfig(): SchemaEnhancerConfig {\n    return { ...this.config };\n  }\n}\n\n/**\n * 创建默认的 Schema 增强器实例\n */\nexport function createSchemaEnhancer(config?: Partial<SchemaEnhancerConfig>): SchemaEnhancer {\n  return new SchemaEnhancer(config);\n}\n"
  },
  {
    "path": "tests/integration/http-api.test.ts",
    "content": "/**\n * HTTP API Integration Tests\n */\n\nimport { describe, it, expect, beforeAll, afterAll } from 'vitest';\nimport { createHttpServer } from '../../src/http/server';\nimport type { AppConfig } from '../../src/types/http';\n\ndescribe('HTTP API Integration Tests', () => {\n  let server: any;\n  const testConfig: AppConfig = {\n    mode: 'http',\n    http: {\n      port: 3001,\n      host: '127.0.0.1',\n      apiKeys: ['test-key'],\n      cors: {\n        origins: '*',\n        credentials: false\n      },\n      rateLimit: {\n        max: 100,\n        window: '1m'\n      },\n      logging: {\n        level: 'error',\n        pretty: false\n      },\n      session: {\n        timeout: 3600000,\n        cleanupInterval: 300000\n      }\n    }\n  };\n\n  beforeAll(async () => {\n    server = await createHttpServer(testConfig);\n    await server.listen({ port: testConfig.http!.port, host: testConfig.http!.host });\n  });\n\n  afterAll(async () => {\n    await server.close();\n  });\n\n  describe('Health Endpoints', () => {\n    it('should return health status', async () => {\n      const response = await server.inject({\n        method: 'GET',\n        url: '/api/health'\n      });\n\n      expect(response.statusCode).toBe(200);\n      const body = JSON.parse(response.body);\n      expect(body.success).toBe(true);\n      expect(body.data.status).toBe('healthy');\n    });\n\n    it('should return service info', async () => {\n      const response = await server.inject({\n        method: 'GET',\n        url: '/api/info'\n      });\n\n      expect(response.statusCode).toBe(200);\n      const body = JSON.parse(response.body);\n      expect(body.success).toBe(true);\n      expect(body.data.name).toBe('universal-db-mcp');\n      expect(body.data.supportedDatabases).toBeInstanceOf(Array);\n    });\n  });\n\n  describe('Authentication', () => {\n    it('should reject requests without API key', async () => {\n      const response = await server.inject({\n        method: 'POST',\n        url: '/api/connect',\n        payload: {\n          type: 'mysql',\n          host: 'localhost',\n          port: 3306\n        }\n      });\n\n      expect(response.statusCode).toBe(401);\n      const body = JSON.parse(response.body);\n      expect(body.success).toBe(false);\n      expect(body.error.code).toBe('UNAUTHORIZED');\n    });\n\n    it('should reject requests with invalid API key', async () => {\n      const response = await server.inject({\n        method: 'POST',\n        url: '/api/connect',\n        headers: {\n          'X-API-Key': 'invalid-key'\n        },\n        payload: {\n          type: 'mysql',\n          host: 'localhost',\n          port: 3306\n        }\n      });\n\n      expect(response.statusCode).toBe(403);\n      const body = JSON.parse(response.body);\n      expect(body.success).toBe(false);\n      expect(body.error.code).toBe('FORBIDDEN');\n    });\n\n    it('should accept requests with valid API key', async () => {\n      const response = await server.inject({\n        method: 'POST',\n        url: '/api/connect',\n        headers: {\n          'X-API-Key': 'test-key'\n        },\n        payload: {\n          type: 'sqlite',\n          filePath: ':memory:'\n        }\n      });\n\n      // May fail due to actual connection, but should pass auth\n      expect([200, 500]).toContain(response.statusCode);\n    });\n  });\n\n  describe('CORS', () => {\n    it('should include CORS headers', async () => {\n      const response = await server.inject({\n        method: 'OPTIONS',\n        url: '/api/health'\n      });\n\n      expect(response.headers['access-control-allow-origin']).toBeDefined();\n      expect(response.headers['access-control-allow-methods']).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "tests/integration/mcp-mode.test.ts",
    "content": "/**\n * MCP Mode Integration Tests\n */\n\nimport { describe, it, expect } from 'vitest';\nimport { DatabaseMCPServer } from '../../src/mcp/mcp-server';\nimport type { DbConfig } from '../../src/types/adapter';\n\ndescribe('MCP Mode Integration Tests', () => {\n  describe('DatabaseMCPServer', () => {\n    it('should create MCP server instance', () => {\n      const config: DbConfig = {\n        type: 'sqlite',\n        filePath: ':memory:',\n        allowWrite: false\n      };\n\n      const server = new DatabaseMCPServer(config);\n      expect(server).toBeDefined();\n    });\n\n    it('should require adapter before starting', async () => {\n      const config: DbConfig = {\n        type: 'sqlite',\n        filePath: ':memory:',\n        allowWrite: false\n      };\n\n      const server = new DatabaseMCPServer(config);\n\n      await expect(server.start()).rejects.toThrow('必须先设置数据库适配器');\n    });\n  });\n});\n"
  },
  {
    "path": "tests/unit/adapter-factory.test.ts",
    "content": "/**\n * Adapter Factory Unit Tests\n */\n\nimport { describe, it, expect } from 'vitest';\nimport { createAdapter, normalizeDbType, validateDbConfig } from '../../src/utils/adapter-factory';\nimport type { DbConfig } from '../../src/types/adapter';\n\ndescribe('Adapter Factory', () => {\n  describe('normalizeDbType', () => {\n    it('should normalize mssql to sqlserver', () => {\n      expect(normalizeDbType('mssql')).toBe('sqlserver');\n    });\n\n    it('should normalize opengauss to gaussdb', () => {\n      expect(normalizeDbType('opengauss')).toBe('gaussdb');\n    });\n\n    it('should keep valid types unchanged', () => {\n      expect(normalizeDbType('mysql')).toBe('mysql');\n      expect(normalizeDbType('postgres')).toBe('postgres');\n    });\n\n    it('should throw error for invalid types', () => {\n      expect(() => normalizeDbType('invalid')).toThrow();\n    });\n  });\n\n  describe('validateDbConfig', () => {\n    it('should validate SQLite config', () => {\n      const config: DbConfig = {\n        type: 'sqlite',\n        filePath: '/path/to/db.sqlite'\n      };\n      expect(() => validateDbConfig(config)).not.toThrow();\n    });\n\n    it('should throw error for SQLite without filePath', () => {\n      const config: DbConfig = {\n        type: 'sqlite'\n      };\n      expect(() => validateDbConfig(config)).toThrow('filePath');\n    });\n\n    it('should validate MySQL config', () => {\n      const config: DbConfig = {\n        type: 'mysql',\n        host: 'localhost',\n        port: 3306\n      };\n      expect(() => validateDbConfig(config)).not.toThrow();\n    });\n\n    it('should throw error for MySQL without host/port', () => {\n      const config: DbConfig = {\n        type: 'mysql'\n      };\n      expect(() => validateDbConfig(config)).toThrow();\n    });\n  });\n\n  describe('createAdapter', () => {\n    it('should create MySQL adapter', () => {\n      const config: DbConfig = {\n        type: 'mysql',\n        host: 'localhost',\n        port: 3306,\n        user: 'root',\n        password: 'password',\n        database: 'test'\n      };\n      const adapter = createAdapter(config);\n      expect(adapter).toBeDefined();\n    });\n\n    it('should create PostgreSQL adapter', () => {\n      const config: DbConfig = {\n        type: 'postgres',\n        host: 'localhost',\n        port: 5432,\n        user: 'postgres',\n        password: 'password',\n        database: 'test'\n      };\n      const adapter = createAdapter(config);\n      expect(adapter).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "tests/unit/config-loader.test.ts",
    "content": "/**\n * Configuration Loader Unit Tests\n */\n\nimport { describe, it, expect, beforeEach, afterEach } from 'vitest';\nimport { loadFromEnv, mergeConfigs } from '../../src/utils/config-loader';\n\ndescribe('Configuration Loader', () => {\n  const originalEnv = process.env;\n\n  beforeEach(() => {\n    process.env = { ...originalEnv };\n  });\n\n  afterEach(() => {\n    process.env = originalEnv;\n  });\n\n  describe('loadFromEnv', () => {\n    it('should load MODE from environment', () => {\n      process.env.MODE = 'http';\n      const config = loadFromEnv();\n      expect(config.mode).toBe('http');\n    });\n\n    it('should load HTTP configuration', () => {\n      process.env.HTTP_PORT = '8080';\n      process.env.HTTP_HOST = '127.0.0.1';\n      process.env.API_KEYS = 'key1,key2';\n\n      const config = loadFromEnv();\n      expect(config.http?.port).toBe(8080);\n      expect(config.http?.host).toBe('127.0.0.1');\n      expect(config.http?.apiKeys).toEqual(['key1', 'key2']);\n    });\n\n    it('should load database configuration', () => {\n      process.env.DB_TYPE = 'mysql';\n      process.env.DB_HOST = 'localhost';\n      process.env.DB_PORT = '3306';\n\n      const config = loadFromEnv();\n      expect(config.database?.type).toBe('mysql');\n      expect(config.database?.host).toBe('localhost');\n      expect(config.database?.port).toBe(3306);\n    });\n  });\n\n  describe('mergeConfigs', () => {\n    it('should merge multiple configs with priority', () => {\n      const config1 = { mode: 'mcp' as const };\n      const config2 = { mode: 'http' as const };\n\n      const merged = mergeConfigs(config1, config2);\n      expect(merged.mode).toBe('http');\n    });\n\n    it('should merge HTTP configs', () => {\n      const config1 = {\n        http: {\n          port: 3000,\n          host: '0.0.0.0',\n          apiKeys: ['key1'],\n          cors: { origins: '*', credentials: false },\n          rateLimit: { max: 100, window: '1m' },\n          logging: { level: 'info' as const, pretty: false },\n          session: { timeout: 3600000, cleanupInterval: 300000 }\n        }\n      };\n      const config2 = {\n        http: {\n          port: 8080,\n          apiKeys: ['key2']\n        }\n      };\n\n      const merged = mergeConfigs(config1, config2);\n      expect(merged.http?.port).toBe(8080);\n      expect(merged.http?.apiKeys).toEqual(['key2']);\n    });\n  });\n});\n"
  },
  {
    "path": "tests/unit/connection-stability.test.ts",
    "content": "/**\n * 连接稳定性增强 - 单元测试\n *\n * 测试范围：\n * 1. isConnectionError - 各类连接错误的识别\n * 2. withRetry - 断线重试逻辑\n * 3. 连接池配置参数验证\n * 4. 达梦心跳保活机制\n */\n\nimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\n\n// ============================================================\n// 1. MySQL 系列 - 连接错误识别 & 重试逻辑\n// ============================================================\ndescribe('MySQL 连接稳定性', () => {\n  // 直接测试 isConnectionError 的正则匹配逻辑\n  const mysqlConnectionErrorPattern =\n    /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/;\n\n  describe('isConnectionError 识别', () => {\n    it('应识别 closed state 错误', () => {\n      expect(mysqlConnectionErrorPattern.test(\"Can't add new command when connection is in closed state\")).toBe(true);\n    });\n\n    it('应识别 ECONNRESET', () => {\n      expect(mysqlConnectionErrorPattern.test('read ECONNRESET')).toBe(true);\n    });\n\n    it('应识别 EPIPE', () => {\n      expect(mysqlConnectionErrorPattern.test('write EPIPE')).toBe(true);\n    });\n\n    it('应识别 ETIMEDOUT', () => {\n      expect(mysqlConnectionErrorPattern.test('connect ETIMEDOUT 10.0.0.1:3306')).toBe(true);\n    });\n\n    it('应识别 PROTOCOL_CONNECTION_LOST', () => {\n      expect(mysqlConnectionErrorPattern.test('PROTOCOL_CONNECTION_LOST')).toBe(true);\n    });\n\n    it('应识别 Connection lost', () => {\n      expect(mysqlConnectionErrorPattern.test('Connection lost: The server closed the connection.')).toBe(true);\n    });\n\n    it('应识别 ECONNREFUSED', () => {\n      expect(mysqlConnectionErrorPattern.test('connect ECONNREFUSED 127.0.0.1:3306')).toBe(true);\n    });\n\n    it('不应误判普通 SQL 错误', () => {\n      expect(mysqlConnectionErrorPattern.test(\"Unknown column 'foo' in 'field list'\")).toBe(false);\n    });\n\n    it('不应误判语法错误', () => {\n      expect(mysqlConnectionErrorPattern.test('You have an error in your SQL syntax')).toBe(false);\n    });\n\n    it('不应误判权限错误', () => {\n      expect(mysqlConnectionErrorPattern.test('Access denied for user')).toBe(false);\n    });\n\n    it('不应误判表不存在错误', () => {\n      expect(mysqlConnectionErrorPattern.test(\"Table 'test.foo' doesn't exist\")).toBe(false);\n    });\n  });\n\n  describe('withRetry 重试逻辑', () => {\n    // 模拟 withRetry 的核心逻辑\n    function createWithRetry(isConnectionError: (e: unknown) => boolean) {\n      return async function withRetry<T>(fn: () => Promise<T>): Promise<T> {\n        try {\n          return await fn();\n        } catch (error) {\n          if (isConnectionError(error)) {\n            return await fn();\n          }\n          throw error;\n        }\n      };\n    }\n\n    const isConnectionError = (error: unknown) => {\n      const msg = String((error as any)?.message || '');\n      return /closed state|ECONNRESET|EPIPE|ETIMEDOUT|PROTOCOL_CONNECTION_LOST|Connection lost|ECONNREFUSED/.test(msg);\n    };\n\n    const withRetry = createWithRetry(isConnectionError);\n\n    it('正常查询不应重试', async () => {\n      const fn = vi.fn().mockResolvedValue([{ id: 1 }]);\n      const result = await withRetry(fn);\n      expect(result).toEqual([{ id: 1 }]);\n      expect(fn).toHaveBeenCalledTimes(1);\n    });\n\n    it('连接错误应自动重试一次', async () => {\n      const fn = vi.fn()\n        .mockRejectedValueOnce(new Error(\"Can't add new command when connection is in closed state\"))\n        .mockResolvedValue([{ id: 1 }]);\n\n      const result = await withRetry(fn);\n      expect(result).toEqual([{ id: 1 }]);\n      expect(fn).toHaveBeenCalledTimes(2);\n    });\n\n    it('ECONNRESET 应自动重试', async () => {\n      const fn = vi.fn()\n        .mockRejectedValueOnce(new Error('read ECONNRESET'))\n        .mockResolvedValue('ok');\n\n      const result = await withRetry(fn);\n      expect(result).toBe('ok');\n      expect(fn).toHaveBeenCalledTimes(2);\n    });\n\n    it('ETIMEDOUT 应自动重试', async () => {\n      const fn = vi.fn()\n        .mockRejectedValueOnce(new Error('connect ETIMEDOUT'))\n        .mockResolvedValue('ok');\n\n      const result = await withRetry(fn);\n      expect(result).toBe('ok');\n      expect(fn).toHaveBeenCalledTimes(2);\n    });\n\n    it('非连接错误不应重试，直接抛出', async () => {\n      const fn = vi.fn().mockRejectedValue(new Error(\"Unknown column 'foo'\"));\n      await expect(withRetry(fn)).rejects.toThrow(\"Unknown column 'foo'\");\n      expect(fn).toHaveBeenCalledTimes(1);\n    });\n\n    it('重试后仍失败应抛出错误', async () => {\n      const fn = vi.fn().mockRejectedValue(new Error(\"Can't add new command when connection is in closed state\"));\n      await expect(withRetry(fn)).rejects.toThrow('closed state');\n      expect(fn).toHaveBeenCalledTimes(2); // 初次 + 重试 1 次\n    });\n  });\n});\n\n// ============================================================\n// 2. PostgreSQL 系列 - 连接错误识别 & 重试逻辑\n// ============================================================\ndescribe('PostgreSQL 连接稳定性', () => {\n  const pgConnectionErrorPattern =\n    /Connection terminated|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|57P01|57P03|08003|08006/;\n\n  describe('isConnectionError 识别', () => {\n    it('应识别 Connection terminated', () => {\n      expect(pgConnectionErrorPattern.test('Connection terminated unexpectedly')).toBe(true);\n    });\n\n    it('应识别 ECONNRESET', () => {\n      expect(pgConnectionErrorPattern.test('read ECONNRESET')).toBe(true);\n    });\n\n    it('应识别 PG 错误码 57P01 (admin_shutdown)', () => {\n      expect(pgConnectionErrorPattern.test('57P01')).toBe(true);\n    });\n\n    it('应识别 PG 错误码 57P03 (cannot_connect_now)', () => {\n      expect(pgConnectionErrorPattern.test('57P03')).toBe(true);\n    });\n\n    it('应识别 PG 错误码 08003 (connection_does_not_exist)', () => {\n      expect(pgConnectionErrorPattern.test('08003')).toBe(true);\n    });\n\n    it('应识别 PG 错误码 08006 (connection_failure)', () => {\n      expect(pgConnectionErrorPattern.test('08006')).toBe(true);\n    });\n\n    it('不应误判普通查询错误', () => {\n      expect(pgConnectionErrorPattern.test('relation \"foo\" does not exist')).toBe(false);\n    });\n\n    it('不应误判语法错误', () => {\n      expect(pgConnectionErrorPattern.test('syntax error at or near \"SELEC\"')).toBe(false);\n    });\n\n    it('不应误判权限错误', () => {\n      expect(pgConnectionErrorPattern.test('permission denied for table users')).toBe(false);\n    });\n  });\n});\n\n// ============================================================\n// 3. Oracle - 连接错误识别\n// ============================================================\ndescribe('Oracle 连接稳定性', () => {\n  const oracleErrPattern =\n    /NJS-003|NJS-500|NJS-521|DPI-1010|DPI-1080|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED/;\n  const oracleErrNums = [3113, 3114, 3135, 12170, 12571, 28547];\n\n  function isOracleConnectionError(error: { message?: string; errorNum?: number }): boolean {\n    const msg = String(error.message || '');\n    return oracleErrPattern.test(msg) || oracleErrNums.includes(error.errorNum || 0);\n  }\n\n  describe('isConnectionError 识别', () => {\n    it('应识别 NJS-500 (internal error)', () => {\n      expect(isOracleConnectionError({ message: 'NJS-500: internal error' })).toBe(true);\n    });\n\n    it('应识别 NJS-003 (invalid connection)', () => {\n      expect(isOracleConnectionError({ message: 'NJS-003: invalid connection' })).toBe(true);\n    });\n\n    it('应识别 DPI-1010 (not connected)', () => {\n      expect(isOracleConnectionError({ message: 'DPI-1010: not connected' })).toBe(true);\n    });\n\n    it('应识别 ORA-03114 (not connected to ORACLE)', () => {\n      expect(isOracleConnectionError({ errorNum: 3114 })).toBe(true);\n    });\n\n    it('应识别 ORA-03113 (end-of-file on communication channel)', () => {\n      expect(isOracleConnectionError({ errorNum: 3113 })).toBe(true);\n    });\n\n    it('应识别 ORA-12170 (TNS connect timeout)', () => {\n      expect(isOracleConnectionError({ errorNum: 12170 })).toBe(true);\n    });\n\n    it('不应误判 ORA-00942 (table not found)', () => {\n      expect(isOracleConnectionError({ message: 'ORA-00942', errorNum: 942 })).toBe(false);\n    });\n\n    it('不应误判 ORA-01017 (invalid username/password)', () => {\n      expect(isOracleConnectionError({ message: 'ORA-01017', errorNum: 1017 })).toBe(false);\n    });\n  });\n});\n\n// ============================================================\n// 4. 达梦 - 连接错误识别 & 心跳逻辑\n// ============================================================\ndescribe('达梦连接稳定性', () => {\n  const dmConnectionErrorPattern = /closed|ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|网络|连接/;\n\n  describe('isConnectionError 识别', () => {\n    it('应识别 closed 错误', () => {\n      expect(dmConnectionErrorPattern.test('connection closed')).toBe(true);\n    });\n\n    it('应识别 ECONNRESET', () => {\n      expect(dmConnectionErrorPattern.test('read ECONNRESET')).toBe(true);\n    });\n\n    it('应识别中文\"网络\"错误', () => {\n      expect(dmConnectionErrorPattern.test('网络异常')).toBe(true);\n    });\n\n    it('应识别中文\"连接\"错误', () => {\n      expect(dmConnectionErrorPattern.test('连接已断开')).toBe(true);\n    });\n\n    it('不应误判普通 SQL 错误', () => {\n      expect(dmConnectionErrorPattern.test('表不存在')).toBe(false);\n    });\n  });\n\n  describe('心跳保活机制', () => {\n    it('startHeartbeat 应创建定时器', () => {\n      vi.useFakeTimers();\n\n      let heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n      const mockExecute = vi.fn().mockResolvedValue(undefined);\n      const mockConnection = { execute: mockExecute };\n\n      // 模拟 startHeartbeat\n      heartbeatTimer = setInterval(async () => {\n        if (mockConnection) {\n          await mockConnection.execute('SELECT 1 FROM DUAL', []);\n        }\n      }, 30000);\n\n      expect(heartbeatTimer).not.toBeNull();\n\n      // 推进 30 秒，触发一次心跳\n      vi.advanceTimersByTime(30000);\n      expect(mockExecute).toHaveBeenCalledTimes(1);\n      expect(mockExecute).toHaveBeenCalledWith('SELECT 1 FROM DUAL', []);\n\n      // 再推进 30 秒，触发第二次心跳\n      vi.advanceTimersByTime(30000);\n      expect(mockExecute).toHaveBeenCalledTimes(2);\n\n      clearInterval(heartbeatTimer);\n      vi.useRealTimers();\n    });\n\n    it('stopHeartbeat 应清除定时器', () => {\n      vi.useFakeTimers();\n\n      const mockExecute = vi.fn().mockResolvedValue(undefined);\n      let heartbeatTimer: ReturnType<typeof setInterval> | null = setInterval(async () => {\n        await mockExecute();\n      }, 30000);\n\n      // 停止心跳\n      clearInterval(heartbeatTimer);\n      heartbeatTimer = null;\n\n      // 推进时间，不应有更多调用\n      vi.advanceTimersByTime(60000);\n      expect(mockExecute).toHaveBeenCalledTimes(0);\n\n      vi.useRealTimers();\n    });\n  });\n});\n\n// ============================================================\n// 5. 连接池配置参数验证\n// ============================================================\ndescribe('连接池配置参数', () => {\n  describe('MySQL 连接池参数', () => {\n    const expectedConfig = {\n      waitForConnections: true,\n      connectionLimit: 3,\n      maxIdle: 1,\n      idleTimeout: 60000,\n      enableKeepAlive: true,\n      keepAliveInitialDelay: 30000,\n    };\n\n    it('connectionLimit 应为 3', () => {\n      expect(expectedConfig.connectionLimit).toBe(3);\n    });\n\n    it('应启用 TCP Keep-Alive', () => {\n      expect(expectedConfig.enableKeepAlive).toBe(true);\n    });\n\n    it('Keep-Alive 初始延迟应为 30 秒', () => {\n      expect(expectedConfig.keepAliveInitialDelay).toBe(30000);\n    });\n\n    it('空闲超时应为 60 秒', () => {\n      expect(expectedConfig.idleTimeout).toBe(60000);\n    });\n\n    it('最大空闲连接应为 1', () => {\n      expect(expectedConfig.maxIdle).toBe(1);\n    });\n  });\n\n  describe('PostgreSQL 连接池参数', () => {\n    const expectedConfig = {\n      max: 3,\n      idleTimeoutMillis: 60000,\n      keepAlive: true,\n      keepAliveInitialDelayMillis: 30000,\n    };\n\n    it('max 应为 3', () => {\n      expect(expectedConfig.max).toBe(3);\n    });\n\n    it('应启用 Keep-Alive', () => {\n      expect(expectedConfig.keepAlive).toBe(true);\n    });\n\n    it('Keep-Alive 初始延迟应为 30 秒', () => {\n      expect(expectedConfig.keepAliveInitialDelayMillis).toBe(30000);\n    });\n\n    it('空闲超时应为 60 秒', () => {\n      expect(expectedConfig.idleTimeoutMillis).toBe(60000);\n    });\n  });\n\n  describe('Oracle 连接池参数', () => {\n    const expectedConfig = {\n      poolMin: 1,\n      poolMax: 3,\n      poolPingInterval: 30,\n    };\n\n    it('poolMax 应为 3', () => {\n      expect(expectedConfig.poolMax).toBe(3);\n    });\n\n    it('poolMin 应为 1', () => {\n      expect(expectedConfig.poolMin).toBe(1);\n    });\n\n    it('poolPingInterval 应为 30 秒', () => {\n      expect(expectedConfig.poolPingInterval).toBe(30);\n    });\n  });\n});\n"
  },
  {
    "path": "tests/unit/data-masking.test.ts",
    "content": "/**\n * Data Masking Utility Tests\n */\n\nimport { describe, it, expect } from 'vitest';\nimport { DataMasker, createDataMasker } from '../../src/utils/data-masking.js';\n\ndescribe('DataMasker', () => {\n  describe('maskValue', () => {\n    it('should mask phone numbers by column name', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('phone', '13812345678')).toBe('138****5678');\n      expect(masker.maskValue('mobile', '13912345678')).toBe('139****5678');\n      expect(masker.maskValue('telephone', '13612345678')).toBe('136****5678');\n    });\n\n    it('should mask email addresses by column name', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('email', 'test@example.com')).toBe('t***@example.com');\n      expect(masker.maskValue('user_email', 'john.doe@company.org')).toBe('j***@company.org');\n    });\n\n    it('should mask ID cards by column name', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('id_card', '110101199001011234')).toBe('110***********1234');\n      expect(masker.maskValue('idcard', '110101199001011234')).toBe('110***********1234');\n    });\n\n    it('should mask bank cards by column name', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('bank_card', '6222021234567890123')).toBe('************0123');\n      expect(masker.maskValue('card_number', '6222021234567890')).toBe('************7890');\n    });\n\n    it('should fully mask passwords and secrets', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('password', 'secret123')).toBe('******');\n      expect(masker.maskValue('api_key', 'sk-1234567890')).toBe('******');\n      expect(masker.maskValue('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9')).toBe('******');\n    });\n\n    it('should partially mask names and addresses', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('real_name', '张三')).toBe('张*');\n      expect(masker.maskValue('full_name', '李四五')).toBe('李*五');\n      expect(masker.maskValue('address', '北京市朝阳区')).toBe('北****区');\n    });\n\n    it('should not mask null or undefined values', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('phone', null)).toBe(null);\n      expect(masker.maskValue('email', undefined)).toBe(undefined);\n    });\n\n    it('should not mask empty strings', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('phone', '')).toBe('');\n      expect(masker.maskValue('email', '   ')).toBe('   ');\n    });\n  });\n\n  describe('auto-detection', () => {\n    it('should auto-detect and mask phone numbers by format', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('some_field', '13812345678')).toBe('138****5678');\n    });\n\n    it('should auto-detect and mask email addresses by format', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('some_field', 'user@domain.com')).toBe('u***@domain.com');\n    });\n\n    it('should auto-detect and mask ID cards by format', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('some_field', '110101199001011234')).toBe('110***********1234');\n    });\n\n    it('should auto-detect and mask bank cards by format', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('some_field', '6222021234567890123')).toBe('************0123');\n    });\n\n    it('should not mask regular values', () => {\n      const masker = new DataMasker();\n      expect(masker.maskValue('status', 'active')).toBe('active');\n      expect(masker.maskValue('count', '123')).toBe('123');\n      expect(masker.maskValue('name', 'Product A')).toBe('Product A');\n    });\n  });\n\n  describe('maskRow', () => {\n    it('should mask sensitive columns in a row', () => {\n      const masker = new DataMasker();\n      const row = {\n        id: 1,\n        name: 'Test',\n        phone: '13812345678',\n        email: 'test@example.com',\n        status: 'active',\n      };\n\n      const { maskedRow, maskedColumns } = masker.maskRow(row);\n\n      // Note: non-sensitive values pass through unchanged (including type)\n      expect(maskedRow.id).toBe(1);\n      expect(maskedRow.name).toBe('Test');\n      expect(maskedRow.phone).toBe('138****5678');\n      expect(maskedRow.email).toBe('t***@example.com');\n      expect(maskedRow.status).toBe('active');\n      expect(maskedColumns).toContain('phone');\n      expect(maskedColumns).toContain('email');\n      expect(maskedColumns).not.toContain('status');\n      expect(maskedColumns).not.toContain('id');\n    });\n  });\n\n  describe('maskRows', () => {\n    it('should mask sensitive columns in multiple rows', () => {\n      const masker = new DataMasker();\n      const rows = [\n        { id: 1, phone: '13812345678' },\n        { id: 2, phone: '13912345678' },\n      ];\n\n      const { maskedRows, maskedColumns } = masker.maskRows(rows);\n\n      expect(maskedRows[0].phone).toBe('138****5678');\n      expect(maskedRows[1].phone).toBe('139****5678');\n      expect(maskedColumns).toContain('phone');\n    });\n  });\n\n  describe('enabled/disabled', () => {\n    it('should not mask when disabled', () => {\n      const masker = new DataMasker(false);\n      expect(masker.maskValue('phone', '13812345678')).toBe('13812345678');\n      expect(masker.maskValue('email', 'test@example.com')).toBe('test@example.com');\n    });\n\n    it('should allow toggling enabled state', () => {\n      const masker = new DataMasker(true);\n      expect(masker.maskValue('phone', '13812345678')).toBe('138****5678');\n\n      masker.setEnabled(false);\n      expect(masker.maskValue('phone', '13812345678')).toBe('13812345678');\n\n      masker.setEnabled(true);\n      expect(masker.maskValue('phone', '13812345678')).toBe('138****5678');\n    });\n  });\n\n  describe('custom rules', () => {\n    it('should support custom masking rules', () => {\n      const masker = new DataMasker(true, [\n        { pattern: /^custom_field$/i, type: 'full' },\n      ]);\n\n      expect(masker.maskValue('custom_field', 'sensitive data')).toBe('******');\n    });\n  });\n\n  describe('createDataMasker', () => {\n    it('should create a DataMasker instance', () => {\n      const masker = createDataMasker();\n      expect(masker).toBeInstanceOf(DataMasker);\n      expect(masker.isEnabled()).toBe(true);\n    });\n\n    it('should create a disabled DataMasker when specified', () => {\n      const masker = createDataMasker(false);\n      expect(masker.isEnabled()).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"lib\": [\"ES2022\"],\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"./src\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"allowSyntheticDefaultImports\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'node',\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'json', 'html'],\n      exclude: [\n        'node_modules/',\n        'dist/',\n        'tests/',\n        '**/*.test.ts',\n        '**/*.config.ts'\n      ]\n    },\n    testTimeout: 10000,\n    hookTimeout: 10000\n  }\n});\n"
  }
]