fix(plugins): package Gemini releases and improve OAuth (#94)

## Summary

- preserve the existing `agentkey.skill` GitHub Release asset and add
platform-named Gemini extension archives for macOS, Linux, and Windows
- opt the Gemini extension into native first-connect OAuth with
`oauth.enabled`, while keeping `/mcp auth agentkey` as the manual retry
path
- add explicit Gemini, Antigravity 2.0, and Antigravity CLI
authentication and connection-verification guidance
- explain Gemini's user-Skill precedence warning and avoid duplicate MCP
registrations when an extension or plugin already owns the server entry
- add regression coverage and trigger the scripts test workflow when
authentication guidance or release packaging changes

## Root causes

Gemini CLI treats a lone generic GitHub Release asset as the extension
archive. AgentKey releases currently publish only `agentkey.skill`, but
Gemini CLI extracts only `.tar.gz` and `.zip` extension archives. After
that extraction failure, Gemini retries Git clone in the same non-empty
temporary directory and fails again.

Separately, the Gemini manifest omitted `oauth.enabled`. Gemini
discovered that AgentKey required OAuth, but only reported `/mcp auth
agentkey` instead of starting the browser flow automatically. A
pre-existing user Skill at `~/.agents/skills/agentkey` can also override
the extension-bundled Skill, hiding new setup guidance even though the
extension MCP entry is active.

## Authentication design

- Gemini uses `httpUrl` plus `oauth.enabled: true`; OAuth endpoints and
client registration remain dynamically discovered.
- Antigravity keeps the documented credential-free `serverUrl`
configuration and uses DCR through its native Authenticate controls.
- No static access token, Authorization header, OAuth client secret, or
hard-coded authorization endpoint is added to either package.

## Validation

- Bats suite: 27/27 passing
- `gemini extensions validate .`
- built and inspected `agentkey.skill`, `darwin.agentkey.tar.gz`,
`linux.agentkey.tar.gz`, and `win32.agentkey.zip`
- verified both Gemini platform archive formats contain `oauth.enabled:
true`, `gemini-extension.json`, and `skills/agentkey/SKILL.md`
- validated workflow YAML, shell syntax, archive roots, manifest
invariants, and `git diff --check`
- verified the live AgentKey endpoint advertises protected-resource
metadata, PKCE, and a dynamic client registration endpoint

## Release coordination

Merge this fix before release PR #92 so the first Gemini-enabled release
publishes compatible archives and the corrected first-connect OAuth
behavior.

---------

Co-authored-by: Allen <0xfatdog@gmail.com>
This commit is contained in:
zzAllenn
2026-08-11 16:30:22 +08:00
committed by GitHub
parent 49a015b408
commit fbec683e87
13 changed files with 323 additions and 34 deletions
+9 -3
View File
@@ -21,7 +21,7 @@ It also works as a **Cursor plugin** (`.cursor-plugin/plugin.json`). The Cursor-
It also works as a **Kimi Code plugin** (`.kimi-plugin/plugin.json`). Kimi requires `mcpServers` to be an inline object in the manifest. The remote AgentKey endpoint uses Kimi's native MCP OAuth flow; after install Kimi shows the standard `/reload` hint, then the user signs in with `/mcp-config login plugin-agentkey:agentkey` when Kimi reports that OAuth is required.
It also works as a **Gemini CLI extension** (root `gemini-extension.json` + `skills/`). Gemini requires the manifest at the extension root, discovers bundled agent skills automatically, and connects to AgentKey with `httpUrl` plus native MCP OAuth discovery. `/mcp auth agentkey` substitutes for step 2.
It also works as a **Gemini CLI extension** (root `gemini-extension.json` + `skills/`). Gemini requires the manifest at the extension root, discovers bundled agent skills automatically, and connects to AgentKey with `httpUrl` plus native MCP OAuth discovery. `oauth.enabled` requests the browser flow automatically; `/mcp auth agentkey` is the manual fallback. Either substitutes for step 2.
It also works as an **Antigravity 2.0 and Antigravity CLI plugin** (root `plugin.json` + `mcp_config.json` + `skills/`). Both runtimes use the same package, require `serverUrl` for remote MCP, and authenticate through automatic OAuth discovery.
@@ -47,6 +47,7 @@ agentkey/
│ ├── scripts/ # check-update helper
│ └── version.txt # Managed by release-please only — must live inside the skill so it survives `npx skills add`
└── scripts/
├── build-release-assets.sh # Builds Skill + Gemini GitHub Release assets
└── uninstall.sh # End-user cleanup helper
```
@@ -110,10 +111,15 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl
**Changes to `gemini-extension.json`:**
- The manifest MUST remain at the repository root because Gemini installs the repository as the extension root and expects the extension name to match its install directory.
- Keep `mcpServers.agentkey` inline and use `httpUrl` for the Streamable HTTP endpoint. Do not use the SSE-only `url` field for `/v1/mcp`.
- Do not add static credentials, `settings`, custom headers, or `trust`. Gemini discovers the AgentKey OAuth metadata after the server's 401, and users authenticate with `/mcp auth agentkey`.
- Keep `oauth` limited to `{"enabled":true}` so Gemini starts its native browser flow after the server's 401 while still discovering all endpoints dynamically. Do not add static credentials, OAuth endpoints/client credentials, `settings`, custom headers, or `trust`. `/mcp auth agentkey` remains the manual fallback.
- Do not duplicate `skills/agentkey/` or add an always-loaded `GEMINI.md`; Gemini discovers the existing skill automatically.
- Keep the endpoint URL in sync with `.mcp.json`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, and `.kimi-plugin/plugin.json`.
**Changes to GitHub Release assets:**
- Keep `agentkey.skill` for Skill consumers, but never publish it as the only generic Release asset. Gemini CLI treats a lone generic asset as an extension archive and only extracts `.tar.gz` or `.zip` files.
- Run `scripts/build-release-assets.sh` to produce `agentkey.skill` plus `darwin.agentkey.tar.gz`, `linux.agentkey.tar.gz`, and `win32.agentkey.zip`.
- Every platform-named Gemini archive MUST contain `gemini-extension.json` and `skills/agentkey/SKILL.md` at its archive root. Keep the platform prefixes so Gemini selects these archives before `agentkey.skill`.
**Changes to root `plugin.json` / `mcp_config.json`:**
- Keep both files at the repository root so Antigravity 2.0 and Antigravity CLI share one plugin package and reuse `skills/agentkey/` without duplication.
- Keep `plugin.json` limited to the documented `$schema`, `name`, and `description` fields. The Antigravity schema has no `version` field, so release-please must not add one.
@@ -133,6 +139,6 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl
- `.mcp.json` registers the remote-HTTP MCP endpoint (`https://api.agentkey.app/v1/mcp`) in Claude Code plugin mode; the API key flows from plugin userConfig into the `Authorization: Bearer ${user_config.AGENTKEY_API_KEY}` header (no stdio binary is launched)
- `.cursor-plugin/plugin.json` registers the same endpoint inline in Cursor plugin mode, authenticated through Cursor's native MCP OAuth flow
- `.kimi-plugin/plugin.json` registers the same endpoint inline in Kimi Code plugin mode. After reloading, the user starts Kimi's native MCP OAuth flow with `/mcp-config login plugin-agentkey:agentkey`.
- `gemini-extension.json` registers the same endpoint through `httpUrl` in Gemini CLI extension mode. Gemini discovers the existing `skills/agentkey/` tree and authenticates through `/mcp auth agentkey`.
- `gemini-extension.json` registers the same endpoint through `httpUrl` in Gemini CLI extension mode. Gemini discovers the existing `skills/agentkey/` tree; `oauth.enabled` starts native OAuth automatically and `/mcp auth agentkey` retries it manually.
- Root `plugin.json` and `mcp_config.json` package the existing skill and the same endpoint for both Antigravity 2.0 and Antigravity CLI; remote MCP uses `serverUrl` and automatic OAuth discovery.
- `README.md` / `docs/README_zh.md` are the public-facing docs; keep them in sync with any structural changes
+11 -12
View File
@@ -22,29 +22,28 @@ jobs:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
publish-skill-asset:
publish-release-assets:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- name: Build agentkey.skill zip
run: |
cd skills/agentkey
zip -r "$GITHUB_WORKSPACE/agentkey.skill" . \
-x "*.DS_Store" \
-x "__pycache__/*" \
-x "*.pyc"
echo "--- contents ---"
unzip -l "$GITHUB_WORKSPACE/agentkey.skill"
- name: Build Skill and Gemini extension assets
run: scripts/build-release-assets.sh dist/release-assets
- name: Upload asset to release
- name: Upload assets to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
gh release upload "$TAG" agentkey.skill \
gh release upload "$TAG" \
dist/release-assets/agentkey.skill \
dist/release-assets/darwin.agentkey.tar.gz \
dist/release-assets/linux.agentkey.tar.gz \
dist/release-assets/win32.agentkey.zip \
--repo "$GITHUB_REPOSITORY" \
--clobber
+13
View File
@@ -3,18 +3,31 @@ on:
push:
paths:
- 'skills/agentkey/scripts/**'
- 'scripts/build-release-assets.sh'
- 'skills/agentkey/SKILL.md'
- 'skills/agentkey/references/setup.md'
- 'gemini-extension.json'
- 'plugin.json'
- 'mcp_config.json'
- 'README.md'
- 'docs/README_zh.md'
- 'tests/**'
- '.github/workflows/release-please.yml'
- '.github/workflows/scripts-test.yml'
pull_request:
paths:
- 'skills/agentkey/scripts/**'
- 'scripts/build-release-assets.sh'
- 'skills/agentkey/SKILL.md'
- 'skills/agentkey/references/setup.md'
- 'gemini-extension.json'
- 'plugin.json'
- 'mcp_config.json'
- 'README.md'
- 'docs/README_zh.md'
- 'tests/**'
- '.github/workflows/release-please.yml'
- '.github/workflows/scripts-test.yml'
jobs:
bats:
+9 -3
View File
@@ -19,7 +19,7 @@ The same repo also works as:
- a **Codex plugin** (`.codex-plugin/plugin.json` + `.codex-plugin/mcp.json`, distributed through `.agents/plugins/marketplace.json`; the repo is its own marketplace: `codex plugin marketplace add chainbase-labs/agentkey`). Codex plugins have no `userConfig`/header-interpolation mechanism, so auth uses MCP OAuth via the server's RFC 9728 metadata discovery (`type` + `url` only in mcp.json), substituting for step 2.
- a **Cursor plugin** (`.cursor-plugin/plugin.json`). The Cursor-native manifest bundles `skills/` and an inline remote-HTTP MCP entry. Cursor authenticates through the server's MCP OAuth discovery, substituting for step 2.
- a **Kimi Code plugin** (`.kimi-plugin/plugin.json`). Kimi requires `mcpServers` to be an inline object in the manifest. The remote AgentKey endpoint uses Kimi's native MCP OAuth flow; after install Kimi shows the standard `/reload` hint, then the user signs in with `/mcp-config login plugin-agentkey:agentkey` when Kimi reports that OAuth is required.
- a **Gemini CLI extension** (root `gemini-extension.json` + `skills/`). Gemini requires the manifest at the extension root, discovers bundled agent skills automatically, and connects to AgentKey with `httpUrl` plus native MCP OAuth discovery. `/mcp auth agentkey` substitutes for step 2.
- a **Gemini CLI extension** (root `gemini-extension.json` + `skills/`). Gemini requires the manifest at the extension root, discovers bundled agent skills automatically, and connects to AgentKey with `httpUrl` plus native MCP OAuth discovery. `oauth.enabled` requests the browser flow automatically; `/mcp auth agentkey` is the manual fallback. Either substitutes for step 2.
- an **Antigravity 2.0 and Antigravity CLI plugin** (root `plugin.json` + `mcp_config.json` + `skills/`). Both runtimes use the same package, require `serverUrl` for remote MCP, and authenticate through automatic OAuth discovery.
## Directory Structure
@@ -44,6 +44,7 @@ agentkey/
│ ├── scripts/ # check-update helper
│ └── version.txt # Managed by release-please only — must live inside the skill so it survives `npx skills add`
└── scripts/
├── build-release-assets.sh # Builds Skill + Gemini GitHub Release assets
└── uninstall.sh # End-user cleanup helper
```
@@ -107,10 +108,15 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl
**Changes to `gemini-extension.json` (Gemini CLI extension path):**
- The manifest MUST remain at the repository root because Gemini installs the repository as the extension root and expects the extension name to match its install directory.
- Keep `mcpServers.agentkey` inline and use `httpUrl` for the Streamable HTTP endpoint. Do not use the SSE-only `url` field for `/v1/mcp`.
- Do not add static credentials, `settings`, custom headers, or `trust`. Gemini discovers the AgentKey OAuth metadata after the server's 401, and users authenticate with `/mcp auth agentkey`.
- Keep `oauth` limited to `{"enabled":true}` so Gemini starts its native browser flow after the server's 401 while still discovering all endpoints dynamically. Do not add static credentials, OAuth endpoints/client credentials, `settings`, custom headers, or `trust`. `/mcp auth agentkey` remains the manual fallback.
- Do not duplicate `skills/agentkey/` or add an always-loaded `GEMINI.md`; Gemini discovers the existing skill automatically.
- Keep the endpoint URL in sync with `.mcp.json`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, and `.kimi-plugin/plugin.json`.
**Changes to GitHub Release assets:**
- Keep `agentkey.skill` for Skill consumers, but never publish it as the only generic Release asset. Gemini CLI treats a lone generic asset as an extension archive and only extracts `.tar.gz` or `.zip` files.
- Run `scripts/build-release-assets.sh` to produce `agentkey.skill` plus `darwin.agentkey.tar.gz`, `linux.agentkey.tar.gz`, and `win32.agentkey.zip`.
- Every platform-named Gemini archive MUST contain `gemini-extension.json` and `skills/agentkey/SKILL.md` at its archive root. Keep the platform prefixes so Gemini selects these archives before `agentkey.skill`.
**Changes to root `plugin.json` / `mcp_config.json` (Antigravity plugin path):**
- Keep both files at the repository root so Antigravity 2.0 and Antigravity CLI share one plugin package and reuse `skills/agentkey/` without duplication.
- Keep `plugin.json` limited to the documented `$schema`, `name`, and `description` fields. The Antigravity schema has no `version` field, so release-please must not add one.
@@ -131,6 +137,6 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl
- `.codex-plugin/mcp.json` registers the same endpoint in Codex plugin mode, authenticated via MCP OAuth (RFC 9728 discovery; no `oauth_resource` — see checklist above)
- `.cursor-plugin/plugin.json` registers the same endpoint inline in Cursor plugin mode, authenticated through Cursor's native MCP OAuth flow
- `.kimi-plugin/plugin.json` registers the same endpoint inline in Kimi Code plugin mode. After reloading, the user starts Kimi's native MCP OAuth flow with `/mcp-config login plugin-agentkey:agentkey`.
- `gemini-extension.json` registers the same endpoint through `httpUrl` in Gemini CLI extension mode. Gemini discovers the existing `skills/agentkey/` tree and authenticates through `/mcp auth agentkey`.
- `gemini-extension.json` registers the same endpoint through `httpUrl` in Gemini CLI extension mode. Gemini discovers the existing `skills/agentkey/` tree; `oauth.enabled` starts native OAuth automatically and `/mcp auth agentkey` retries it manually.
- Root `plugin.json` and `mcp_config.json` package the existing skill and the same endpoint for both Antigravity 2.0 and Antigravity CLI; remote MCP uses `serverUrl` and automatic OAuth discovery.
- `README.md` / `docs/README_zh.md` are the public-facing docs; keep them in sync with any structural changes
+12 -4
View File
@@ -394,9 +394,11 @@ gemini extensions install https://github.com/chainbase-labs/agentkey
gemini extensions link /absolute/path/to/agentkey
```
Restart Gemini CLI after installing or linking. If the MCP server requires authentication, run `/mcp auth agentkey` and approve the browser authorization; Gemini then stores and refreshes the OAuth tokens. Use `/mcp reload` after changing the server configuration.
Restart Gemini CLI after installing or linking. On the first connection, the extension's `oauth.enabled` setting asks Gemini to start its native browser authorization automatically. Complete that flow, then run `/mcp reload` and `/mcp list` to confirm that `agentkey` is connected. If Gemini only reports that authentication is required, or the browser flow was closed, run `/mcp auth agentkey` to start it manually. Gemini stores and refreshes the OAuth tokens, so this is normally a one-time sign-in. Do not add a second user-level MCP entry or run `@agentkey/cli --auth-login` in extension mode.
**Antigravity 2.0 / Antigravity CLI plugin mode** — both runtimes use the root `plugin.json`, `mcp_config.json`, and existing `skills/` directory. The MCP entry uses Antigravity's `serverUrl` schema and automatic OAuth discovery, so there is **no API key to paste and no second `@agentkey/cli` step**.
If Gemini reports that `~/.agents/skills/agentkey` overrides the copy bundled by the extension, that is a separate Skill-precedence warning rather than an OAuth failure. A previously installed user Skill has higher priority and can safely remain when it is the same version—especially if other agents use that shared directory. Remove it with `gemini skills uninstall agentkey --scope user` only when it is no longer needed elsewhere, then run `/skills reload`.
**Antigravity 2.0 / Antigravity CLI plugin mode** — both runtimes use the root `plugin.json`, `mcp_config.json`, and existing `skills/` directory. The MCP entry uses Antigravity's `serverUrl` schema and automatic OAuth discovery through dynamic client registration, so there is **no API key to paste, no OAuth client secret to configure, and no second `@agentkey/cli` step**.
For Antigravity 2.0, place the repository at workspace scope or global scope, then restart Antigravity:
@@ -415,7 +417,12 @@ agy plugin install /absolute/path/to/agentkey
agy plugin list
```
Antigravity 2.0 exposes OAuth through **Settings → Customizations → Authenticate**. In Antigravity CLI, open `/mcp` to inspect or reload the server and follow the authentication prompt when it first connects.
After Antigravity discovers the plugin, authenticate its bundled MCP entry rather than adding a duplicate:
- **Antigravity 2.0:** open **Settings → Customizations → Installed MCP Servers**, click **Authenticate** next to AgentKey, complete the browser flow, copy the authorization code back into the settings panel, and submit it. The server reconnects automatically; click **Refresh** if the status does not update.
- **Antigravity CLI:** open `/mcp`, select `agentkey`, choose **Authenticate**, and follow the browser/code prompts. Reload the server in the same panel and confirm the AgentKey tools are listed; inspect its connection logs there if it remains disconnected.
Keep `mcp_config.json` free of static headers, access tokens, and OAuth client credentials. AgentKey publishes protected-resource and authorization-server metadata, including a dynamic registration endpoint, for both Antigravity runtimes to discover.
**Repo layout:**
@@ -439,13 +446,14 @@ agentkey/
│ ├── scripts/ # check-update helper
│ └── version.txt # Managed by release-please
└── scripts/
├── build-release-assets.sh # Build Skill + Gemini GitHub Release assets
├── install.sh # One-command installer (mac/linux)
├── install.ps1 # Windows PowerShell installer
├── uninstall.sh # One-command uninstaller (mac/linux)
└── uninstall.ps1 # Windows PowerShell uninstaller
```
**Release a new version (maintainers):** releases are cut automatically by [release-please](https://github.com/googleapis/release-please). Merging a PR with a `feat:` or `fix:` title opens a Release PR that bumps `skills/agentkey/version.txt`, all four versioned plugin manifests, `gemini-extension.json`, and `CHANGELOG.md`. The Antigravity schema has no `version` field, so its root `plugin.json` is not part of version syncing. Merging the Release PR creates the tag + GitHub Release + uploads the `agentkey.skill` asset.
**Release a new version (maintainers):** releases are cut automatically by [release-please](https://github.com/googleapis/release-please). Merging a PR with a `feat:` or `fix:` title opens a Release PR that bumps `skills/agentkey/version.txt`, all four versioned plugin manifests, `gemini-extension.json`, and `CHANGELOG.md`. The Antigravity schema has no `version` field, so its root `plugin.json` is not part of version syncing. Merging the Release PR creates the tag + GitHub Release, preserves the `agentkey.skill` asset, and uploads platform-named Gemini extension archives whose roots contain `gemini-extension.json`.
</details>
+12 -4
View File
@@ -394,9 +394,11 @@ gemini extensions install https://github.com/chainbase-labs/agentkey
gemini extensions link /absolute/path/to/agentkey
```
安装或链接后重启 Gemini CLI。如果 MCP server 提示需要认证,执行 `/mcp auth agentkey` 并在浏览器完成授权;之后 Gemini 会保存并自动刷新 OAuth token。修改 server 配置后可执行 `/mcp reload`
安装或链接后重启 Gemini CLI。首次连接时extension 的 `oauth.enabled` 会要求 Gemini 自动启动原生浏览器授权;完成授权后执行 `/mcp reload``/mcp list`,确认 `agentkey` 已连接。如果 Gemini 只提示需要认证,或者浏览器流程被关闭,则执行 `/mcp auth agentkey` 手动重新发起。Gemini 会保存并自动刷新 OAuth token因此通常只需要登录一次。Extension 模式下不要再添加一条用户级 MCP 配置,也不要运行 `@agentkey/cli --auth-login`
**Antigravity 2.0 / Antigravity CLI 插件模式** —— 两个运行时共用根目录的 `plugin.json``mcp_config.json` 和现有 `skills/`。MCP 配置使用 Antigravity 规定的 `serverUrl` 并依赖自动 OAuth discovery**不用粘贴 API Key也不需要再单独运行 `@agentkey/cli`**
如果 Gemini 提示 `~/.agents/skills/agentkey` 覆盖了 extension 捆绑的 Skill这是独立的 Skill 优先级告警,不是 OAuth 失败。之前安装的用户级 Skill 优先级更高;当两份版本一致时可以安全保留,尤其是其他 Agent 也依赖这个共享目录时。只有确认其他 Agent 不再需要它之后,才执行 `gemini skills uninstall agentkey --scope user`,再运行 `/skills reload`
**Antigravity 2.0 / Antigravity CLI 插件模式** —— 两个运行时共用根目录的 `plugin.json``mcp_config.json` 和现有 `skills/`。MCP 配置使用 Antigravity 规定的 `serverUrl`,并通过动态客户端注册自动发现 OAuth**不用粘贴 API Key、不用配置 OAuth client secret也不需要再单独运行 `@agentkey/cli`**。
Antigravity 2.0 可按 workspace 或全局范围放置插件,完成后重启 Antigravity
@@ -415,7 +417,12 @@ agy plugin install /absolute/path/to/agentkey
agy plugin list
```
Antigravity 2.0 在 **Settings → Customizations → Authenticate** 中完成 OAuth。Antigravity CLI 首次连接时按认证提示操作;需要检查状态或重新加载 server 时打开 `/mcp`
Antigravity 发现插件后,应认证插件捆绑的 MCP 配置,不要重复添加另一条 server
- **Antigravity 2.0**打开 **Settings → Customizations → Installed MCP Servers**,在 AgentKey 旁点击 **Authenticate**;在浏览器完成授权后,把 authorization code 复制回设置面板并提交。Server 会自动重连;状态没有更新时点击 **Refresh**
- **Antigravity CLI**打开 `/mcp`,选择 `agentkey` 并点击 **Authenticate**,按界面给出的浏览器/验证码流程完成授权;在同一面板 reload server确认 AgentKey 工具已经出现。如果仍是 disconnected可直接在这里检查连接日志。
不要在 `mcp_config.json` 中写入静态 header、access token 或 OAuth client credential。AgentKey 已发布 protected-resource 与 authorization-server metadata并提供 dynamic registration endpoint两个 Antigravity 运行时都应通过这些元数据完成发现。
**仓库结构:**
@@ -439,13 +446,14 @@ agentkey/
│ ├── scripts/ # check-update 辅助脚本
│ └── version.txt # 由 release-please 自动维护
└── scripts/
├── build-release-assets.sh # 构建 Skill + Gemini GitHub Release 产物
├── install.sh # 一键安装脚本mac/linux
├── install.ps1 # Windows PowerShell 安装脚本
├── uninstall.sh # 一键卸载脚本mac/linux
└── uninstall.ps1 # Windows PowerShell 卸载脚本
```
**发布新版本Maintainer** 发版由 [release-please](https://github.com/googleapis/release-please) 自动触发。合并一个 `feat:``fix:` 的 PR 后release-please 会开一个 Release PR自动 bump `skills/agentkey/version.txt`、四个带版本号的插件清单、`gemini-extension.json``CHANGELOG.md`。Antigravity schema 没有 `version` 字段,因此根目录 `plugin.json` 不参与版本同步。合并这个 Release PR 即会创建 tag + GitHub Release + 上传 `agentkey.skill` 产物。
**发布新版本Maintainer** 发版由 [release-please](https://github.com/googleapis/release-please) 自动触发。合并一个 `feat:``fix:` 的 PR 后release-please 会开一个 Release PR自动 bump `skills/agentkey/version.txt`、四个带版本号的插件清单、`gemini-extension.json``CHANGELOG.md`。Antigravity schema 没有 `version` 字段,因此根目录 `plugin.json` 不参与版本同步。合并这个 Release PR 即会创建 tag + GitHub Release,保留 `agentkey.skill` 产物,并上传根目录包含 `gemini-extension.json` 的平台命名 Gemini 扩展压缩包
</details>
+4 -1
View File
@@ -4,7 +4,10 @@
"description": "AgentKey gives Gemini CLI one-stop access to live web, social, finance, crypto, e-commerce, business, weather, maps, and travel data.",
"mcpServers": {
"agentkey": {
"httpUrl": "https://api.agentkey.app/v1/mcp"
"httpUrl": "https://api.agentkey.app/v1/mcp",
"oauth": {
"enabled": true
}
}
}
}
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUTPUT_ARG="${1:-dist/release-assets}"
case "$OUTPUT_ARG" in
/*) OUTPUT_DIR="$OUTPUT_ARG" ;;
*) OUTPUT_DIR="$REPO_ROOT/$OUTPUT_ARG" ;;
esac
for command_name in git tar unzip zip; do
if ! command -v "$command_name" >/dev/null 2>&1; then
echo "Required command not found: $command_name" >&2
exit 1
fi
done
mkdir -p "$OUTPUT_DIR"
ASSET_NAMES=(
agentkey.skill
darwin.agentkey.tar.gz
linux.agentkey.tar.gz
win32.agentkey.zip
)
for asset_name in "${ASSET_NAMES[@]}"; do
rm -f "$OUTPUT_DIR/$asset_name"
done
(
cd "$REPO_ROOT/skills/agentkey"
zip -qr "$OUTPUT_DIR/agentkey.skill" . \
-x "*.DS_Store" \
-x "__pycache__/*" \
-x "*.pyc"
)
git -C "$REPO_ROOT" archive \
--format=tar.gz \
--output="$OUTPUT_DIR/darwin.agentkey.tar.gz" \
HEAD
cp "$OUTPUT_DIR/darwin.agentkey.tar.gz" "$OUTPUT_DIR/linux.agentkey.tar.gz"
git -C "$REPO_ROOT" archive \
--format=zip \
--output="$OUTPUT_DIR/win32.agentkey.zip" \
HEAD
for archive_name in darwin.agentkey.tar.gz linux.agentkey.tar.gz; do
tar -tzf "$OUTPUT_DIR/$archive_name" | grep -Fx 'gemini-extension.json' >/dev/null
tar -tzf "$OUTPUT_DIR/$archive_name" | grep -Fx 'skills/agentkey/SKILL.md' >/dev/null
done
unzip -Z1 "$OUTPUT_DIR/win32.agentkey.zip" | grep -Fx 'gemini-extension.json' >/dev/null
unzip -Z1 "$OUTPUT_DIR/win32.agentkey.zip" | grep -Fx 'skills/agentkey/SKILL.md' >/dev/null
unzip -Z1 "$OUTPUT_DIR/agentkey.skill" | grep -Fx 'SKILL.md' >/dev/null
echo "Built release assets:"
for asset_name in "${ASSET_NAMES[@]}"; do
echo " $OUTPUT_DIR/$asset_name"
done
+8
View File
@@ -89,6 +89,14 @@ Never expose raw error details to the user.
The skill is useless without the AgentKey MCP server registered with the user's agent. Two ways to connect — **try OAuth first**; fall back to an API key only if OAuth isn't available.
Before adding anything, check whether an `agentkey` MCP server is already present but disconnected or waiting for authentication. Plugin and extension installs bundle that server entry. **Authenticate the bundled entry; do not register a duplicate server and do not run the standalone AgentKey CLI for that client.**
- **Gemini CLI extension:** the bundled MCP entry requests native OAuth automatically. Complete the browser flow when it opens. If Gemini only reports that authentication is required, run `/mcp auth agentkey` manually; then `/mcp reload` and confirm the server is connected with `/mcp list`.
- **Antigravity 2.0 plugin:** open **Settings → Customizations → Installed MCP Servers**, click **Authenticate** next to AgentKey, complete the browser flow, paste the authorization code, and submit it.
- **Antigravity CLI plugin:** open `/mcp`, select the `agentkey` server, choose **Authenticate**, follow the displayed browser/code prompts, then reload it and confirm it is connected.
If the client or its exact controls are uncertain, load `references/setup.md` and follow the matching client-specific flow.
### 1 — OAuth (preferred)
Register the hosted MCP server into **whatever client you're running in**, using that client's own mechanism (an `mcp add` CLI command, an MCP settings panel, or editing its config file). Connection params:
+49 -5
View File
@@ -6,16 +6,58 @@ OAuth, or the OAuth flow fails.
## OAuth registration (preferred)
Add the server with **no API key** and let the client run its own browser OAuth —
nothing to copy or store. The exact step depends on the client; these are
examples, not the only supported clients:
First check whether the client already lists an `agentkey` MCP server. Plugin
and extension installs bundle that entry, so authenticate it in place. Do not
add a second server and do not run `@agentkey/cli --auth-login` for that client.
### Gemini CLI extension
1. Confirm `agentkey` is active with `/extensions list`.
2. On the first connection, the extension's `oauth.enabled` setting asks
Gemini to start its native browser authorization automatically. Complete
that flow when it opens.
3. If Gemini only reports that authentication is required, or the browser flow
was closed, run `/mcp auth agentkey` to start it manually.
4. Run `/mcp reload`, then `/mcp list` and confirm `agentkey` is connected.
5. Retry the original request only after `find_tools`, `describe_tool`, and
`execute_tool` are visible.
A warning that `~/.agents/skills/agentkey` overrides the extension's bundled
skill is separate from MCP authentication. Gemini gives user skills higher
precedence than extension skills. If both copies are the same version, the
warning is harmless. Remove the user copy only when no other agent relies on
that shared skill directory.
### Antigravity plugin
AgentKey supports dynamic client registration, so keep `mcp_config.json`
credential-free and authenticate the bundled `serverUrl` entry:
- **Antigravity 2.0:** open **Settings → Customizations → Installed MCP
Servers**, click **Authenticate** next to AgentKey, complete the browser
flow, copy the authorization code, paste it into the settings panel, and
submit it. The server reconnects automatically; use **Refresh** if its status
does not update.
- **Antigravity CLI:** open `/mcp`, select the `agentkey` server, choose
**Authenticate**, and follow the browser/code prompts shown by the manager.
Reload the server in the same panel, inspect its logs if it remains
disconnected, and retry only after the AgentKey tools appear.
Do not put OAuth client secrets, access tokens, or an `Authorization` header in
the plugin package.
### Other clients
If no AgentKey server entry exists, add the server with **no API key** and let
the client run its own browser OAuth. The exact step depends on the client;
these are examples, not the only supported clients:
- **Claude Code:** `claude mcp add --transport http agentkey https://api.agentkey.app/v1/mcp`,
then `/mcp` → agentkey → **Authenticate**.
- **Cursor / Claude Desktop:** add a remote MCP server in settings with URL
`https://api.agentkey.app/v1/mcp` and no auth header; the app prompts to sign
in on first use.
- **Any other client:** add the same URL as an HTTP MCP server with no
- **Another client:** add the same URL as an HTTP MCP server with no
`Authorization` header. If the client supports MCP OAuth it prompts to
authorize on first connect; if it doesn't, use the API-key fallback below.
@@ -25,7 +67,9 @@ reconnects/restarts.
## API-key fallback
Use when the client can't do MCP OAuth, or OAuth failed.
Use only when the client can't do MCP OAuth, or its native OAuth flow failed.
An extension/plugin server that merely starts as disconnected is not a reason
to fall back; complete its client-specific authentication flow first.
1. Grab a key at https://console.agentkey.app/
2. Paste this into the agent's MCP config (path varies per agent):
+9 -2
View File
@@ -18,12 +18,15 @@ assert manifest["description"]
assert manifest["mcpServers"] == {
"agentkey": {
"httpUrl": "https://api.agentkey.app/v1/mcp",
"oauth": {
"enabled": True,
},
}
}
PY
}
@test "Gemini extension relies on native OAuth discovery" {
@test "Gemini extension requests native OAuth while relying on dynamic discovery" {
python3 - "$MANIFEST" <<'PY'
import json
import sys
@@ -34,7 +37,11 @@ with open(sys.argv[1], encoding="utf-8") as handle:
assert "settings" not in manifest
server = manifest["mcpServers"]["agentkey"]
assert "headers" not in server
assert "oauth" not in server
assert server["oauth"] == {"enabled": True}
assert "authorizationUrl" not in server["oauth"]
assert "tokenUrl" not in server["oauth"]
assert "clientId" not in server["oauth"]
assert "clientSecret" not in server["oauth"]
assert "authProviderType" not in server
assert "trust" not in server
PY
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env bats
setup() {
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/.." && pwd)"
SKILL="$REPO_ROOT/skills/agentkey/SKILL.md"
SETUP_GUIDE="$REPO_ROOT/skills/agentkey/references/setup.md"
}
@test "AgentKey skill authenticates bundled MCP entries before registering another server" {
python3 - "$SKILL" <<'PY'
import sys
with open(sys.argv[1], encoding="utf-8") as handle:
skill = handle.read()
assert "Authenticate the bundled entry" in skill
assert "do not register a duplicate server" in skill
assert "do not run the standalone AgentKey CLI" in skill
PY
}
@test "Gemini extension setup gives an explicit OAuth and verification flow" {
python3 - "$SETUP_GUIDE" <<'PY'
import sys
with open(sys.argv[1], encoding="utf-8") as handle:
guide = " ".join(handle.read().split())
for expected in (
"### Gemini CLI extension",
"/extensions list",
"extension's `oauth.enabled` setting asks Gemini to start its native browser authorization automatically",
"/mcp auth agentkey",
"/mcp reload",
"/mcp list",
"Gemini gives user skills higher precedence than extension skills",
):
assert expected in guide, expected
PY
}
@test "Antigravity setup gives desktop and CLI OAuth flows without credentials" {
python3 - "$SETUP_GUIDE" <<'PY'
import sys
with open(sys.argv[1], encoding="utf-8") as handle:
guide = " ".join(handle.read().split())
for expected in (
"### Antigravity plugin",
"Settings → Customizations → Installed MCP Servers",
"click **Authenticate** next to AgentKey",
"**Antigravity CLI:** open `/mcp`",
"dynamic client registration",
"Do not put OAuth client secrets, access tokens, or an `Authorization` header",
):
assert expected in guide, expected
PY
}
@test "English and Chinese public docs mirror both client auth flows" {
python3 - "$REPO_ROOT/README.md" "$REPO_ROOT/docs/README_zh.md" <<'PY'
import sys
for path in sys.argv[1:]:
with open(path, encoding="utf-8") as handle:
readme = " ".join(handle.read().split())
for expected in (
"/mcp auth agentkey",
"/mcp reload",
"/mcp list",
"gemini skills uninstall agentkey --scope user",
"Settings → Customizations → Installed MCP Servers",
"dynamic registration endpoint",
):
assert expected in readme, f"{path}: {expected}"
PY
}
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bats
setup_file() {
local repo_root
repo_root="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
"$repo_root/scripts/build-release-assets.sh" "$BATS_FILE_TMPDIR/assets"
}
setup() {
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/.." && pwd)"
ASSET_DIR="$BATS_FILE_TMPDIR/assets"
}
@test "release build preserves the Skill asset" {
[ -f "$ASSET_DIR/agentkey.skill" ]
run unzip -Z1 "$ASSET_DIR/agentkey.skill"
[ "$status" -eq 0 ]
[[ "$output" == *"SKILL.md"* ]]
[[ "$output" == *"scripts/check-update.sh"* ]]
}
@test "release build creates a Gemini archive for every supported platform" {
[ -f "$ASSET_DIR/darwin.agentkey.tar.gz" ]
[ -f "$ASSET_DIR/linux.agentkey.tar.gz" ]
[ -f "$ASSET_DIR/win32.agentkey.zip" ]
run cmp "$ASSET_DIR/darwin.agentkey.tar.gz" "$ASSET_DIR/linux.agentkey.tar.gz"
[ "$status" -eq 0 ]
}
@test "Gemini release archives expose the manifest and Skill at their roots" {
for archive_name in darwin.agentkey.tar.gz linux.agentkey.tar.gz; do
run tar -tzf "$ASSET_DIR/$archive_name"
[ "$status" -eq 0 ]
[[ "$output" == *"gemini-extension.json"* ]]
[[ "$output" == *"skills/agentkey/SKILL.md"* ]]
done
run unzip -Z1 "$ASSET_DIR/win32.agentkey.zip"
[ "$status" -eq 0 ]
[[ "$output" == *"gemini-extension.json"* ]]
[[ "$output" == *"skills/agentkey/SKILL.md"* ]]
}