Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

```
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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_<KEY>}`: those env vars are only exported to stdio/subprocess servers and hook/monitor commands, and are not interpolated into an http server's headers.
Expand All @@ -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=<server url>` 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
Expand All @@ -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 <ids>` 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
18 changes: 18 additions & 0 deletions .cursor-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -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"]
}
]
}
31 changes: 31 additions & 0 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
3 changes: 2 additions & 1 deletion .github/workflows/claude-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/scripts-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/verify-version-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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
Loading
Loading