- name
- kingdee-skill-publisher
- description
-
金蝶云苍穹业务Skill快速发布工具。这是一个元Skill,用于基于金蝶苍穹开放平台已发布的API和MCP服务,快速创建和发布财务凭证查询、供应链订单查询等业务Skill。
使用此Skill时:
1. 用户需要配置金蝶苍穹服务器URL和API认证凭证,支持两种认证方式:
- 经典认证(默认):user、appId、appSecret、accountId,通过 `POST {baseUrl}/api/login.do` 获取Token
- 增强型Token认证:client_id、client_secret、username、accountId,通过 `POST {baseUrl}/kapi/oauth2/getToken` 获取Token
2. Skill自动根据 auth_type 选择认证方式并获取 `access_token`
3. Claude通过自然语言查询金蝶API清单,用户选择所需API
4. Claude自动包装成Skill并发布
5. 未来兼容MCP服务集成
触发场景:当用户想要快速发布金蝶业务Skill、配置金蝶API接口、查询金蝶API清单时,使用此Skill。
# 金蝶云苍穹业务Skill发布器
这是一个元Skill(Meta Skill),用于快速发布基于金蝶云苍穹开放平台的业务Skill。它简化了从API集成到Skill发布的全流程。
---
## ⛔ 强制执行规则(最高优先级)
> **本 Skill 的所有操作(凭证验证、API 查询、API 详情获取、Skill 生成)都必须通过执行 Python 脚本完成。AI 不得自行编写、猜测或拼凑任何业务文件内容。**
### 必须遵守
1. **凭证验证** → 必须执行 `publisher.setup_credentials()` Python 代码
2. **API 列表查询** → 必须执行 `publisher.search_apis()` Python 代码
3. **API 详情获取** → 必须执行 `publisher.api_client.get_api_detail()` Python 代码
4. **Skill 生成** → 必须执行 `publisher.create_skill_from_api()` 或 `SkillGenerator.generate_skill()` Python 代码
5. **所有 API URL** → 必须来自服务器 `getDetail` 接口返回的 `urlformat` 字段,禁止猜测或拼凑
### 绝对禁止
- ❌ **禁止 AI 自行编写 SKILL.md、api_call.py 等业务文件**(必须由 Python 脚本生成)
- ❌ **禁止 AI 猜测 API 的 URL 地址**(必须从服务器获取)
- ❌ **禁止 AI 猜测 API 的请求参数和返回参数**(必须从 getDetail 获取)
- ❌ **禁止跳过 Python 脚本直接用 write_to_file 创建 Skill 文件**
### 执行方式
所有 Python 代码必须通过 `execute_command` 工具执行,示例:
```bash
cd /path/to/kingdee-skill-publisher && python3 -c "
from scripts import KingdeeSkillPublisher
publisher = KingdeeSkillPublisher()
publisher.setup_credentials(server_url=..., app_id=..., app_secret=..., account_id=..., user=...)
result = publisher.search_apis(appid_number='xxx', keyword='yyy')
print(result)
"
```
---
## 核心功能
### 1. 凭证管理
- 引导用户配置金蝶服务器连接信息
- 存储和验证API认证凭证(user、appId、appSecret、accountId)
- 按 `login.do` 协议获取并缓存 `access_token`
- 在Token失效时自动重新获取
### 2. API探索与选择
- 自然语言查询金蝶API清单
- 支持按模块、功能、API编码搜索
- 展示API文档细节和参数信息
### 3. Skill自动生成
- 基于选定的API自动生成Skill
- 智能包装参数校验和错误处理
- 生成Skill的README和使用说明
### 4. 发布与测试
- 打包Skill文件(.skill格式)
- 生成测试用例
- 提供Skill安装指引
## 工作流
```
┌─────────────────────────────────────────┐
│ 1. 配置凭证与连接 │
│ - Server URL │
│ - user / appId / appSecret / accountId│
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 2. 询问 appid_number │
│ - 必须询问用户提供应用编码 │
│ - 未提供则停止执行 │
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 3. 搜索API列表 │
│ - 调用 queryByApp 获取API清单 │
│ - 展示API名称、编码、描述 │
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 4. 用户选择API │
│ - 展示API列表供用户选择 │
│ - 必须等待用户明确选择 │
│ - 未选择则停止执行 │
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 5. 获取API详情 (getDetail) │
│ - 使用API ID调用详情接口 │
│ - 获取请求头、请求参数、返回参数 │
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 6. 封装Skill │
│ - 根据详情生成请求头处理代码 │
│ - 生成参数验证和响应解析逻辑 │
│ - 生成完整Skill结构 │
└────────────┬────────────────────────────┘
│
┌────────────▼────────────────────────────┐
│ 7. 测试与发布 │
│ - 生成测试用例 │
│ - 打包 Skill │
│ - 提供安装指引 │
└─────────────────────────────────────────┘
```
## 快速开始
### 第一步:初始化配置
当用户开始使用此Skill时,引导进行以下操作:
**需要收集的信息(根据认证方式选择):**
**经典认证(默认,auth_type="login_do"):**
```
金蝶服务器配置:
├─ 服务器 URL(必须)
│ 示例:https://xxx.kingdee.com/ierp
│
├─ appId(必须)
│ 由金蝶开放平台第三方应用申请
│
├─ appSecret(必须)
│ 需妥善保管,不应暴露
│
├─ accountId(必须)
│ 租户账套ID
│
└─ user(可选,默认admin)
当前操作用户
```
**增强型Token认证(auth_type="oauth2"):**
```
金蝶服务器配置:
├─ 服务器 URL(必须)
│
├─ client_id(必须)
│ 示例:${YOUR_CLIENT_ID}
│
├─ client_secret(必须)
│ AccessToken认证密钥,示例:${YOUR_CLIENT_SECRET},需妥善保管
│
├─ username(必须)
│ 用户名或手机号,示例:${YOUR_USERNAME}
│
├─ accountId(必须)
│ 租户账套ID
│
└─ language(可选,默认zh_CN)
语言设置
```
> `nonce` 和 `timestamp` 由客户端自动生成,无需配置。
**配置验证步骤:**
1. 检查服务器连通性
2. 根据 `auth_type` 调用对应的Token接口获取 `access_token`
3. 使用 `Authorization: Bearer {access_token}` 调用测试接口验证权限
4. 列出可用的API清单(验证查询能力)
### 第二步:探索与查询API(⚠️ 必须执行 Python 脚本)
> ⛔ 必须通过 `execute_command` 执行 `publisher.search_apis()` Python 代码查询,禁止 AI 自行构造 HTTP 请求。
本Skill使用金蝶官方的 `queryByApp` 接口按应用编码查询API列表,确保返回结果与当前应用实际发布的API保持一致。
**接口路径**: `GET /kapi/v2/open/openapi_apilist/queryByApp`
**⚠️ 重要:查询前必须获取 appid_number**
在调用API查询前,**必须在对话框中询问用户提供 `appid_number`**(应用编码)。
- 如果用户提供了 `appid_number`:继续执行查询
- **如果用户未提供 `appid_number`:停止执行,不再进行后续任务**
**询问示例**:
```
我需要查询API列表,请提供应用编码(appid_number)。
例如:basedata、ar、ap、pm 等
```
用户可以通过多种方式查询API:
**方式1:按应用编码获取完整列表**
- 用户必须显式传入 `appid_number`
- `pageNo` 默认值为 `1`
- `pageSize` 默认值为 `10`
**方式2:对结果做本地过滤**
- 关键词过滤:匹配 API 编码、名称、描述
- 模块过滤:基于返回记录中的编码或 URL 做最佳努力过滤
**查询返回信息:**
- API编码 (apiCode) - 用于API调用
- API名称 (apiName) - 中文描述
- 请求方式 (method) - GET/POST
- API描述 (apiDescription) - 功能说明
- 所属模块 (module) - ar/ap/pm等
- API版本 (version) - 版本号
- API状态 (status) - 发布/草稿等
- 请求参数 (requestParams) - 完整的参数定义
- 返回参数 (returnParams) - 返回字段定义
- 错误码 (errorCodes) - 业务错误码
**示例查询结果:**
```python
# 注意:appid_number 必须询问用户提供
result = publisher.search_apis(
appid_number="basedata", # 用户提供的应用编码
keyword="凭证"
)
# 输出示例:
{
"success": True,
"total": 5,
"apis": [
{
"apiCode": "ar_getBillDetail",
"apiName": "应收凭证详情",
"method": "GET",
"module": "ar",
"apiDescription": "查询应收凭证的详细信息",
"requestParams": [
{"name": "billId", "type": "String", "required": True, "description": "凭证ID"}
],
"returnParams": [
{"name": "id", "type": "String", "description": "凭证ID"},
{"name": "billNo", "type": "String", "description": "凭证号"}
]
},
# ... 更多API
]
}
```
**⚠️ 重要:必须等待用户选择API**
返回API列表后,**必须在对话框中展示API列表并询问用户选择**,示例如下:
```
找到以下API,请选择一个继续:
1. ar_getBillDetail - 应收凭证详情
描述:查询应收凭证的详细信息
2. ar_getBillList - 应收凭证列表
描述:查询应收凭证列表
请输入序号(1-2)或直接告诉我API名称:
```
**执行规则**:
- 如果用户**选择了API**:继续执行第三步获取API详情
- **如果用户没有选择API:停止执行,不再进行后续任务**
### 第三步:获取API详情(⚠️ 必须执行 Python 脚本)
> ⛔ 必须通过 `execute_command` 执行 `publisher.api_client.get_api_detail(api_id)` Python 代码获取详情,禁止 AI 自行猜测 API 的 URL、参数和返回值。
**前置条件:用户已明确选择了一个API**
用户选择API后,Claude必须通过执行Python代码调用详情接口获取完整的API定义(包括真实URL):
**接口信息**:
- **接口地址**: `GET /v2/open/openapi_apilist/getDetail`
- **请求方式**: GET
- **请求头**:
- `Content-Type`: application/json
- `accesstoken`: {access_token}
- **Query参数**:
- `id`: API主键ID(必填,从第二步API列表中获取)
- `pageSize`: 分页大小(**必填**,即使只查询单条记录,默认10)
- `pageNo`: 查询页码(可选,默认1)
**⚠️ 重要提示**: 此查询接口**必须传递分页参数 `pageSize` 和 `pageNo`**,即使只查询单条记录。
**返回内容** (`data.rows[0]`):
```json
{
"success": true,
"api_detail": {
"id": "API主键ID",
"api_code": "API编码",
"api_name": "API名称",
"api_description": "API描述",
"method": "GET/POST",
"url": "/v2/open/...",
"request_headers": [
{"name": "Content-Type", "value": "application/json", "description": "内容格式", "required": true},
{"name": "accesstoken", "value": "...", "description": "请求令牌", "required": true}
],
"request_query_params": [
{"name": "id", "type": "Long", "description": "主键ID", "required": true, "example": ""}
],
"request_body_params": [
{"name": "param1", "type": "String", "description": "参数说明", "required": true, "example": "..."}
],
"response_params": [
{"name": "field1", "type": "String", "description": "字段说明", "required": true, "level": "1"}
],
"error_codes": [
{"code": "400", "description": "参数错误"}
]
}
}
```
**参数来源说明**(根据金蝶OpenAPI文档):
| 规范化字段 | 原始字段 | 说明 |
|------------|----------|------|
| `request_headers` | `headerentryentity` | 请求头参数 |
| `request_query_params` | `urlparamentryentity` | URL查询参数 |
| `request_body_params` | `bodyentryentity` | 请求体参数 |
| `response_params` | `respentryentity` | 返回参数 |
| `error_codes` | `errorcodeentity` | 错误码定义 |
| `orderby_rules` | `orderby_entry` | 排序规则 |
| `save_params` | `saveparamentryentity` | 操作参数 |
```
### 第四步:封装Skill(⚠️ 必须通过 Python 代码生成)
**⚠️⚠️⚠️ 关键原则:必须通过执行 Python 代码生成 Skill,禁止手动编写文件内容**
获取到完整的API详情后,Claude **必须调用项目中的 Python 代码**来生成 Skill,而**不是自己直接编写文件内容**。Python 代码内置了 YAML 描述头生成和验证逻辑,能确保生成的 SKILL.md 格式正确。
**方式1(推荐):使用 `KingdeeSkillPublisher.create_skill_from_api_id()`**
```python
from scripts import KingdeeSkillPublisher
publisher = KingdeeSkillPublisher()
publisher.setup_credentials(
server_url=server_url,
app_id=app_id,
app_secret=app_secret,
account_id=account_id,
user=user
)
# 使用用户选择的 API 的主键 ID 直接生成 Skill
result = publisher.create_skill_from_api_id(
api_id=selected_api['id'], # 用户选择的 API 主键 ID
skill_name="ar-bill-detail-query", # 可选,默认使用 API 编码
skill_description="查询应收凭证详情" # 可选
)
if result['success']:
print(f"✅ Skill 已生成: {result['skill_path']}")
else:
print(f"❌ 生成失败: {result['message']}")
```
**方式2:使用 `KingdeeSkillPublisher.create_skill_from_api()`**
```python
# 使用 search_apis 返回的 api_info + use_detail=True 自动获取详情
result = publisher.create_skill_from_api(
api_info=selected_api, # 用户选择的 API(包含 id 字段)
skill_name="ar-bill-detail-query",
skill_description="查询应收凭证详情",
use_detail=True # 自动调用 getDetail 获取完整详情
)
```
**方式3:直接使用 `SkillGenerator`**
```python
from scripts.skill_generator import SkillGenerator
generator = SkillGenerator(output_dir="./outputs")
skill_dir = generator.generate_skill(
api_info=api_detail, # 完整的 API 详情字典
custom_name="ar-bill-detail-query",
custom_description="查询应收凭证详情"
)
print(f"✅ Skill 已生成: {skill_dir}")
```
**Python 代码会自动完成以下工作**:
1. **生成带 YAML 描述头的 SKILL.md**(内置 frontmatter 验证,确保 `name:` 和 `description: |` 字段完整)
2. 根据 `request_headers` 生成请求头处理代码(`scripts/api_call.py`)
3. 复制 API 客户端代码(`scripts/api_client.py`,含 Token 管理)
4. 根据 `request_query_params` 和 `request_body_params` 生成参数验证逻辑
5. 根据 `response_params` 生成 API schema(`references/api_schema.json`)
6. 根据 `error_codes` 生成错误码对照表(`references/error_codes.json`)
7. 生成使用示例(`references/examples.json`)
8. 生成 README.md 和 LICENSE.txt
9. **最终验证** SKILL.md 描述头完整性
**生成的 Skill 目录结构**:
```
${skill_name}/
├─ SKILL.md(包含 YAML 描述头,由 Python 代码自动生成并验证)
├─ scripts/
│ ├─ __init__.py
│ ├─ api_call.py(API 调用逻辑)
│ ├─ api_client.py(API 客户端,Token 管理)
│ └─ utils.py(工具函数)
├─ references/
│ ├─ api_schema.json(API 参数 schema)
│ ├─ error_codes.json(错误码对照)
│ └─ examples.json(使用示例)
├─ README.md
└─ LICENSE.txt
```
**⚠️ 禁止事项**:
- ❌ 禁止手动编写 SKILL.md 文件内容(会遗漏描述头)
- ❌ 禁止跳过 Python 代码直接创建文件
- ❌ 禁止修改生成的 SKILL.md 描述头格式
**API 详情字段说明**(Python 代码内部使用):
| 规范化字段 | 原始字段 | 说明 |
|------------|----------|------|
| `request_headers` | `headerentryentity` | 请求头参数 |
| `request_query_params` | `urlparamentryentity` | URL 查询参数 |
| `request_body_params` | `bodyentryentity` | 请求体参数 |
| `response_params` | `respentryentity` | 返回参数 |
View on GitHub