Klavis SDK 升级全流程解析:基于 Fern 的 openapi.json 驱动代码生成与 PyPI/NPM 发布管线
【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis
Klavis 仓库的fern/目录是整个 SDK 体系的"单一事实来源":本文以 fern/README.md 中描述的 SDK 升级三步流程为主线,结合 fern/generators.yml、fern/overrides.yml 与 SDK 发布工作流 等仓库证据,讲清楚"如何从一份 OpenAPI 规范出发,自动生成并发布 Python 与 TypeScript 双语言 SDK"。读完本文,你将掌握 Klavis SDK 的完整升级链路:规范更新、PR 合并、GitHub Actions 手动触发发布,以及 Fern 生成器的关键配置项各自影响 SDK 的哪一部分。
一、SDK 升级的官方三步流程
fern/README.md 定义了 Klavis SDK 升级的标准操作,全文共三步:
- 更新 openapi.json 文件:将最新的 API 规范写入
openapi.json; - 提交 PR 并合并:把变更合并到 main 分支;
- 去 GitHub Actions 手动触发发布:点击
Publish Python SDK和Publish TypeScript SDK工作流,填写新版本号,流水线会自动生成并发布新版本 SDK。
整个流程的核心思想是:API 规范(OpenAPI)先行,SDK 代码零手写。开发者只需要维护规范文件,Python SDK 与 TypeScript SDK 的接口定义、类型、客户端方法全部由 Fern 生成器从规范推导而来。下面逐步拆解每一步在仓库中的落地形式。
二、第一步:更新 API 规范文件
规范文件的位置与引用方式
fern/generators.yml声明了生成器的输入规范:
api: specs: - openapi: ../docs/api-reference/openapi.json overrides: overrides.yml origin: https://api.klavis.ai/openapi.json(见 fern/generators.yml)
openapi: ../docs/api-reference/openapi.json:本地仓库中的规范文件,实际位于 docs/api-reference/openapi.json。该文件是一份 OpenAPI 3.1.0 规范,标题为 "Klavis AI",声明了 US 与 EU 两套生产 API 服务器;overrides: overrides.yml:指定类型重命名与 SDK 方法命名覆盖规则,见 fern/overrides.yml;origin:生产环境规范的远端地址,用于在线同步(下文工作流部分会用到)。
如何更新规范
仓库提供了一条半自动的同步路径。.github/workflows/sync-openapi.yml 定义了名为Sync OpenAPI Specs的手动触发工作流,其核心步骤为:
- name: Update API with Fern uses: fern-api/sync-openapi@v2 with: update_from_source: true token: ${{ secrets.OPENAPI_SYNC_TOKEN }} branch: 'update-api' auto_merge: false add_timestamp: true该工作流会从origin地址拉取线上最新 API 规范,写入update-api分支并自动追加时间戳,且auto_merge: false——即不会自动合并,必须走人工审查。这正对应 README 三步流程中的第二步:规范更新以 PR 形式进入 main 分支,保证 API 变更经过评审后才进入 SDK 生成链路。
从源码结构看,规范文件本身覆盖了三类接口域,与 SDK 最终暴露的模块一一对应:MCP 服务(如/mcp-server/call-tool、/mcp-server/list-tools)、OAuth 授权(如/oauth/slack/authorize等数十个服务的 authorize 端点)、以及各类型沙箱的initialize/dump端点。
三、第二步:提交 PR 并合并到 main 分支
README 明确要求规范变更通过 PR 合并至 main。从仓库的 CI 结构可以推断这一设计的意图:
- 发布工作流(见下节)以
main分支上的fern/目录和docs/api-reference/openapi.json为输入,PR 合并是"规范冻结"的动作; sync-openapi.yml的auto_merge: false配置保证了任何规范变更(无论是人工编辑还是从远端同步)都必须经过一次代码评审;- fern/README.md 中的顺序设计(先合并规范、后触发发布)意味着发布时点与 main 分支上的规范版本严格一致,避免"规范与 SDK 版本错位"。
这一步没有任何代码逻辑,其价值在于把 OpenAPI 文件变成受版本控制、受评审约束的发布契约。
四、第三步:GitHub Actions 手动触发 SDK 发布
README 中的第三步对应仓库里两个workflow_dispatch手动触发的工作流。
Publish Python SDK
.github/workflows/python-sdk-release.yml 的完整执行链路为:
name: Publish Python SDK on: workflow_dispatch: inputs: version: description: "The version of the Python SDK that you would like to release" required: true type: string执行步骤依次是:
- 检出代码(
actions/checkout@v4),要求contents: write权限以打 tag; - 全局安装 Fern CLI:
npm install -g fern-api; - 执行发布命令,注入
FERN_TOKEN与PYPI_TOKEN两个 secret:
fern generate --group python-sdk --version ${{ inputs.version }} --log-level debug(见 python-sdk-release.yml)
- 使用
softprops/action-gh-release@v1创建 GitHub Release,tag 为python-v${{ inputs.version }},自动基于上次 tag 以来的 commit 生成 release notes。
命令中的--group python-sdk精确指向generators.yml中定义的python-sdk生成组,--version即 README 所说的"specify new version"。
Publish TypeScript SDK
.github/workflows/typescript-sdk-release.yml 与 Python 版几乎同构,差异仅在:
- 执行
fern generate --group ts-sdk --version ${{ inputs.version }}(见 typescript-sdk-release.yml); - 注入
FERN_TOKEN与NPM_TOKEN; - GitHub Release 的 tag 前缀为
ts-v${{ inputs.version }}。
两条工作流的命名(Publish Python SDK/Publish TypeScript SDK)正是 README 第三步在 GitHub Actions 界面上看到的按钮名称。
五、generators.yml 深度解析:SDK 长什么样由这里决定
全局生成设置(api.specs.settings)
fern/generators.yml的settings段(见 fern/generators.yml)控制规范到 SDK 类型的全局翻译规则:
| 配置项 | 取值 | 作用 |
|---|---|---|
title-as-schema-name | true | 用 schema 的 title 作为类型名,使生成的类名更贴近 API 语义 |
type-dates-as-strings | true | 日期字段统一生成为字符串类型,避免跨语言日期库差异 |
object-query-parameters | false | 查询参数不包装成对象 |
idiomatic-request-names | false | 请求体类型名保持规范原名 |
respect-nullable-schemas | false | 不强制按规范的 nullable 标注生成可空类型 |
wrap-references-to-nullable-in-optional | true | 指向可空 schema 的引用包装为 Optional |
coerce-optional-schemas-to-nullable | true | 可选 schema 归一化为可空类型 |
inline-path-parameters | false | 路径参数保持独立,不内联进方法签名结构 |
coerce-enums-to-literals | true | 枚举转换为字面量联合类型 |
这些布尔开关共同决定了生成 SDK 中类型可空性、命名风格等"手感"层面的行为,升级规范时如果某次 API 变更引入了新的可空字段,这些设置会影响新字段在 SDK 中的呈现方式。
python-sdk 生成组
python-sdk: generators: - name: fernapi/fern-python-sdk version: 4.32.2 output: location: pypi package-name: klavis token: ${PYPI_TOKEN} config: client_class_name: Klavis pydantic_config: enum_type: python_enums metadata: package-description: Open Source MCP Integration for AI applications license: Apache-2.0 smart-casing: true(见 fern/generators.yml)
关键事实:
- 产物发布到 PyPI,包名
klavis,与 docs/sdk/python.mdx 中pip install klavis的安装方式一致; - 客户端类名固定为
Klavis,即文档示例里klavis_client = Klavis(api_key="...")的入口; - 枚举使用 Python 原生
Enum(enum_type: python_enums),因此from klavis.types import McpServerName中的McpServerName.YOUTUBE是标准枚举成员; - 发布凭据来自环境变量
${PYPI_TOKEN},与发布工作流中注入的 secret 名称相互印证。
ts-sdk 生成组
ts-sdk: generators: - name: fernapi/fern-typescript-node-sdk version: 1.7.0 output: location: npm package-name: klavis token: ${NPM_TOKEN} config: namespaceExport: Klavis allowCustomFetcher: true skipResponseValidation: true includeApiReference: true noSerdeLayer: true extraDevDependencies: msw: 2.11.2(见 fern/generators.yml)
- 产物发布到 npm,包名同样为
klavis,与 docs/sdk/typescript.mdx 及 README.md 中import { KlavisClient, McpServerName } from 'klavis'的用法对应; namespaceExport: Klavis提供命名空间导出;noSerdeLayer: true关闭序列化层,skipResponseValidation: true跳过响应校验,allowCustomFetcher: true允许调用方注入自定义 fetch 实现;msw(Mock Service Worker)作为额外 dev 依赖被写进产物,供生成代码的测试使用。
六、overrides.yml:让生成结果符合 SDK 命名约束
OpenAPI 规范中的原始命名(带连字符的 schema 名、大量同构端点)直接生成会得到不可用的 SDK 代码,fern/overrides.yml 共 636 行,通过x-fern-*注解做了三类修正:
1. FastAPI 变体类型改名
FastAPI 会为响应模型生成-Input/-Output两个 schema 变体,overrides 将它们统一改名为合法驼峰标识符:
components: schemas: # Fix duplicate type names from FastAPI -Input/-Output schema variants AirtableData-Input: x-fern-type-name: AirtableDataInput AirtableData-Output: x-fern-type-name: AirtableDataOutput(见 fern/overrides.yml,同类映射覆盖 Slack、Notion、GitHub 等数十个服务的数据类型)
2. 枚举值大写化
McpServerName枚举的显示名(如 "GitHub"、"YouTube")被映射为大写枚举成员:
McpServerName: x-fern-enum: "GitHub": name: GITHUB "YouTube": name: YOUTUBE(见 fern/overrides.yml)这解释了 SDK 文档中McpServerName.YOUTUBE这类全大写成员的由来。
3. 端点归组与方法重命名
overrides 的paths段(见 fern/overrides.yml)把 REST 端点整理成 SDK 的分组方法:
POST /mcp-server/call-tool→mcp_server.call_tools;POST /mcp-server/list-tools→mcp_server.list_tools;GET /mcp-server/tools/{serverName}→mcp_server.get_tools;- 每个
/oauth/{service}/authorize端点归入oauth组并重命名为authorize_{service}(如authorize_gmail、authorize_slack); - 各沙箱的
{service}/{sandbox_id}/initialize与dump端点分别重命名为initialize_{service}_sandbox/dump_{service}_sandbox,文件中的注释写明 "all 35 sandbox types need unique method names"——即靠重命名解决 35 种沙箱端点生成的方法名冲突问题。
从源码结构看,正是这些x-fern-sdk-group-name/x-fern-sdk-method-name注解,使得generators.yml生成的 SDK 呈现出klavis_client.mcp_server.call_tools(...)、klavis_client.oauth.authorize_gmail(...)这类层级清晰的调用结构,与 docs/api-reference/sandbox 等 API 参考文档的分组保持一致。
七、发布后的验证路径
一次成功升级后,可以在仓库内通过以下路径验证 SDK 与规范的对应关系:
- Python 安装与调用示例:docs/sdk/python.mdx(
pip install klavis,含 OpenAI function calling 的完整示例); - TypeScript 安装与调用示例:docs/sdk/typescript.mdx;
- 规范原文:docs/api-reference/openapi.json;
- Fern 全局配置:fern/fern.config.json(组织名
klavis、版本3.5.0)。
八、小结:一次完整升级的操作清单
把 README 的三步落到具体动作:
- 在 GitHub Actions 手动运行
Sync OpenAPI Specs(或在本地编辑 docs/api-reference/openapi.json 并同步 fern/overrides.yml 中的命名修正),确认 diff 无误; - 将变更以 PR 形式合并到 main 分支;
- 分别手动触发
Publish Python SDK与Publish TypeScript SDK,在version输入框填入目标版本号;流水线会自动执行fern generate --group python-sdk|ts-sdk,把新版本推送到 PyPI / npm,并创建python-v{version}/ts-v{version}的 GitHub Release。
需要说明的前提:触发发布工作流依赖仓库维护者配置的FERN_TOKEN、PYPI_TOKEN、NPM_TOKEN、OPENAPI_SYNC_TOKEN等 secrets,该操作属于仓库维护者权限;对于普通贡献者而言,可验证与可参与的环节集中在规范文件的 PR 修改与 overrides 规则的补充上。
【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考