{"id":"79819ccd-a97e-4332-be46-a2b6cdef0c86","entityType":"agent","slug":"clawhub-aliramw-dingtalk-ai-table","name":"Dingtalk Ai Table","canonicalUrl":"https://www.xpersona.co/agent/clawhub-aliramw-dingtalk-ai-table","canonicalPath":"/agent/clawhub-aliramw-dingtalk-ai-table","generatedAt":"2026-10-09T21:55:42.914Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":null},"description":"钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 5.3K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s174xfzpfa9vjsavb1twmf90mx83kgrz:dingtalk-ai-table","sourceUrl":"https://clawhub.ai/aliramw/dingtalk-ai-table","homepage":"https://clawhub.ai/aliramw/skills/dingtalk-ai-table","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/aliramw/dingtalk-ai-table","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/aliramw/skills/dingtalk-ai-table","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":70,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Dingtalk Ai Table technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":null},"stars":null,"forks":null,"downloads":5261,"packageName":null,"latestVersion":"0.6.0","tractionLabel":"5.3K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T04:13:54.569Z","lastCrawledAt":"2026-10-09T04:13:54.569Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T04:13:54.569Z","lastVerifiedAt":null,"highlights":[{"version":"0.6.0","createdAt":"2026-03-31T14:16:36.414Z","changelog":"新增完整 skill metadata、快速开始说明、触发测试与示例脚本；发布前验证通过：security 21/21，triggering 2/2","fileCount":null,"zipByteSize":null},{"version":"0.5.4","createdAt":"2026-03-31T08:28:37.086Z","changelog":"发布新的 patch 版本，基于当前最新仓库状态重新发版，无额外功能改动；发布前安全测试 21/21 通过","fileCount":10,"zipByteSize":27568},{"version":"0.5.3","createdAt":"2026-03-31T08:17:33.399Z","changelog":"发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry；复核当前技能目录无未提交功能改动；安全测试 21/21 通过","fileCount":11,"zipByteSize":29755},{"version":"0.5.2","createdAt":"2026-03-10T18:24:05.571Z","changelog":"Add one-time MCP schema gate, fix new MCP link, and keep guidance generic.","fileCount":11,"zipByteSize":26845},{"version":"0.5.1","createdAt":"2026-03-10T16:49:03.077Z","changelog":"修复 ClawHub 审核指出的 metadata mismatch，补充必需二进制与环境变量声明：mcporter、python3、DINGTALK_MCP_URL、OPENCLAW_WORKSPACE。","fileCount":11,"zipByteSize":25377},{"version":"0.5.0","createdAt":"2026-03-10T16:45:44.439Z","changelog":"全面切换到新版钉钉 AI 表格 MCP schema，覆盖 19 个 tools，重写脚本 / 文档 / 测试，21/21 测试通过。","fileCount":11,"zipByteSize":24807},{"version":"0.4.1","createdAt":"2026-03-10T02:27:50.291Z","changelog":"README / SKILL 补充能力更新说明，提示 MCP 能力变化时优先升级技能；无脚本逻辑变更","fileCount":45,"zipByteSize":47997},{"version":"0.4.0","createdAt":"2026-03-06T23:14:39.819Z","changelog":"Fix instruction-scope mismatch for TABLE.md path and align dentryUuid validation with actual API-returned IDs.","fileCount":11,"zipByteSize":27643}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s174xfzpfa9vjsavb1twmf90mx83kgrz:dingtalk-ai-table","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s174xfzpfa9vjsavb1twmf90mx83kgrz:dingtalk-ai-table` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/aliramw/dingtalk-ai-table before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T21:55:42.909Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-aliramw-dingtalk-ai-table/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":null},"readme":"Skill: Dingtalk Ai Table\n\nOwner: aliramw\n\nSummary: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取...\n\nTags: ai-table:0.6.0, dingtalk:0.6.0, latest:0.6.0, mcp:0.6.0, openclaw:0.6.0, skill:0.6.0\n\nVersion history:\n\nv0.6.0 | 2026-03-31T14:16:36.414Z | user\n\n新增完整 skill metadata、快速开始说明、触发测试与示例脚本；发布前验证通过：security 21/21，triggering 2/2\n\nv0.5.4 | 2026-03-31T08:28:37.086Z | user\n\n发布新的 patch 版本，基于当前最新仓库状态重新发版，无额外功能改动；发布前安全测试 21/21 通过\n\nv0.5.3 | 2026-03-31T08:17:33.399Z | user\n\n发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry；复核当前技能目录无未提交功能改动；安全测试 21/21 通过\n\nv0.5.2 | 2026-03-10T18:24:05.571Z | user\n\nAdd one-time MCP schema gate, fix new MCP link, and keep guidance generic.\n\nv0.5.1 | 2026-03-10T16:49:03.077Z | user\n\n修复 ClawHub 审核指出的 metadata mismatch，补充必需二进制与环境变量声明：mcporter、python3、DINGTALK_MCP_URL、OPENCLAW_WORKSPACE。\n\nv0.5.0 | 2026-03-10T16:45:44.439Z | user\n\n全面切换到新版钉钉 AI 表格 MCP schema，覆盖 19 个 tools，重写脚本 / 文档 / 测试，21/21 测试通过。\n\nv0.4.1 | 2026-03-10T02:27:50.291Z | user\n\nREADME / SKILL 补充能力更新说明，提示 MCP 能力变化时优先升级技能；无脚本逻辑变更\n\nv0.4.0 | 2026-03-06T23:14:39.819Z | user\n\nFix instruction-scope mismatch for TABLE.md path and align dentryUuid validation with actual API-returned IDs.\n\nv0.3.9 | 2026-03-06T22:37:12.790Z | user\n\n修正文档中的 mcporter 参数命名示例，明确 key:value 调用需使用 camelCase，补充 5000001 的排查说明。\n\nv0.3.8 | 2026-03-04T20:50:50.899Z | user\n\n新增根节点配置章节：根节点 UUID 保存在 TABLE.md，无需每次调 API 查询\n\nv0.3.7 | 2026-03-02T04:41:28.219Z | user\n\n文档修正：更新 MCP 配置按钮名称说明\n\nv0.3.6 | 2026-03-02T04:32:29.076Z | auto\n\n- 修正 SKILL.md 文档中的认证配置描述，将“获取 MCP Server 配置”误写为“获取 MCP 凭证配置”\n- 版本号未提升，其他功能无变更\n\nv0.3.5 | 2026-02-28T08:52:12.870Z | user\n\n文档完善：补充 add_base_table 创建数据表的示例代码，确保 14/14 API 方法全部覆盖\n\nv0.3.4 | 2026-02-28T05:15:37.175Z | user\n\nv0.3.4: 安全加固 - 添加路径沙箱、UUID 验证、文件白名单、大小限制等安全保护措施\n\nv0.3.3 | 2026-02-27T10:48:13.987Z | user\n\n修复元数据声明：添加 metadata.openclaw.requires 声明 env/bins 需求\n\nv0.3.2 | 2026-02-27T10:37:44.477Z | user\n\n更新获取 Streamable HTTP URL 的说明\n\nv0.3.1 | 2026-02-27T10:01:34.936Z | auto\n\n- 增加了通过环境变量（DINGTALK_MCP_URL）配置 MCP server 的说明，补充了与使用 mcporter config 的对比推荐\n- 优化了凭证安全提醒，推荐持久化存储方式并减少命令历史泄漏风险\n- 说明文档结构优化，提升配置和使用指引的清晰度\n- 未涉及功能接口或参数变更，仅文档细节调整\n\nv0.3.0 | 2026-02-27T09:47:16.588Z | auto\n\n- Version bump to 0.3.0.\n- Updated CHANGELOG.md.\n- No user-facing functionality changes noted in this version.\n\nv0.2.9 | 2026-02-27T09:44:33.129Z | auto\n\ndingtalk-ai-table v0.2.9\n\n- SKILL.md 简化，移除了 requiresBinaries 字段和 requiresCredentials 详细说明，仅简单要求配置 DINGTALK_MCP_URL。\n- 基本说明、命令示例和使用方法未更动，保留安全与操作说明。\n- 依赖、使用场景、注意事项等内容与先前版本大体一致，仅精简认证与依赖要求描述。\n- 版本号更新为 0.2.9。\n\nv0.2.8 | 2026-02-27T09:38:11.570Z | auto\n\n- Added requirements section to SKILL.md, specifying required binaries and credentials.\n- Declared DINGTALK_MCP_URL as a required credential for MCP server access.\n- No breaking changes to workflow or commands; documentation improved for deployment clarity.\n\nv0.2.7 | 2026-02-27T09:32:12.586Z | auto\n\nVersion 0.2.7\n\n- 增强了文档中的安全警示，补充了安装和认证安全注意事项\n- 新增了针对 CLI 和脚本的安全声明与操作建议\n- 明确要求用户在测试环境验证后再操作生产数据\n- 更新了 Streamable HTTP URL 的凭证管理建议\n- 说明了脚本本地行为与网络安全边界\n\nv0.2.6 | 2026-02-27T09:29:16.946Z | auto\n\n- Updated package version to 0.2.6.\n- Updated CHANGELOG.md with latest changes.\n- No functional or documentation changes to the skill itself.\n\nv0.2.5 | 2026-02-27T09:20:27.786Z | auto\n\ndingtalk-ai-table 0.2.5\n\n- Added a new README.md file for clearer usage and documentation.\n- Updated package metadata and changelog.\n- No changes to the core skill logic or commands.\n\nv0.2.4 | 2026-02-26T13:22:12.153Z | auto\n\n- 修正了 MCP Server 配置指引，官方入口由“实例详情”改为“钉钉 MCP 广场”，更新了获取 URL 的页面路径说明。\n- 文档中相关链接与操作路径同步调整，便于用户准确获取配置信息。\n\nv0.2.3 | 2026-02-26T12:04:39.687Z | user\n\n添加 GitHub 仓库链接\n\nv0.2.2 | 2026-02-26T11:36:15.018Z | user\n\n新增 package.json 依赖说明和 Changelog\n\nv0.2.1 | 2026-02-26T10:35:21.298Z | user\n\n更新 MCP Server 配置说明，引导用户从钉钉 MCP 平台获取 Streamable HTTP URL\n\nv0.2.0 | 2026-02-26T10:31:22.918Z | user\n\n更新 MCP Server 配置说明，引导用户从钉钉 MCP 平台获取 Streamable HTTP URL\n\nv0.1.0 | 2026-02-26T07:55:13.739Z | auto\n\nInitial release of dingtalk-ai-table.\n\n- Provides command-line access to DingTalk AI Sheet (multi-dimensional table) via mcporter CLI and MCP server.\n- Supports creating tables, managing table structures, performing CRUD on fields and records.\n- Includes sample workflows, batch operation scripts, and usage instructions.\n- Details field types, typical use cases (data import/export, project/inventory management), and important notes.\n- References API docs and error code documentation for further help.\n\nArchive index:\n\nArchive v0.5.4: 10 files, 27568 bytes\n\nFiles: api-reference.md (10811b), bulk_add_fields.py (9288b), CHANGELOG.md (11952b), error-codes.md (4822b), import_records.py (10552b), package.json (1651b), README.md (1113b), SKILL.md (9872b), test_security.py (9079b), _meta.json (136b)\n\nFile v0.5.4:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\nversion: 0.5.4\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n        - OPENCLAW_WORKSPACE\n      bins:\n        - mcporter\n        - python3\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 版本守门规则（每个 MCP Server 地址只强制检查一次）\n\n在真正开始任何 AI 表格操作前，必须先检查当前 `mcporter` 注册的 `dingtalk-ai-table` MCP server 实际返回的 tools schema。**但这个检查不该每次都重复做；同一个 MCP Server 地址只需要强制检查一次。**\n\n### 一次性检查策略\n\n1. 先读取当前 `mcporter` 里 `dingtalk-ai-table` 对应的 MCP Server 地址。\n2. 用这个地址生成一个本地检查标记（例如基于完整 URL 或其 hash）。\n3. 在工作区保存检查结果，例如放到：\n\n```text\n~/.openclaw/workspace/.cache/dingtalk-ai-table/\n```\n\n建议文件名模式：\n\n```text\nschema-check-<url-hash>.json\n```\n\n4. 如果当前地址对应的检查标记已经存在，并且结果是“已确认新版 schema”，则**跳过重复检查**，直接继续后续 AI 表格操作。\n5. 只有在以下情况才重新强制检查：\n   - 第一次运行，没有检查标记\n   - `mcporter` 里的 MCP Server 地址变了\n   - 之前检查结果是旧版 schema / 检查失败\n   - 用户明确要求重新验证\n\n### 强制检查时执行\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n### 判断标准\n\n如果返回的 tools 仍然是旧版这一套，例如出现：\n- `get_root_node_of_my_document`\n- `create_base_app`\n- `list_base_tables`\n- `add_base_record`\n- `search_base_record`\n- `list_base_field`\n\n或者整体仍然基于：\n- `dentryUuid`\n- `sheetIdOrName`\n- `fieldIdOrName`\n\n那么说明：**虽然 skill 文件已经是新版，但 mcporter 里注册的 MCP server 地址还是旧的，不能继续操作。**\n\n### 遇到旧版 schema 时的强制提示\n\n此时必须明确提示用户：\n\n1. 打开这个页面：\n   `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n2. 点击右侧 **「获取 MCP Server 配置」** 按钮\n3. 复制新的 MCP Server 地址\n4. 用新的地址替换 `mcporter` 里已经注册的 `dingtalk-ai-table` 地址\n5. 替换完成后，再重新执行：\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n只有当返回的 tools 已经变成新版 schema，例如出现：\n- `list_bases`\n- `get_base`\n- `get_tables`\n- `get_fields`\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n- `prepare_attachment_upload`\n\n才允许继续真正的 AI 表格操作。\n\n### 通过检查后的处理\n\n一旦确认当前 MCP Server 地址返回的是新版 schema，就把结果写入本地检查标记。后续只要 `mcporter` 里的 `dingtalk-ai-table` 地址没变，就不要再重复做这一步守门检查。\n\n### 用户提示文案（可直接复用）\n\n```text\n当前 mcporter 里注册的 dingtalk-ai-table 还是旧版 MCP schema，暂时不能按新版技能操作。\n请打开 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail ，点击右侧“获取 MCP Server 配置”按钮，复制新的 MCP Server 地址，并替换 mcporter 里已注册的 dingtalk-ai-table 地址。替换后重新检查 schema，确认出现 list_bases / get_base / create_records 等新版 tools 后，再继续操作 AI 表格。\n```\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail 获取新版钉钉 AI 表格 MCP 的 `Streamable HTTP URL`。\n\n方式一：直接配置到 mcporter\n\n```bash\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n方式二：使用环境变量\n\n```bash\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n> 这个 URL 带访问令牌，等同密码，不要泄露。\n\n### 工作区沙箱\n\n脚本读取本地文件时，会优先使用 `OPENCLAW_WORKSPACE` 作为允许根目录：\n\n```bash\nexport OPENCLAW_WORKSPACE=\"$HOME/.openclaw/workspace\"\n```\n\n未设置时默认使用当前工作目录。\n\n## 核心工具集\n\n### Base 层\n- `list_bases`\n- `search_bases`\n- `get_base`\n- `create_base`\n- `update_base`\n- `delete_base`\n- `search_templates`\n\n### Table 层\n- `get_tables`\n- `create_table`\n- `update_table`\n- `delete_table`\n\n### Field 层\n- `get_fields`\n- `create_fields`\n- `update_field`\n- `delete_field`\n\n### Record 层\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n### 附件层\n- `prepare_attachment_upload`\n\n## 推荐工作流\n\n### 1. 先找 Base\n\n```bash\nmcporter call dingtalk-ai-table list_bases limit=10\nmcporter call dingtalk-ai-table search_bases query=\"销售\"\n```\n\n### 2. 再拿 Table 目录\n\n```bash\nmcporter call dingtalk-ai-table get_base baseId=\"base_xxx\"\n```\n\n### 3. 再展开表结构\n\n```bash\nmcporter call dingtalk-ai-table get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n```\n\n### 4. 字段复杂时读完整配置\n\n```bash\nmcporter call dingtalk-ai-table get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n### 5. 再查 / 写记录\n\n```bash\nmcporter call dingtalk-ai-table query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":20}'\n\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}'\n```\n\n### 6. 写入附件字段\n\nattachment 字段支持三种写法：\n\n**方式一：先上传，再写 fileToken（推荐，可靠）**\n\n```bash\n# Step 1：申请上传地址（返回 uploadUrl 和 fileToken）\nmcporter call dingtalk-ai-table prepare_attachment_upload \\\n  --args '{\"baseId\":\"base_xxx\",\"fileName\":\"report.pdf\",\"size\":102400,\"mimeType\":\"application/pdf\"}'\n\n# Step 2：把文件 PUT 到 uploadUrl（必须带 Content-Type，值必须与 mimeType 完全一致）\ncurl -X PUT \"<uploadUrl>\" \\\n  -H \"Content-Type: application/pdf\" \\\n  --data-binary @report.pdf\n\n# Step 3：把 fileToken 写入记录\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"fileToken\":\"ft_xxx\"}]}}]}'\n```\n\n**方式二：直接传外链 URL（异步转存，best-effort）**\n\n```bash\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"url\":\"https://example.com/file.pdf\"}]}}]}'\n```\n\n> URL 转存是 best-effort 异步链路，返回成功仅表示已受理，不保证立即可读。可靠写入请用 fileToken 方式。\n\n**方式三：原样回传已有附件数据（保留 / 追加已有附件时使用）**\n\n从 `query_records` 读出的 attachment 单元格数据是完整对象数组，字段形状如下：\n\n```json\n[\n  {\n    \"filename\": \"a.xlsx\",\n    \"size\": 92250,\n    \"type\": \"xls\",\n    \"resourceId\": \"<id>\",\n    \"resourceUrl\": \"<resourceUrl>\"\n  }\n]\n```\n\n其中 `type` 是文件类别枚举，常见值为 `\"xls\"`、`\"image\"` 等；`resourceUrl` 通常为有时效的下载链接。\n\n如需保留已有附件，把读出的值原样塞回即可。如需追加新附件，把新的 `{\"fileToken\":\"ft_xxx\"}` 与已有对象合并成一个数组一起传入。\n\n`update_records` 的 attachment 字段格式相同，传入后会整体覆盖该字段。\n\n## 脚本\n\n### 批量新增字段\n\n```bash\npython3 scripts/bulk_add_fields.py <baseId> <tableId> fields.json\n```\n\n`fields.json` 示例：\n\n```json\n[\n  {\"fieldName\":\"任务名\",\"type\":\"text\"},\n  {\"fieldName\":\"优先级\",\"type\":\"singleSelect\",\"config\":{\"options\":[{\"name\":\"高\"},{\"name\":\"中\"},{\"name\":\"低\"}]}}\n]\n```\n\n兼容项：\n- `name` 会自动映射为 `fieldName`\n- `phone` 会自动映射为 `telephone`\n\n### 批量导入记录\n\n```bash\npython3 scripts/import_records.py <baseId> <tableId> data.csv\npython3 scripts/import_records.py <baseId> <tableId> data.json 50\n```\n\n说明：\n- CSV 表头默认按 `fieldId` 解释\n- JSON 支持：\n  - `[{\"cells\": {...}}]`\n  - `[{\"fld_xxx\": \"value\"}]`\n\n## 安全规则\n\n- 文件路径受 `OPENCLAW_WORKSPACE` 沙箱限制\n- 仅允许读取工作区内 `.json` / `.csv` 文件\n- Base / Table / Field / Record ID 都做格式校验\n- 批量上限按 MCP server 实际限制控制：\n  - `create_fields`：最多 15\n  - `get_tables / get_fields`：最多 10\n  - `create_records / update_records / delete_records`：最多 100\n\n## 调试原则\n\n- 先 `get_base`，再 `get_tables`，必要时 `get_fields`\n- 不要猜 `fieldId`\n- 复杂参数一律用 `--args` JSON\n- `singleSelect / multipleSelect` 过滤时必须传 option ID，不是 option name\n\n## 参考\n\n- API 参考：`references/api-reference.md`\n- 错误排查：`references/error-codes.md`\n\nFile v0.5.4:README.md\n\n# dingtalk-ai-table（官方维护）\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\nClawHub 技能地址：https://clawhub.ai/aliramw/dingtalk-ai-table\n\n## 依赖与环境声明\n\n- 必需二进制：`mcporter`、`python3`\n- 必需环境变量：`DINGTALK_MCP_URL`\n- 推荐环境变量：`OPENCLAW_WORKSPACE`（脚本本地文件沙箱根目录）\n\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。\n\nFile v0.5.4:_meta.json\n\n{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.4\",\n  \"publishedAt\": 1774945717086\n}\n\nFile v0.5.4:api-reference.md\n\n# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 1. 能力总览\n\n当前 MCP tools 共 20 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n### 附件管理\n- `prepare_attachment_upload`：为 attachment 字段申请 OSS 直传地址\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10\nmcporter call '<mcp-url>' .search_bases query='销售'\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx'\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}'\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}'\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报'\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n\n```json\n{\n  \"fieldName\": \"优先级\",\n  \"type\": \"singleSelect\",\n  \"config\": {\n    \"options\": [\n      {\"name\": \"高\"},\n      {\"name\": \"中\"},\n      {\"name\": \"低\"}\n    ]\n  }\n}\n```\n\n## 3.10 update_table\n\n重命名 table。\n\n参数：\n- `baseId`\n- `tableId`\n- `newTableName`\n\n## 3.11 delete_table\n\n删除 table。若它是 Base 里最后一张表，会失败。\n\n参数：\n- `baseId`\n- `tableId`\n- `reason`（建议填写）\n\n## 3.12 get_fields\n\n获取字段完整配置。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldIds`：单次最多 10 个\n\n关键用途：\n- 读取单选 / 多选字段 option id\n- 读取日期 / 进度 / 评分等 config\n- 读取关联字段 linkedSheetId\n\n## 3.13 create_fields\n\n批量新增字段。\n\n参数：\n- `baseId`\n- `tableId`\n- `fields`：1~15 个\n\n适用场景：\n- 建表后补字段\n- 添加复杂字段（关联 / 进度 / 评分等）\n\n## 3.14 update_field\n\n更新字段名称或 config；**不能改字段类型**。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n- `newFieldName`（可选）\n- `config`（可选）\n\n注意：\n- `newFieldName` 与 `config` 至少传一个\n- 更新单选 / 多选时，`options` 要传**完整列表**，不是追加\n- 已有选项应尽量保留原 `id`\n\n## 3.15 delete_field\n\n删除字段，不可逆。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n\n限制：\n- 不能删主字段\n- 不能删最后一个字段\n\n## 3.16 query_records\n\n查询记录，支持：\n- `recordIds` 精准查\n- `filters` 条件查\n- `keyword` 全文查\n- `sort` 排序\n- `cursor` 分页\n- `fieldIds` 限定返回字段\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`（可选）\n- `filters`（可选）\n- `keyword`（可选）\n- `sort`（可选）\n- `fieldIds`（可选）\n- `limit`（默认 100，最大 100）\n- `cursor`（可选）\n\n### filters 说明\n\n结构：\n\n```json\n{\n  \"operator\": \"and\",\n  \"operands\": [\n    {\n      \"operator\": \"eq\",\n      \"operands\": [\"fld_status\", \"进行中\"]\n    }\n  ]\n}\n```\n\n注意：\n- `singleSelect / multipleSelect` 做过滤时，**必须传 option id，不是 option name**\n- option id 需先通过 `get_fields` 获取\n\n## 3.17 create_records\n\n批量新增记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`：单次最多 100 条\n\n记录结构：\n\n```json\n{\n  \"cells\": {\n    \"fld_text\": \"文本\",\n    \"fld_num\": 123,\n    \"fld_select\": \"进行中\"\n  }\n}\n```\n\n注意：\n- key 是 **fieldId**，不是字段名\n- `singleSelect / multipleSelect` 写入时可以传 option name\n- `url` 必须传对象：`{\"text\":\"官网\",\"link\":\"https://...\"}`\n- `richText` 必须传对象：`{\"markdown\":\"**加粗**\"}`\n- `group` 字段 key 是 `cid`，不是 `openConversationId`\n- `attachment` 支持三种写法：\n  - `[{\"fileToken\":\"ft_xxx\"}]`：通过 `prepare_attachment_upload` 上传后填入（推荐）\n  - `[{\"url\":\"https://...\"}]`：外链 URL，服务端异步转存，best-effort\n  - `[{\"filename\":\"a.xlsx\",\"size\":92250,\"type\":\"xls\"|\"image\",\"resourceId\":\"<id>\",\"resourceUrl\":\"<resourceUrl>\"}]`：从 `query_records` 读出的原始对象原样回传，用于保留已有附件；`type` 为文件类别枚举（`\"xls\"`、`\"image\"` 等）；追加新附件时与 `fileToken` 对象合并为数组\n\n## 3.18 update_records\n\n批量更新记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`\n\n结构：\n\n```json\n{\n  \"recordId\": \"rec_xxx\",\n  \"cells\": {\n    \"fld_status\": \"已完成\"\n  }\n}\n```\n\n注意：\n- 只传要更新的字段即可\n- 未传字段保持原值\n- `attachment` 字段传入后**整体覆盖**（三种写法均支持：`fileToken`、`url`、完整对象数组）；需保留已有附件时，先从 `query_records` 读出原始对象再原样合并回传\n\n## 3.19 delete_records\n\n批量删除记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`：最多 100 个\n\n## 3.20 prepare_attachment_upload\n\n为 attachment 字段申请带容量校验的 OSS 直传地址。**仅用于 attachment 字段写入链路，不是通用文件上传入口。**\n\n参数：\n- `baseId`：必填\n- `fileName`：必填，必须包含扩展名（如 `report.xlsx`、`photo.png`）\n- `size`：必填，文件字节数，必须大于 0\n- `mimeType`：可选，如 `application/pdf`、`image/png`；不传时服务端按扩展名推断\n\n返回字段（关键）：\n- `uploadUrl`：PUT 上传地址\n- `fileToken`：写入 attachment 字段用的 token\n\n完整上传流程：\n\n```bash\n# 1. 申请上传地址\nmcporter call dingtalk-ai-table prepare_attachment_upload \\\n  --args '{\"baseId\":\"base_xxx\",\"fileName\":\"report.pdf\",\"size\":102400,\"mimeType\":\"application/pdf\"}'\n\n# 2. PUT 文件到 uploadUrl（Content-Type 必须与 mimeType 完全一致）\ncurl -X PUT \"<uploadUrl>\" \\\n  -H \"Content-Type: application/pdf\" \\\n  --data-binary @report.pdf\n\n# 3. 写入记录\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"fileToken\":\"ft_xxx\"}]}}]}'\n```\n\n注意：\n- PUT 请求必须携带 `Content-Type` header，值必须与 `mimeType` 完全一致\n- `prepare_attachment_upload` 不接收文件二进制，实际上传在 MCP 外由客户端完成\n- 此工具不适用于导入类任务的文件上传\n\n---\n\n## 4. 字段类型速查\n\n支持的主要字段类型：\n\n- `text`\n- `number`\n- `singleSelect`\n- `multipleSelect`\n- `date`\n- `currency`\n- `user`\n- `department`\n- `group`\n- `progress`\n- `rating`\n- `checkbox`\n- `attachment`\n- `url`\n- `richText`\n- `telephone`\n- `email`\n- `idCard`\n- `barcode`\n- `geolocation`\n- `primaryDoc`\n- `formula`\n- `unidirectionalLink`\n- `bidirectionalLink`\n- `creator`\n- `lastModifier`\n- `createdTime`\n- `lastModifiedTime`\n\n---\n\n## 5. 已知边界\n\n- `create_table` / `create_fields` 单次最多 **15 个字段**\n- `get_tables` / `get_fields` 单次最多 **10 个对象**\n- `create_records` / `update_records` / `delete_records` / `query_records.recordIds` 单次最多 **100 条**\n- `formula` 字段当前服务实例可能返回 `not supported yet`\n- 关联字段即使传了 `linkedSheetId`，也可能因底层主键约束失败\n- 删除最后一张表会失败：`cannot delete the last sheet`\n\n---\n\n## 6. 参数命名规则\n\n通过 `mcporter call ... key=value` 传参时，参数名必须用 **camelCase**：\n\n- `baseId`\n- `tableId`\n- `fieldId`\n- `recordIds`\n- `newTableName`\n\n不要写成 kebab-case，例如：\n- `base-id`\n- `table-id`\n- `field-id`\n\nCLI 帮助里会显示 `cliName`，但你在 `mcporter call` 命令里最稳的方式仍然是：\n- 简单参数 → `key=value`\n- 复杂参数 → `--args '<json>'`\n\n复杂 payload 一律优先 `--args`。\n\nFile v0.5.4:CHANGELOG.md\n\n## [0.5.4] - 2026-03-31\n\n### 维护发布\n\n- ✅ 发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry\n- ✅ 基于当前最新仓库状态重新发版，无额外功能改动\n- ✅ 发布前重新执行安全测试，结果仍为 21 / 21 通过\n\n## [0.5.3] - 2026-03-31\n\n### 维护发布\n\n- ✅ 发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry\n- ✅ 复核当前技能目录无未提交功能改动，确认本次为发布补发而非代码变更\n- ✅ 发布前重新执行安全测试，结果仍为 21 / 21 通过\n\n## [0.5.2] - 2026-03-11\n\n### 技能流程优化\n\n- ✅ 新增“版本守门规则”：若 `mcporter` 注册的 `dingtalk-ai-table` 仍返回旧版 schema，必须先提示用户去新版 MCP 页面获取新的 Server 地址，再替换本地注册配置\n- ✅ 修正新版 MCP 获取页面链接为 `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n- ✅ 将守门逻辑优化为“同一个 MCP Server 地址只强制检查一次”，避免每次运行重复做迁移检查\n- ✅ 移除带真实业务场景的示例内容，保留通用、可复用的技能规则\n\n## [0.5.1] - 2026-03-11\n\n### 元数据修复\n\n- ✅ 补回 `SKILL.md` frontmatter 中的 `version` 与 `metadata.openclaw.requires` 声明\n- ✅ 明确声明必需环境变量：`DINGTALK_MCP_URL`、`OPENCLAW_WORKSPACE`\n- ✅ 明确声明必需二进制：`mcporter`、`python3`\n- ✅ `package.json` 同步补充 `requiredEnv` / `requiresBinaries` / credentials 信息，修复 ClawHub 审核指出的 metadata mismatch\n- ✅ README 同步补充依赖与环境声明\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参数命名，再查 ID / 权限\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 修复 issue #1 中提到的调用误导问题\n\n## [0.3.8] - 2026-03-05\n\n### 文档更新\n\n**SKILL.md 更新：**\n- ✅ 新增\"根节点配置\"章节：根节点 UUID 保存在 `TABLE.md`，无需每次调 API 查询\n- ✅ 提供从 `TABLE.md` 读取根节点并创建表格的示例命令\n\n## [0.3.7] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n# Changelog\n## [0.3.6] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n\n# Changelog\n## [0.3.5] - 2025-12-21\n\n### 文档完善\n\n**SKILL.md 更新：**\n- ✅ 补充 `add_base_table` 创建数据表的示例代码（之前缺失）\n- ✅ 数据表操作部分现在包含完整的 CRUD 示例（创建/列出/重命名/删除）\n- ✅ 确保所有 14 个 API 方法在文档中都有覆盖\n\n**验证结果：**\n- 14/14 API 方法全部覆盖 ✅\n- SKILL.md 和 api-reference.md 保持一致 ✅\n\n**变更说明：**\n- 此版本仅文档更新，无功能变更\n- 修复了用户反馈的\"数据表操作缺少创建方法说明\"问题\n\n\n## [0.3.4] - 2025-02-27\n\n### 🔒 安全加固（重大更新）\n\n**新增安全功能：**\n- ✅ **路径沙箱** - 新增 `resolve_safe_path()` 函数，防止目录遍历攻击（如 `../etc/passwd`）\n- ✅ **dentryUuid 合法性验证** - 所有 dentryUuid 参数都会校验为 API 返回的合法 ID 形态，避免空值和明显异常输入\n- ✅ **文件扩展名白名单** - 仅允许 `.json` 和 `.csv` 文件\n- ✅ **文件大小限制** - JSON 最大 10MB，CSV 最大 50MB，防止 DoS 攻击\n- ✅ **字段类型白名单** - 仅允许预定义的 11 种字段类型\n- ✅ **命令超时保护** - mcporter 命令超时限制（60-120 秒）\n- ✅ **输入清理** - 自动去除空白、验证空值、数字类型自动转换\n\n**脚本重构：**\n- `scripts/bulk_add_fields.py` - 全面安全加固，Python 3.9 兼容\n- `scripts/import_records.py` - 全面安全加固，新增 JSON 导入支持\n\n**测试覆盖：**\n- 新增 `tests/test_security.py` - 25 项自动化安全测试，全部通过 ✅\n- 新增 `tests/TEST_REPORT.md` - 完整测试报告和安全对比分析\n\n**文档更新：**\n- SKILL.md 新增\"安全加固措施\"章节，透明说明所有保护机制\n- 添加配置建议：`OPENCLAW_WORKSPACE` 环境变量\n\n**对比改进：**\n- 安全维度对齐 ontology (Benign) 标准\n- 除 mcporter 外部依赖外，其他风险已降至最低\n\n---\n\n## [0.3.3] - 2026-02-27\n\n### 安全与元数据\n- 在 SKILL.md frontmatter 中添加 `metadata.openclaw.requires` 声明\n- 明确声明需要的环境变量：`DINGTALK_MCP_URL`\n- 明确声明需要的二进制文件：`mcporter`\n- 添加 `primaryEnv: DINGTALK_MCP_URL` 指定主要凭证\n- 添加 `homepage` 字段指向 GitHub 仓库\n- 修复 ClawHub 审核指出的元数据不一致问题\n\n\n## [0.3.2] - 2026-02-27\n\n### 文档\n- 更新获取 Streamable HTTP URL 的说明，添加\"点击'获取 MCP 凭证配置'按钮\"步骤\n- README.md 和 SKILL.md 同步更新\n\n## [0.3.1] - 2026-02-27\n\n### 修复\n- 修复 credentials 存储方式说明不一致的问题\n- package.json 移除 `requiredEnv`，添加 `storageMethod` 说明\n- SKILL.md 补充两种凭证配置方式：`mcporter config`（推荐）和环境变量\n\n## [0.3.0] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.9] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.8] - 2026-02-27\n\n### 修复\n- 修复 registry metadata 未正确声明 required credentials 的问题\n- SKILL.md frontmatter 添加 `requiresCredentials` 和 `requiresBinaries` 声明\n- package.json 改用 `peerDependencies` 声明 mcporter 依赖\n- 明确凭证名称 `DINGTALK_MCP_URL` 和获取方式\n\n## [0.2.7] - 2026-02-27\n\n### 安全\n- 新增\"安全须知\"章节，明确安装前注意事项\n- 添加 mcporter 官方来源说明和验证提示\n- 增加 Streamable HTTP URL 凭证安全警告\n- 补充脚本使用安全说明（源码审查、测试环境优先）\n\n## [0.2.6] - 2026-02-27\n\n### 修复\n- 添加 ClawHub 元数据声明，明确标注所需二进制文件和认证要求\n- 修复安全警告中提到的 metadata omissions 问题\n\n## [0.2.5] - 2026-02-27\n\n### 改进\n- 大幅完善 README.md，增加详细使用指南\n- 新增\"常用命令速查\"表格，方便快速参考\n- 新增\"支持的字段类型\"说明表\n- 新增\"故障排查\"章节（认证失败、权限错误、字段类型不匹配等）\n- 补充批量操作脚本使用说明\n- 添加钉钉讨论群链接\n\n### 文档\n- README.md 从 526 字节扩展至完整使用指南\n\n## [0.2.4] - 2026-02-26\n\n### 更新\n- 更新 MCP 广场 URL 地址为市场详情页 (mcpId=1060)\n\n---\n\n# Changelog\n\n## [0.2.3] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了 GitHub 仓库链接\n\n## [0.2.2] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了包依赖说明\n- 添加了 Changelog\n\n---\n\n## [0.2.1] - 2026-02-26\n\n### 新增\n- 完善 CHANGELOG.md 和 package.json 文件\n- 添加完整的版本管理和发布文档\n\n### 修复\n- 修正技能元数据信息\n\n---\n\n## [0.2.0] - 2026-02-25\n\n### 新增\n- 支持批量操作（最多 1000 条记录）\n- 添加 `update_records` 方法用于批量更新记录\n- 添加字段类型说明文档\n\n### 改进\n- 优化错误处理和错误码说明\n- 完善 API 参考文档\n\n---\n\n## [0.1.0] - 2026-02-24\n\n### 新增\n- 钉钉 AI 表格（多维表）操作支持\n- 表格创建、数据表管理、字段操作、记录增删改查\n- 支持 7 种字段类型：text, number, singleSelect, multipleSelect, date, user, attachment\n\n### 功能详情\n- `get_root_node_of_my_document` - 获取文档根节点\n- `create_base_app` - 创建 AI 表格\n- `search_accessible_ai_tables` - 搜索可访问的表格\n- `list_base_tables` - 列出数据表\n- `update_base_tables` - 重命名数据表\n- `delete_base_table` - 删除数据表\n- `list_base_field` - 查看字段列表\n- `add_base_field` - 添加字段\n- `delete_base_field` - 删除字段\n- `search_base_record` - 查询记录\n- `add_base_record` - 添加记录\n- `delete_base_record` - 删除记录\n\n### 文档\n- API 参考文档 (references/api-reference.md)\n- 错误码说明 (references/error-codes.md)\n- 示例脚本 (scripts/)\n\n### 依赖\n- mcporter CLI (v0.7.0+)\n- 钉钉 MCP Server 配置\n\nFile v0.5.4:error-codes.md\n\n# 钉钉 AI 表格 MCP 常见错误与排查\n\n> 以下内容针对 2026-03-10 后的新 schema：`baseId / tableId / fieldId / recordId`。\n\n## 1. 常见错误模式\n\n### 参数体系写错\n\n**现象**\n- 还在用旧参数：`dentryUuid` / `sheetIdOrName`\n- 接口直接报参数缺失 / 无效请求\n\n**原因**\n- MCP server 已升级到新 schema，但本地脚本或技能文档没跟上\n\n**解决**\n- Base 级：用 `baseId`\n- Table 级：用 `tableId`\n- Field 级：用 `fieldId`\n- Record 级：用 `recordId` / `recordIds`\n\n---\n\n### 参数名大小写或命名风格错误\n\n**现象**\n- 参数看起来传了，但服务端像没收到\n- 报字段缺失 / 资源不存在\n\n**原因**\n- `mcporter call key=value` 方式下参数名必须是 **camelCase**\n\n**正确示例**\n```bash\nmcporter call server.get_base baseId='base_xxx'\nmcporter call server.update_table baseId='base_xxx' tableId='tbl_xxx' newTableName='新表名'\n```\n\n**错误示例**\n```bash\nmcporter call server.get_base base-id='base_xxx'\nmcporter call server.update_table table-id='tbl_xxx'\n```\n\n**建议**\n- 简单参数用 `key=value`\n- 复杂对象、数组一律用 `--args '<json>'`\n\n---\n\n### 输出模式理解错误\n\n**现象**\n- 用较老版本 `mcporter` 调用时，输出格式和预期不一致\n- 误以为 AI 表格 MCP 的返回不是标准 JSON\n\n**解决**\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n---\n\n### 查询记录时单选 / 多选过滤无结果\n\n**现象**\n- 明明记录存在，但 `query_records.filters` 查不出来\n\n**原因**\n- 对 `singleSelect / multipleSelect` 字段做过滤时，必须传 **option id**，不能传 option name\n\n**解决**\n1. 先 `get_fields` 读取字段完整配置\n2. 找到 options 里的 id\n3. 在 filters 里传 id\n\n---\n\n### create_records / update_records 写入失败\n\n**常见原因**\n- `cells` 的 key 用了字段名，不是 `fieldId`\n- `url` 字段直接传字符串\n- `richText` 字段直接传字符串\n- `group` 字段写成 `openConversationId`\n- 单次超过 100 条\n\n**解决**\n- 先用 `get_tables` 拿字段目录，必要时 `get_fields`\n- `url` 用：\n  ```json\n  {\"text\":\"官网\",\"link\":\"https://...\"}\n  ```\n- `richText` 用：\n  ```json\n  {\"markdown\":\"**加粗**\"}\n  ```\n- `group` 用：\n  ```json\n  [{\"cid\":\"74577067501\"}]\n  ```\n\n---\n\n### update_field 更新单选 / 多选后历史数据异常\n\n**现象**\n- 更新选项后，已有单元格显示错乱或丢值\n\n**原因**\n- 更新 `options` 时没有传完整列表\n- 已有 option 没保留原 `id`\n\n**解决**\n- 先 `get_fields` 取完整配置\n- 更新时传完整 options 列表\n- 已有项尽量保留原 `id`\n- 新增项可不传 `id`\n\n---\n\n### delete_table 失败：cannot delete the last sheet\n\n**原因**\n- 该表是 Base 中最后一张表\n\n**解决**\n- 先新建一张表，再删旧表\n- 或者如果目标就是整个 Base 都不要了，改用 `delete_base`\n\n---\n\n### create_fields / create_table 某些字段类型失败\n\n**已知边界**\n- `formula` 当前实例可能 `not supported yet`\n- 关联字段可能因为下游主键约束失败，即使已传 `linkedSheetId`\n\n**建议**\n- 复杂字段拆开单独创建\n- 先建立基础结构，再逐项补复杂字段\n- 遇到关联字段失败，优先检查被关联表的主字段 / 主键约束\n\n---\n\n## 2. 推荐排查顺序\n\n### 先确认 ID 链路\n\n1. `list_bases` / `search_bases` → 拿 `baseId`\n2. `get_base` → 拿 `tableId`\n3. `get_tables` → 拿 `fieldId`\n4. `query_records` / 结果对象 → 拿 `recordId`\n\n别跳步，别猜 ID。\n\n### 再确认 payload 结构\n\n- 新增 / 更新记录：看 `cells`\n- 新增字段：看 `fields[]`\n- 更新字段：看 `config`\n- 查询过滤：看 `filters`\n\n### 最后确认批量上限\n\n- 字段批量：15\n- table / field 详情批量：10\n- record 批量：100\n\n---\n\n## 3. 调试命令模板\n\n### 看 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10\nmcporter call '<mcp-url>' .get_base baseId='base_xxx'\n```\n\n### 看 Table / Field\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n### 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":10}'\n```\n\n### 新增记录\n\n```bash\nmcporter call '<mcp-url>' .create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}'\n```\n\n---\n\n## 4. 一句话原则\n\n- **别再用旧 schema。**\n- **别猜 ID。**\n- **复杂参数一律 `--args`。**\n- **先读结构，再写数据。**\n\nFile v0.5.4:package.json\n\n{\n  \"name\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.4\",\n  \"description\": \"钉钉 AI 表格（多维表）操作技能。基于新版 MCP tools，使用 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 管理。脚本文件 I/O 限制在工作区内。\",\n  \"keywords\": [\n    \"dingtalk\",\n    \"ai-table\",\n    \"mcp\",\n    \"多维表\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"Marila@Dingtalk\",\n  \"contributors\": [\n    \"Marila@Dingtalk\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://clawhub.com/skills/dingtalk-ai-table\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table/issues\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"mcporter\": \">=0.8.1\"\n  },\n  \"clawhub\": {\n    \"requiresBinaries\": [\n      \"mcporter\",\n      \"python3\"\n    ],\n    \"requiredEnv\": [\n      \"DINGTALK_MCP_URL\",\n      \"OPENCLAW_WORKSPACE\"\n    ],\n    \"credentials\": [\n      {\n        \"name\": \"DINGTALK_MCP_URL\",\n        \"description\": \"钉钉 MCP Server Streamable HTTP URL (含访问令牌)\",\n        \"docs\": \"https://mcp.dingtalk.com/#/detail?mcpId=9555\",\n        \"storageMethod\": \"mcporter config (recommended) or environment variable\"\n      },\n      {\n        \"name\": \"OPENCLAW_WORKSPACE\",\n        \"description\": \"本地脚本文件读写沙箱根目录；建议设置为 ~/.openclaw/workspace\",\n        \"docs\": \"https://github.com/aliramw/dingtalk-ai-table\",\n        \"storageMethod\": \"environment variable\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"test\": \"python3 tests/test_security.py\"\n  }\n}\n\nArchive v0.5.3: 11 files, 29755 bytes\n\nFiles: api-reference.md (10811b), bulk_add_fields.py (9288b), CHANGELOG.md (11682b), error-codes.md (4822b), import_records.py (10552b), package.json (1651b), README.md (1113b), SKILL.md (9872b), TEST_REPORT.md (5005b), test_security.py (9079b), _meta.json (136b)\n\nFile v0.5.3:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\nversion: 0.5.3\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n        - OPENCLAW_WORKSPACE\n      bins:\n        - mcporter\n        - python3\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 版本守门规则（每个 MCP Server 地址只强制检查一次）\n\n在真正开始任何 AI 表格操作前，必须先检查当前 `mcporter` 注册的 `dingtalk-ai-table` MCP server 实际返回的 tools schema。**但这个检查不该每次都重复做；同一个 MCP Server 地址只需要强制检查一次。**\n\n### 一次性检查策略\n\n1. 先读取当前 `mcporter` 里 `dingtalk-ai-table` 对应的 MCP Server 地址。\n2. 用这个地址生成一个本地检查标记（例如基于完整 URL 或其 hash）。\n3. 在工作区保存检查结果，例如放到：\n\n```text\n~/.openclaw/workspace/.cache/dingtalk-ai-table/\n```\n\n建议文件名模式：\n\n```text\nschema-check-<url-hash>.json\n```\n\n4. 如果当前地址对应的检查标记已经存在，并且结果是“已确认新版 schema”，则**跳过重复检查**，直接继续后续 AI 表格操作。\n5. 只有在以下情况才重新强制检查：\n   - 第一次运行，没有检查标记\n   - `mcporter` 里的 MCP Server 地址变了\n   - 之前检查结果是旧版 schema / 检查失败\n   - 用户明确要求重新验证\n\n### 强制检查时执行\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n### 判断标准\n\n如果返回的 tools 仍然是旧版这一套，例如出现：\n- `get_root_node_of_my_document`\n- `create_base_app`\n- `list_base_tables`\n- `add_base_record`\n- `search_base_record`\n- `list_base_field`\n\n或者整体仍然基于：\n- `dentryUuid`\n- `sheetIdOrName`\n- `fieldIdOrName`\n\n那么说明：**虽然 skill 文件已经是新版，但 mcporter 里注册的 MCP server 地址还是旧的，不能继续操作。**\n\n### 遇到旧版 schema 时的强制提示\n\n此时必须明确提示用户：\n\n1. 打开这个页面：\n   `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n2. 点击右侧 **「获取 MCP Server 配置」** 按钮\n3. 复制新的 MCP Server 地址\n4. 用新的地址替换 `mcporter` 里已经注册的 `dingtalk-ai-table` 地址\n5. 替换完成后，再重新执行：\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n只有当返回的 tools 已经变成新版 schema，例如出现：\n- `list_bases`\n- `get_base`\n- `get_tables`\n- `get_fields`\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n- `prepare_attachment_upload`\n\n才允许继续真正的 AI 表格操作。\n\n### 通过检查后的处理\n\n一旦确认当前 MCP Server 地址返回的是新版 schema，就把结果写入本地检查标记。后续只要 `mcporter` 里的 `dingtalk-ai-table` 地址没变，就不要再重复做这一步守门检查。\n\n### 用户提示文案（可直接复用）\n\n```text\n当前 mcporter 里注册的 dingtalk-ai-table 还是旧版 MCP schema，暂时不能按新版技能操作。\n请打开 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail ，点击右侧“获取 MCP Server 配置”按钮，复制新的 MCP Server 地址，并替换 mcporter 里已注册的 dingtalk-ai-table 地址。替换后重新检查 schema，确认出现 list_bases / get_base / create_records 等新版 tools 后，再继续操作 AI 表格。\n```\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail 获取新版钉钉 AI 表格 MCP 的 `Streamable HTTP URL`。\n\n方式一：直接配置到 mcporter\n\n```bash\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n方式二：使用环境变量\n\n```bash\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n> 这个 URL 带访问令牌，等同密码，不要泄露。\n\n### 工作区沙箱\n\n脚本读取本地文件时，会优先使用 `OPENCLAW_WORKSPACE` 作为允许根目录：\n\n```bash\nexport OPENCLAW_WORKSPACE=\"$HOME/.openclaw/workspace\"\n```\n\n未设置时默认使用当前工作目录。\n\n## 核心工具集\n\n### Base 层\n- `list_bases`\n- `search_bases`\n- `get_base`\n- `create_base`\n- `update_base`\n- `delete_base`\n- `search_templates`\n\n### Table 层\n- `get_tables`\n- `create_table`\n- `update_table`\n- `delete_table`\n\n### Field 层\n- `get_fields`\n- `create_fields`\n- `update_field`\n- `delete_field`\n\n### Record 层\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n### 附件层\n- `prepare_attachment_upload`\n\n## 推荐工作流\n\n### 1. 先找 Base\n\n```bash\nmcporter call dingtalk-ai-table list_bases limit=10\nmcporter call dingtalk-ai-table search_bases query=\"销售\"\n```\n\n### 2. 再拿 Table 目录\n\n```bash\nmcporter call dingtalk-ai-table get_base baseId=\"base_xxx\"\n```\n\n### 3. 再展开表结构\n\n```bash\nmcporter call dingtalk-ai-table get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n```\n\n### 4. 字段复杂时读完整配置\n\n```bash\nmcporter call dingtalk-ai-table get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n### 5. 再查 / 写记录\n\n```bash\nmcporter call dingtalk-ai-table query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":20}'\n\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}'\n```\n\n### 6. 写入附件字段\n\nattachment 字段支持三种写法：\n\n**方式一：先上传，再写 fileToken（推荐，可靠）**\n\n```bash\n# Step 1：申请上传地址（返回 uploadUrl 和 fileToken）\nmcporter call dingtalk-ai-table prepare_attachment_upload \\\n  --args '{\"baseId\":\"base_xxx\",\"fileName\":\"report.pdf\",\"size\":102400,\"mimeType\":\"application/pdf\"}'\n\n# Step 2：把文件 PUT 到 uploadUrl（必须带 Content-Type，值必须与 mimeType 完全一致）\ncurl -X PUT \"<uploadUrl>\" \\\n  -H \"Content-Type: application/pdf\" \\\n  --data-binary @report.pdf\n\n# Step 3：把 fileToken 写入记录\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"fileToken\":\"ft_xxx\"}]}}]}'\n```\n\n**方式二：直接传外链 URL（异步转存，best-effort）**\n\n```bash\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"url\":\"https://example.com/file.pdf\"}]}}]}'\n```\n\n> URL 转存是 best-effort 异步链路，返回成功仅表示已受理，不保证立即可读。可靠写入请用 fileToken 方式。\n\n**方式三：原样回传已有附件数据（保留 / 追加已有附件时使用）**\n\n从 `query_records` 读出的 attachment 单元格数据是完整对象数组，字段形状如下：\n\n```json\n[\n  {\n    \"filename\": \"a.xlsx\",\n    \"size\": 92250,\n    \"type\": \"xls\",\n    \"resourceId\": \"<id>\",\n    \"resourceUrl\": \"<resourceUrl>\"\n  }\n]\n```\n\n其中 `type` 是文件类别枚举，常见值为 `\"xls\"`、`\"image\"` 等；`resourceUrl` 通常为有时效的下载链接。\n\n如需保留已有附件，把读出的值原样塞回即可。如需追加新附件，把新的 `{\"fileToken\":\"ft_xxx\"}` 与已有对象合并成一个数组一起传入。\n\n`update_records` 的 attachment 字段格式相同，传入后会整体覆盖该字段。\n\n## 脚本\n\n### 批量新增字段\n\n```bash\npython3 scripts/bulk_add_fields.py <baseId> <tableId> fields.json\n```\n\n`fields.json` 示例：\n\n```json\n[\n  {\"fieldName\":\"任务名\",\"type\":\"text\"},\n  {\"fieldName\":\"优先级\",\"type\":\"singleSelect\",\"config\":{\"options\":[{\"name\":\"高\"},{\"name\":\"中\"},{\"name\":\"低\"}]}}\n]\n```\n\n兼容项：\n- `name` 会自动映射为 `fieldName`\n- `phone` 会自动映射为 `telephone`\n\n### 批量导入记录\n\n```bash\npython3 scripts/import_records.py <baseId> <tableId> data.csv\npython3 scripts/import_records.py <baseId> <tableId> data.json 50\n```\n\n说明：\n- CSV 表头默认按 `fieldId` 解释\n- JSON 支持：\n  - `[{\"cells\": {...}}]`\n  - `[{\"fld_xxx\": \"value\"}]`\n\n## 安全规则\n\n- 文件路径受 `OPENCLAW_WORKSPACE` 沙箱限制\n- 仅允许读取工作区内 `.json` / `.csv` 文件\n- Base / Table / Field / Record ID 都做格式校验\n- 批量上限按 MCP server 实际限制控制：\n  - `create_fields`：最多 15\n  - `get_tables / get_fields`：最多 10\n  - `create_records / update_records / delete_records`：最多 100\n\n## 调试原则\n\n- 先 `get_base`，再 `get_tables`，必要时 `get_fields`\n- 不要猜 `fieldId`\n- 复杂参数一律用 `--args` JSON\n- `singleSelect / multipleSelect` 过滤时必须传 option ID，不是 option name\n\n## 参考\n\n- API 参考：`references/api-reference.md`\n- 错误排查：`references/error-codes.md`\n\nFile v0.5.3:README.md\n\n# dingtalk-ai-table（官方维护）\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\nClawHub 技能地址：https://clawhub.ai/aliramw/dingtalk-ai-table\n\n## 依赖与环境声明\n\n- 必需二进制：`mcporter`、`python3`\n- 必需环境变量：`DINGTALK_MCP_URL`\n- 推荐环境变量：`OPENCLAW_WORKSPACE`（脚本本地文件沙箱根目录）\n\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。\n\nFile v0.5.3:_meta.json\n\n{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.3\",\n  \"publishedAt\": 1774945053399\n}\n\nFile v0.5.3:api-reference.md\n\n# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 1. 能力总览\n\n当前 MCP tools 共 20 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n### 附件管理\n- `prepare_attachment_upload`：为 attachment 字段申请 OSS 直传地址\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10\nmcporter call '<mcp-url>' .search_bases query='销售'\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx'\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}'\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}'\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报'\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n\n```json\n{\n  \"fieldName\": \"优先级\",\n  \"type\": \"singleSelect\",\n  \"config\": {\n    \"options\": [\n      {\"name\": \"高\"},\n      {\"name\": \"中\"},\n      {\"name\": \"低\"}\n    ]\n  }\n}\n```\n\n## 3.10 update_table\n\n重命名 table。\n\n参数：\n- `baseId`\n- `tableId`\n- `newTableName`\n\n## 3.11 delete_table\n\n删除 table。若它是 Base 里最后一张表，会失败。\n\n参数：\n- `baseId`\n- `tableId`\n- `reason`（建议填写）\n\n## 3.12 get_fields\n\n获取字段完整配置。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldIds`：单次最多 10 个\n\n关键用途：\n- 读取单选 / 多选字段 option id\n- 读取日期 / 进度 / 评分等 config\n- 读取关联字段 linkedSheetId\n\n## 3.13 create_fields\n\n批量新增字段。\n\n参数：\n- `baseId`\n- `tableId`\n- `fields`：1~15 个\n\n适用场景：\n- 建表后补字段\n- 添加复杂字段（关联 / 进度 / 评分等）\n\n## 3.14 update_field\n\n更新字段名称或 config；**不能改字段类型**。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n- `newFieldName`（可选）\n- `config`（可选）\n\n注意：\n- `newFieldName` 与 `config` 至少传一个\n- 更新单选 / 多选时，`options` 要传**完整列表**，不是追加\n- 已有选项应尽量保留原 `id`\n\n## 3.15 delete_field\n\n删除字段，不可逆。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n\n限制：\n- 不能删主字段\n- 不能删最后一个字段\n\n## 3.16 query_records\n\n查询记录，支持：\n- `recordIds` 精准查\n- `filters` 条件查\n- `keyword` 全文查\n- `sort` 排序\n- `cursor` 分页\n- `fieldIds` 限定返回字段\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`（可选）\n- `filters`（可选）\n- `keyword`（可选）\n- `sort`（可选）\n- `fieldIds`（可选）\n- `limit`（默认 100，最大 100）\n- `cursor`（可选）\n\n### filters 说明\n\n结构：\n\n```json\n{\n  \"operator\": \"and\",\n  \"operands\": [\n    {\n      \"operator\": \"eq\",\n      \"operands\": [\"fld_status\", \"进行中\"]\n    }\n  ]\n}\n```\n\n注意：\n- `singleSelect / multipleSelect` 做过滤时，**必须传 option id，不是 option name**\n- option id 需先通过 `get_fields` 获取\n\n## 3.17 create_records\n\n批量新增记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`：单次最多 100 条\n\n记录结构：\n\n```json\n{\n  \"cells\": {\n    \"fld_text\": \"文本\",\n    \"fld_num\": 123,\n    \"fld_select\": \"进行中\"\n  }\n}\n```\n\n注意：\n- key 是 **fieldId**，不是字段名\n- `singleSelect / multipleSelect` 写入时可以传 option name\n- `url` 必须传对象：`{\"text\":\"官网\",\"link\":\"https://...\"}`\n- `richText` 必须传对象：`{\"markdown\":\"**加粗**\"}`\n- `group` 字段 key 是 `cid`，不是 `openConversationId`\n- `attachment` 支持三种写法：\n  - `[{\"fileToken\":\"ft_xxx\"}]`：通过 `prepare_attachment_upload` 上传后填入（推荐）\n  - `[{\"url\":\"https://...\"}]`：外链 URL，服务端异步转存，best-effort\n  - `[{\"filename\":\"a.xlsx\",\"size\":92250,\"type\":\"xls\"|\"image\",\"resourceId\":\"<id>\",\"resourceUrl\":\"<resourceUrl>\"}]`：从 `query_records` 读出的原始对象原样回传，用于保留已有附件；`type` 为文件类别枚举（`\"xls\"`、`\"image\"` 等）；追加新附件时与 `fileToken` 对象合并为数组\n\n## 3.18 update_records\n\n批量更新记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`\n\n结构：\n\n```json\n{\n  \"recordId\": \"rec_xxx\",\n  \"cells\": {\n    \"fld_status\": \"已完成\"\n  }\n}\n```\n\n注意：\n- 只传要更新的字段即可\n- 未传字段保持原值\n- `attachment` 字段传入后**整体覆盖**（三种写法均支持：`fileToken`、`url`、完整对象数组）；需保留已有附件时，先从 `query_records` 读出原始对象再原样合并回传\n\n## 3.19 delete_records\n\n批量删除记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`：最多 100 个\n\n## 3.20 prepare_attachment_upload\n\n为 attachment 字段申请带容量校验的 OSS 直传地址。**仅用于 attachment 字段写入链路，不是通用文件上传入口。**\n\n参数：\n- `baseId`：必填\n- `fileName`：必填，必须包含扩展名（如 `report.xlsx`、`photo.png`）\n- `size`：必填，文件字节数，必须大于 0\n- `mimeType`：可选，如 `application/pdf`、`image/png`；不传时服务端按扩展名推断\n\n返回字段（关键）：\n- `uploadUrl`：PUT 上传地址\n- `fileToken`：写入 attachment 字段用的 token\n\n完整上传流程：\n\n```bash\n# 1. 申请上传地址\nmcporter call dingtalk-ai-table prepare_attachment_upload \\\n  --args '{\"baseId\":\"base_xxx\",\"fileName\":\"report.pdf\",\"size\":102400,\"mimeType\":\"application/pdf\"}'\n\n# 2. PUT 文件到 uploadUrl（Content-Type 必须与 mimeType 完全一致）\ncurl -X PUT \"<uploadUrl>\" \\\n  -H \"Content-Type: application/pdf\" \\\n  --data-binary @report.pdf\n\n# 3. 写入记录\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_attach\":[{\"fileToken\":\"ft_xxx\"}]}}]}'\n```\n\n注意：\n- PUT 请求必须携带 `Content-Type` header，值必须与 `mimeType` 完全一致\n- `prepare_attachment_upload` 不接收文件二进制，实际上传在 MCP 外由客户端完成\n- 此工具不适用于导入类任务的文件上传\n\n---\n\n## 4. 字段类型速查\n\n支持的主要字段类型：\n\n- `text`\n- `number`\n- `singleSelect`\n- `multipleSelect`\n- `date`\n- `currency`\n- `user`\n- `department`\n- `group`\n- `progress`\n- `rating`\n- `checkbox`\n- `attachment`\n- `url`\n- `richText`\n- `telephone`\n- `email`\n- `idCard`\n- `barcode`\n- `geolocation`\n- `primaryDoc`\n- `formula`\n- `unidirectionalLink`\n- `bidirectionalLink`\n- `creator`\n- `lastModifier`\n- `createdTime`\n- `lastModifiedTime`\n\n---\n\n## 5. 已知边界\n\n- `create_table` / `create_fields` 单次最多 **15 个字段**\n- `get_tables` / `get_fields` 单次最多 **10 个对象**\n- `create_records` / `update_records` / `delete_records` / `query_records.recordIds` 单次最多 **100 条**\n- `formula` 字段当前服务实例可能返回 `not supported yet`\n- 关联字段即使传了 `linkedSheetId`，也可能因底层主键约束失败\n- 删除最后一张表会失败：`cannot delete the last sheet`\n\n---\n\n## 6. 参数命名规则\n\n通过 `mcporter call ... key=value` 传参时，参数名必须用 **camelCase**：\n\n- `baseId`\n- `tableId`\n- `fieldId`\n- `recordIds`\n- `newTableName`\n\n不要写成 kebab-case，例如：\n- `base-id`\n- `table-id`\n- `field-id`\n\nCLI 帮助里会显示 `cliName`，但你在 `mcporter call` 命令里最稳的方式仍然是：\n- 简单参数 → `key=value`\n- 复杂参数 → `--args '<json>'`\n\n复杂 payload 一律优先 `--args`。\n\nFile v0.5.3:CHANGELOG.md\n\n## [0.5.3] - 2026-03-31\n\n### 维护发布\n\n- ✅ 发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry\n- ✅ 复核当前技能目录无未提交功能改动，确认本次为发布补发而非代码变更\n- ✅ 发布前重新执行安全测试，结果仍为 21 / 21 通过\n\n## [0.5.2] - 2026-03-11\n\n### 技能流程优化\n\n- ✅ 新增“版本守门规则”：若 `mcporter` 注册的 `dingtalk-ai-table` 仍返回旧版 schema，必须先提示用户去新版 MCP 页面获取新的 Server 地址，再替换本地注册配置\n- ✅ 修正新版 MCP 获取页面链接为 `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n- ✅ 将守门逻辑优化为“同一个 MCP Server 地址只强制检查一次”，避免每次运行重复做迁移检查\n- ✅ 移除带真实业务场景的示例内容，保留通用、可复用的技能规则\n\n## [0.5.1] - 2026-03-11\n\n### 元数据修复\n\n- ✅ 补回 `SKILL.md` frontmatter 中的 `version` 与 `metadata.openclaw.requires` 声明\n- ✅ 明确声明必需环境变量：`DINGTALK_MCP_URL`、`OPENCLAW_WORKSPACE`\n- ✅ 明确声明必需二进制：`mcporter`、`python3`\n- ✅ `package.json` 同步补充 `requiredEnv` / `requiresBinaries` / credentials 信息，修复 ClawHub 审核指出的 metadata mismatch\n- ✅ README 同步补充依赖与环境声明\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参数命名，再查 ID / 权限\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 修复 issue #1 中提到的调用误导问题\n\n## [0.3.8] - 2026-03-05\n\n### 文档更新\n\n**SKILL.md 更新：**\n- ✅ 新增\"根节点配置\"章节：根节点 UUID 保存在 `TABLE.md`，无需每次调 API 查询\n- ✅ 提供从 `TABLE.md` 读取根节点并创建表格的示例命令\n\n## [0.3.7] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n# Changelog\n## [0.3.6] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n\n# Changelog\n## [0.3.5] - 2025-12-21\n\n### 文档完善\n\n**SKILL.md 更新：**\n- ✅ 补充 `add_base_table` 创建数据表的示例代码（之前缺失）\n- ✅ 数据表操作部分现在包含完整的 CRUD 示例（创建/列出/重命名/删除）\n- ✅ 确保所有 14 个 API 方法在文档中都有覆盖\n\n**验证结果：**\n- 14/14 API 方法全部覆盖 ✅\n- SKILL.md 和 api-reference.md 保持一致 ✅\n\n**变更说明：**\n- 此版本仅文档更新，无功能变更\n- 修复了用户反馈的\"数据表操作缺少创建方法说明\"问题\n\n\n## [0.3.4] - 2025-02-27\n\n### 🔒 安全加固（重大更新）\n\n**新增安全功能：**\n- ✅ **路径沙箱** - 新增 `resolve_safe_path()` 函数，防止目录遍历攻击（如 `../etc/passwd`）\n- ✅ **dentryUuid 合法性验证** - 所有 dentryUuid 参数都会校验为 API 返回的合法 ID 形态，避免空值和明显异常输入\n- ✅ **文件扩展名白名单** - 仅允许 `.json` 和 `.csv` 文件\n- ✅ **文件大小限制** - JSON 最大 10MB，CSV 最大 50MB，防止 DoS 攻击\n- ✅ **字段类型白名单** - 仅允许预定义的 11 种字段类型\n- ✅ **命令超时保护** - mcporter 命令超时限制（60-120 秒）\n- ✅ **输入清理** - 自动去除空白、验证空值、数字类型自动转换\n\n**脚本重构：**\n- `scripts/bulk_add_fields.py` - 全面安全加固，Python 3.9 兼容\n- `scripts/import_records.py` - 全面安全加固，新增 JSON 导入支持\n\n**测试覆盖：**\n- 新增 `tests/test_security.py` - 25 项自动化安全测试，全部通过 ✅\n- 新增 `tests/TEST_REPORT.md` - 完整测试报告和安全对比分析\n\n**文档更新：**\n- SKILL.md 新增\"安全加固措施\"章节，透明说明所有保护机制\n- 添加配置建议：`OPENCLAW_WORKSPACE` 环境变量\n\n**对比改进：**\n- 安全维度对齐 ontology (Benign) 标准\n- 除 mcporter 外部依赖外，其他风险已降至最低\n\n---\n\n## [0.3.3] - 2026-02-27\n\n### 安全与元数据\n- 在 SKILL.md frontmatter 中添加 `metadata.openclaw.requires` 声明\n- 明确声明需要的环境变量：`DINGTALK_MCP_URL`\n- 明确声明需要的二进制文件：`mcporter`\n- 添加 `primaryEnv: DINGTALK_MCP_URL` 指定主要凭证\n- 添加 `homepage` 字段指向 GitHub 仓库\n- 修复 ClawHub 审核指出的元数据不一致问题\n\n\n## [0.3.2] - 2026-02-27\n\n### 文档\n- 更新获取 Streamable HTTP URL 的说明，添加\"点击'获取 MCP 凭证配置'按钮\"步骤\n- README.md 和 SKILL.md 同步更新\n\n## [0.3.1] - 2026-02-27\n\n### 修复\n- 修复 credentials 存储方式说明不一致的问题\n- package.json 移除 `requiredEnv`，添加 `storageMethod` 说明\n- SKILL.md 补充两种凭证配置方式：`mcporter config`（推荐）和环境变量\n\n## [0.3.0] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.9] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.8] - 2026-02-27\n\n### 修复\n- 修复 registry metadata 未正确声明 required credentials 的问题\n- SKILL.md frontmatter 添加 `requiresCredentials` 和 `requiresBinaries` 声明\n- package.json 改用 `peerDependencies` 声明 mcporter 依赖\n- 明确凭证名称 `DINGTALK_MCP_URL` 和获取方式\n\n## [0.2.7] - 2026-02-27\n\n### 安全\n- 新增\"安全须知\"章节，明确安装前注意事项\n- 添加 mcporter 官方来源说明和验证提示\n- 增加 Streamable HTTP URL 凭证安全警告\n- 补充脚本使用安全说明（源码审查、测试环境优先）\n\n## [0.2.6] - 2026-02-27\n\n### 修复\n- 添加 ClawHub 元数据声明，明确标注所需二进制文件和认证要求\n- 修复安全警告中提到的 metadata omissions 问题\n\n## [0.2.5] - 2026-02-27\n\n### 改进\n- 大幅完善 README.md，增加详细使用指南\n- 新增\"常用命令速查\"表格，方便快速参考\n- 新增\"支持的字段类型\"说明表\n- 新增\"故障排查\"章节（认证失败、权限错误、字段类型不匹配等）\n- 补充批量操作脚本使用说明\n- 添加钉钉讨论群链接\n\n### 文档\n- README.md 从 526 字节扩展至完整使用指南\n\n## [0.2.4] - 2026-02-26\n\n### 更新\n- 更新 MCP 广场 URL 地址为市场详情页 (mcpId=1060)\n\n---\n\n# Changelog\n\n## [0.2.3] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了 GitHub 仓库链接\n\n## [0.2.2] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了包依赖说明\n- 添加了 Changelog\n\n---\n\n## [0.2.1] - 2026-02-26\n\n### 新增\n- 完善 CHANGELOG.md 和 package.json 文件\n- 添加完整的版本管理和发布文档\n\n### 修复\n- 修正技能元数据信息\n\n---\n\n## [0.2.0] - 2026-02-25\n\n### 新增\n- 支持批量操作（最多 1000 条记录）\n- 添加 `update_records` 方法用于批量更新记录\n- 添加字段类型说明文档\n\n### 改进\n- 优化错误处理和错误码说明\n- 完善 API 参考文档\n\n---\n\n## [0.1.0] - 2026-02-24\n\n### 新增\n- 钉钉 AI 表格（多维表）操作支持\n- 表格创建、数据表管理、字段操作、记录增删改查\n- 支持 7 种字段类型：text, number, singleSelect, multipleSelect, date, user, attachment\n\n### 功能详情\n- `get_root_node_of_my_document` - 获取文档根节点\n- `create_base_app` - 创建 AI 表格\n- `search_accessible_ai_tables` - 搜索可访问的表格\n- `list_base_tables` - 列出数据表\n- `update_base_tables` - 重命名数据表\n- `delete_base_table` - 删除数据表\n- `list_base_field` - 查看字段列表\n- `add_base_field` - 添加字段\n- `delete_base_field` - 删除字段\n- `search_base_record` - 查询记录\n- `add_base_record` - 添加记录\n- `delete_base_record` - 删除记录\n\n### 文档\n- API 参考文档 (references/api-reference.md)\n- 错误码说明 (references/error-codes.md)\n- 示例脚本 (scripts/)\n\n### 依赖\n- mcporter CLI (v0.7.0+)\n- 钉钉 MCP Server 配置\n\nFile v0.5.3:error-codes.md\n\n# 钉钉 AI 表格 MCP 常见错误与排查\n\n> 以下内容针对 2026-03-10 后的新 schema：`baseId / tableId / fieldId / recordId`。\n\n## 1. 常见错误模式\n\n### 参数体系写错\n\n**现象**\n- 还在用旧参数：`dentryUuid` / `sheetIdOrName`\n- 接口直接报参数缺失 / 无效请求\n\n**原因**\n- MCP server 已升级到新 schema，但本地脚本或技能文档没跟上\n\n**解决**\n- Base 级：用 `baseId`\n- Table 级：用 `tableId`\n- Field 级：用 `fieldId`\n- Record 级：用 `recordId` / `recordIds`\n\n---\n\n### 参数名大小写或命名风格错误\n\n**现象**\n- 参数看起来传了，但服务端像没收到\n- 报字段缺失 / 资源不存在\n\n**原因**\n- `mcporter call key=value` 方式下参数名必须是 **camelCase**\n\n**正确示例**\n```bash\nmcporter call server.get_base baseId='base_xxx'\nmcporter call server.update_table baseId='base_xxx' tableId='tbl_xxx' newTableName='新表名'\n```\n\n**错误示例**\n```bash\nmcporter call server.get_base base-id='base_xxx'\nmcporter call server.update_table table-id='tbl_xxx'\n```\n\n**建议**\n- 简单参数用 `key=value`\n- 复杂对象、数组一律用 `--args '<json>'`\n\n---\n\n### 输出模式理解错误\n\n**现象**\n- 用较老版本 `mcporter` 调用时，输出格式和预期不一致\n- 误以为 AI 表格 MCP 的返回不是标准 JSON\n\n**解决**\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n---\n\n### 查询记录时单选 / 多选过滤无结果\n\n**现象**\n- 明明记录存在，但 `query_records.filters` 查不出来\n\n**原因**\n- 对 `singleSelect / multipleSelect` 字段做过滤时，必须传 **option id**，不能传 option name\n\n**解决**\n1. 先 `get_fields` 读取字段完整配置\n2. 找到 options 里的 id\n3. 在 filters 里传 id\n\n---\n\n### create_records / update_records 写入失败\n\n**常见原因**\n- `cells` 的 key 用了字段名，不是 `fieldId`\n- `url` 字段直接传字符串\n- `richText` 字段直接传字符串\n- `group` 字段写成 `openConversationId`\n- 单次超过 100 条\n\n**解决**\n- 先用 `get_tables` 拿字段目录，必要时 `get_fields`\n- `url` 用：\n  ```json\n  {\"text\":\"官网\",\"link\":\"https://...\"}\n  ```\n- `richText` 用：\n  ```json\n  {\"markdown\":\"**加粗**\"}\n  ```\n- `group` 用：\n  ```json\n  [{\"cid\":\"74577067501\"}]\n  ```\n\n---\n\n### update_field 更新单选 / 多选后历史数据异常\n\n**现象**\n- 更新选项后，已有单元格显示错乱或丢值\n\n**原因**\n- 更新 `options` 时没有传完整列表\n- 已有 option 没保留原 `id`\n\n**解决**\n- 先 `get_fields` 取完整配置\n- 更新时传完整 options 列表\n- 已有项尽量保留原 `id`\n- 新增项可不传 `id`\n\n---\n\n### delete_table 失败：cannot delete the last sheet\n\n**原因**\n- 该表是 Base 中最后一张表\n\n**解决**\n- 先新建一张表，再删旧表\n- 或者如果目标就是整个 Base 都不要了，改用 `delete_base`\n\n---\n\n### create_fields / create_table 某些字段类型失败\n\n**已知边界**\n- `formula` 当前实例可能 `not supported yet`\n- 关联字段可能因为下游主键约束失败，即使已传 `linkedSheetId`\n\n**建议**\n- 复杂字段拆开单独创建\n- 先建立基础结构，再逐项补复杂字段\n- 遇到关联字段失败，优先检查被关联表的主字段 / 主键约束\n\n---\n\n## 2. 推荐排查顺序\n\n### 先确认 ID 链路\n\n1. `list_bases` / `search_bases` → 拿 `baseId`\n2. `get_base` → 拿 `tableId`\n3. `get_tables` → 拿 `fieldId`\n4. `query_records` / 结果对象 → 拿 `recordId`\n\n别跳步，别猜 ID。\n\n### 再确认 payload 结构\n\n- 新增 / 更新记录：看 `cells`\n- 新增字段：看 `fields[]`\n- 更新字段：看 `config`\n- 查询过滤：看 `filters`\n\n### 最后确认批量上限\n\n- 字段批量：15\n- table / field 详情批量：10\n- record 批量：100\n\n---\n\n## 3. 调试命令模板\n\n### 看 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10\nmcporter call '<mcp-url>' .get_base baseId='base_xxx'\n```\n\n### 看 Table / Field\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n### 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":10}'\n```\n\n### 新增记录\n\n```bash\nmcporter call '<mcp-url>' .create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}'\n```\n\n---\n\n## 4. 一句话原则\n\n- **别再用旧 schema。**\n- **别猜 ID。**\n- **复杂参数一律 `--args`。**\n- **先读结构，再写数据。**\n\nFile v0.5.3:TEST_REPORT.md\n\n# 安全加固测试报告\n\n**技能**: dingtalk-ai-table  \n**版本**: 0.3.4 (安全加固版)  \n**测试日期**: 2025-02-27  \n**Python 版本**: 3.9.6\n\n---\n\n## 测试概览\n\n| 项目 | 结果 |\n|------|------|\n| 测试用例总数 | 25 |\n| 通过 | 25 ✅ |\n| 失败 | 0 |\n| 错误 | 0 |\n| 覆盖率 | 安全功能 100% |\n\n---\n\n## 测试类别\n\n### 1. 路径安全限制 (7 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_relative_path_within_root` | 相对路径在允许范围内 | ✅ |\n| `test_subdirectory_path` | 子目录路径在允许范围内 | ✅ |\n| `test_absolute_path_within_root` | 绝对路径在允许范围内 | ✅ |\n| `test_path_traversal_attack` | 目录遍历攻击 (`../etc/passwd`) | ✅ 已阻止 |\n| `test_path_traversal_with_dots` | 多层目录遍历攻击 (`../../etc/passwd`) | ✅ 已阻止 |\n| `test_absolute_path_outside_root` | 绝对路径超出允许范围 (`/etc/passwd`) | ✅ 已阻止 |\n| `test_default_allowed_root` | 未指定允许根目录时使用环境变量 | ✅ |\n\n**安全措施**: `resolve_safe_path()` 函数确保所有文件操作限制在 `OPENCLAW_WORKSPACE` 环境变量或当前工作目录内。\n\n---\n\n### 2. UUID 格式验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_uuid` | 有效的 UUID (含大小写、带换行) | ✅ |\n| `test_invalid_uuid` | 无效的 UUID (空、短、无连字符、无效字符) | ✅ 已拒绝 |\n\n**验证规则**: `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`\n\n---\n\n### 3. 文件扩展名验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_allowed_extensions` | 允许的扩展名 (.json, .csv) | ✅ |\n| `test_disallowed_extensions` | 不允许的扩展名 (.txt, .exe, 无扩展名) | ✅ 已拒绝 |\n\n**白名单**:\n- `bulk_add_fields.py`: `['.json']`\n- `import_records.py`: `['.csv', '.json']`\n\n---\n\n### 4. JSON 安全加载 (3 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_json` | 有效的 JSON 文件 | ✅ |\n| `test_file_size_limit` | 文件大小限制 (10MB) | ✅ 已阻止 |\n| `test_invalid_json` | 无效的 JSON 格式 | ✅ 已捕获异常 |\n\n**限制**: 最大 10MB (bulk_add_fields) / 50MB (import_records)\n\n---\n\n### 5. 字段配置验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_field_configs` | 有效的字段配置 (11 种类型) | ✅ |\n| `test_invalid_field_configs` | 无效的字段配置 (缺少 name、空 name、无效类型等) | ✅ 已拒绝 |\n\n**允许的字段类型**:\n```\ntext, number, singleSelect, multipleSelect,\ndate, user, attachment, checkbox, phone, email, url\n```\n\n---\n\n### 6. 记录验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_record` | 有效的记录格式 | ✅ |\n| `test_invalid_record` | 无效的记录格式 (非对象、缺少 fields 等) | ✅ 已拒绝 |\n\n---\n\n### 7. 记录值清理 (5 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_string_value` | 字符串值保持不变 | ✅ |\n| `test_integer_value` | 整数字符串转换为整数 | ✅ |\n| `test_float_value` | 浮点数字符串转换为浮点数 | ✅ |\n| `test_empty_value` | 空值返回 None | ✅ |\n| `test_whitespace_trimming` | 自动去除首尾空白 | ✅ |\n\n---\n\n### 8. 集成测试 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_bulk_add_fields_workflow` | bulk_add_fields 完整工作流程 | ✅ |\n| `test_import_records_workflow` | import_records 完整工作流程 | ✅ |\n\n---\n\n## 安全改进对比\n\n| 安全维度 | 改进前 | 改进后 |\n|----------|--------|--------|\n| 路径限制 | ❌ 无 | ✅ `resolve_safe_path()` 沙箱 |\n| UUID 验证 | ❌ 无 | ✅ 严格正则验证 |\n| 文件扩展名 | ❌ 无 | ✅ 白名单机制 |\n| 文件大小 | ❌ 无 | ✅ 10MB/50MB 限制 |\n| 字段类型 | ❌ 无 | ✅ 白名单验证 |\n| 命令超时 | ❌ 无 | ✅ 60-120 秒超时 |\n| 输入清理 | ❌ 无 | ✅ 空白修剪、空值处理 |\n| 测试覆盖 | ❌ 无 | ✅ 25 项自动化测试 |\n\n---\n\n## 运行测试\n\n```bash\ncd ~/.openclaw/workspace/skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n---\n\n## 结论\n\n✅ **所有安全加固措施已实施并通过测试**\n\n此次加固显著降低了以下风险：\n1. **目录遍历攻击** - 通过路径沙箱完全阻止\n2. **任意文件读取** - 通过扩展名白名单和路径限制阻止\n3. **命令注入** - 通过 UUID 验证和输入清理降低风险\n4. **DoS 攻击** - 通过文件大小限制和命令超时阻止\n5. **无效数据注入** - 通过字段类型白名单和记录验证阻止\n\n**剩余风险**（已知限制）：\n- 依赖 `mcporter` CLI 工具的安全性（无法避免）\n- 钉钉 API 凭证的安全性（需用户妥善保管）\n\n---\n\n**测试执行者**: AI Agent (main - qwen3.5-397b)  \n**测试环境**: macOS Darwin 25.3.0 (arm64), Python 3.9.6\n\nFile v0.5.3:package.json\n\n{\n  \"name\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.3\",\n  \"description\": \"钉钉 AI 表格（多维表）操作技能。基于新版 MCP tools，使用 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 管理。脚本文件 I/O 限制在工作区内。\",\n  \"keywords\": [\n    \"dingtalk\",\n    \"ai-table\",\n    \"mcp\",\n    \"多维表\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"Marila@Dingtalk\",\n  \"contributors\": [\n    \"Marila@Dingtalk\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://clawhub.com/skills/dingtalk-ai-table\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table/issues\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"mcporter\": \">=0.8.1\"\n  },\n  \"clawhub\": {\n    \"requiresBinaries\": [\n      \"mcporter\",\n      \"python3\"\n    ],\n    \"requiredEnv\": [\n      \"DINGTALK_MCP_URL\",\n      \"OPENCLAW_WORKSPACE\"\n    ],\n    \"credentials\": [\n      {\n        \"name\": \"DINGTALK_MCP_URL\",\n        \"description\": \"钉钉 MCP Server Streamable HTTP URL (含访问令牌)\",\n        \"docs\": \"https://mcp.dingtalk.com/#/detail?mcpId=9555\",\n        \"storageMethod\": \"mcporter config (recommended) or environment variable\"\n      },\n      {\n        \"name\": \"OPENCLAW_WORKSPACE\",\n        \"description\": \"本地脚本文件读写沙箱根目录；建议设置为 ~/.openclaw/workspace\",\n        \"docs\": \"https://github.com/aliramw/dingtalk-ai-table\",\n        \"storageMethod\": \"environment variable\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"test\": \"python3 tests/test_security.py\"\n  }\n}\n\nArchive v0.5.2: 11 files, 26845 bytes\n\nFiles: CHANGELOG.md (11382b), package.json (1651b), README.md (1026b), references/api-reference.md (8428b), references/error-codes.md (4529b), scripts/bulk_add_fields.py (8140b), scripts/import_records.py (9404b), SKILL.md (7707b), tests/TEST_REPORT.md (5005b), tests/test_security.py (9079b), _meta.json (136b)\n\nFile v0.5.2:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\nversion: 0.5.2\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n        - OPENCLAW_WORKSPACE\n      bins:\n        - mcporter\n        - python3\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n## 版本守门规则（每个 MCP Server 地址只强制检查一次）\n\n在真正开始任何 AI 表格操作前，必须先检查当前 `mcporter` 注册的 `dingtalk-ai-table` MCP server 实际返回的 tools schema。**但这个检查不该每次都重复做；同一个 MCP Server 地址只需要强制检查一次。**\n\n### 一次性检查策略\n\n1. 先读取当前 `mcporter` 里 `dingtalk-ai-table` 对应的 MCP Server 地址。\n2. 用这个地址生成一个本地检查标记（例如基于完整 URL 或其 hash）。\n3. 在工作区保存检查结果，例如放到：\n\n```text\n~/.openclaw/workspace/.cache/dingtalk-ai-table/\n```\n\n建议文件名模式：\n\n```text\nschema-check-<url-hash>.json\n```\n\n4. 如果当前地址对应的检查标记已经存在，并且结果是“已确认新版 schema”，则**跳过重复检查**，直接继续后续 AI 表格操作。\n5. 只有在以下情况才重新强制检查：\n   - 第一次运行，没有检查标记\n   - `mcporter` 里的 MCP Server 地址变了\n   - 之前检查结果是旧版 schema / 检查失败\n   - 用户明确要求重新验证\n\n### 强制检查时执行\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n### 判断标准\n\n如果返回的 tools 仍然是旧版这一套，例如出现：\n- `get_root_node_of_my_document`\n- `create_base_app`\n- `list_base_tables`\n- `add_base_record`\n- `search_base_record`\n- `list_base_field`\n\n或者整体仍然基于：\n- `dentryUuid`\n- `sheetIdOrName`\n- `fieldIdOrName`\n\n那么说明：**虽然 skill 文件已经是新版，但 mcporter 里注册的 MCP server 地址还是旧的，不能继续操作。**\n\n### 遇到旧版 schema 时的强制提示\n\n此时必须明确提示用户：\n\n1. 打开这个页面：\n   `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n2. 点击右侧 **「获取 MCP Server 配置」** 按钮\n3. 复制新的 MCP Server 地址\n4. 用新的地址替换 `mcporter` 里已经注册的 `dingtalk-ai-table` 地址\n5. 替换完成后，再重新执行：\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n只有当返回的 tools 已经变成新版 schema，例如出现：\n- `list_bases`\n- `get_base`\n- `get_tables`\n- `get_fields`\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n才允许继续真正的 AI 表格操作。\n\n### 通过检查后的处理\n\n一旦确认当前 MCP Server 地址返回的是新版 schema，就把结果写入本地检查标记。后续只要 `mcporter` 里的 `dingtalk-ai-table` 地址没变，就不要再重复做这一步守门检查。\n\n### 用户提示文案（可直接复用）\n\n```text\n当前 mcporter 里注册的 dingtalk-ai-table 还是旧版 MCP schema，暂时不能按新版技能操作。\n请打开 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail ，点击右侧“获取 MCP Server 配置”按钮，复制新的 MCP Server 地址，并替换 mcporter 里已注册的 dingtalk-ai-table 地址。替换后重新检查 schema，确认出现 list_bases / get_base / create_records 等新版 tools 后，再继续操作 AI 表格。\n```\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail 获取新版钉钉 AI 表格 MCP 的 `Streamable HTTP URL`。\n\n方式一：直接配置到 mcporter\n\n```bash\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n方式二：使用环境变量\n\n```bash\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n> 这个 URL 带访问令牌，等同密码，不要泄露。\n\n### 工作区沙箱\n\n脚本读取本地文件时，会优先使用 `OPENCLAW_WORKSPACE` 作为允许根目录：\n\n```bash\nexport OPENCLAW_WORKSPACE=\"$HOME/.openclaw/workspace\"\n```\n\n未设置时默认使用当前工作目录。\n\n## 核心工具集\n\n### Base 层\n- `list_bases`\n- `search_bases`\n- `get_base`\n- `create_base`\n- `update_base`\n- `delete_base`\n- `search_templates`\n\n### Table 层\n- `get_tables`\n- `create_table`\n- `update_table`\n- `delete_table`\n\n### Field 层\n- `get_fields`\n- `create_fields`\n- `update_field`\n- `delete_field`\n\n### Record 层\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n## 推荐工作流\n\n### 1. 先找 Base\n\n```bash\nmcporter call dingtalk-ai-table list_bases limit=10 --output json\nmcporter call dingtalk-ai-table search_bases query=\"销售\" --output json\n```\n\n### 2. 再拿 Table 目录\n\n```bash\nmcporter call dingtalk-ai-table get_base baseId=\"base_xxx\" --output json\n```\n\n### 3. 再展开表结构\n\n```bash\nmcporter call dingtalk-ai-table get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n### 4. 字段复杂时读完整配置\n\n```bash\nmcporter call dingtalk-ai-table get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 5. 再查 / 写记录\n\n```bash\nmcporter call dingtalk-ai-table query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":20}' \\\n  --output json\n\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n## 脚本\n\n### 批量新增字段\n\n```bash\npython3 scripts/bulk_add_fields.py <baseId> <tableId> fields.json\n```\n\n`fields.json` 示例：\n\n```json\n[\n  {\"fieldName\":\"任务名\",\"type\":\"text\"},\n  {\"fieldName\":\"优先级\",\"type\":\"singleSelect\",\"config\":{\"options\":[{\"name\":\"高\"},{\"name\":\"中\"},{\"name\":\"低\"}]}}\n]\n```\n\n兼容项：\n- `name` 会自动映射为 `fieldName`\n- `phone` 会自动映射为 `telephone`\n\n### 批量导入记录\n\n```bash\npython3 scripts/import_records.py <baseId> <tableId> data.csv\npython3 scripts/import_records.py <baseId> <tableId> data.json 50\n```\n\n说明：\n- CSV 表头默认按 `fieldId` 解释\n- JSON 支持：\n  - `[{\"cells\": {...}}]`\n  - `[{\"fld_xxx\": \"value\"}]`\n\n## 安全规则\n\n- 文件路径受 `OPENCLAW_WORKSPACE` 沙箱限制\n- 仅允许读取工作区内 `.json` / `.csv` 文件\n- Base / Table / Field / Record ID 都做格式校验\n- 批量上限按 MCP server 实际限制控制：\n  - `create_fields`：最多 15\n  - `get_tables / get_fields`：最多 10\n  - `create_records / update_records / delete_records`：最多 100\n\n## 调试原则\n\n- 先 `get_base`，再 `get_tables`，必要时 `get_fields`\n- 不要猜 `fieldId`\n- 复杂参数一律用 `--args` JSON\n- `singleSelect / multipleSelect` 过滤时必须传 option ID，不是 option name\n\n## 参考\n\n- API 参考：`references/api-reference.md`\n- 错误排查：`references/error-codes.md`\n\nFile v0.5.2:README.md\n\n# dingtalk-ai-table\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\n## 依赖与环境声明\n\n- 必需二进制：`mcporter`、`python3`\n- 必需环境变量：`DINGTALK_MCP_URL`\n- 推荐环境变量：`OPENCLAW_WORKSPACE`（脚本本地文件沙箱根目录）\n\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。\n\nFile v0.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.2\",\n  \"publishedAt\": 1773167045571\n}\n\nFile v0.5.2:references/api-reference.md\n\n# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n## 1. 能力总览\n\n当前 MCP tools 共 19 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .search_bases query='销售' --output json\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}' \\\n  --output json\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}' \\\n  --output json\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报' --output json\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n\n```json\n{\n  \"fieldName\": \"优先级\",\n  \"type\": \"singleSelect\",\n  \"config\": {\n    \"options\": [\n      {\"name\": \"高\"},\n      {\"name\": \"中\"},\n      {\"name\": \"低\"}\n    ]\n  }\n}\n```\n\n## 3.10 update_table\n\n重命名 table。\n\n参数：\n- `baseId`\n- `tableId`\n- `newTableName`\n\n## 3.11 delete_table\n\n删除 table。若它是 Base 里最后一张表，会失败。\n\n参数：\n- `baseId`\n- `tableId`\n- `reason`（建议填写）\n\n## 3.12 get_fields\n\n获取字段完整配置。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldIds`：单次最多 10 个\n\n关键用途：\n- 读取单选 / 多选字段 option id\n- 读取日期 / 进度 / 评分等 config\n- 读取关联字段 linkedSheetId\n\n## 3.13 create_fields\n\n批量新增字段。\n\n参数：\n- `baseId`\n- `tableId`\n- `fields`：1~15 个\n\n适用场景：\n- 建表后补字段\n- 添加复杂字段（关联 / 进度 / 评分等）\n\n## 3.14 update_field\n\n更新字段名称或 config；**不能改字段类型**。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n- `newFieldName`（可选）\n- `config`（可选）\n\n注意：\n- `newFieldName` 与 `config` 至少传一个\n- 更新单选 / 多选时，`options` 要传**完整列表**，不是追加\n- 已有选项应尽量保留原 `id`\n\n## 3.15 delete_field\n\n删除字段，不可逆。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n\n限制：\n- 不能删主字段\n- 不能删最后一个字段\n\n## 3.16 query_records\n\n查询记录，支持：\n- `recordIds` 精准查\n- `filters` 条件查\n- `keyword` 全文查\n- `sort` 排序\n- `cursor` 分页\n- `fieldIds` 限定返回字段\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`（可选）\n- `filters`（可选）\n- `keyword`（可选）\n- `sort`（可选）\n- `fieldIds`（可选）\n- `limit`（默认 100，最大 100）\n- `cursor`（可选）\n\n### filters 说明\n\n结构：\n\n```json\n{\n  \"operator\": \"and\",\n  \"operands\": [\n    {\n      \"operator\": \"eq\",\n      \"operands\": [\"fld_status\", \"进行中\"]\n    }\n  ]\n}\n```\n\n注意：\n- `singleSelect / multipleSelect` 做过滤时，**必须传 option id，不是 option name**\n- option id 需先通过 `get_fields` 获取\n\n## 3.17 create_records\n\n批量新增记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`：单次最多 100 条\n\n记录结构：\n\n```json\n{\n  \"cells\": {\n    \"fld_text\": \"文本\",\n    \"fld_num\": 123,\n    \"fld_select\": \"进行中\"\n  }\n}\n```\n\n注意：\n- key 是 **fieldId**，不是字段名\n- `singleSelect / multipleSelect` 写入时可以传 option name\n- `url` 必须传对象：`{\"text\":\"官网\",\"link\":\"https://...\"}`\n- `richText` 必须传对象：`{\"markdown\":\"**加粗**\"}`\n- `group` 字段 key 是 `cid`，不是 `openConversationId`\n\n## 3.18 update_records\n\n批量更新记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`\n\n结构：\n\n```json\n{\n  \"recordId\": \"rec_xxx\",\n  \"cells\": {\n    \"fld_status\": \"已完成\"\n  }\n}\n```\n\n注意：\n- 只传要更新的字段即可\n- 未传字段保持原值\n\n## 3.19 delete_records\n\n批量删除记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`：最多 100 个\n\n---\n\n## 4. 字段类型速查\n\n支持的主要字段类型：\n\n- `text`\n- `number`\n- `singleSelect`\n- `multipleSelect`\n- `date`\n- `currency`\n- `user`\n- `department`\n- `group`\n- `progress`\n- `rating`\n- `checkbox`\n- `attachment`\n- `url`\n- `richText`\n- `telephone`\n- `email`\n- `idCard`\n- `barcode`\n- `geolocation`\n- `primaryDoc`\n- `formula`\n- `unidirectionalLink`\n- `bidirectionalLink`\n- `creator`\n- `lastModifier`\n- `createdTime`\n- `lastModifiedTime`\n\n---\n\n## 5. 已知边界\n\n- `create_table` / `create_fields` 单次最多 **15 个字段**\n- `get_tables` / `get_fields` 单次最多 **10 个对象**\n- `create_records` / `update_records` / `delete_records` / `query_records.recordIds` 单次最多 **100 条**\n- `formula` 字段当前服务实例可能返回 `not supported yet`\n- 关联字段即使传了 `linkedSheetId`，也可能因底层主键约束失败\n- 删除最后一张表会失败：`cannot delete the last sheet`\n\n---\n\n## 6. 参数命名规则\n\n通过 `mcporter call ... key=value` 传参时，参数名必须用 **camelCase**：\n\n- `baseId`\n- `tableId`\n- `fieldId`\n- `recordIds`\n- `newTableName`\n\n不要写成 kebab-case，例如：\n- `base-id`\n- `table-id`\n- `field-id`\n\nCLI 帮助里会显示 `cliName`，但你在 `mcporter call` 命令里最稳的方式仍然是：\n- 简单参数 → `key=value`\n- 复杂参数 → `--args '<json>'`\n\n复杂 payload 一律优先 `--args`。\n\nFile v0.5.2:references/error-codes.md\n\n# 钉钉 AI 表格 MCP 常见错误与排查\n\n> 以下内容针对 2026-03-10 后的新 schema：`baseId / tableId / fieldId / recordId`。\n\n## 1. 常见错误模式\n\n### 参数体系写错\n\n**现象**\n- 还在用旧参数：`dentryUuid` / `sheetIdOrName`\n- 接口直接报参数缺失 / 无效请求\n\n**原因**\n- MCP server 已升级到新 schema，但本地脚本或技能文档没跟上\n\n**解决**\n- Base 级：用 `baseId`\n- Table 级：用 `tableId`\n- Field 级：用 `fieldId`\n- Record 级：用 `recordId` / `recordIds`\n\n---\n\n### 参数名大小写或命名风格错误\n\n**现象**\n- 参数看起来传了，但服务端像没收到\n- 报字段缺失 / 资源不存在\n\n**原因**\n- `mcporter call key=value` 方式下参数名必须是 **camelCase**\n\n**正确示例**\n```bash\nmcporter call server.get_base baseId='base_xxx'\nmcporter call server.update_table baseId='base_xxx' tableId='tbl_xxx' newTableName='新表名'\n```\n\n**错误示例**\n```bash\nmcporter call server.get_base base-id='base_xxx'\nmcporter call server.update_table table-id='tbl_xxx'\n```\n\n**建议**\n- 简单参数用 `key=value`\n- 复杂对象、数组一律用 `--args '<json>'`\n\n---\n\n### 查询记录时单选 / 多选过滤无结果\n\n**现象**\n- 明明记录存在，但 `query_records.filters` 查不出来\n\n**原因**\n- 对 `singleSelect / multipleSelect` 字段做过滤时，必须传 **option id**，不能传 option name\n\n**解决**\n1. 先 `get_fields` 读取字段完整配置\n2. 找到 options 里的 id\n3. 在 filters 里传 id\n\n---\n\n### create_records / update_records 写入失败\n\n**常见原因**\n- `cells` 的 key 用了字段名，不是 `fieldId`\n- `url` 字段直接传字符串\n- `richText` 字段直接传字符串\n- `group` 字段写成 `openConversationId`\n- 单次超过 100 条\n\n**解决**\n- 先用 `get_tables` 拿字段目录，必要时 `get_fields`\n- `url` 用：\n  ```json\n  {\"text\":\"官网\",\"link\":\"https://...\"}\n  ```\n- `richText` 用：\n  ```json\n  {\"markdown\":\"**加粗**\"}\n  ```\n- `group` 用：\n  ```json\n  [{\"cid\":\"74577067501\"}]\n  ```\n\n---\n\n### update_field 更新单选 / 多选后历史数据异常\n\n**现象**\n- 更新选项后，已有单元格显示错乱或丢值\n\n**原因**\n- 更新 `options` 时没有传完整列表\n- 已有 option 没保留原 `id`\n\n**解决**\n- 先 `get_fields` 取完整配置\n- 更新时传完整 options 列表\n- 已有项尽量保留原 `id`\n- 新增项可不传 `id`\n\n---\n\n### delete_table 失败：cannot delete the last sheet\n\n**原因**\n- 该表是 Base 中最后一张表\n\n**解决**\n- 先新建一张表，再删旧表\n- 或者如果目标就是整个 Base 都不要了，改用 `delete_base`\n\n---\n\n### create_fields / create_table 某些字段类型失败\n\n**已知边界**\n- `formula` 当前实例可能 `not supported yet`\n- 关联字段可能因为下游主键约束失败，即使已传 `linkedSheetId`\n\n**建议**\n- 复杂字段拆开单独创建\n- 先建立基础结构，再逐项补复杂字段\n- 遇到关联字段失败，优先检查被关联表的主字段 / 主键约束\n\n---\n\n## 2. 推荐排查顺序\n\n### 先确认 ID 链路\n\n1. `list_bases` / `search_bases` → 拿 `baseId`\n2. `get_base` → 拿 `tableId`\n3. `get_tables` → 拿 `fieldId`\n4. `query_records` / 结果对象 → 拿 `recordId`\n\n别跳步，别猜 ID。\n\n### 再确认 payload 结构\n\n- 新增 / 更新记录：看 `cells`\n- 新增字段：看 `fields[]`\n- 更新字段：看 `config`\n- 查询过滤：看 `filters`\n\n### 最后确认批量上限\n\n- 字段批量：15\n- table / field 详情批量：10\n- record 批量：100\n\n---\n\n## 3. 调试命令模板\n\n### 看 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n### 看 Table / Field\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":10}' \\\n  --output json\n```\n\n### 新增记录\n\n```bash\nmcporter call '<mcp-url>' .create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n---\n\n## 4. 一句话原则\n\n- **别再用旧 schema。**\n- **别猜 ID。**\n- **复杂参数一律 `--args`。**\n- **先读结构，再写数据。**\n\nFile v0.5.2:CHANGELOG.md\n\n## [0.5.2] - 2026-03-11\n\n### 技能流程优化\n\n- ✅ 新增“版本守门规则”：若 `mcporter` 注册的 `dingtalk-ai-table` 仍返回旧版 schema，必须先提示用户去新版 MCP 页面获取新的 Server 地址，再替换本地注册配置\n- ✅ 修正新版 MCP 获取页面链接为 `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n- ✅ 将守门逻辑优化为“同一个 MCP Server 地址只强制检查一次”，避免每次运行重复做迁移检查\n- ✅ 移除带真实业务场景的示例内容，保留通用、可复用的技能规则\n\n## [0.5.1] - 2026-03-11\n\n### 元数据修复\n\n- ✅ 补回 `SKILL.md` frontmatter 中的 `version` 与 `metadata.openclaw.requires` 声明\n- ✅ 明确声明必需环境变量：`DINGTALK_MCP_URL`、`OPENCLAW_WORKSPACE`\n- ✅ 明确声明必需二进制：`mcporter`、`python3`\n- ✅ `package.json` 同步补充 `requiredEnv` / `requiresBinaries` / credentials 信息，修复 ClawHub 审核指出的 metadata mismatch\n- ✅ README 同步补充依赖与环境声明\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参数命名，再查 ID / 权限\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 修复 issue #1 中提到的调用误导问题\n\n## [0.3.8] - 2026-03-05\n\n### 文档更新\n\n**SKILL.md 更新：**\n- ✅ 新增\"根节点配置\"章节：根节点 UUID 保存在 `TABLE.md`，无需每次调 API 查询\n- ✅ 提供从 `TABLE.md` 读取根节点并创建表格的示例命令\n\n## [0.3.7] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n# Changelog\n## [0.3.6] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n\n# Changelog\n## [0.3.5] - 2025-12-21\n\n### 文档完善\n\n**SKILL.md 更新：**\n- ✅ 补充 `add_base_table` 创建数据表的示例代码（之前缺失）\n- ✅ 数据表操作部分现在包含完整的 CRUD 示例（创建/列出/重命名/删除）\n- ✅ 确保所有 14 个 API 方法在文档中都有覆盖\n\n**验证结果：**\n- 14/14 API 方法全部覆盖 ✅\n- SKILL.md 和 api-reference.md 保持一致 ✅\n\n**变更说明：**\n- 此版本仅文档更新，无功能变更\n- 修复了用户反馈的\"数据表操作缺少创建方法说明\"问题\n\n\n## [0.3.4] - 2025-02-27\n\n### 🔒 安全加固（重大更新）\n\n**新增安全功能：**\n- ✅ **路径沙箱** - 新增 `resolve_safe_path()` 函数，防止目录遍历攻击（如 `../etc/passwd`）\n- ✅ **dentryUuid 合法性验证** - 所有 dentryUuid 参数都会校验为 API 返回的合法 ID 形态，避免空值和明显异常输入\n- ✅ **文件扩展名白名单** - 仅允许 `.json` 和 `.csv` 文件\n- ✅ **文件大小限制** - JSON 最大 10MB，CSV 最大 50MB，防止 DoS 攻击\n- ✅ **字段类型白名单** - 仅允许预定义的 11 种字段类型\n- ✅ **命令超时保护** - mcporter 命令超时限制（60-120 秒）\n- ✅ **输入清理** - 自动去除空白、验证空值、数字类型自动转换\n\n**脚本重构：**\n- `scripts/bulk_add_fields.py` - 全面安全加固，Python 3.9 兼容\n- `scripts/import_records.py` - 全面安全加固，新增 JSON 导入支持\n\n**测试覆盖：**\n- 新增 `tests/test_security.py` - 25 项自动化安全测试，全部通过 ✅\n- 新增 `tests/TEST_REPORT.md` - 完整测试报告和安全对比分析\n\n**文档更新：**\n- SKILL.md 新增\"安全加固措施\"章节，透明说明所有保护机制\n- 添加配置建议：`OPENCLAW_WORKSPACE` 环境变量\n\n**对比改进：**\n- 安全维度对齐 ontology (Benign) 标准\n- 除 mcporter 外部依赖外，其他风险已降至最低\n\n---\n\n## [0.3.3] - 2026-02-27\n\n### 安全与元数据\n- 在 SKILL.md frontmatter 中添加 `metadata.openclaw.requires` 声明\n- 明确声明需要的环境变量：`DINGTALK_MCP_URL`\n- 明确声明需要的二进制文件：`mcporter`\n- 添加 `primaryEnv: DINGTALK_MCP_URL` 指定主要凭证\n- 添加 `homepage` 字段指向 GitHub 仓库\n- 修复 ClawHub 审核指出的元数据不一致问题\n\n\n## [0.3.2] - 2026-02-27\n\n### 文档\n- 更新获取 Streamable HTTP URL 的说明，添加\"点击'获取 MCP 凭证配置'按钮\"步骤\n- README.md 和 SKILL.md 同步更新\n\n## [0.3.1] - 2026-02-27\n\n### 修复\n- 修复 credentials 存储方式说明不一致的问题\n- package.json 移除 `requiredEnv`，添加 `storageMethod` 说明\n- SKILL.md 补充两种凭证配置方式：`mcporter config`（推荐）和环境变量\n\n## [0.3.0] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.9] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.8] - 2026-02-27\n\n### 修复\n- 修复 registry metadata 未正确声明 required credentials 的问题\n- SKILL.md frontmatter 添加 `requiresCredentials` 和 `requiresBinaries` 声明\n- package.json 改用 `peerDependencies` 声明 mcporter 依赖\n- 明确凭证名称 `DINGTALK_MCP_URL` 和获取方式\n\n## [0.2.7] - 2026-02-27\n\n### 安全\n- 新增\"安全须知\"章节，明确安装前注意事项\n- 添加 mcporter 官方来源说明和验证提示\n- 增加 Streamable HTTP URL 凭证安全警告\n- 补充脚本使用安全说明（源码审查、测试环境优先）\n\n## [0.2.6] - 2026-02-27\n\n### 修复\n- 添加 ClawHub 元数据声明，明确标注所需二进制文件和认证要求\n- 修复安全警告中提到的 metadata omissions 问题\n\n## [0.2.5] - 2026-02-27\n\n### 改进\n- 大幅完善 README.md，增加详细使用指南\n- 新增\"常用命令速查\"表格，方便快速参考\n- 新增\"支持的字段类型\"说明表\n- 新增\"故障排查\"章节（认证失败、权限错误、字段类型不匹配等）\n- 补充批量操作脚本使用说明\n- 添加钉钉讨论群链接\n\n### 文档\n- README.md 从 526 字节扩展至完整使用指南\n\n## [0.2.4] - 2026-02-26\n\n### 更新\n- 更新 MCP 广场 URL 地址为市场详情页 (mcpId=1060)\n\n---\n\n# Changelog\n\n## [0.2.3] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了 GitHub 仓库链接\n\n## [0.2.2] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了包依赖说明\n- 添加了 Changelog\n\n---\n\n## [0.2.1] - 2026-02-26\n\n### 新增\n- 完善 CHANGELOG.md 和 package.json 文件\n- 添加完整的版本管理和发布文档\n\n### 修复\n- 修正技能元数据信息\n\n---\n\n## [0.2.0] - 2026-02-25\n\n### 新增\n- 支持批量操作（最多 1000 条记录）\n- 添加 `update_records` 方法用于批量更新记录\n- 添加字段类型说明文档\n\n### 改进\n- 优化错误处理和错误码说明\n- 完善 API 参考文档\n\n---\n\n## [0.1.0] - 2026-02-24\n\n### 新增\n- 钉钉 AI 表格（多维表）操作支持\n- 表格创建、数据表管理、字段操作、记录增删改查\n- 支持 7 种字段类型：text, number, singleSelect, multipleSelect, date, user, attachment\n\n### 功能详情\n- `get_root_node_of_my_document` - 获取文档根节点\n- `create_base_app` - 创建 AI 表格\n- `search_accessible_ai_tables` - 搜索可访问的表格\n- `list_base_tables` - 列出数据表\n- `update_base_tables` - 重命名数据表\n- `delete_base_table` - 删除数据表\n- `list_base_field` - 查看字段列表\n- `add_base_field` - 添加字段\n- `delete_base_field` - 删除字段\n- `search_base_record` - 查询记录\n- `add_base_record` - 添加记录\n- `delete_base_record` - 删除记录\n\n### 文档\n- API 参考文档 (references/api-reference.md)\n- 错误码说明 (references/error-codes.md)\n- 示例脚本 (scripts/)\n\n### 依赖\n- mcporter CLI (v0.7.0+)\n- 钉钉 MCP Server 配置\n\nFile v0.5.2:tests/TEST_REPORT.md\n\n# 安全加固测试报告\n\n**技能**: dingtalk-ai-table  \n**版本**: 0.3.4 (安全加固版)  \n**测试日期**: 2025-02-27  \n**Python 版本**: 3.9.6\n\n---\n\n## 测试概览\n\n| 项目 | 结果 |\n|------|------|\n| 测试用例总数 | 25 |\n| 通过 | 25 ✅ |\n| 失败 | 0 |\n| 错误 | 0 |\n| 覆盖率 | 安全功能 100% |\n\n---\n\n## 测试类别\n\n### 1. 路径安全限制 (7 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_relative_path_within_root` | 相对路径在允许范围内 | ✅ |\n| `test_subdirectory_path` | 子目录路径在允许范围内 | ✅ |\n| `test_absolute_path_within_root` | 绝对路径在允许范围内 | ✅ |\n| `test_path_traversal_attack` | 目录遍历攻击 (`../etc/passwd`) | ✅ 已阻止 |\n| `test_path_traversal_with_dots` | 多层目录遍历攻击 (`../../etc/passwd`) | ✅ 已阻止 |\n| `test_absolute_path_outside_root` | 绝对路径超出允许范围 (`/etc/passwd`) | ✅ 已阻止 |\n| `test_default_allowed_root` | 未指定允许根目录时使用环境变量 | ✅ |\n\n**安全措施**: `resolve_safe_path()` 函数确保所有文件操作限制在 `OPENCLAW_WORKSPACE` 环境变量或当前工作目录内。\n\n---\n\n### 2. UUID 格式验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_uuid` | 有效的 UUID (含大小写、带换行) | ✅ |\n| `test_invalid_uuid` | 无效的 UUID (空、短、无连字符、无效字符) | ✅ 已拒绝 |\n\n**验证规则**: `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`\n\n---\n\n### 3. 文件扩展名验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_allowed_extensions` | 允许的扩展名 (.json, .csv) | ✅ |\n| `test_disallowed_extensions` | 不允许的扩展名 (.txt, .exe, 无扩展名) | ✅ 已拒绝 |\n\n**白名单**:\n- `bulk_add_fields.py`: `['.json']`\n- `import_records.py`: `['.csv', '.json']`\n\n---\n\n### 4. JSON 安全加载 (3 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_json` | 有效的 JSON 文件 | ✅ |\n| `test_file_size_limit` | 文件大小限制 (10MB) | ✅ 已阻止 |\n| `test_invalid_json` | 无效的 JSON 格式 | ✅ 已捕获异常 |\n\n**限制**: 最大 10MB (bulk_add_fields) / 50MB (import_records)\n\n---\n\n### 5. 字段配置验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_field_configs` | 有效的字段配置 (11 种类型) | ✅ |\n| `test_invalid_field_configs` | 无效的字段配置 (缺少 name、空 name、无效类型等) | ✅ 已拒绝 |\n\n**允许的字段类型**:\n```\ntext, number, singleSelect, multipleSelect,\ndate, user, attachment, checkbox, phone, email, url\n```\n\n---\n\n### 6. 记录验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_record` | 有效的记录格式 | ✅ |\n| `test_invalid_record` | 无效的记录格式 (非对象、缺少 fields 等) | ✅ 已拒绝 |\n\n---\n\n### 7. 记录值清理 (5 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_string_value` | 字符串值保持不变 | ✅ |\n| `test_integer_value` | 整数字符串转换为整数 | ✅ |\n| `test_float_value` | 浮点数字符串转换为浮点数 | ✅ |\n| `test_empty_value` | 空值返回 None | ✅ |\n| `test_whitespace_trimming` | 自动去除首尾空白 | ✅ |\n\n---\n\n### 8. 集成测试 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_bulk_add_fields_workflow` | bulk_add_fields 完整工作流程 | ✅ |\n| `test_import_records_workflow` | import_records 完整工作流程 | ✅ |\n\n---\n\n## 安全改进对比\n\n| 安全维度 | 改进前 | 改进后 |\n|----------|--------|--------|\n| 路径限制 | ❌ 无 | ✅ `resolve_safe_path()` 沙箱 |\n| UUID 验证 | ❌ 无 | ✅ 严格正则验证 |\n| 文件扩展名 | ❌ 无 | ✅ 白名单机制 |\n| 文件大小 | ❌ 无 | ✅ 10MB/50MB 限制 |\n| 字段类型 | ❌ 无 | ✅ 白名单验证 |\n| 命令超时 | ❌ 无 | ✅ 60-120 秒超时 |\n| 输入清理 | ❌ 无 | ✅ 空白修剪、空值处理 |\n| 测试覆盖 | ❌ 无 | ✅ 25 项自动化测试 |\n\n---\n\n## 运行测试\n\n```bash\ncd ~/.openclaw/workspace/skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n---\n\n## 结论\n\n✅ **所有安全加固措施已实施并通过测试**\n\n此次加固显著降低了以下风险：\n1. **目录遍历攻击** - 通过路径沙箱完全阻止\n2. **任意文件读取** - 通过扩展名白名单和路径限制阻止\n3. **命令注入** - 通过 UUID 验证和输入清理降低风险\n4. **DoS 攻击** - 通过文件大小限制和命令超时阻止\n5. **无效数据注入** - 通过字段类型白名单和记录验证阻止\n\n**剩余风险**（已知限制）：\n- 依赖 `mcporter` CLI 工具的安全性（无法避免）\n- 钉钉 API 凭证的安全性（需用户妥善保管）\n\n---\n\n**测试执行者**: AI Agent (main - qwen3.5-397b)  \n**测试环境**: macOS Darwin 25.3.0 (arm64), Python 3.9.6\n\nFile v0.5.2:package.json\n\n{\n  \"name\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.2\",\n  \"description\": \"钉钉 AI 表格（多维表）操作技能。基于新版 MCP tools，使用 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 管理。脚本文件 I/O 限制在工作区内。\",\n  \"keywords\": [\n    \"dingtalk\",\n    \"ai-table\",\n    \"mcp\",\n    \"多维表\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"Marila@Dingtalk\",\n  \"contributors\": [\n    \"Marila@Dingtalk\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://clawhub.com/skills/dingtalk-ai-table\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table/issues\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"mcporter\": \">=0.7.0\"\n  },\n  \"clawhub\": {\n    \"requiresBinaries\": [\n      \"mcporter\",\n      \"python3\"\n    ],\n    \"requiredEnv\": [\n      \"DINGTALK_MCP_URL\",\n      \"OPENCLAW_WORKSPACE\"\n    ],\n    \"credentials\": [\n      {\n        \"name\": \"DINGTALK_MCP_URL\",\n        \"description\": \"钉钉 MCP Server Streamable HTTP URL (含访问令牌)\",\n        \"docs\": \"https://mcp.dingtalk.com/#/detail?mcpId=9555\",\n        \"storageMethod\": \"mcporter config (recommended) or environment variable\"\n      },\n      {\n        \"name\": \"OPENCLAW_WORKSPACE\",\n        \"description\": \"本地脚本文件读写沙箱根目录；建议设置为 ~/.openclaw/workspace\",\n        \"docs\": \"https://github.com/aliramw/dingtalk-ai-table\",\n        \"storageMethod\": \"environment variable\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"test\": \"python3 tests/test_security.py\"\n  }\n}\n\nArchive v0.5.1: 11 files, 25377 bytes\n\nFiles: CHANGELOG.md (10788b), package.json (1651b), README.md (1026b), references/api-reference.md (8428b), references/error-codes.md (4529b), scripts/bulk_add_fields.py (8140b), scripts/import_records.py (9404b), SKILL.md (4599b), tests/TEST_REPORT.md (5005b), tests/test_security.py (9079b), _meta.json (136b)\n\nFile v0.5.1:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\nversion: 0.5.1\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n        - OPENCLAW_WORKSPACE\n      bins:\n        - mcporter\n        - python3\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail 获取新版钉钉 AI 表格 MCP 的 `Streamable HTTP URL`。\n\n方式一：直接配置到 mcporter\n\n```bash\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n方式二：使用环境变量\n\n```bash\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n> 这个 URL 带访问令牌，等同密码，不要泄露。\n\n### 工作区沙箱\n\n脚本读取本地文件时，会优先使用 `OPENCLAW_WORKSPACE` 作为允许根目录：\n\n```bash\nexport OPENCLAW_WORKSPACE=\"$HOME/.openclaw/workspace\"\n```\n\n未设置时默认使用当前工作目录。\n\n## 核心工具集\n\n### Base 层\n- `list_bases`\n- `search_bases`\n- `get_base`\n- `create_base`\n- `update_base`\n- `delete_base`\n- `search_templates`\n\n### Table 层\n- `get_tables`\n- `create_table`\n- `update_table`\n- `delete_table`\n\n### Field 层\n- `get_fields`\n- `create_fields`\n- `update_field`\n- `delete_field`\n\n### Record 层\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n## 推荐工作流\n\n### 1. 先找 Base\n\n```bash\nmcporter call dingtalk-ai-table list_bases limit=10 --output json\nmcporter call dingtalk-ai-table search_bases query=\"销售\" --output json\n```\n\n### 2. 再拿 Table 目录\n\n```bash\nmcporter call dingtalk-ai-table get_base baseId=\"base_xxx\" --output json\n```\n\n### 3. 再展开表结构\n\n```bash\nmcporter call dingtalk-ai-table get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n### 4. 字段复杂时读完整配置\n\n```bash\nmcporter call dingtalk-ai-table get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 5. 再查 / 写记录\n\n```bash\nmcporter call dingtalk-ai-table query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":20}' \\\n  --output json\n\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n## 脚本\n\n### 批量新增字段\n\n```bash\npython3 scripts/bulk_add_fields.py <baseId> <tableId> fields.json\n```\n\n`fields.json` 示例：\n\n```json\n[\n  {\"fieldName\":\"任务名\",\"type\":\"text\"},\n  {\"fieldName\":\"优先级\",\"type\":\"singleSelect\",\"config\":{\"options\":[{\"name\":\"高\"},{\"name\":\"中\"},{\"name\":\"低\"}]}}\n]\n```\n\n兼容项：\n- `name` 会自动映射为 `fieldName`\n- `phone` 会自动映射为 `telephone`\n\n### 批量导入记录\n\n```bash\npython3 scripts/import_records.py <baseId> <tableId> data.csv\npython3 scripts/import_records.py <baseId> <tableId> data.json 50\n```\n\n说明：\n- CSV 表头默认按 `fieldId` 解释\n- JSON 支持：\n  - `[{\"cells\": {...}}]`\n  - `[{\"fld_xxx\": \"value\"}]`\n\n## 安全规则\n\n- 文件路径受 `OPENCLAW_WORKSPACE` 沙箱限制\n- 仅允许读取工作区内 `.json` / `.csv` 文件\n- Base / Table / Field / Record ID 都做格式校验\n- 批量上限按 MCP server 实际限制控制：\n  - `create_fields`：最多 15\n  - `get_tables / get_fields`：最多 10\n  - `create_records / update_records / delete_records`：最多 100\n\n## 调试原则\n\n- 先 `get_base`，再 `get_tables`，必要时 `get_fields`\n- 不要猜 `fieldId`\n- 复杂参数一律用 `--args` JSON\n- `singleSelect / multipleSelect` 过滤时必须传 option ID，不是 option name\n\n## 参考\n\n- API 参考：`references/api-reference.md`\n- 错误排查：`references/error-codes.md`\n\nFile v0.5.1:README.md\n\n# dingtalk-ai-table\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\n## 依赖与环境声明\n\n- 必需二进制：`mcporter`、`python3`\n- 必需环境变量：`DINGTALK_MCP_URL`\n- 推荐环境变量：`OPENCLAW_WORKSPACE`（脚本本地文件沙箱根目录）\n\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。\n\nFile v0.5.1:_meta.json\n\n{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.1\",\n  \"publishedAt\": 1773161343077\n}\n\nFile v0.5.1:references/api-reference.md\n\n# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n## 1. 能力总览\n\n当前 MCP tools 共 19 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .search_bases query='销售' --output json\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}' \\\n  --output json\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}' \\\n  --output json\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报' --output json\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n\n```json\n{\n  \"fieldName\": \"优先级\",\n  \"type\": \"singleSelect\",\n  \"config\": {\n    \"options\": [\n      {\"name\": \"高\"},\n      {\"name\": \"中\"},\n      {\"name\": \"低\"}\n    ]\n  }\n}\n```\n\n## 3.10 update_table\n\n重命名 table。\n\n参数：\n- `baseId`\n- `tableId`\n- `newTableName`\n\n## 3.11 delete_table\n\n删除 table。若它是 Base 里最后一张表，会失败。\n\n参数：\n- `baseId`\n- `tableId`\n- `reason`（建议填写）\n\n## 3.12 get_fields\n\n获取字段完整配置。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldIds`：单次最多 10 个\n\n关键用途：\n- 读取单选 / 多选字段 option id\n- 读取日期 / 进度 / 评分等 config\n- 读取关联字段 linkedSheetId\n\n## 3.13 create_fields\n\n批量新增字段。\n\n参数：\n- `baseId`\n- `tableId`\n- `fields`：1~15 个\n\n适用场景：\n- 建表后补字段\n- 添加复杂字段（关联 / 进度 / 评分等）\n\n## 3.14 update_field\n\n更新字段名称或 config；**不能改字段类型**。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n- `newFieldName`（可选）\n- `config`（可选）\n\n注意：\n- `newFieldName` 与 `config` 至少传一个\n- 更新单选 / 多选时，`options` 要传**完整列表**，不是追加\n- 已有选项应尽量保留原 `id`\n\n## 3.15 delete_field\n\n删除字段，不可逆。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n\n限制：\n- 不能删主字段\n- 不能删最后一个字段\n\n## 3.16 query_records\n\n查询记录，支持：\n- `recordIds` 精准查\n- `filters` 条件查\n- `keyword` 全文查\n- `sort` 排序\n- `cursor` 分页\n- `fieldIds` 限定返回字段\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`（可选）\n- `filters`（可选）\n- `keyword`（可选）\n- `sort`（可选）\n- `fieldIds`（可选）\n- `limit`（默认 100，最大 100）\n- `cursor`（可选）\n\n### filters 说明\n\n结构：\n\n```json\n{\n  \"operator\": \"and\",\n  \"operands\": [\n    {\n      \"operator\": \"eq\",\n      \"operands\": [\"fld_status\", \"进行中\"]\n    }\n  ]\n}\n```\n\n注意：\n- `singleSelect / multipleSelect` 做过滤时，**必须传 option id，不是 option name**\n- option id 需先通过 `get_fields` 获取\n\n## 3.17 create_records\n\n批量新增记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`：单次最多 100 条\n\n记录结构：\n\n```json\n{\n  \"cells\": {\n    \"fld_text\": \"文本\",\n    \"fld_num\": 123,\n    \"fld_select\": \"进行中\"\n  }\n}\n```\n\n注意：\n- key 是 **fieldId**，不是字段名\n- `singleSelect / multipleSelect` 写入时可以传 option name\n- `url` 必须传对象：`{\"text\":\"官网\",\"link\":\"https://...\"}`\n- `richText` 必须传对象：`{\"markdown\":\"**加粗**\"}`\n- `group` 字段 key 是 `cid`，不是 `openConversationId`\n\n## 3.18 update_records\n\n批量更新记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`\n\n结构：\n\n```json\n{\n  \"recordId\": \"rec_xxx\",\n  \"cells\": {\n    \"fld_status\": \"已完成\"\n  }\n}\n```\n\n注意：\n- 只传要更新的字段即可\n- 未传字段保持原值\n\n## 3.19 delete_records\n\n批量删除记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`：最多 100 个\n\n---\n\n## 4. 字段类型速查\n\n支持的主要字段类型：\n\n- `text`\n- `number`\n- `singleSelect`\n- `multipleSelect`\n- `date`\n- `currency`\n- `user`\n- `department`\n- `group`\n- `progress`\n- `rating`\n- `checkbox`\n- `attachment`\n- `url`\n- `richText`\n- `telephone`\n- `email`\n- `idCard`\n- `barcode`\n- `geolocation`\n- `primaryDoc`\n- `formula`\n- `unidirectionalLink`\n- `bidirectionalLink`\n- `creator`\n- `lastModifier`\n- `createdTime`\n- `lastModifiedTime`\n\n---\n\n## 5. 已知边界\n\n- `create_table` / `create_fields` 单次最多 **15 个字段**\n- `get_tables` / `get_fields` 单次最多 **10 个对象**\n- `create_records` / `update_records` / `delete_records` / `query_records.recordIds` 单次最多 **100 条**\n- `formula` 字段当前服务实例可能返回 `not supported yet`\n- 关联字段即使传了 `linkedSheetId`，也可能因底层主键约束失败\n- 删除最后一张表会失败：`cannot delete the last sheet`\n\n---\n\n## 6. 参数命名规则\n\n通过 `mcporter call ... key=value` 传参时，参数名必须用 **camelCase**：\n\n- `baseId`\n- `tableId`\n- `fieldId`\n- `recordIds`\n- `newTableName`\n\n不要写成 kebab-case，例如：\n- `base-id`\n- `table-id`\n- `field-id`\n\nCLI 帮助里会显示 `cliName`，但你在 `mcporter call` 命令里最稳的方式仍然是：\n- 简单参数 → `key=value`\n- 复杂参数 → `--args '<json>'`\n\n复杂 payload 一律优先 `--args`。\n\nFile v0.5.1:references/error-codes.md\n\n# 钉钉 AI 表格 MCP 常见错误与排查\n\n> 以下内容针对 2026-03-10 后的新 schema：`baseId / tableId / fieldId / recordId`。\n\n## 1. 常见错误模式\n\n### 参数体系写错\n\n**现象**\n- 还在用旧参数：`dentryUuid` / `sheetIdOrName`\n- 接口直接报参数缺失 / 无效请求\n\n**原因**\n- MCP server 已升级到新 schema，但本地脚本或技能文档没跟上\n\n**解决**\n- Base 级：用 `baseId`\n- Table 级：用 `tableId`\n- Field 级：用 `fieldId`\n- Record 级：用 `recordId` / `recordIds`\n\n---\n\n### 参数名大小写或命名风格错误\n\n**现象**\n- 参数看起来传了，但服务端像没收到\n- 报字段缺失 / 资源不存在\n\n**原因**\n- `mcporter call key=value` 方式下参数名必须是 **camelCase**\n\n**正确示例**\n```bash\nmcporter call server.get_base baseId='base_xxx'\nmcporter call server.update_table baseId='base_xxx' tableId='tbl_xxx' newTableName='新表名'\n```\n\n**错误示例**\n```bash\nmcporter call server.get_base base-id='base_xxx'\nmcporter call server.update_table table-id='tbl_xxx'\n```\n\n**建议**\n- 简单参数用 `key=value`\n- 复杂对象、数组一律用 `--args '<json>'`\n\n---\n\n### 查询记录时单选 / 多选过滤无结果\n\n**现象**\n- 明明记录存在，但 `query_records.filters` 查不出来\n\n**原因**\n- 对 `singleSelect / multipleSelect` 字段做过滤时，必须传 **option id**，不能传 option name\n\n**解决**\n1. 先 `get_fields` 读取字段完整配置\n2. 找到 options 里的 id\n3. 在 filters 里传 id\n\n---\n\n### create_records / update_records 写入失败\n\n**常见原因**\n- `cells` 的 key 用了字段名，不是 `fieldId`\n- `url` 字段直接传字符串\n- `richText` 字段直接传字符串\n- `group` 字段写成 `openConversationId`\n- 单次超过 100 条\n\n**解决**\n- 先用 `get_tables` 拿字段目录，必要时 `get_fields`\n- `url` 用：\n  ```json\n  {\"text\":\"官网\",\"link\":\"https://...\"}\n  ```\n- `richText` 用：\n  ```json\n  {\"markdown\":\"**加粗**\"}\n  ```\n- `group` 用：\n  ```json\n  [{\"cid\":\"74577067501\"}]\n  ```\n\n---\n\n### update_field 更新单选 / 多选后历史数据异常\n\n**现象**\n- 更新选项后，已有单元格显示错乱或丢值\n\n**原因**\n- 更新 `options` 时没有传完整列表\n- 已有 option 没保留原 `id`\n\n**解决**\n- 先 `get_fields` 取完整配置\n- 更新时传完整 options 列表\n- 已有项尽量保留原 `id`\n- 新增项可不传 `id`\n\n---\n\n### delete_table 失败：cannot delete the last sheet\n\n**原因**\n- 该表是 Base 中最后一张表\n\n**解决**\n- 先新建一张表，再删旧表\n- 或者如果目标就是整个 Base 都不要了，改用 `delete_base`\n\n---\n\n### create_fields / create_table 某些字段类型失败\n\n**已知边界**\n- `formula` 当前实例可能 `not supported yet`\n- 关联字段可能因为下游主键约束失败，即使已传 `linkedSheetId`\n\n**建议**\n- 复杂字段拆开单独创建\n- 先建立基础结构，再逐项补复杂字段\n- 遇到关联字段失败，优先检查被关联表的主字段 / 主键约束\n\n---\n\n## 2. 推荐排查顺序\n\n### 先确认 ID 链路\n\n1. `list_bases` / `search_bases` → 拿 `baseId`\n2. `get_base` → 拿 `tableId`\n3. `get_tables` → 拿 `fieldId`\n4. `query_records` / 结果对象 → 拿 `recordId`\n\n别跳步，别猜 ID。\n\n### 再确认 payload 结构\n\n- 新增 / 更新记录：看 `cells`\n- 新增字段：看 `fields[]`\n- 更新字段：看 `config`\n- 查询过滤：看 `filters`\n\n### 最后确认批量上限\n\n- 字段批量：15\n- table / field 详情批量：10\n- record 批量：100\n\n---\n\n## 3. 调试命令模板\n\n### 看 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n### 看 Table / Field\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":10}' \\\n  --output json\n```\n\n### 新增记录\n\n```bash\nmcporter call '<mcp-url>' .create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n---\n\n## 4. 一句话原则\n\n- **别再用旧 schema。**\n- **别猜 ID。**\n- **复杂参数一律 `--args`。**\n- **先读结构，再写数据。**\n\nFile v0.5.1:CHANGELOG.md\n\n## [0.5.1] - 2026-03-11\n\n### 元数据修复\n\n- ✅ 补回 `SKILL.md` frontmatter 中的 `version` 与 `metadata.openclaw.requires` 声明\n- ✅ 明确声明必需环境变量：`DINGTALK_MCP_URL`、`OPENCLAW_WORKSPACE`\n- ✅ 明确声明必需二进制：`mcporter`、`python3`\n- ✅ `package.json` 同步补充 `requiredEnv` / `requiresBinaries` / credentials 信息，修复 ClawHub 审核指出的 metadata mismatch\n- ✅ README 同步补充依赖与环境声明\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参数命名，再查 ID / 权限\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 修复 issue #1 中提到的调用误导问题\n\n## [0.3.8] - 2026-03-05\n\n### 文档更新\n\n**SKILL.md 更新：**\n- ✅ 新增\"根节点配置\"章节：根节点 UUID 保存在 `TABLE.md`，无需每次调 API 查询\n- ✅ 提供从 `TABLE.md` 读取根节点并创建表格的示例命令\n\n## [0.3.7] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n# Changelog\n## [0.3.6] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n\n# Changelog\n## [0.3.5] - 2025-12-21\n\n### 文档完善\n\n**SKILL.md 更新：**\n- ✅ 补充 `add_base_table` 创建数据表的示例代码（之前缺失）\n- ✅ 数据表操作部分现在包含完整的 CRUD 示例（创建/列出/重命名/删除）\n- ✅ 确保所有 14 个 API 方法在文档中都有覆盖\n\n**验证结果：**\n- 14/14 API 方法全部覆盖 ✅\n- SKILL.md 和 api-reference.md 保持一致 ✅\n\n**变更说明：**\n- 此版本仅文档更新，无功能变更\n- 修复了用户反馈的\"数据表操作缺少创建方法说明\"问题\n\n\n## [0.3.4] - 2025-02-27\n\n### 🔒 安全加固（重大更新）\n\n**新增安全功能：**\n- ✅ **路径沙箱** - 新增 `resolve_safe_path()` 函数，防止目录遍历攻击（如 `../etc/passwd`）\n- ✅ **dentryUuid 合法性验证** - 所有 dentryUuid 参数都会校验为 API 返回的合法 ID 形态，避免空值和明显异常输入\n- ✅ **文件扩展名白名单** - 仅允许 `.json` 和 `.csv` 文件\n- ✅ **文件大小限制** - JSON 最大 10MB，CSV 最大 50MB，防止 DoS 攻击\n- ✅ **字段类型白名单** - 仅允许预定义的 11 种字段类型\n- ✅ **命令超时保护** - mcporter 命令超时限制（60-120 秒）\n- ✅ **输入清理** - 自动去除空白、验证空值、数字类型自动转换\n\n**脚本重构：**\n- `scripts/bulk_add_fields.py` - 全面安全加固，Python 3.9 兼容\n- `scripts/import_records.py` - 全面安全加固，新增 JSON 导入支持\n\n**测试覆盖：**\n- 新增 `tests/test_security.py` - 25 项自动化安全测试，全部通过 ✅\n- 新增 `tests/TEST_REPORT.md` - 完整测试报告和安全对比分析\n\n**文档更新：**\n- SKILL.md 新增\"安全加固措施\"章节，透明说明所有保护机制\n- 添加配置建议：`OPENCLAW_WORKSPACE` 环境变量\n\n**对比改进：**\n- 安全维度对齐 ontology (Benign) 标准\n- 除 mcporter 外部依赖外，其他风险已降至最低\n\n---\n\n## [0.3.3] - 2026-02-27\n\n### 安全与元数据\n- 在 SKILL.md frontmatter 中添加 `metadata.openclaw.requires` 声明\n- 明确声明需要的环境变量：`DINGTALK_MCP_URL`\n- 明确声明需要的二进制文件：`mcporter`\n- 添加 `primaryEnv: DINGTALK_MCP_URL` 指定主要凭证\n- 添加 `homepage` 字段指向 GitHub 仓库\n- 修复 ClawHub 审核指出的元数据不一致问题\n\n\n## [0.3.2] - 2026-02-27\n\n### 文档\n- 更新获取 Streamable HTTP URL 的说明，添加\"点击'获取 MCP 凭证配置'按钮\"步骤\n- README.md 和 SKILL.md 同步更新\n\n## [0.3.1] - 2026-02-27\n\n### 修复\n- 修复 credentials 存储方式说明不一致的问题\n- package.json 移除 `requiredEnv`，添加 `storageMethod` 说明\n- SKILL.md 补充两种凭证配置方式：`mcporter config`（推荐）和环境变量\n\n## [0.3.0] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.9] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.8] - 2026-02-27\n\n### 修复\n- 修复 registry metadata 未正确声明 required credentials 的问题\n- SKILL.md frontmatter 添加 `requiresCredentials` 和 `requiresBinaries` 声明\n- package.json 改用 `peerDependencies` 声明 mcporter 依赖\n- 明确凭证名称 `DINGTALK_MCP_URL` 和获取方式\n\n## [0.2.7] - 2026-02-27\n\n### 安全\n- 新增\"安全须知\"章节，明确安装前注意事项\n- 添加 mcporter 官方来源说明和验证提示\n- 增加 Streamable HTTP URL 凭证安全警告\n- 补充脚本使用安全说明（源码审查、测试环境优先）\n\n## [0.2.6] - 2026-02-27\n\n### 修复\n- 添加 ClawHub 元数据声明，明确标注所需二进制文件和认证要求\n- 修复安全警告中提到的 metadata omissions 问题\n\n## [0.2.5] - 2026-02-27\n\n### 改进\n- 大幅完善 README.md，增加详细使用指南\n- 新增\"常用命令速查\"表格，方便快速参考\n- 新增\"支持的字段类型\"说明表\n- 新增\"故障排查\"章节（认证失败、权限错误、字段类型不匹配等）\n- 补充批量操作脚本使用说明\n- 添加钉钉讨论群链接\n\n### 文档\n- README.md 从 526 字节扩展至完整使用指南\n\n## [0.2.4] - 2026-02-26\n\n### 更新\n- 更新 MCP 广场 URL 地址为市场详情页 (mcpId=1060)\n\n---\n\n# Changelog\n\n## [0.2.3] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了 GitHub 仓库链接\n\n## [0.2.2] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了包依赖说明\n- 添加了 Changelog\n\n---\n\n## [0.2.1] - 2026-02-26\n\n### 新增\n- 完善 CHANGELOG.md 和 package.json 文件\n- 添加完整的版本管理和发布文档\n\n### 修复\n- 修正技能元数据信息\n\n---\n\n## [0.2.0] - 2026-02-25\n\n### 新增\n- 支持批量操作（最多 1000 条记录）\n- 添加 `update_records` 方法用于批量更新记录\n- 添加字段类型说明文档\n\n### 改进\n- 优化错误处理和错误码说明\n- 完善 API 参考文档\n\n---\n\n## [0.1.0] - 2026-02-24\n\n### 新增\n- 钉钉 AI 表格（多维表）操作支持\n- 表格创建、数据表管理、字段操作、记录增删改查\n- 支持 7 种字段类型：text, number, singleSelect, multipleSelect, date, user, attachment\n\n### 功能详情\n- `get_root_node_of_my_document` - 获取文档根节点\n- `create_base_app` - 创建 AI 表格\n- `search_accessible_ai_tables` - 搜索可访问的表格\n- `list_base_tables` - 列出数据表\n- `update_base_tables` - 重命名数据表\n- `delete_base_table` - 删除数据表\n- `list_base_field` - 查看字段列表\n- `add_base_field` - 添加字段\n- `delete_base_field` - 删除字段\n- `search_base_record` - 查询记录\n- `add_base_record` - 添加记录\n- `delete_base_record` - 删除记录\n\n### 文档\n- API 参考文档 (references/api-reference.md)\n- 错误码说明 (references/error-codes.md)\n- 示例脚本 (scripts/)\n\n### 依赖\n- mcporter CLI (v0.7.0+)\n- 钉钉 MCP Server 配置\n\nFile v0.5.1:tests/TEST_REPORT.md\n\n# 安全加固测试报告\n\n**技能**: dingtalk-ai-table  \n**版本**: 0.3.4 (安全加固版)  \n**测试日期**: 2025-02-27  \n**Python 版本**: 3.9.6\n\n---\n\n## 测试概览\n\n| 项目 | 结果 |\n|------|------|\n| 测试用例总数 | 25 |\n| 通过 | 25 ✅ |\n| 失败 | 0 |\n| 错误 | 0 |\n| 覆盖率 | 安全功能 100% |\n\n---\n\n## 测试类别\n\n### 1. 路径安全限制 (7 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_relative_path_within_root` | 相对路径在允许范围内 | ✅ |\n| `test_subdirectory_path` | 子目录路径在允许范围内 | ✅ |\n| `test_absolute_path_within_root` | 绝对路径在允许范围内 | ✅ |\n| `test_path_traversal_attack` | 目录遍历攻击 (`../etc/passwd`) | ✅ 已阻止 |\n| `test_path_traversal_with_dots` | 多层目录遍历攻击 (`../../etc/passwd`) | ✅ 已阻止 |\n| `test_absolute_path_outside_root` | 绝对路径超出允许范围 (`/etc/passwd`) | ✅ 已阻止 |\n| `test_default_allowed_root` | 未指定允许根目录时使用环境变量 | ✅ |\n\n**安全措施**: `resolve_safe_path()` 函数确保所有文件操作限制在 `OPENCLAW_WORKSPACE` 环境变量或当前工作目录内。\n\n---\n\n### 2. UUID 格式验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_uuid` | 有效的 UUID (含大小写、带换行) | ✅ |\n| `test_invalid_uuid` | 无效的 UUID (空、短、无连字符、无效字符) | ✅ 已拒绝 |\n\n**验证规则**: `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`\n\n---\n\n### 3. 文件扩展名验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_allowed_extensions` | 允许的扩展名 (.json, .csv) | ✅ |\n| `test_disallowed_extensions` | 不允许的扩展名 (.txt, .exe, 无扩展名) | ✅ 已拒绝 |\n\n**白名单**:\n- `bulk_add_fields.py`: `['.json']`\n- `import_records.py`: `['.csv', '.json']`\n\n---\n\n### 4. JSON 安全加载 (3 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_json` | 有效的 JSON 文件 | ✅ |\n| `test_file_size_limit` | 文件大小限制 (10MB) | ✅ 已阻止 |\n| `test_invalid_json` | 无效的 JSON 格式 | ✅ 已捕获异常 |\n\n**限制**: 最大 10MB (bulk_add_fields) / 50MB (import_records)\n\n---\n\n### 5. 字段配置验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_field_configs` | 有效的字段配置 (11 种类型) | ✅ |\n| `test_invalid_field_configs` | 无效的字段配置 (缺少 name、空 name、无效类型等) | ✅ 已拒绝 |\n\n**允许的字段类型**:\n```\ntext, number, singleSelect, multipleSelect,\ndate, user, attachment, checkbox, phone, email, url\n```\n\n---\n\n### 6. 记录验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_record` | 有效的记录格式 | ✅ |\n| `test_invalid_record` | 无效的记录格式 (非对象、缺少 fields 等) | ✅ 已拒绝 |\n\n---\n\n### 7. 记录值清理 (5 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_string_value` | 字符串值保持不变 | ✅ |\n| `test_integer_value` | 整数字符串转换为整数 | ✅ |\n| `test_float_value` | 浮点数字符串转换为浮点数 | ✅ |\n| `test_empty_value` | 空值返回 None | ✅ |\n| `test_whitespace_trimming` | 自动去除首尾空白 | ✅ |\n\n---\n\n### 8. 集成测试 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_bulk_add_fields_workflow` | bulk_add_fields 完整工作流程 | ✅ |\n| `test_import_records_workflow` | import_records 完整工作流程 | ✅ |\n\n---\n\n## 安全改进对比\n\n| 安全维度 | 改进前 | 改进后 |\n|----------|--------|--------|\n| 路径限制 | ❌ 无 | ✅ `resolve_safe_path()` 沙箱 |\n| UUID 验证 | ❌ 无 | ✅ 严格正则验证 |\n| 文件扩展名 | ❌ 无 | ✅ 白名单机制 |\n| 文件大小 | ❌ 无 | ✅ 10MB/50MB 限制 |\n| 字段类型 | ❌ 无 | ✅ 白名单验证 |\n| 命令超时 | ❌ 无 | ✅ 60-120 秒超时 |\n| 输入清理 | ❌ 无 | ✅ 空白修剪、空值处理 |\n| 测试覆盖 | ❌ 无 | ✅ 25 项自动化测试 |\n\n---\n\n## 运行测试\n\n```bash\ncd ~/.openclaw/workspace/skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n---\n\n## 结论\n\n✅ **所有安全加固措施已实施并通过测试**\n\n此次加固显著降低了以下风险：\n1. **目录遍历攻击** - 通过路径沙箱完全阻止\n2. **任意文件读取** - 通过扩展名白名单和路径限制阻止\n3. **命令注入** - 通过 UUID 验证和输入清理降低风险\n4. **DoS 攻击** - 通过文件大小限制和命令超时阻止\n5. **无效数据注入** - 通过字段类型白名单和记录验证阻止\n\n**剩余风险**（已知限制）：\n- 依赖 `mcporter` CLI 工具的安全性（无法避免）\n- 钉钉 API 凭证的安全性（需用户妥善保管）\n\n---\n\n**测试执行者**: AI Agent (main - qwen3.5-397b)  \n**测试环境**: macOS Darwin 25.3.0 (arm64), Python 3.9.6\n\nFile v0.5.1:package.json\n\n{\n  \"name\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.1\",\n  \"description\": \"钉钉 AI 表格（多维表）操作技能。基于新版 MCP tools，使用 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 管理。脚本文件 I/O 限制在工作区内。\",\n  \"keywords\": [\n    \"dingtalk\",\n    \"ai-table\",\n    \"mcp\",\n    \"多维表\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"Marila@Dingtalk\",\n  \"contributors\": [\n    \"Marila@Dingtalk\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://clawhub.com/skills/dingtalk-ai-table\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table/issues\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"mcporter\": \">=0.7.0\"\n  },\n  \"clawhub\": {\n    \"requiresBinaries\": [\n      \"mcporter\",\n      \"python3\"\n    ],\n    \"requiredEnv\": [\n      \"DINGTALK_MCP_URL\",\n      \"OPENCLAW_WORKSPACE\"\n    ],\n    \"credentials\": [\n      {\n        \"name\": \"DINGTALK_MCP_URL\",\n        \"description\": \"钉钉 MCP Server Streamable HTTP URL (含访问令牌)\",\n        \"docs\": \"https://mcp.dingtalk.com/#/detail?mcpId=9555\",\n        \"storageMethod\": \"mcporter config (recommended) or environment variable\"\n      },\n      {\n        \"name\": \"OPENCLAW_WORKSPACE\",\n        \"description\": \"本地脚本文件读写沙箱根目录；建议设置为 ~/.openclaw/workspace\",\n        \"docs\": \"https://github.com/aliramw/dingtalk-ai-table\",\n        \"storageMethod\": \"environment variable\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"test\": \"python3 tests/test_security.py\"\n  }\n}\n\nArchive v0.5.0: 11 files, 24807 bytes\n\nFiles: CHANGELOG.md (10320b), package.json (1280b), README.md (830b), references/api-reference.md (8428b), references/error-codes.md (4529b), scripts/bulk_add_fields.py (8140b), scripts/import_records.py (9404b), SKILL.md (4109b), tests/TEST_REPORT.md (5005b), tests/test_security.py (9079b), _meta.json (136b)\n\nFile v0.5.0:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 https://mcp.dingtalk.com/#/detail?mcpId=1060&detailType=marketMcpDetail 获取新版钉钉 AI 表格 MCP 的 `Streamable HTTP URL`。\n\n方式一：直接配置到 mcporter\n\n```bash\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n方式二：使用环境变量\n\n```bash\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n> 这个 URL 带访问令牌，等同密码，不要泄露。\n\n## 核心工具集\n\n### Base 层\n- `list_bases`\n- `search_bases`\n- `get_base`\n- `create_base`\n- `update_base`\n- `delete_base`\n- `search_templates`\n\n### Table 层\n- `get_tables`\n- `create_table`\n- `update_table`\n- `delete_table`\n\n### Field 层\n- `get_fields`\n- `create_fields`\n- `update_field`\n- `delete_field`\n\n### Record 层\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n\n## 推荐工作流\n\n### 1. 先找 Base\n\n```bash\nmcporter call dingtalk-ai-table list_bases limit=10 --output json\nmcporter call dingtalk-ai-table search_bases query=\"销售\" --output json\n```\n\n### 2. 再拿 Table 目录\n\n```bash\nmcporter call dingtalk-ai-table get_base baseId=\"base_xxx\" --output json\n```\n\n### 3. 再展开表结构\n\n```bash\nmcporter call dingtalk-ai-table get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n### 4. 字段复杂时读完整配置\n\n```bash\nmcporter call dingtalk-ai-table get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 5. 再查 / 写记录\n\n```bash\nmcporter call dingtalk-ai-table query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":20}' \\\n  --output json\n\nmcporter call dingtalk-ai-table create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n## 脚本\n\n### 批量新增字段\n\n```bash\npython scripts/bulk_add_fields.py <baseId> <tableId> fields.json\n```\n\n`fields.json` 示例：\n\n```json\n[\n  {\"fieldName\":\"任务名\",\"type\":\"text\"},\n  {\"fieldName\":\"优先级\",\"type\":\"singleSelect\",\"config\":{\"options\":[{\"name\":\"高\"},{\"name\":\"中\"},{\"name\":\"低\"}]}}\n]\n```\n\n兼容项：\n- `name` 会自动映射为 `fieldName`\n- `phone` 会自动映射为 `telephone`\n\n### 批量导入记录\n\n```bash\npython scripts/import_records.py <baseId> <tableId> data.csv\npython scripts/import_records.py <baseId> <tableId> data.json 50\n```\n\n说明：\n- CSV 表头默认按 `fieldId` 解释\n- JSON 支持：\n  - `[{\"cells\": {...}}]`\n  - `[{\"fld_xxx\": \"value\"}]`\n\n## 安全规则\n\n- 文件路径受 `OPENCLAW_WORKSPACE` 沙箱限制\n- 仅允许读取工作区内 `.json` / `.csv` 文件\n- Base / Table / Field / Record ID 都做格式校验\n- 批量上限按 MCP server 实际限制控制：\n  - `create_fields`：最多 15\n  - `get_tables / get_fields`：最多 10\n  - `create_records / update_records / delete_records`：最多 100\n\n## 调试原则\n\n- 先 `get_base`，再 `get_tables`，必要时 `get_fields`\n- 不要猜 `fieldId`\n- 复杂参数一律用 `--args` JSON\n- `singleSelect / multipleSelect` 过滤时必须传 option ID，不是 option name\n\n## 参考\n\n- API 参考：`references/api-reference.md`\n- 错误排查：`references/error-codes.md`\n\nFile v0.5.0:README.md\n\n# dingtalk-ai-table\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。\n\nFile v0.5.0:_meta.json\n\n{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.0\",\n  \"publishedAt\": 1773161144439\n}\n\nFile v0.5.0:references/api-reference.md\n\n# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n## 1. 能力总览\n\n当前 MCP tools 共 19 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .search_bases query='销售' --output json\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}' \\\n  --output json\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}' \\\n  --output json\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报' --output json\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n\n```json\n{\n  \"fieldName\": \"优先级\",\n  \"type\": \"singleSelect\",\n  \"config\": {\n    \"options\": [\n      {\"name\": \"高\"},\n      {\"name\": \"中\"},\n      {\"name\": \"低\"}\n    ]\n  }\n}\n```\n\n## 3.10 update_table\n\n重命名 table。\n\n参数：\n- `baseId`\n- `tableId`\n- `newTableName`\n\n## 3.11 delete_table\n\n删除 table。若它是 Base 里最后一张表，会失败。\n\n参数：\n- `baseId`\n- `tableId`\n- `reason`（建议填写）\n\n## 3.12 get_fields\n\n获取字段完整配置。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldIds`：单次最多 10 个\n\n关键用途：\n- 读取单选 / 多选字段 option id\n- 读取日期 / 进度 / 评分等 config\n- 读取关联字段 linkedSheetId\n\n## 3.13 create_fields\n\n批量新增字段。\n\n参数：\n- `baseId`\n- `tableId`\n- `fields`：1~15 个\n\n适用场景：\n- 建表后补字段\n- 添加复杂字段（关联 / 进度 / 评分等）\n\n## 3.14 update_field\n\n更新字段名称或 config；**不能改字段类型**。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n- `newFieldName`（可选）\n- `config`（可选）\n\n注意：\n- `newFieldName` 与 `config` 至少传一个\n- 更新单选 / 多选时，`options` 要传**完整列表**，不是追加\n- 已有选项应尽量保留原 `id`\n\n## 3.15 delete_field\n\n删除字段，不可逆。\n\n参数：\n- `baseId`\n- `tableId`\n- `fieldId`\n\n限制：\n- 不能删主字段\n- 不能删最后一个字段\n\n## 3.16 query_records\n\n查询记录，支持：\n- `recordIds` 精准查\n- `filters` 条件查\n- `keyword` 全文查\n- `sort` 排序\n- `cursor` 分页\n- `fieldIds` 限定返回字段\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`（可选）\n- `filters`（可选）\n- `keyword`（可选）\n- `sort`（可选）\n- `fieldIds`（可选）\n- `limit`（默认 100，最大 100）\n- `cursor`（可选）\n\n### filters 说明\n\n结构：\n\n```json\n{\n  \"operator\": \"and\",\n  \"operands\": [\n    {\n      \"operator\": \"eq\",\n      \"operands\": [\"fld_status\", \"进行中\"]\n    }\n  ]\n}\n```\n\n注意：\n- `singleSelect / multipleSelect` 做过滤时，**必须传 option id，不是 option name**\n- option id 需先通过 `get_fields` 获取\n\n## 3.17 create_records\n\n批量新增记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`：单次最多 100 条\n\n记录结构：\n\n```json\n{\n  \"cells\": {\n    \"fld_text\": \"文本\",\n    \"fld_num\": 123,\n    \"fld_select\": \"进行中\"\n  }\n}\n```\n\n注意：\n- key 是 **fieldId**，不是字段名\n- `singleSelect / multipleSelect` 写入时可以传 option name\n- `url` 必须传对象：`{\"text\":\"官网\",\"link\":\"https://...\"}`\n- `richText` 必须传对象：`{\"markdown\":\"**加粗**\"}`\n- `group` 字段 key 是 `cid`，不是 `openConversationId`\n\n## 3.18 update_records\n\n批量更新记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `records`\n\n结构：\n\n```json\n{\n  \"recordId\": \"rec_xxx\",\n  \"cells\": {\n    \"fld_status\": \"已完成\"\n  }\n}\n```\n\n注意：\n- 只传要更新的字段即可\n- 未传字段保持原值\n\n## 3.19 delete_records\n\n批量删除记录。\n\n参数：\n- `baseId`\n- `tableId`\n- `recordIds`：最多 100 个\n\n---\n\n## 4. 字段类型速查\n\n支持的主要字段类型：\n\n- `text`\n- `number`\n- `singleSelect`\n- `multipleSelect`\n- `date`\n- `currency`\n- `user`\n- `department`\n- `group`\n- `progress`\n- `rating`\n- `checkbox`\n- `attachment`\n- `url`\n- `richText`\n- `telephone`\n- `email`\n- `idCard`\n- `barcode`\n- `geolocation`\n- `primaryDoc`\n- `formula`\n- `unidirectionalLink`\n- `bidirectionalLink`\n- `creator`\n- `lastModifier`\n- `createdTime`\n- `lastModifiedTime`\n\n---\n\n## 5. 已知边界\n\n- `create_table` / `create_fields` 单次最多 **15 个字段**\n- `get_tables` / `get_fields` 单次最多 **10 个对象**\n- `create_records` / `update_records` / `delete_records` / `query_records.recordIds` 单次最多 **100 条**\n- `formula` 字段当前服务实例可能返回 `not supported yet`\n- 关联字段即使传了 `linkedSheetId`，也可能因底层主键约束失败\n- 删除最后一张表会失败：`cannot delete the last sheet`\n\n---\n\n## 6. 参数命名规则\n\n通过 `mcporter call ... key=value` 传参时，参数名必须用 **camelCase**：\n\n- `baseId`\n- `tableId`\n- `fieldId`\n- `recordIds`\n- `newTableName`\n\n不要写成 kebab-case，例如：\n- `base-id`\n- `table-id`\n- `field-id`\n\nCLI 帮助里会显示 `cliName`，但你在 `mcporter call` 命令里最稳的方式仍然是：\n- 简单参数 → `key=value`\n- 复杂参数 → `--args '<json>'`\n\n复杂 payload 一律优先 `--args`。\n\nFile v0.5.0:references/error-codes.md\n\n# 钉钉 AI 表格 MCP 常见错误与排查\n\n> 以下内容针对 2026-03-10 后的新 schema：`baseId / tableId / fieldId / recordId`。\n\n## 1. 常见错误模式\n\n### 参数体系写错\n\n**现象**\n- 还在用旧参数：`dentryUuid` / `sheetIdOrName`\n- 接口直接报参数缺失 / 无效请求\n\n**原因**\n- MCP server 已升级到新 schema，但本地脚本或技能文档没跟上\n\n**解决**\n- Base 级：用 `baseId`\n- Table 级：用 `tableId`\n- Field 级：用 `fieldId`\n- Record 级：用 `recordId` / `recordIds`\n\n---\n\n### 参数名大小写或命名风格错误\n\n**现象**\n- 参数看起来传了，但服务端像没收到\n- 报字段缺失 / 资源不存在\n\n**原因**\n- `mcporter call key=value` 方式下参数名必须是 **camelCase**\n\n**正确示例**\n```bash\nmcporter call server.get_base baseId='base_xxx'\nmcporter call server.update_table baseId='base_xxx' tableId='tbl_xxx' newTableName='新表名'\n```\n\n**错误示例**\n```bash\nmcporter call server.get_base base-id='base_xxx'\nmcporter call server.update_table table-id='tbl_xxx'\n```\n\n**建议**\n- 简单参数用 `key=value`\n- 复杂对象、数组一律用 `--args '<json>'`\n\n---\n\n### 查询记录时单选 / 多选过滤无结果\n\n**现象**\n- 明明记录存在，但 `query_records.filters` 查不出来\n\n**原因**\n- 对 `singleSelect / multipleSelect` 字段做过滤时，必须传 **option id**，不能传 option name\n\n**解决**\n1. 先 `get_fields` 读取字段完整配置\n2. 找到 options 里的 id\n3. 在 filters 里传 id\n\n---\n\n### create_records / update_records 写入失败\n\n**常见原因**\n- `cells` 的 key 用了字段名，不是 `fieldId`\n- `url` 字段直接传字符串\n- `richText` 字段直接传字符串\n- `group` 字段写成 `openConversationId`\n- 单次超过 100 条\n\n**解决**\n- 先用 `get_tables` 拿字段目录，必要时 `get_fields`\n- `url` 用：\n  ```json\n  {\"text\":\"官网\",\"link\":\"https://...\"}\n  ```\n- `richText` 用：\n  ```json\n  {\"markdown\":\"**加粗**\"}\n  ```\n- `group` 用：\n  ```json\n  [{\"cid\":\"74577067501\"}]\n  ```\n\n---\n\n### update_field 更新单选 / 多选后历史数据异常\n\n**现象**\n- 更新选项后，已有单元格显示错乱或丢值\n\n**原因**\n- 更新 `options` 时没有传完整列表\n- 已有 option 没保留原 `id`\n\n**解决**\n- 先 `get_fields` 取完整配置\n- 更新时传完整 options 列表\n- 已有项尽量保留原 `id`\n- 新增项可不传 `id`\n\n---\n\n### delete_table 失败：cannot delete the last sheet\n\n**原因**\n- 该表是 Base 中最后一张表\n\n**解决**\n- 先新建一张表，再删旧表\n- 或者如果目标就是整个 Base 都不要了，改用 `delete_base`\n\n---\n\n### create_fields / create_table 某些字段类型失败\n\n**已知边界**\n- `formula` 当前实例可能 `not supported yet`\n- 关联字段可能因为下游主键约束失败，即使已传 `linkedSheetId`\n\n**建议**\n- 复杂字段拆开单独创建\n- 先建立基础结构，再逐项补复杂字段\n- 遇到关联字段失败，优先检查被关联表的主字段 / 主键约束\n\n---\n\n## 2. 推荐排查顺序\n\n### 先确认 ID 链路\n\n1. `list_bases` / `search_bases` → 拿 `baseId`\n2. `get_base` → 拿 `tableId`\n3. `get_tables` → 拿 `fieldId`\n4. `query_records` / 结果对象 → 拿 `recordId`\n\n别跳步，别猜 ID。\n\n### 再确认 payload 结构\n\n- 新增 / 更新记录：看 `cells`\n- 新增字段：看 `fields[]`\n- 更新字段：看 `config`\n- 查询过滤：看 `filters`\n\n### 最后确认批量上限\n\n- 字段批量：15\n- table / field 详情批量：10\n- record 批量：100\n\n---\n\n## 3. 调试命令模板\n\n### 看 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10 --output json\nmcporter call '<mcp-url>' .get_base baseId='base_xxx' --output json\n```\n\n### 看 Table / Field\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}' \\\n  --output json\n\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}' \\\n  --output json\n```\n\n### 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":10}' \\\n  --output json\n```\n\n### 新增记录\n\n```bash\nmcporter call '<mcp-url>' .create_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"records\":[{\"cells\":{\"fld_name\":\"张三\"}}]}' \\\n  --output json\n```\n\n---\n\n## 4. 一句话原则\n\n- **别再用旧 schema。**\n- **别猜 ID。**\n- **复杂参数一律 `--args`。**\n- **先读结构，再写数据。**\n\nFile v0.5.0:CHANGELOG.md\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参数命名，再查 ID / 权限\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 修复 issue #1 中提到的调用误导问题\n\n## [0.3.8] - 2026-03-05\n\n### 文档更新\n\n**SKILL.md 更新：**\n- ✅ 新增\"根节点配置\"章节：根节点 UUID 保存在 `TABLE.md`，无需每次调 API 查询\n- ✅ 提供从 `TABLE.md` 读取根节点并创建表格的示例命令\n\n## [0.3.7] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n# Changelog\n## [0.3.6] - 2026-03-02\n\n### 文档修正\n\n**SKILL.md 更新：**\n- ✅ 修正 MCP 配置按钮名称：\"获取 MCP 凭证配置\" → \"获取 MCP Server 配置\"\n\n**变更说明：**\n- 此版本仅文档修正，无功能变更\n- 确保文档与钉钉 MCP 广场实际 UI 保持一致\n\n\n# Changelog\n## [0.3.5] - 2025-12-21\n\n### 文档完善\n\n**SKILL.md 更新：**\n- ✅ 补充 `add_base_table` 创建数据表的示例代码（之前缺失）\n- ✅ 数据表操作部分现在包含完整的 CRUD 示例（创建/列出/重命名/删除）\n- ✅ 确保所有 14 个 API 方法在文档中都有覆盖\n\n**验证结果：**\n- 14/14 API 方法全部覆盖 ✅\n- SKILL.md 和 api-reference.md 保持一致 ✅\n\n**变更说明：**\n- 此版本仅文档更新，无功能变更\n- 修复了用户反馈的\"数据表操作缺少创建方法说明\"问题\n\n\n## [0.3.4] - 2025-02-27\n\n### 🔒 安全加固（重大更新）\n\n**新增安全功能：**\n- ✅ **路径沙箱** - 新增 `resolve_safe_path()` 函数，防止目录遍历攻击（如 `../etc/passwd`）\n- ✅ **dentryUuid 合法性验证** - 所有 dentryUuid 参数都会校验为 API 返回的合法 ID 形态，避免空值和明显异常输入\n- ✅ **文件扩展名白名单** - 仅允许 `.json` 和 `.csv` 文件\n- ✅ **文件大小限制** - JSON 最大 10MB，CSV 最大 50MB，防止 DoS 攻击\n- ✅ **字段类型白名单** - 仅允许预定义的 11 种字段类型\n- ✅ **命令超时保护** - mcporter 命令超时限制（60-120 秒）\n- ✅ **输入清理** - 自动去除空白、验证空值、数字类型自动转换\n\n**脚本重构：**\n- `scripts/bulk_add_fields.py` - 全面安全加固，Python 3.9 兼容\n- `scripts/import_records.py` - 全面安全加固，新增 JSON 导入支持\n\n**测试覆盖：**\n- 新增 `tests/test_security.py` - 25 项自动化安全测试，全部通过 ✅\n- 新增 `tests/TEST_REPORT.md` - 完整测试报告和安全对比分析\n\n**文档更新：**\n- SKILL.md 新增\"安全加固措施\"章节，透明说明所有保护机制\n- 添加配置建议：`OPENCLAW_WORKSPACE` 环境变量\n\n**对比改进：**\n- 安全维度对齐 ontology (Benign) 标准\n- 除 mcporter 外部依赖外，其他风险已降至最低\n\n---\n\n## [0.3.3] - 2026-02-27\n\n### 安全与元数据\n- 在 SKILL.md frontmatter 中添加 `metadata.openclaw.requires` 声明\n- 明确声明需要的环境变量：`DINGTALK_MCP_URL`\n- 明确声明需要的二进制文件：`mcporter`\n- 添加 `primaryEnv: DINGTALK_MCP_URL` 指定主要凭证\n- 添加 `homepage` 字段指向 GitHub 仓库\n- 修复 ClawHub 审核指出的元数据不一致问题\n\n\n## [0.3.2] - 2026-02-27\n\n### 文档\n- 更新获取 Streamable HTTP URL 的说明，添加\"点击'获取 MCP 凭证配置'按钮\"步骤\n- README.md 和 SKILL.md 同步更新\n\n## [0.3.1] - 2026-02-27\n\n### 修复\n- 修复 credentials 存储方式说明不一致的问题\n- package.json 移除 `requiredEnv`，添加 `storageMethod` 说明\n- SKILL.md 补充两种凭证配置方式：`mcporter config`（推荐）和环境变量\n\n## [0.3.0] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.9] - 2026-02-27\n\n### 修复\n- 调整 registry metadata 格式，使用 `requiredEnv` 和 `credentials` 字段\n- SKILL.md description 中明确提及需要 DINGTALK_MCP_URL 凭证\n- 移除 frontmatter 中的非标准字段（仅保留 name 和 description）\n\n## [0.2.8] - 2026-02-27\n\n### 修复\n- 修复 registry metadata 未正确声明 required credentials 的问题\n- SKILL.md frontmatter 添加 `requiresCredentials` 和 `requiresBinaries` 声明\n- package.json 改用 `peerDependencies` 声明 mcporter 依赖\n- 明确凭证名称 `DINGTALK_MCP_URL` 和获取方式\n\n## [0.2.7] - 2026-02-27\n\n### 安全\n- 新增\"安全须知\"章节，明确安装前注意事项\n- 添加 mcporter 官方来源说明和验证提示\n- 增加 Streamable HTTP URL 凭证安全警告\n- 补充脚本使用安全说明（源码审查、测试环境优先）\n\n## [0.2.6] - 2026-02-27\n\n### 修复\n- 添加 ClawHub 元数据声明，明确标注所需二进制文件和认证要求\n- 修复安全警告中提到的 metadata omissions 问题\n\n## [0.2.5] - 2026-02-27\n\n### 改进\n- 大幅完善 README.md，增加详细使用指南\n- 新增\"常用命令速查\"表格，方便快速参考\n- 新增\"支持的字段类型\"说明表\n- 新增\"故障排查\"章节（认证失败、权限错误、字段类型不匹配等）\n- 补充批量操作脚本使用说明\n- 添加钉钉讨论群链接\n\n### 文档\n- README.md 从 526 字节扩展至完整使用指南\n\n## [0.2.4] - 2026-02-26\n\n### 更新\n- 更新 MCP 广场 URL 地址为市场详情页 (mcpId=1060)\n\n---\n\n# Changelog\n\n## [0.2.3] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了 GitHub 仓库链接\n\n## [0.2.2] - 2026-02-26\n\n### 新增\n- 在 package.json 中添加了包依赖说明\n- 添加了 Changelog\n\n---\n\n## [0.2.1] - 2026-02-26\n\n### 新增\n- 完善 CHANGELOG.md 和 package.json 文件\n- 添加完整的版本管理和发布文档\n\n### 修复\n- 修正技能元数据信息\n\n---\n\n## [0.2.0] - 2026-02-25\n\n### 新增\n- 支持批量操作（最多 1000 条记录）\n- 添加 `update_records` 方法用于批量更新记录\n- 添加字段类型说明文档\n\n### 改进\n- 优化错误处理和错误码说明\n- 完善 API 参考文档\n\n---\n\n## [0.1.0] - 2026-02-24\n\n### 新增\n- 钉钉 AI 表格（多维表）操作支持\n- 表格创建、数据表管理、字段操作、记录增删改查\n- 支持 7 种字段类型：text, number, singleSelect, multipleSelect, date, user, attachment\n\n### 功能详情\n- `get_root_node_of_my_document` - 获取文档根节点\n- `create_base_app` - 创建 AI 表格\n- `search_accessible_ai_tables` - 搜索可访问的表格\n- `list_base_tables` - 列出数据表\n- `update_base_tables` - 重命名数据表\n- `delete_base_table` - 删除数据表\n- `list_base_field` - 查看字段列表\n- `add_base_field` - 添加字段\n- `delete_base_field` - 删除字段\n- `search_base_record` - 查询记录\n- `add_base_record` - 添加记录\n- `delete_base_record` - 删除记录\n\n### 文档\n- API 参考文档 (references/api-reference.md)\n- 错误码说明 (references/error-codes.md)\n- 示例脚本 (scripts/)\n\n### 依赖\n- mcporter CLI (v0.7.0+)\n- 钉钉 MCP Server 配置\n\nFile v0.5.0:tests/TEST_REPORT.md\n\n# 安全加固测试报告\n\n**技能**: dingtalk-ai-table  \n**版本**: 0.3.4 (安全加固版)  \n**测试日期**: 2025-02-27  \n**Python 版本**: 3.9.6\n\n---\n\n## 测试概览\n\n| 项目 | 结果 |\n|------|------|\n| 测试用例总数 | 25 |\n| 通过 | 25 ✅ |\n| 失败 | 0 |\n| 错误 | 0 |\n| 覆盖率 | 安全功能 100% |\n\n---\n\n## 测试类别\n\n### 1. 路径安全限制 (7 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_relative_path_within_root` | 相对路径在允许范围内 | ✅ |\n| `test_subdirectory_path` | 子目录路径在允许范围内 | ✅ |\n| `test_absolute_path_within_root` | 绝对路径在允许范围内 | ✅ |\n| `test_path_traversal_attack` | 目录遍历攻击 (`../etc/passwd`) | ✅ 已阻止 |\n| `test_path_traversal_with_dots` | 多层目录遍历攻击 (`../../etc/passwd`) | ✅ 已阻止 |\n| `test_absolute_path_outside_root` | 绝对路径超出允许范围 (`/etc/passwd`) | ✅ 已阻止 |\n| `test_default_allowed_root` | 未指定允许根目录时使用环境变量 | ✅ |\n\n**安全措施**: `resolve_safe_path()` 函数确保所有文件操作限制在 `OPENCLAW_WORKSPACE` 环境变量或当前工作目录内。\n\n---\n\n### 2. UUID 格式验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_uuid` | 有效的 UUID (含大小写、带换行) | ✅ |\n| `test_invalid_uuid` | 无效的 UUID (空、短、无连字符、无效字符) | ✅ 已拒绝 |\n\n**验证规则**: `^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`\n\n---\n\n### 3. 文件扩展名验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_allowed_extensions` | 允许的扩展名 (.json, .csv) | ✅ |\n| `test_disallowed_extensions` | 不允许的扩展名 (.txt, .exe, 无扩展名) | ✅ 已拒绝 |\n\n**白名单**:\n- `bulk_add_fields.py`: `['.json']`\n- `import_records.py`: `['.csv', '.json']`\n\n---\n\n### 4. JSON 安全加载 (3 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_json` | 有效的 JSON 文件 | ✅ |\n| `test_file_size_limit` | 文件大小限制 (10MB) | ✅ 已阻止 |\n| `test_invalid_json` | 无效的 JSON 格式 | ✅ 已捕获异常 |\n\n**限制**: 最大 10MB (bulk_add_fields) / 50MB (import_records)\n\n---\n\n### 5. 字段配置验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_field_configs` | 有效的字段配置 (11 种类型) | ✅ |\n| `test_invalid_field_configs` | 无效的字段配置 (缺少 name、空 name、无效类型等) | ✅ 已拒绝 |\n\n**允许的字段类型**:\n```\ntext, number, singleSelect, multipleSelect,\ndate, user, attachment, checkbox, phone, email, url\n```\n\n---\n\n### 6. 记录验证 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_valid_record` | 有效的记录格式 | ✅ |\n| `test_invalid_record` | 无效的记录格式 (非对象、缺少 fields 等) | ✅ 已拒绝 |\n\n---\n\n### 7. 记录值清理 (5 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_string_value` | 字符串值保持不变 | ✅ |\n| `test_integer_value` | 整数字符串转换为整数 | ✅ |\n| `test_float_value` | 浮点数字符串转换为浮点数 | ✅ |\n| `test_empty_value` | 空值返回 None | ✅ |\n| `test_whitespace_trimming` | 自动去除首尾空白 | ✅ |\n\n---\n\n### 8. 集成测试 (2 项测试)\n\n| 测试项 | 描述 | 结果 |\n|--------|------|------|\n| `test_bulk_add_fields_workflow` | bulk_add_fields 完整工作流程 | ✅ |\n| `test_import_records_workflow` | import_records 完整工作流程 | ✅ |\n\n---\n\n## 安全改进对比\n\n| 安全维度 | 改进前 | 改进后 |\n|----------|--------|--------|\n| 路径限制 | ❌ 无 | ✅ `resolve_safe_path()` 沙箱 |\n| UUID 验证 | ❌ 无 | ✅ 严格正则验证 |\n| 文件扩展名 | ❌ 无 | ✅ 白名单机制 |\n| 文件大小 | ❌ 无 | ✅ 10MB/50MB 限制 |\n| 字段类型 | ❌ 无 | ✅ 白名单验证 |\n| 命令超时 | ❌ 无 | ✅ 60-120 秒超时 |\n| 输入清理 | ❌ 无 | ✅ 空白修剪、空值处理 |\n| 测试覆盖 | ❌ 无 | ✅ 25 项自动化测试 |\n\n---\n\n## 运行测试\n\n```bash\ncd ~/.openclaw/workspace/skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n---\n\n## 结论\n\n✅ **所有安全加固措施已实施并通过测试**\n\n此次加固显著降低了以下风险：\n1. **目录遍历攻击** - 通过路径沙箱完全阻止\n2. **任意文件读取** - 通过扩展名白名单和路径限制阻止\n3. **命令注入** - 通过 UUID 验证和输入清理降低风险\n4. **DoS 攻击** - 通过文件大小限制和命令超时阻止\n5. **无效数据注入** - 通过字段类型白名单和记录验证阻止\n\n**剩余风险**（已知限制）：\n- 依赖 `mcporter` CLI 工具的安全性（无法避免）\n- 钉钉 API 凭证的安全性（需用户妥善保管）\n\n---\n\n**测试执行者**: AI Agent (main - qwen3.5-397b)  \n**测试环境**: macOS Darwin 25.3.0 (arm64), Python 3.9.6\n\nFile v0.5.0:package.json\n\n{\n  \"name\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.0\",\n  \"description\": \"钉钉 AI 表格（多维表）操作技能。基于新版 MCP tools，使用 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 管理。脚本文件 I/O 限制在工作区内。\",\n  \"keywords\": [\n    \"dingtalk\",\n    \"ai-table\",\n    \"mcp\",\n    \"多维表\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"Marila@Dingtalk\",\n  \"contributors\": [\n    \"Marila@Dingtalk\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://clawhub.com/skills/dingtalk-ai-table\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/aliramw/dingtalk-ai-table/issues\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0.0\"\n  },\n  \"peerDependencies\": {\n    \"mcporter\": \">=0.7.0\"\n  },\n  \"clawhub\": {\n    \"requiresBinaries\": [\n      \"mcporter\"\n    ],\n    \"credentials\": [\n      {\n        \"name\": \"DINGTALK_MCP_URL\",\n        \"description\": \"钉钉 MCP Server Streamable HTTP URL (含访问令牌)\",\n        \"docs\": \"https://mcp.dingtalk.com/#/detail?mcpId=9555\",\n        \"storageMethod\": \"mcporter config (recommended) or environment variable\"\n      }\n    ]\n  },\n  \"scripts\": {\n    \"test\": \"python3 tests/test_security.py\"\n  }\n}\n\nArchive v0.4.1: 45 files, 47997 bytes\n\nFiles: .git/COMMIT_EDITMSG (29b), .git/config (343b), .git/description (73b), .git/FETCH_HEAD (312b), .git/HEAD (21b), .git/hooks/applypatch-msg.sample (478b), .git/hooks/commit-msg.sample (896b), .git/hooks/fsmonitor-watchman.sample (4726b), .git/hooks/post-update.sample (189b), .git/hooks/pre-applypatch.sample (424b), .git/hooks/pre-commit.sample (1649b), .git/hooks/pre-merge-commit.sample (416b), .git/hooks/pre-push.sample (1374b), .git/hooks/pre-rebase.sample (4898b), .git/hooks/pre-receive.sample (544b), .git/hooks/prepare-commit-msg.sample (1492b), .git/hooks/push-to-checkout.sample (2783b), .git/hooks/sendemail-validate.sample (2308b), .git/hooks/update.sample (3650b), .git/info/exclude (240b), .git/logs/HEAD (2115b), .git/logs/refs/heads/main (2115b), .git/logs/refs/remotes/origin/HEAD (195b), .git/logs/refs/remotes/origin/main (1461b), .git/ORIG_HEAD (41b), .git/packed-refs (1228b), .git/refs/heads/main (41b), .git/refs/remotes/origin/HEAD (30b), .git/refs/remotes/origin/main (41b), .git/refs/tags/v0.3.6 (41b), .git/refs/tags/v0.3.7 (41b), .git/refs/tags/v0.3.8 (41b), .git/refs/tags/v0.3.9 (41b), .git/refs/tags/v0.4.0 (41b), CHANGELOG.md (8783b), package.json (1265b), README.md (3880b), references/api-reference.md (3353b), references/error-codes.md (2625b), scripts/bulk_add_fields.py (8731b), scripts/import_records.py (14780b), SKILL.md (10044b), tests/TEST_REPORT.md (5005b), tests/test_security.py (15673b), _meta.json (136b)\n\nFile v0.4.1:SKILL.md\n\n---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉 MCP server 执行表格创建、数据表管理、字段操作、记录增删改查。需要配置 DINGTALK_MCP_URL 凭证。使用场景：创建 AI 表格、管理数据表结构、批量导入导出数据、自动化库存/项目管理等表格操作任务。\nversion: 0.4.1\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n      bins:\n        - mcporter\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作\n\n通过 MCP 协议连接钉钉 AI 表格 API，执行表格和数据操作。\n\n## ⚠️ 安全须知\n\n**安装前请阅读：**\n\n1. **本技能需要外部 CLI 工具** - 需安装 `mcporter` (npm/bun 全局安装)\n2. **需要配置认证凭证** - Streamable HTTP URL 包含访问令牌，请妥善保管\n3. **脚本审查建议** - `scripts/` 目录包含 Python 辅助脚本，建议先审查再运行\n4. **测试环境优先** - 首次使用建议在测试表格中验证，确认无误后再操作生产数据\n\n### 🔒 安全加固措施（v0.3.4+）\n\n脚本已实施以下安全保护：\n\n| 保护措施 | 说明 |\n|----------|------|\n| **路径沙箱** | `resolve_safe_path()` 防止目录遍历攻击，限制文件访问在 `OPENCLAW_WORKSPACE` 内 |\n| **dentryUuid 验证** | 验证 API 返回的 dentryUuid 格式，兼容平台返回的合法 ID，防止空值和明显异常输入 |\n| **文件扩展名白名单** | 仅允许 `.json` / `.csv` 文件 |\n| **文件大小限制** | JSON 最大 10MB，CSV 最大 50MB，防止 DoS |\n| **字段类型白名单** | 仅允许预定义的字段类型 |\n| **命令超时** | mcporter 命令超时限制（60-120 秒） |\n| **输入清理** | 自动去除空白、验证空值 |\n\n**配置建议：**\n```bash\n# 设置工作目录限制（推荐）\nexport OPENCLAW_WORKSPACE=/Users/marila/.openclaw/workspace\n```\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n本技能依赖 `mcporter` 工具。安装前请确认来源可信：\n\n- **官方仓库**: https://github.com/mcporter/mcporter (请验证)\n- **npm 包**: `npm install -g mcporter`\n\n```bash\n# 使用 npm 安装\nnpm install -g mcporter\n\n# 或使用 bun 安装\nbun install -g mcporter\n```\n\n验证安装：\n```bash\nmcporter --version\n```\n\n> **注意**: 全局安装的 CLI 工具具有用户级执行权限，请确保从可信来源安装。\n\n### 配置 MCP Server\n\n**获取 Streamable HTTP URL：**\n\n1. 访问钉钉 MCP 广场：https://mcp.dingtalk.com/#/detail?mcpId=1060&detailType=marketMcpDetail\n2. 在页面**右侧**点击“获取 MCP Server 配置”按钮，然后找到 `Streamable HTTP URL`\n3. 复制该 URL 并用于下方配置\n\n**方式一：使用 mcporter config（推荐）**\n\n```bash\n# 添加钉钉 AI 表格服务器配置（持久化存储）\nmcporter config add dingtalk-ai-table --url \"<Streamable_HTTP_URL>\"\n```\n\n**方式二：使用环境变量**\n\n```bash\n# 临时设置（当前终端会话有效）\nexport DINGTALK_MCP_URL=\"<Streamable_HTTP_URL>\"\n```\n\n将 `<Streamable_HTTP_URL>` 替换为实际获取的完整 URL。\n\n> **⚠️ 凭证安全**: Streamable HTTP URL 包含访问令牌，等同于密码：\n> - 不要提交到版本控制系统\n> - 不要分享给他人\n> - 推荐使用 `mcporter config` 持久化存储，避免在命令历史中暴露\n\n### 基本命令模式\n\n所有操作通过 `mcporter call dingtalk-ai-table <tool>` 执行：\n\n```bash\n# 获取文档根节点\nmcporter call dingtalk-ai-table get_root_node_of_my_document --output json\n\n# 创建 AI 表格\nmcporter call dingtalk-ai-table create_base_\n\nArchive v0.4.0: 11 files, 27643 bytes\n\nFiles: CHANGELOG.md (8268b), package.json (1265b), README.md (3803b), references/api-reference.md (3353b), references/error-codes.md (2625b), scripts/bulk_add_fields.py (8731b), scripts/import_records.py (14780b), SKILL.md (9699b), tests/TEST_REPORT.md (5005b), tests/test_security.py (15673b), _meta.json (136b)\n\nArchive v0.3.9: 11 files, 26764 bytes\n\nFiles: CHANGELOG.md (7580b), package.json (1224b), README.md (3654b), references/api-reference.md (3292b), references/error-codes.md (2522b), scripts/bulk_add_fields.py (8615b), scripts/import_records.py (14664b), SKILL.md (9225b), tests/TEST_REPORT.md (5005b), tests/test_security.py (15508b), _meta.json (136b)\n\nArchive v0.3.8: 11 files, 26053 bytes\n\nFiles: CHANGELOG.md (6952b), package.json (1224b), README.md (3214b), references/api-reference.md (3292b), references/error-codes.md (1960b), scripts/bulk_add_fields.py (8615b), scripts/import_records.py (14664b), SKILL.md (9226b), tests/TEST_REPORT.md (5005b), tests/test_security.py (15508b), _meta.json (136b)","readmeExcerpt":"Skill: Dingtalk Ai Table Owner: aliramw Summary: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取... Tags: ai-table:0.6.0, dingtalk:0.6.0, latest:0.6.0, mcp:0.6.0, openclaw:0.6.0, skill:0.6.0 Version history: v0.6.0 | 2026-03-31T14:16:36.414Z | user 新增完整 skill metadata、快速开始说明、触发测试与示例脚本；发布前验证通过：security 21/21，t","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"~/.openclaw/workspace/.cache/dingtalk-ai-table/"},{"language":"text","snippet":"schema-check-<url-hash>.json"},{"language":"bash","snippet":"mcporter list dingtalk-ai-table --schema"},{"language":"bash","snippet":"mcporter list dingtalk-ai-table --schema"},{"language":"text","snippet":"当前 mcporter 里注册的 dingtalk-ai-table 还是旧版 MCP schema，暂时不能按新版技能操作。\n请打开 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail ，点击右侧“获取 MCP Server 配置”按钮，复制新的 MCP Server 地址，并替换 mcporter 里已注册的 dingtalk-ai-table 地址。替换后重新检查 schema，确认出现 list_bases / get_base / create_records 等新版 tools 后，再继续操作 AI 表格。"},{"language":"bash","snippet":"npm install -g mcporter\n# 或\nbun install -g mcporter"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: dingtalk-ai-table\ndescription: 钉钉 AI 表格（多维表）操作技能。使用 mcporter CLI 连接钉钉官方新版 AI 表格 MCP server，基于 baseId / tableId / fieldId / recordId 体系执行 Base、Table、Field、Record 的查询与增删改。适用于创建 AI 表格、搜索表格、读取表结构、批量增删改记录、批量建字段、更新字段配置、按模板建表等场景。需要配置 DINGTALK_MCP_URL 或直接使用 Streamable HTTP URL。\nversion: 0.5.4\nmetadata:\n  openclaw:\n    requires:\n      env:\n        - DINGTALK_MCP_URL\n        - OPENCLAW_WORKSPACE\n      bins:\n        - mcporter\n        - python3\n    primaryEnv: DINGTALK_MCP_URL\n    homepage: https://github.com/aliramw/dingtalk-ai-table\n---\n\n# 钉钉 AI 表格操作（新版 MCP）\n\n按 **新版 MCP schema** 工作：\n- Base：`baseId`\n- Table：`tableId`\n- Field：`fieldId`\n- Record：`recordId`\n\n不要再用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 版本守门规则（每个 MCP Server 地址只强制检查一次）\n\n在真正开始任何 AI 表格操作前，必须先检查当前 `mcporter` 注册的 `dingtalk-ai-table` MCP server 实际返回的 tools schema。**但这个检查不该每次都重复做；同一个 MCP Server 地址只需要强制检查一次。**\n\n### 一次性检查策略\n\n1. 先读取当前 `mcporter` 里 `dingtalk-ai-table` 对应的 MCP Server 地址。\n2. 用这个地址生成一个本地检查标记（例如基于完整 URL 或其 hash）。\n3. 在工作区保存检查结果，例如放到：\n\n```text\n~/.openclaw/workspace/.cache/dingtalk-ai-table/\n```\n\n建议文件名模式：\n\n```text\nschema-check-<url-hash>.json\n```\n\n4. 如果当前地址对应的检查标记已经存在，并且结果是“已确认新版 schema”，则**跳过重复检查**，直接继续后续 AI 表格操作。\n5. 只有在以下情况才重新强制检查：\n   - 第一次运行，没有检查标记\n   - `mcporter` 里的 MCP Server 地址变了\n   - 之前检查结果是旧版 schema / 检查失败\n   - 用户明确要求重新验证\n\n### 强制检查时执行\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n### 判断标准\n\n如果返回的 tools 仍然是旧版这一套，例如出现：\n- `get_root_node_of_my_document`\n- `create_base_app`\n- `list_base_tables`\n- `add_base_record`\n- `search_base_record`\n- `list_base_field`\n\n或者整体仍然基于：\n- `dentryUuid`\n- `sheetIdOrName`\n- `fieldIdOrName`\n\n那么说明：**虽然 skill 文件已经是新版，但 mcporter 里注册的 MCP server 地址还是旧的，不能继续操作。**\n\n### 遇到旧版 schema 时的强制提示\n\n此时必须明确提示用户：\n\n1. 打开这个页面：\n   `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n2. 点击右侧 **「获取 MCP Server 配置」** 按钮\n3. 复制新的 MCP Server 地址\n4. 用新的地址替换 `mcporter` 里已经注册的 `dingtalk-ai-table` 地址\n5. 替换完成后，再重新执行：\n\n```bash\nmcporter list dingtalk-ai-table --schema\n```\n\n只有当返回的 tools 已经变成新版 schema，例如出现：\n- `list_bases`\n- `get_base`\n- `get_tables`\n- `get_fields`\n- `query_records`\n- `create_records`\n- `update_records`\n- `delete_records`\n- `prepare_attachment_upload`\n\n才允许继续真正的 AI 表格操作。\n\n### 通过检查后的处理\n\n一旦确认当前 MCP Server 地址返回的是新版 schema，就把结果写入本地检查标记。后续只要 `mcporter` 里的 `dingtalk-ai-table` 地址没变，就不要再重复做这一步守门检查。\n\n### 用户提示文案（可直接复用）\n\n```text\n当前 mcporter 里注册的 dingtalk-ai-table 还是旧版 MCP schema，暂时不能按新版技能操作。\n请打开 https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail ，点击右侧“获取 MCP Server 配置”按钮，复制新的 MCP Server 地址，并替换 mcporter 里已注册的 dingtalk-ai-table 地址。替换后重新检查 schema，确认出现 list_bases / get_base / create_records 等新版 tools 后，再继续操作 AI 表格。\n```\n\n## 前置要求\n\n### 安装 mcporter CLI\n\n```bash\nnpm install -g mcporter\n# 或\nbun install -g mcporter\n```\n\n验证：\n\n```bash\nmcporter --version\n```\n\n### 配置 MCP Server\n\n在钉钉 MCP 广场 "},{"path":"README.md","content":"# dingtalk-ai-table（官方维护）\n\n钉钉 AI 表格技能，已适配 **2026-03-10 发布的新版 MCP tools**。\n\nClawHub 技能地址：https://clawhub.ai/aliramw/dingtalk-ai-table\n\n## 依赖与环境声明\n\n- 必需二进制：`mcporter`、`python3`\n- 必需环境变量：`DINGTALK_MCP_URL`\n- 推荐环境变量：`OPENCLAW_WORKSPACE`（脚本本地文件沙箱根目录）\n\n\n## 本次升级重点\n\n- 全面切换到新 schema：`baseId / tableId / fieldId / recordId`\n- 覆盖 19 个 MCP tools\n- 重写批量字段脚本\n- 重写批量导入脚本\n- 重写测试，当前 `21 / 21` 通过\n\n## 目录\n\n- `SKILL.md`：技能说明\n- `references/api-reference.md`：新版 API 参考\n- `references/error-codes.md`：错误排查\n- `scripts/bulk_add_fields.py`：批量新增字段\n- `scripts/import_records.py`：批量导入记录\n- `tests/test_security.py`：安全与构造测试\n\n## 测试\n\n```bash\ncd /Users/marila/Skills/dingtalk-ai-table\npython3 tests/test_security.py\n```\n\n## 注意\n\n旧版脚本依赖 `dentryUuid / sheetIdOrName`，现在已经废弃。后续调用必须使用新版 ID 体系。"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn74g6pc77st4d6e6t88g2cd0d81wfq3\",\n  \"slug\": \"dingtalk-ai-table\",\n  \"version\": \"0.5.4\",\n  \"publishedAt\": 1774945717086\n}"},{"path":"api-reference.md","content":"# 钉钉 AI 表格 MCP API 参考（2026-03-10 新版）\n\n> 以 MCP server 实际 schema 为准，不再使用旧版 `dentryUuid / sheetIdOrName / fieldIdOrName` 体系。\n> 新版核心 ID 体系：`baseId` / `tableId` / `fieldId` / `recordId`。\n\n推荐使用 `mcporter 0.8.1` 及以上版本。\n\n输出模式兼容说明：\n- `mcporter 0.8.1+` 可直接调用\n- 更低版本需要显式加 `--output text`\n- AI 表格 MCP 无论使用哪种模式，返回体本身都是标准 JSON；差异主要在 `mcporter` 的输出处理方式\n\n## 1. 能力总览\n\n当前 MCP tools 共 20 个：\n\n### Base 管理\n- `list_bases`：列出我可访问的 Base\n- `search_bases`：按名称搜索 Base\n- `get_base`：获取 Base 目录级信息（tables / dashboards 摘要）\n- `create_base`：创建 Base\n- `update_base`：更新 Base 名称 / 描述\n- `delete_base`：删除 Base\n- `search_templates`：搜索可用于创建 Base 的模板\n\n### Table 管理\n- `get_tables`：批量获取指定 tables 的结构摘要\n- `create_table`：创建 table，并可初始化最多 15 个字段\n- `update_table`：重命名 table\n- `delete_table`：删除 table\n\n### Field 管理\n- `get_fields`：获取字段详细配置\n- `create_fields`：批量新增字段\n- `update_field`：更新字段名称或配置\n- `delete_field`：删除字段\n\n### Record 管理\n- `query_records`：按条件 / 关键词 / ID 查询记录\n- `create_records`：批量新增记录\n- `update_records`：批量更新记录\n- `delete_records`：批量删除记录\n\n### 附件管理\n- `prepare_attachment_upload`：为 attachment 字段申请 OSS 直传地址\n\n---\n\n## 2. 推荐工作流\n\n### 2.1 查找 Base\n\n```bash\nmcporter call '<mcp-url>' .list_bases limit=10\nmcporter call '<mcp-url>' .search_bases query='销售'\n```\n\n先拿到 `baseId`，后续所有操作都从它出发。\n\n### 2.2 进入 Base 看目录\n\n```bash\nmcporter call '<mcp-url>' .get_base baseId='base_xxx'\n```\n\n从返回结果里先拿 `tableId`；如果只是想知道有哪些表，这一步就够了。\n\n### 2.3 看表结构\n\n```bash\nmcporter call '<mcp-url>' .get_tables \\\n  --args '{\"baseId\":\"base_xxx\",\"tableIds\":[\"tbl_xxx\"]}'\n```\n\n这一步会返回：\n- `tableId`\n- `tableName`\n- `fields`（仅摘要）\n- `views`\n\n### 2.4 看字段完整配置\n\n```bash\nmcporter call '<mcp-url>' .get_fields \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"fieldIds\":[\"fld_xxx\"]}'\n```\n\n当字段是单选、多选、日期、进度、关联字段时，**要用这一步读完整 config**，不要只看 `get_tables` 摘要。\n\n### 2.5 查记录\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"limit\":100}'\n```\n\n按 recordId 精准取：\n\n```bash\nmcporter call '<mcp-url>' .query_records \\\n  --args '{\"baseId\":\"base_xxx\",\"tableId\":\"tbl_xxx\",\"recordIds\":[\"rec_xxx\"]}'\n```\n\n---\n\n## 3. 关键工具详解\n\n## 3.1 list_bases\n\n列出当前用户可访问的 Base。\n\n参数：\n- `limit`：每页数量，默认 10，最大 30\n- `cursor`：分页游标\n\n## 3.2 search_bases\n\n按名称搜索 Base。\n\n参数：\n- `query`：关键词，必填\n- `cursor`：分页游标\n\n## 3.3 get_base\n\n获取 Base 目录信息。\n\n参数：\n- `baseId`：必填\n\n适用场景：\n- 先拿 table 列表\n- 后续配合 `get_tables` / `get_fields`\n\n## 3.4 create_base\n\n创建新的 AI 表格 Base。\n\n参数：\n- `baseName`：必填\n- `templateId`：可选，可通过 `search_templates` 获取\n\n示例：\n\n```bash\nmcporter call '<mcp-url>' .create_base baseName='销售日报'\n```\n\n## 3.5 update_base\n\n更新 Base 名称或备注。\n\n参数：\n- `baseId`\n- `newBaseName`\n- `description`（可选）\n\n## 3.6 delete_base\n\n删除整个 Base，高风险、不可逆。\n\n参数：\n- `baseId`\n- `reason`（建议填写）\n\n## 3.7 search_templates\n\n搜索模板，用于 `create_base.templateId`。\n\n参数：\n- `query`\n- `limit`\n- `cursor`\n\n## 3.8 get_tables\n\n批量获取表级信息。\n\n参数：\n- `baseId`\n- `tableIds`：数组，单次最多 10 个\n\n适用场景：\n- 从 `get_base` 拿到 tableId 后展开字段目录\n- 获取 fieldId / view 信息\n\n## 3.9 create_table\n\n创建 table，可附带初始字段。\n\n参数：\n- `baseId`\n- `tableName`\n- `fields`：至少 1 个，最多 15 个\n\n字段对象结构：\n"},{"path":"CHANGELOG.md","content":"## [0.5.4] - 2026-03-31\n\n### 维护发布\n\n- ✅ 发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry\n- ✅ 基于当前最新仓库状态重新发版，无额外功能改动\n- ✅ 发布前重新执行安全测试，结果仍为 21 / 21 通过\n\n## [0.5.3] - 2026-03-31\n\n### 维护发布\n\n- ✅ 发布新的 patch 版本，重新同步 GitHub Release 与 ClawHub registry\n- ✅ 复核当前技能目录无未提交功能改动，确认本次为发布补发而非代码变更\n- ✅ 发布前重新执行安全测试，结果仍为 21 / 21 通过\n\n## [0.5.2] - 2026-03-11\n\n### 技能流程优化\n\n- ✅ 新增“版本守门规则”：若 `mcporter` 注册的 `dingtalk-ai-table` 仍返回旧版 schema，必须先提示用户去新版 MCP 页面获取新的 Server 地址，再替换本地注册配置\n- ✅ 修正新版 MCP 获取页面链接为 `https://mcp.dingtalk.com/#/detail?mcpId=9555&detailType=marketMcpDetail`\n- ✅ 将守门逻辑优化为“同一个 MCP Server 地址只强制检查一次”，避免每次运行重复做迁移检查\n- ✅ 移除带真实业务场景的示例内容，保留通用、可复用的技能规则\n\n## [0.5.1] - 2026-03-11\n\n### 元数据修复\n\n- ✅ 补回 `SKILL.md` frontmatter 中的 `version` 与 `metadata.openclaw.requires` 声明\n- ✅ 明确声明必需环境变量：`DINGTALK_MCP_URL`、`OPENCLAW_WORKSPACE`\n- ✅ 明确声明必需二进制：`mcporter`、`python3`\n- ✅ `package.json` 同步补充 `requiredEnv` / `requiresBinaries` / credentials 信息，修复 ClawHub 审核指出的 metadata mismatch\n- ✅ README 同步补充依赖与环境声明\n\n## [0.5.0] - 2026-03-11\n\n### 重大升级\n\n**全面切换到钉钉 AI 表格新版 MCP schema：**\n- ✅ 从旧参数体系 `dentryUuid / sheetIdOrName / fieldIdOrName` 全面切换到新体系 `baseId / tableId / fieldId / recordId`\n- ✅ 以 2026-03-10 发布的新 MCP server 实际 methods 为准，重建技能文档与脚本\n- ✅ 覆盖新版全部 19 个 tools：Base / Table / Field / Record 全链路能力\n\n### 脚本重写\n\n**`scripts/bulk_add_fields.py`：**\n- ✅ 改为调用 `create_fields`\n- ✅ 输入参数改为 `<baseId> <tableId> fields.json`\n- ✅ 支持 `name -> fieldName` 自动兼容\n- ✅ 支持 `phone -> telephone` 自动兼容\n- ✅ 增加新字段类型与关联字段 config 校验\n\n**`scripts/import_records.py`：**\n- ✅ 改为调用 `create_records`\n- ✅ 输入参数改为 `<baseId> <tableId> data.(csv|json)`\n- ✅ 记录结构改为 `cells`\n- ✅ CSV 表头按 `fieldId` 解释\n- ✅ JSON 同时支持裸对象和 `{\"cells\": ...}` 两种格式\n- ✅ 支持布尔值 / 数字自动清洗\n\n### 文档重写\n\n- ✅ `SKILL.md` 按新版 schema 重写\n- ✅ `references/api-reference.md` 按真实 MCP schema 重写\n- ✅ `references/error-codes.md` 按新版排障逻辑重写\n- ✅ `README.md` 更新为新版说明\n- ✅ `package.json` 描述同步更新，版本提升到 `0.5.0`\n\n### 测试\n\n- ✅ `tests/test_security.py` 重写为新版 schema 测试\n- ✅ 自动化测试 **21 / 21 全通过**\n- ✅ Python 语法编译通过：`bulk_add_fields.py`、`import_records.py`、`test_security.py`\n\n## [0.4.1] - 2026-03-10\n\n### 文档更新\n\n**README / SKILL 同步补充：**\n- ✅ README 增加说明：本技能会随着钉钉 AI 表格 MCP 能力更新持续同步更新\n- ✅ SKILL 新增“能力更新”章节，明确当 MCP Server 方法与技能说明不一致时，应优先升级技能\n- ✅ SKILL 补充最新技能获取入口：ClawHub 页面与 GitHub 仓库链接\n\n**变更说明：**\n- 此版本仅文档更新，无脚本逻辑变更\n- 目标是降低因 MCP 能力演进导致的使用偏差\n\n## [0.4.0] - 2026-03-07\n\n### 修复\n\n**ClawHub 审核问题修复：**\n- ✅ 将根节点缓存文件路径从工作区外的 `~/workspace/TABLE.md` 改为工作区内的 `$OPENCLAW_WORKSPACE/TABLE.md`\n- ✅ 文档明确要求根节点缓存文件必须位于工作区内，避免 instruction scope 与脚本安全边界冲突\n- ✅ 脚本中的 `dentryUuid` 校验从“仅允许 UUID v4”放宽为“兼容平台返回的合法 dentryUuid”\n- ✅ README / SKILL / references 同步说明：`dentryUuid` 以 API 实际返回为准，不要求必须是 UUID v4\n- ✅ 安全测试用例同步更新，覆盖 `dtcn_...` 风格 ID\n\n## [0.3.9] - 2026-03-07\n\n### 文档修正\n\n**参数命名说明修复：**\n- ✅ 修正 `SKILL.md` 中 `list_base_tables` 示例参数名：`dentry-uuid` → `dentryUuid`\n- ✅ 在 `README.md` 故障排查中补充说明：`mcporter call ... key:value` 方式必须使用 camelCase 参数名\n- ✅ 在 `references/error-codes.md` 中补充 `5000001` 的常见诱因：误用 kebab-case 参数名\n- ✅ 在 `references/error-codes.md` 的 FAQ 中增加明确排查顺序：先查参"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1100,"uniquenessScore":37,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:13:54.569Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T21:55:42.914Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}