Skip to content
Merged
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
21 changes: 13 additions & 8 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ It also works as a **Gemini CLI extension** (root `gemini-extension.json` + `ski

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.

It also has a **CLI-managed DeepSeek Harness integration**. The installers detect `${DSH_HOME:-~/.dsh}` / `dsh`, install the skill globally (never `skills add -a dsh`), and let `@agentkey/cli --auth-login --only dsh` maintain one marked `@deepseek-ai/dsh-mcp-client` entry in `$DSH_HOME/cordis.patch.yml`. DSH composes that home layer over current and future profiles; running processes watch it through HMR. DSH rc.7 has no MCP OAuth `authProvider`, so this path requires the CLI-written Bearer key. Tool policy may still hide tools.

## Directory Structure

```
Expand Down Expand Up @@ -93,28 +95,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`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`.
- Keep each plugin endpoint aligned with the Server routing contract. Kimi uses the attributed `/kimi/v1/mcp` alias; the other plugin manifests currently use `/v1/mcp`. Do not require every client path to be byte-identical.

**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`.
- Keep the Cursor endpoint at `/v1/mcp` until the Server routing contract assigns it a client-specific path.
- 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`.
- Keep the HTTP entry minimal: `{"agentkey":{"url":"https://api.agentkey.app/kimi/v1/mcp"}}`. Kimi infers the transport from `url`; the path preserves Kimi attribution while reaching the same MCP surface.
- 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`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, and `gemini-extension.json`.
- Keep the Kimi endpoint aligned with the Server's `/kimi/v1/mcp` attributed alias.

**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`.
- 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`.
- Keep the Gemini endpoint at `/v1/mcp` until the Server routing contract assigns it a client-specific path.

**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.
Expand All @@ -126,20 +128,23 @@ Releases are driven by [release-please](https://github.com/googleapis/release-pl
- 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.
- Keep `mcpServers.agentkey` inline in `mcp_config.json` and use `serverUrl`; legacy `url` and `httpUrl` fields are unsupported.
- Do not add static credentials, headers, or manual OAuth client secrets. AgentKey supports dynamic client registration, so Antigravity performs automatic OAuth discovery.
- Keep the endpoint URL in sync with `.mcp.json`, `.codex-plugin/mcp.json`, `.cursor-plugin/plugin.json`, `.kimi-plugin/plugin.json`, and `gemini-extension.json`.
- Keep the Antigravity endpoint at `/v1/mcp` until the Server routing contract assigns it a client-specific path.

**Changes to install/uninstall docs:**
- Update both `README.md` and `docs/README_zh.md` together — they mirror each other
- The canonical install is always the two-command sequence (`npx skills add …` + `npx -y @agentkey/cli --auth-login`). Don't imply either command does both.
- Do **not** re-add OpenClaw / per-agent installers without a new design — historical context is in git history (removed in chore/remove-archive-directory)
- Describe DSH as a CLI-managed MCP integration, not a native installable DSH plugin. Do not reintroduce the removed README-only `.dsh-plugin/agentkey/` placeholder without a real package and install contract.
- Never commit a real DSH Authorization key. Tests and examples use obviously fake values; production keys live only in the user's local `cordis.patch.yml`.

## Architecture Constraints

- 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.
- `@agentkey/cli --auth-login` auto-writes MCP configs for 18 agents (canonical list lives in `AGENT_REGISTRY` in `../AgentKey-Server/cli/src/lib/mcp-clients.ts`), including Hermes and DeepSeek Harness. The `--only <ids>` flag filters this list. Most ids match `npx skills add -a`; `claude-desktop` has no skill path, `hermes` is a local CLI exception, and `dsh` deliberately uses only the global `skills add -g` path. Goose / kode / kilo still need manual MCP setup. Keep the Bash/PowerShell installer target subsets and uninstall cleanup behavior synchronized with their intended registry entries.
- DSH automatic config is `${DSH_HOME:-~/.dsh}/cordis.patch.yml`, with exactly one `# agentkey:start` / `# agentkey:end` block in the home patch. The Loader entry id and `serverName` are both `agentkey`. Existing per-profile managed blocks are migration inputs only; recognize markers at column 1 and never inside indented YAML block scalars. Structurally detected unmarked legacy Loader rows must stop migration for manual removal, never trigger guessed text deletion. Symlinked profile patches are read-only migration inputs: allow clean ones, but stop before all writes when either legacy form is present. A profile is not required before installation. Archive a legacy `.agent-presets/agentkey` directory instead of deleting it. `Mounted` is not connection proof; readiness requires the three core MCP tools to be visible and callable in the intended tool policy.
- `.mcp.json` registers the remote-HTTP MCP endpoint (`https://api.agentkey.app/v1/mcp`) in Claude Code plugin mode with no static header or `userConfig`; Claude Code performs native MCP OAuth discovery after the server's 401 response.
- `.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`.
- `.kimi-plugin/plugin.json` registers the attributed `https://api.agentkey.app/kimi/v1/mcp` 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; `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
8 changes: 8 additions & 0 deletions .github/workflows/scripts-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ jobs:
sudo apt-get update && sudo apt-get install -y bats
fi
- run: bats tests/

dsh-powershell-marker:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Preserve indented DSH block-scalar markers
shell: pwsh
run: ./tests/dsh-uninstall-marker.ps1
2 changes: 1 addition & 1 deletion .kimi-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"skills": "./skills/",
"mcpServers": {
"agentkey": {
"url": "https://api.agentkey.app/v1/mcp"
"url": "https://api.agentkey.app/kimi/v1/mcp"
}
},
"interface": {
Expand Down
Loading
Loading