diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 0127a92..a7ef59c 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -17,8 +17,12 @@ The same repo also works as a Claude Code plugin (via `.claude-plugin/plugin.jso It additionally works as a **Codex plugin** (via `.codex-plugin/plugin.json` + `.codex-plugin/mcp.json`, distributed through `.agents/plugins/marketplace.json` — the repo is its own marketplace, added with `codex plugin marketplace add chainbase-labs/agentkey`). Codex plugins have no `userConfig`/header-interpolation mechanism, so auth uses MCP OAuth instead: the server's `/v1/mcp` endpoint advertises `WWW-Authenticate: Bearer resource_metadata=…` (RFC 9728) and supports dynamic client registration, so `.codex-plugin/mcp.json` needs only `type` + `url` — discovery does the rest. In that mode the OAuth sign-in substitutes for step 2. +It also works as 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. + 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. + ## Directory Structure ``` @@ -27,10 +31,13 @@ agentkey/ ├── .codex-plugin/ │ ├── plugin.json # Codex plugin manifest (skills + mcpServers + interface metadata) │ └── mcp.json # Codex MCP entry — http + oauth_resource (NOT the root .mcp.json) +├── .cursor-plugin/ +│ └── plugin.json # Cursor manifest with skills + inline HTTP MCP entry (OAuth) ├── .kimi-plugin/ │ └── plugin.json # Kimi Code manifest with inline HTTP MCP entry (OAuth) ├── .agents/plugins/marketplace.json # Codex marketplace listing this repo as a local-source plugin ├── .mcp.json # Auto-registers AgentKey MCP when installed as a Claude Code plugin +├── gemini-extension.json # Gemini CLI extension — Streamable HTTP + OAuth discovery ├── skills/agentkey/ │ ├── SKILL.md # Decision tree + routing rules (end-user facing) │ ├── scripts/ # check-update helper @@ -58,11 +65,11 @@ git tag -d vX.Y.Z && git push origin :refs/tags/vX.Y.Z gh release delete vX.Y.Z --repo chainbase-labs/agentkey --yes ``` -Releases are driven by [release-please](https://github.com/googleapis/release-please): merged PRs with Conventional Commit messages (`feat:`, `fix:`, `feat!:`, etc.) update an open Release PR that bumps `skills/agentkey/version.txt`, all three plugin manifest versions, and `CHANGELOG.md`. Merging the Release PR tags the release and creates the GitHub Release, which in turn triggers plugin updates for users. +Releases are driven by [release-please](https://github.com/googleapis/release-please): merged PRs with Conventional Commit messages (`feat:`, `fix:`, `feat!:`, etc.) update an open Release PR that bumps `skills/agentkey/version.txt`, all four plugin manifest versions, `gemini-extension.json`, and `CHANGELOG.md`. Merging the Release PR tags the release and creates the GitHub Release, which in turn triggers plugin updates for users. ## Version & Release Rules -- `skills/agentkey/version.txt`, the versions in `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and `.kimi-plugin/plugin.json`, plus `CHANGELOG.md`, are managed by release-please based on Conventional Commits — never edit manually except via PR that intentionally amends them. +- `skills/agentkey/version.txt`, the versions in `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`, plus `CHANGELOG.md`, are managed by release-please based on Conventional Commits — never edit manually except via PR that intentionally amends them. - `version.txt` lives inside `skills/agentkey/` (not at repo root) so it travels with the skill when the Skills CLI copies the subdirectory. `release-please-config.json` points at this path via `version-file`. - Tag format: `v` prefix (e.g. `v0.4.5`) - Plugin updates trigger on **GitHub Release** publication, not on plain commits @@ -71,7 +78,7 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl ## Change Checklists **Changes to any `plugin.json`:** -- release-please automatically bumps all three manifest versions + `CHANGELOG.md` from merged conventional-commit PRs; maintainers review + merge the generated Release PR rather than editing these files directly +- release-please automatically bumps all four manifest versions + `CHANGELOG.md` from merged conventional-commit PRs; maintainers review + merge the generated Release PR rather than editing these files directly **Changes to `.mcp.json`:** - The MCP server is `type: http` (remote endpoint, no subprocess), so inject the API key by interpolating the userConfig value as `${user_config.AGENTKEY_API_KEY}` in the `Authorization` header — the key name MUST match the `plugin.json` `userConfig` key. Do NOT use `${CLAUDE_PLUGIN_OPTION_}`: those env vars are only exported to stdio/subprocess servers and hook/monitor commands, and are not interpolated into an http server's headers. @@ -80,14 +87,28 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl **Changes to `.codex-plugin/mcp.json`:** - Codex plugin MCP config does NOT support `${user_config.*}` interpolation — a literal `${…}` would be sent as the Authorization header. Auth is MCP OAuth via RFC 9728 discovery: the server's 401 advertises `resource_metadata`, and the rmcp client automatically appends `resource=` to the authorization request. - Do NOT set `oauth_resource`: rmcp already sends `resource` on its own, and Codex appends `oauth_resource` as a *second* `resource` query param without deduplication (`codex-rs/rmcp-client/src/perform_oauth_login.rs`). Clerk enforces RFC 6749 (no repeated params) and rejects the request with `invalid_request: The request includes the parameter 'resource' more than once`. The official Notion/Figma plugins get away with it only because their authorization servers tolerate duplicates. -- Keep the endpoint URL in sync with the root `.mcp.json` — both must point at the same `/v1/mcp` endpoint. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`. + +**Changes to `.cursor-plugin/plugin.json`:** +- The manifest MUST stay at `.cursor-plugin/plugin.json`; component paths resolve from the plugin root. +- Use only fields documented by the Cursor plugin reference. Do not copy Codex/Kimi-only metadata such as `interface` into this manifest. +- Keep `skills` pointed at `./skills/` and `mcpServers` as the minimal inline `{"agentkey":{"url":"https://api.agentkey.app/v1/mcp"}}` entry. Do not add static credentials or `${user_config.*}` interpolation; Cursor handles MCP OAuth itself. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.codex-plugin/mcp.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`. +- This repository is a single Cursor plugin, so `.cursor-plugin/marketplace.json` is not required. Submit the public repository URL through Cursor's marketplace publisher. **Changes to `.kimi-plugin/plugin.json`:** - `mcpServers` MUST be an inline object. Kimi does not accept a path such as `"./mcp.json"` for this field. - Keep the HTTP entry minimal: `{"agentkey":{"url":"https://api.agentkey.app/v1/mcp"}}`. Kimi infers the transport from `url`. - Do not add `userConfig`, a static Authorization header, or `${user_config.*}` interpolation. Kimi discovers and persists MCP OAuth credentials itself. - Kimi displays `Run /new or /reload to apply plugin changes.` after install. Once reloaded, the user completes native MCP OAuth with `/mcp-config login plugin-agentkey:agentkey` when Kimi reports that authentication is required. -- Keep the endpoint URL in sync with the root `.mcp.json` and `.codex-plugin/mcp.json`. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, and `gemini-extension.json`. + +**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`. +- 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 install/uninstall docs:** - Update both `README.md` and `docs/README_zh.md` together — they mirror each other @@ -99,5 +120,7 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl - Setup mode in SKILL.md runs `! npx -y @agentkey/cli --auth-login` to authenticate via browser — same command as step 2 of the public install - `@agentkey/cli --auth-login` auto-writes MCP configs for 16 agents (canonical list lives in `AGENT_REGISTRY` in `../AgentKey-Server/cli/src/lib/mcp-clients.ts`): Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, OpenCode, Qwen Code, iFlow CLI, Kimi CLI, Kiro CLI, Windsurf, Warp, Amp, Crush, droid, openclaw. The `--only ` flag (used by install.sh's `MCP_TARGETS` and install.ps1's `$McpTargets`) filters this list — its id values MUST match `npx skills add -a` ids, with `claude-desktop` as the one documented MCP-only exception. Goose / kode / kilo still need a manual JSON paste (see SKILL.md's "Fallback" section); when adding more agents server-side, keep `MCP_AUTO_AGENTS` in both install scripts and the cleanup list in both uninstall scripts in sync. - `.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`. - `README.md` / `docs/README_zh.md` are the public-facing docs; keep them in sync with any structural changes diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json new file mode 100644 index 0000000..2d85d04 --- /dev/null +++ b/.cursor-plugin/marketplace.json @@ -0,0 +1,18 @@ +{ + "name": "agentkey", + "description": "One-stop live data marketplace for your agent: web search, web scraping, social media, finance, crypto, e-commerce, business data, weather/maps, and travel", + "owner": { + "name": "Chainbase Labs", + "url": "https://agentkey.app" + }, + "plugins": [ + { + "name": "agentkey", + "description": "AgentKey — one-stop live data marketplace for your agent: web search, web scraping, social media, finance, crypto, e-commerce, business data, weather/maps, and travel through a single MCP server. No API keys to manage, auto failover across providers, free to start.", + "source": "./", + "category": "data", + "homepage": "https://github.com/chainbase-labs/agentkey", + "tags": ["agentkey", "web-search", "scraping", "social-media", "finance", "crypto", "blockchain", "e-commerce", "business-data", "weather", "maps", "travel", "real-time-data"] + } + ] +} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json new file mode 100644 index 0000000..39b7e6e --- /dev/null +++ b/.cursor-plugin/plugin.json @@ -0,0 +1,31 @@ +{ + "name": "agentkey", + "version": "1.13.1", + "description": "AgentKey — one-stop live data marketplace for your agent: web search, web scraping, social media, finance, crypto, e-commerce, business data, weather/maps, and travel through a single MCP server. No API keys to manage, auto failover across providers, free to start.", + "author": { + "name": "Chainbase Labs" + }, + "homepage": "https://agentkey.app", + "license": "MIT", + "keywords": [ + "agentkey", + "web-search", + "scraping", + "social-media", + "finance", + "crypto", + "blockchain", + "e-commerce", + "business-data", + "weather", + "maps", + "travel", + "real-time-data" + ], + "skills": "./skills/", + "mcpServers": { + "agentkey": { + "url": "https://api.agentkey.app/v1/mcp" + } + } +} diff --git a/.github/workflows/claude-pr-review.yml b/.github/workflows/claude-pr-review.yml index 1b2590e..ef46a2c 100644 --- a/.github/workflows/claude-pr-review.yml +++ b/.github/workflows/claude-pr-review.yml @@ -192,7 +192,8 @@ jobs: from release-please itself, which won't trigger this review since author.type == Bot) - `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, - and `.kimi-plugin/plugin.json` version fields — managed + `.cursor-plugin/plugin.json`, and `.kimi-plugin/plugin.json` + version fields — managed ### 4c. Repo invariants - `skills/agentkey/scripts/check-update.sh` REPO line diff --git a/.github/workflows/scripts-test.yml b/.github/workflows/scripts-test.yml index 1018093..12fb843 100644 --- a/.github/workflows/scripts-test.yml +++ b/.github/workflows/scripts-test.yml @@ -3,11 +3,13 @@ on: push: paths: - 'skills/agentkey/scripts/**' + - 'gemini-extension.json' - 'tests/**' - '.github/workflows/scripts-test.yml' pull_request: paths: - 'skills/agentkey/scripts/**' + - 'gemini-extension.json' - 'tests/**' jobs: diff --git a/.github/workflows/verify-version-sync.yml b/.github/workflows/verify-version-sync.yml index fcfbef2..54c918c 100644 --- a/.github/workflows/verify-version-sync.yml +++ b/.github/workflows/verify-version-sync.yml @@ -13,7 +13,9 @@ on: - 'skills/agentkey/SKILL.md' - '.claude-plugin/plugin.json' - '.codex-plugin/plugin.json' + - '.cursor-plugin/plugin.json' - '.kimi-plugin/plugin.json' + - 'gemini-extension.json' - 'release-please-config.json' pull_request: paths: @@ -22,7 +24,9 @@ on: - 'skills/agentkey/SKILL.md' - '.claude-plugin/plugin.json' - '.codex-plugin/plugin.json' + - '.cursor-plugin/plugin.json' - '.kimi-plugin/plugin.json' + - 'gemini-extension.json' - 'release-please-config.json' jobs: @@ -38,19 +42,25 @@ jobs: | head -1 | sed -E 's/^LOCAL_VERSION="([^"]+)".*/\1/') claude_plugin=$(python3 -c 'import json; print(json.load(open(".claude-plugin/plugin.json"))["version"])') codex_plugin=$(python3 -c 'import json; print(json.load(open(".codex-plugin/plugin.json"))["version"])') + cursor_plugin=$(python3 -c 'import json; print(json.load(open(".cursor-plugin/plugin.json"))["version"])') kimi_plugin=$(python3 -c 'import json; print(json.load(open(".kimi-plugin/plugin.json"))["version"])') + gemini_extension=$(python3 -c 'import json; print(json.load(open("gemini-extension.json"))["version"])') skill=$(awk '/^---/{c++; next} c==1 && /^version:/{print $2; exit}' skills/agentkey/SKILL.md) echo "version.txt: $canonical" echo "check-update.sh: $script" echo "Claude plugin: $claude_plugin" echo "Codex plugin: $codex_plugin" + echo "Cursor plugin: $cursor_plugin" echo "Kimi plugin: $kimi_plugin" + echo "Gemini extension: $gemini_extension" echo "SKILL.md: $skill" if [ "$canonical" != "$script" ] \ || [ "$canonical" != "$claude_plugin" ] \ || [ "$canonical" != "$codex_plugin" ] \ + || [ "$canonical" != "$cursor_plugin" ] \ || [ "$canonical" != "$kimi_plugin" ] \ + || [ "$canonical" != "$gemini_extension" ] \ || [ "$canonical" != "$skill" ]; then - echo "::error::Version drift detected. release-please syncs all six values from version.txt — re-run release-please or restore the values manually." + echo "::error::Version drift detected. release-please syncs all eight values from version.txt — re-run release-please or restore the values manually." exit 1 fi diff --git a/AGENTS.md b/AGENTS.md index 7c0f924..233688f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,9 @@ The same repo also works as: - a **Claude Code plugin** (`.claude-plugin/plugin.json` + root `.mcp.json`) — the plugin's `userConfig` injects the API key via `${user_config.AGENTKEY_API_KEY}`, substituting for step 2. - 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. ## Directory Structure @@ -27,10 +29,13 @@ agentkey/ ├── .codex-plugin/ │ ├── plugin.json # Codex plugin manifest (skills + mcpServers + interface metadata) │ └── mcp.json # Codex MCP entry — http + oauth_resource (NOT the root .mcp.json) +├── .cursor-plugin/ +│ └── plugin.json # Cursor manifest with skills + inline HTTP MCP entry (OAuth) ├── .kimi-plugin/ │ └── plugin.json # Kimi Code manifest with inline HTTP MCP entry (OAuth) ├── .agents/plugins/marketplace.json # Codex marketplace listing this repo as a local-source plugin ├── .mcp.json # Auto-registers AgentKey MCP when installed as a Claude Code plugin +├── gemini-extension.json # Gemini CLI extension — Streamable HTTP + OAuth discovery ├── skills/agentkey/ │ ├── SKILL.md # Decision tree + routing rules (end-user facing) │ ├── scripts/ # check-update helper @@ -58,11 +63,11 @@ git tag -d vX.Y.Z && git push origin :refs/tags/vX.Y.Z gh release delete vX.Y.Z --repo chainbase-labs/agentkey --yes ``` -Releases are driven by [release-please](https://github.com/googleapis/release-please): merged PRs with Conventional Commit messages (`feat:`, `fix:`, `feat!:`, etc.) update an open Release PR that bumps `skills/agentkey/version.txt`, all three plugin manifest versions, and `CHANGELOG.md`. Merging the Release PR tags the release and creates the GitHub Release, which in turn triggers plugin updates for users. +Releases are driven by [release-please](https://github.com/googleapis/release-please): merged PRs with Conventional Commit messages (`feat:`, `fix:`, `feat!:`, etc.) update an open Release PR that bumps `skills/agentkey/version.txt`, all four plugin manifest versions, `gemini-extension.json`, and `CHANGELOG.md`. Merging the Release PR tags the release and creates the GitHub Release, which in turn triggers plugin updates for users. ## Version & Release Rules -- `skills/agentkey/version.txt`, the versions in `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and `.kimi-plugin/plugin.json`, plus `CHANGELOG.md`, are managed by release-please based on Conventional Commits — never edit manually except via PR that intentionally amends them. +- `skills/agentkey/version.txt`, the versions in `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`, plus `CHANGELOG.md`, are managed by release-please based on Conventional Commits — never edit manually except via PR that intentionally amends them. - `version.txt` lives inside `skills/agentkey/` (not at repo root) so it travels with the skill when the Skills CLI copies the subdirectory. `release-please-config.json` points at this path via `version-file`. - Tag format: `v` prefix (e.g. `v0.4.5`) - Plugin updates trigger on **GitHub Release** publication, not on plain commits @@ -71,7 +76,7 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl ## Change Checklists **Changes to any `plugin.json`:** -- release-please automatically bumps all three manifest versions + `CHANGELOG.md` from merged conventional-commit PRs; maintainers review + merge the generated Release PR rather than editing these files directly +- release-please automatically bumps all four manifest versions + `CHANGELOG.md` from merged conventional-commit PRs; maintainers review + merge the generated Release PR rather than editing these files directly **Changes to the root `.mcp.json` (Claude Code plugin path):** - The MCP server is `type: http` (remote endpoint, no subprocess), so inject the API key by interpolating the userConfig value as `${user_config.AGENTKEY_API_KEY}` in the `Authorization` header — the key name MUST match the `.claude-plugin/plugin.json` `userConfig` key. Do NOT use `${CLAUDE_PLUGIN_OPTION_}`: those env vars are only exported to stdio/subprocess servers and hook/monitor commands, and are not interpolated into an http server's headers. @@ -80,14 +85,28 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl **Changes to `.codex-plugin/mcp.json` (Codex plugin path):** - Codex plugin MCP config does NOT support `${user_config.*}` interpolation — a literal `${…}` would be sent as the Authorization header. Auth is MCP OAuth via RFC 9728 discovery: the server's 401 advertises `resource_metadata`, and the rmcp client automatically appends `resource=` to the authorization request. - Do NOT set `oauth_resource`: rmcp already sends `resource` on its own, and Codex appends `oauth_resource` as a *second* `resource` query param without deduplication (`codex-rs/rmcp-client/src/perform_oauth_login.rs`). Clerk enforces RFC 6749 (no repeated params) and rejects the request with `invalid_request: The request includes the parameter 'resource' more than once`. The official Notion/Figma plugins get away with it only because their authorization servers tolerate duplicates. -- Keep the endpoint URL in sync with the root `.mcp.json` — both must point at the same `/v1/mcp` endpoint. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`. + +**Changes to `.cursor-plugin/plugin.json` (Cursor plugin path):** +- The manifest MUST stay at `.cursor-plugin/plugin.json`; component paths resolve from the plugin root. +- Use only fields documented by the Cursor plugin reference. Do not copy Codex/Kimi-only metadata such as `interface` into this manifest. +- Keep `skills` pointed at `./skills/` and `mcpServers` as the minimal inline `{"agentkey":{"url":"https://api.agentkey.app/v1/mcp"}}` entry. Do not add static credentials or `${user_config.*}` interpolation; Cursor handles MCP OAuth itself. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.codex-plugin/mcp.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`. +- This repository is a single Cursor plugin, so `.cursor-plugin/marketplace.json` is not required. Submit the public repository URL through Cursor's marketplace publisher. **Changes to `.kimi-plugin/plugin.json` (Kimi Code plugin path):** - `mcpServers` MUST be an inline object. Kimi does not accept a path such as `"./mcp.json"` for this field. - Keep the HTTP entry minimal: `{"agentkey":{"url":"https://api.agentkey.app/v1/mcp"}}`. Kimi infers the transport from `url`. - Do not add `userConfig`, a static Authorization header, or `${user_config.*}` interpolation. Kimi discovers and persists MCP OAuth credentials itself. - Kimi displays `Run /new or /reload to apply plugin changes.` after install. Once reloaded, the user completes native MCP OAuth with `/mcp-config login plugin-agentkey:agentkey` when Kimi reports that authentication is required. -- Keep the endpoint URL in sync with the root `.mcp.json` and `.codex-plugin/mcp.json`. +- Keep the endpoint URL in sync with the root `.mcp.json`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, and `gemini-extension.json`. + +**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`. +- 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 install/uninstall docs:** - Update both `README.md` and `docs/README_zh.md` together — they mirror each other @@ -100,5 +119,7 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl - `@agentkey/cli --auth-login` auto-writes MCP configs for 16 agents (canonical list lives in `AGENT_REGISTRY` in `../AgentKey-Server/cli/src/lib/mcp-clients.ts`): Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, OpenCode, Qwen Code, iFlow CLI, Kimi CLI, Kiro CLI, Windsurf, Warp, Amp, Crush, droid, openclaw. The `--only ` flag (used by install.sh's `MCP_TARGETS` and install.ps1's `$McpTargets`) filters this list — its id values MUST match `npx skills add -a` ids, with `claude-desktop` as the one documented MCP-only exception. Goose / kode / kilo still need a manual JSON paste (see SKILL.md's "Fallback" section); when adding more agents server-side, keep `MCP_AUTO_AGENTS` in both install scripts and the cleanup list in both uninstall scripts in sync. - Root `.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) - `.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`. - `README.md` / `docs/README_zh.md` are the public-facing docs; keep them in sync with any structural changes diff --git a/README.md b/README.md index a756518..33f0551 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,22 @@ Kimi copies local plugins into its managed plugin directory. Re-run `/plugins in If you previously worked around an older AgentKey plugin by adding a user-global `agentkey` entry through `/mcp-config`, remove that old entry once with `/mcp-config remove agentkey` before reloading. The plugin now owns its namespaced MCP entry; keeping both would create duplicate tools and authentication attempts. +**Cursor plugin mode** — install AgentKey from the Cursor Marketplace after the listing is published. The Cursor-native manifest at `.cursor-plugin/plugin.json` bundles the same Skill and an inline remote-HTTP MCP entry, so there is **no API key to paste and no second `@agentkey/cli` step**. When Cursor prompts for MCP authentication, approve the AgentKey browser sign-in. + +For maintainers, push the plugin to a public Git repository and submit the repository URL at [cursor.com/marketplace/publish](https://cursor.com/marketplace/publish). Before submitting, test the plugin in the current Cursor release and confirm that both the `agentkey` Skill and MCP server load successfully after OAuth. The manifest follows the [Cursor plugin reference](https://cursor.com/docs/reference/plugins); keep its component paths relative to the plugin root. + +**Gemini CLI extension mode** — install the repository as an extension. The root `gemini-extension.json` bundles the existing AgentKey skill and the remote Streamable HTTP MCP server, so there is **no API key to paste and no second `@agentkey/cli` step**: + +```bash +# Public install +gemini extensions install https://github.com/chainbase-labs/agentkey + +# Or link a local checkout for development +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. + **Repo layout:** ``` @@ -388,10 +404,13 @@ agentkey/ ├── .codex-plugin/ │ ├── plugin.json # Codex plugin manifest │ └── mcp.json # Codex MCP entry (OAuth, no user_config) +├── .cursor-plugin/ +│ └── plugin.json # Cursor manifest with Skill + inline MCP OAuth ├── .kimi-plugin/ │ └── plugin.json # Kimi manifest with inline MCP OAuth entry ├── .agents/plugins/marketplace.json # Codex marketplace (this repo is its own marketplace) ├── .mcp.json # Used when installed as a Claude Code plugin +├── gemini-extension.json # Gemini CLI extension manifest (MCP OAuth + skills) ├── skills/agentkey/ │ ├── SKILL.md # Decision tree + routing rules │ ├── scripts/ # check-update helper @@ -403,7 +422,7 @@ agentkey/ └── 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 three plugin manifests, and `CHANGELOG.md`. 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 plugin manifests, `gemini-extension.json`, and `CHANGELOG.md`. Merging the Release PR creates the tag + GitHub Release + uploads the `agentkey.skill` asset. diff --git a/docs/README_zh.md b/docs/README_zh.md index 9d5c4fc..644d5dc 100644 --- a/docs/README_zh.md +++ b/docs/README_zh.md @@ -380,6 +380,22 @@ Kimi 会把本地插件复制到自己的托管目录。修改原 checkout 后 如果你曾为旧版 AgentKey plugin 手工通过 `/mcp-config` 添加过用户全局的 `agentkey` 条目,请在 reload 前执行一次 `/mcp-config remove agentkey` 删除旧条目。现在 plugin 会维护自己的命名空间 MCP;同时保留两份会造成工具和鉴权流程重复。 +**Cursor 插件模式** —— 插件上架后,从 Cursor Marketplace 安装 AgentKey。`.cursor-plugin/plugin.json` 这个 Cursor 原生清单会同时捆绑同一个 Skill 和内联的远程 HTTP MCP 配置,因此**不用粘贴 API Key,也不需要再单独运行 `@agentkey/cli`**。Cursor 提示 MCP 需要认证时,在浏览器完成 AgentKey 登录即可。 + +维护者需要先把插件推送到公开 Git 仓库,再到 [cursor.com/marketplace/publish](https://cursor.com/marketplace/publish) 提交仓库地址。提交前请使用当前版本 Cursor 实际安装测试,确认 OAuth 完成后 `agentkey` Skill 和 MCP server 都能正常加载。清单遵循 [Cursor 插件参考](https://cursor.com/cn/docs/reference/plugins),其中所有组件路径都必须相对于插件根目录。 + +**Gemini CLI 扩展模式** —— 把本仓库直接安装为 extension。根目录的 `gemini-extension.json` 会捆绑现有 AgentKey skill 和远程 Streamable HTTP MCP server,**不用粘贴 API Key,也不需要再单独跑 `@agentkey/cli`**: + +```bash +# 公开安装 +gemini extensions install https://github.com/chainbase-labs/agentkey + +# 或链接本地 checkout,用于开发 +gemini extensions link /absolute/path/to/agentkey +``` + +安装或链接后重启 Gemini CLI。如果 MCP server 提示需要认证,执行 `/mcp auth agentkey` 并在浏览器完成授权;之后 Gemini 会保存并自动刷新 OAuth token。修改 server 配置后可执行 `/mcp reload`。 + **仓库结构:** ``` @@ -388,10 +404,13 @@ agentkey/ ├── .codex-plugin/ │ ├── plugin.json # Codex 插件清单 │ └── mcp.json # Codex MCP 配置(OAuth,无 user_config) +├── .cursor-plugin/ +│ └── plugin.json # Cursor 清单,捆绑 Skill 与内联 MCP OAuth ├── .kimi-plugin/ │ └── plugin.json # Kimi 清单,内联 MCP OAuth 配置 ├── .agents/plugins/marketplace.json # Codex marketplace(本仓库即自己的 marketplace) ├── .mcp.json # 作为 Claude Code 插件安装时使用 +├── gemini-extension.json # Gemini CLI 扩展清单(MCP OAuth + skills) ├── skills/agentkey/ │ ├── SKILL.md # 决策树 & 路由规则 │ ├── scripts/ # check-update 辅助脚本 @@ -403,7 +422,7 @@ agentkey/ └── 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`、三个插件清单和 `CHANGELOG.md`。合并这个 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`。合并这个 Release PR 即会创建 tag + GitHub Release + 上传 `agentkey.skill` 产物。 diff --git a/gemini-extension.json b/gemini-extension.json new file mode 100644 index 0000000..451088e --- /dev/null +++ b/gemini-extension.json @@ -0,0 +1,10 @@ +{ + "name": "agentkey", + "version": "1.13.1", + "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" + } + } +} diff --git a/release-please-config.json b/release-please-config.json index 9699591..e1bd95c 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -20,11 +20,21 @@ "path": ".codex-plugin/plugin.json", "jsonpath": "$.version" }, + { + "type": "json", + "path": ".cursor-plugin/plugin.json", + "jsonpath": "$.version" + }, { "type": "json", "path": ".kimi-plugin/plugin.json", "jsonpath": "$.version" }, + { + "type": "json", + "path": "gemini-extension.json", + "jsonpath": "$.version" + }, { "type": "generic", "path": "skills/agentkey/scripts/check-update.sh" diff --git a/tests/gemini-extension.bats b/tests/gemini-extension.bats new file mode 100644 index 0000000..01104e9 --- /dev/null +++ b/tests/gemini-extension.bats @@ -0,0 +1,55 @@ +#!/usr/bin/env bats + +setup() { + REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/.." && pwd)" + MANIFEST="$REPO_ROOT/gemini-extension.json" +} + +@test "Gemini extension declares the AgentKey Streamable HTTP server inline" { + python3 - "$MANIFEST" <<'PY' +import json +import sys + +with open(sys.argv[1], encoding="utf-8") as handle: + manifest = json.load(handle) + +assert manifest["name"] == "agentkey" +assert manifest["description"] +assert manifest["mcpServers"] == { + "agentkey": { + "httpUrl": "https://api.agentkey.app/v1/mcp", + } +} +PY +} + +@test "Gemini extension relies on native OAuth discovery" { + python3 - "$MANIFEST" <<'PY' +import json +import sys + +with open(sys.argv[1], encoding="utf-8") as handle: + manifest = json.load(handle) + +assert "settings" not in manifest +server = manifest["mcpServers"]["agentkey"] +assert "headers" not in server +assert "oauth" not in server +assert "authProviderType" not in server +assert "trust" not in server +PY +} + +@test "Gemini extension bundles the existing AgentKey skill" { + [ -f "$REPO_ROOT/skills/agentkey/SKILL.md" ] + + python3 - "$REPO_ROOT/skills/agentkey/SKILL.md" <<'PY' +import sys + +with open(sys.argv[1], encoding="utf-8") as handle: + skill = handle.read() + +frontmatter = skill.split("---", 2)[1] +assert "\nname: agentkey\n" in f"\n{frontmatter}\n" +PY +}