> ## Documentation Index
> Fetch the complete documentation index at: https://www.plungeai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# plungeai-in-claude-code

> Connect the Claude Code CLI to PlungeAI (Ocean Studio) over MCP — 'claude mcp add' one-liner, project-scoped .mcp.json with an env-var key, the skills/plugin install path, and a plungeai_whoami + plungeai_list_agents verify.


Connect the Claude Code CLI to PlungeAI (Ocean Studio) over MCP — 'claude mcp add' one-liner, project-scoped .mcp.json with an env-var key, the skills/plugin install path, and a plungeai_whoami + plungeai_list_agents verify. Use when the user is in Claude Code and says connect / install / set up PlungeAI, add an MCP server, mentions claude mcp add or ozk_, or a PlungeAI tool call in Claude Code is failing. For claude.ai web or Claude Desktop use plungeai-in-claude-ai; for another editor use its plungeai-in-<tool> skill; for an unlisted but MCP-capable client use plungeai-mcp-setup's generic client config.

[Download zip](https://skills.plungeai.com/plungeai-in-claude-code.zip) · [View raw SKILL.md](https://skills.plungeai.com/plungeai-in-claude-code/SKILL.md)

Claude Code talks to PlungeAI over the Streamable HTTP MCP server at
`https://mcp.plungeai.com/v1`. One `ozk_` bearer key authenticates it (and
the One API, if generated code calls PlungeAI directly).

## Prerequisites

- An `ozk_` key: Dashboard → **One API → Keys** (https://dashboard.plungeai.com) —
  self-service, shown once, copy it now.
- Claude Code CLI installed and on PATH (`claude --version`).

## Connect (once)

### Terminal one-liner (simplest)

    claude mcp add --transport http plungeai `https://mcp.plungeai.com/v1` \
      --header "Authorization: Bearer ozk_YOUR_KEY" --scope user

- Default scope is `local` — this project only, stored in `~/.claude.json`.
  `--scope user` makes the server available in every project (same file).
- **Never `--scope project` with a literal key** — that writes the key into
  `.mcp.json` inside the repo, which gets committed.

### Project-scoped `.mcp.json` (committed-safe, env-var key)

Use this when the team should share the server definition in the repo
without anyone's literal key landing in git:

    {
      "mcpServers": {
        "plungeai": {
          "type": "http",
          "url": "`https://mcp.plungeai.com/v1`",
          "headers": { "Authorization": "Bearer ${PLUNGEAI_API_KEY}" }
        }
      }
    }

Export `PLUNGEAI_API_KEY` in each developer's own shell before launching
Claude Code — the file itself never holds a literal key, so it's safe to
commit.

## Verify

1. `claude mcp list` (or `/mcp` inside a session) shows `plungeai` connected.
2. Ask Claude: "use plungeai_whoami to confirm my identity" → an identity
   card (user id, auth tier, key label, rate window, server).
3. "use plungeai_list_agents to search 'web search'" → live results from the
   active agent catalog — proves the catalog is reachable, not just auth.

## Quirks

- `tools/list` is authoritative: a key can be fenced to a subset of
  `plungeai_*` tools — seeing fewer tools than a colleague is policy, not a
  bug.
- Money-verb operations (payments, sends) still stop: a gated call pauses
  with a structured `needs_approval` outcome (relay it, then
  `plungeai_continue` once the user decides) regardless of any auto-approve
  setting — never retry blind, never approve on your own.
- Long CNL workflow runs: prefer `mode: "async"` +
  `plungeai_get_workflow_status` polling over one long synchronous call.
- Skills for the agent — teach PlungeAI conventions (discovery-first, CNL
  authoring) as an installable skill directory:
  - **Public repo `PlungeAI/plungeai-agent-skills` — once published**:
    `npx skills add PlungeAI/plungeai-agent-skills` (installs into
    `.agents/skills/` or `.claude/skills/`, `-g` for the user-level home
    `~/.claude/skills/`), or `claude plugin marketplace add
    PlungeAI/plungeai-agent-skills` then `claude plugin install
    plungeai@plungeai`.
  - **Working today:** download https://mcp.plungeai.com/skill.zip and
    unzip into `.claude/skills/` (or `~/.claude/skills/`).
- 401 (`No valid authentication provided...`; a `WWW-Authenticate:
  Bearer error="invalid_token"` header means a key arrived and was rejected)
  → key typo'd, pasted with whitespace, or the header never made it into
  `~/.claude.json` / `.mcp.json` — re-check the header field, not the key
  value.
- Connected but no `plungeai_*` tools listed → restart the session after any
  config edit before debugging further.

## What the agent should know (One API 2.3.0)

The `plungeai_*` tools operate PlungeAI from chat; the block below is for the
code the agent writes against `https://api.plungeai.com`. This skill already
carries it. To make it always-on for a project, paste it into `CLAUDE.md`
— that file is committed, so never put the key in it.
The minimal saved-workflow body (`workflow:` / `tasks:` YAML) is in **plungeai-api-setup**.

```text
PlungeAI One API 2.3.0. Base URL https://api.plungeai.com. Spec: GET /v1/openapi.json (no auth) - never invent a route.
AUTH: Authorization: Bearer ozk_YOUR_KEY on every call; key in an env var, server side only. When a connector attaches auth, NEVER add your own Authorization header.
ME: GET /v1/whoami -> {user_id, via, tier, key_label}. GET /v1/key -> {data:{label, limit, usage, rate_limit}}.
FIND (never from memory): GET /v1/discovery/search?q=<capability>&kind=agents -> {cards} (without kind, skill cards come first). POST /v1/discovery/resolve {task}. GET /v1/agents. GET /v1/tools. GET /v1/tools/{id} = the contract.
DOOR 1, one agent or tool: POST /v1/agents/{id}/execute {prompt|input, sync?, model?} -> 200 {content, workflow_id, task_id, request_id}.
  POST /v1/tools/{id}/execute {operation, params} -> {ok, content, outcome}; 422 invalid_params echoes the contract.
DOOR 2, saved workflow or bot: POST /v1/workflows/{id}/execute {input?, inputs?} -> {success, workflow_id, final_task_id, request_id, content}, synchronous.
  POST /v1/workflows/{id}/execute-stream = SSE. Inline YAML: POST /v1/workflows/execute. No content? GET /v1/workflows/results/{workflowId}/{taskId} (taskId = final_task_id).
DOOR 3, Agent Call: POST /v1/execute, the body is the program: {agent:"<saved id>[@n]", input} or {workflow:{...}} or {tasks:[...]}. dry_run:true plans without running;
  on_behalf_of:"<customer id>" uses that customer's connections.
ASYNC: POST /v1/agents/{id}/execute {sync:false} -> 202 {workflow_id, task_id, request_id}; redeem GET /v1/agents/results/{workflowId}/{taskId} -> {content}; 404 not_ready = poll, 2s+.
EXECUTIONS: the run id is the body's workflow_id (also the x-execution-id header, and your x-trace-id UUID if you sent one; replaying one is 409 duplicate_execution_id).
  GET /v1/executions (source, status, workflow_id). GET /v1/executions/{id}: running | completed | incomplete | failed | cancelled | needs_input | needs_approval.
  GET /v1/executions/{id}/output -> {content, steps}. GET /v1/executions/{id}/files. GET /v1/executions/{id}/conversation. DELETE /v1/executions/{id}. GET /v1/executions/{id}/stream = SSE.
  POST /v1/executions/{id}/continue {answer | approve, allow_scope: once|run|always}. POST /v1/executions/{id}/followup {text}. POST /v1/executions/{id}/cancel.
  POST /v1/executions/{id}/steer {text} queues a message for a live run (202), else 409 execution_finished.
WORKFLOWS: GET|POST /v1/workflows. GET|PATCH|DELETE /v1/workflows/{id}. GET|POST /v1/workflows/{id}/versions. POST /v1/workflows/{id}/versions/{versionId}/restore.
  Save needs {name, kind, yaml}; kind = workflow|agent|bot|campaign. GET /v1/workflows lists every kind unless ?kind=bot (or campaign). 422 invalid_workflow lists errors, writes nothing.
SCHEDULES: POST /v1/schedules {name, schedule, workflow_id, timezone?, parameters?}; schedule = a cron, or "@once" with run_at (ISO-8601 WITH a UTC offset, in the future);
  400 run_at_required | run_at_past. GET /v1/schedules. GET|PATCH|DELETE /v1/schedules/{id}. GET /v1/schedules/{id}/runs (execution_id per run).
  POST /v1/schedules/{id}/run. POST /v1/schedules/{id}/pause. POST /v1/schedules/{id}/resume. POST /v1/schedules/{id}/wake {note?, in?} fires it once, now or later.
TRIGGERS (every call names schedule_id; a secret is shown once): GET|POST /v1/triggers/webhook. DELETE /v1/triggers/webhook/{token}. POST /v1/triggers/webhook/{token}/rotate.
  The same four under /v1/triggers/email {allowed_from}. GET|POST /v1/triggers/hooks {url, events}. DELETE /v1/triggers/hooks/{id}.
PERMISSIONS: GET|PUT /v1/workflows/{id}/permissions {classes:{send|write|pay|delete: allow|ask|deny|hand_off}, locks, budget_usd_run, budget_usd_month}; locks need a team admin (403 lock_admin_required).
BOT DATA: GET /v1/workflows/{id}/workspace-files. GET /v1/workflows/{id}/workspace-files/download?path=. GET /v1/workflows/{id}/inbox. GET|POST /v1/workflows/{id}/bindings {channel, sender_id}.
  DELETE /v1/workflows/{id}/bindings/{channel}/{sender_id}. GET /v1/channels. POST /v1/channels/pair {channel}.
  GET|POST /v1/bot-groups {name, members = 2-6 of your bot ids}. PUT|DELETE /v1/bot-groups/{id}. GET /v1/bot-groups/{id}/thread.
MEMORY: GET /v1/memory/recall?q=. POST /v1/memory/remember {text, scope: memory|user}. POST /v1/memory/forget {id | text}. GET /v1/memory/runs?q= (q required). GET /v1/memory/runs/{id}.
SKILLS: GET /v1/skills. POST /v1/skills/learn {name, body} saves the body you send (it does not distill a URL). DELETE /v1/skills/{id}.
TEMPLATES: GET /v1/templates?kind=workflow|agent|bot. GET /v1/templates/{id}. POST /v1/templates/{id}/use {name?} -> 201 {workflow}.
CONNECTIONS: GET /v1/connections. POST /v1/connections/{provider} {api_key, on_behalf_of?}. DELETE /v1/connections/{provider}. POST /v1/connections/{provider}/link -> {url, expires_at}.
MODELS (OpenAI-shaped, Bearer only): GET /v1/models. POST /v1/chat/completions. POST /v1/embeddings.
TRACES: GET /v1/traces/{id}, id = the run's workflow_id.
LISTS: {workflows|executions|schedules|cards:[...], total, limit, offset, has_more}; POST /v1/schedules -> {schedule}.
ERRORS: {"error":{"code","message"}} plus an X-Error-Code header. 400 validation; 401 unauthorized; 403 refused | agent_not_active; 404 <thing>_not_found (a stranger's id too);
  409 approval_required, or not_paused | execution_finished | duplicate_execution_id | name_taken; 422 invalid_params; 429 rate_limited + Retry-After; 502/503 retry once.
  424 connection_required | credential_required carries error.connect {provider, method, link}: connect via POST /v1/connections/{provider} or its /link.
FENCES: 403 refused is final - surface it, never retry. 409 approval_required is a human boundary - never approve for the user. tools/{id}/execute: a human approves in Studio, then re-issue.
  A paused agent reply: re-send with approved:true plus its action_token (both). A run reading needs_approval: POST /v1/executions/{id}/continue, never the original call.
```

## Slash commands (`/ocean-*`)

Installing the plugin (`/plugin marketplace add PlungeAI/plungeai-agent-skills`, `/plugin install plungeai@plungeai`)
also adds one command per PlungeAI job; each runs `ocean-cli` for you (install and log in first: **plungeai-cli-setup**).
`/ocean` lists them all:

- Workflows: `/ocean-create <goal>`, `/ocean-refine <id> <change>`, `/ocean-edit <id>`, `/ocean-show [id|name|bots]`,
  `/ocean-run <id|file> [-i input]`, `/ocean-versions <id> [save|restore <v>|undo]`, `/ocean-delete <id>`.
- Runs: `/ocean-runs`, `/ocean-results [id]`, `/ocean-followup <id> <question>`, `/ocean-thread <id>`,
  `/ocean-steer <id> <text>`, `/ocean-export <id>`.
- Schedules and missions: `/ocean-schedule`, `/ocean-schedule-once <workflow-id> <time>`, `/ocean-mission <goal>`.
- Bots: `/ocean-bot-permissions <bot-id>`, `/ocean-bot-files <bot-id>`, `/ocean-bot-groups`.
- Platform: `/ocean-agent`, `/ocean-search <objective>`, `/ocean-memory`, `/ocean-templates`, `/ocean-learn`,
  `/ocean-sessions`, `/ocean-local`, `/ocean-whoami`, `/ocean-doctor`.

## Where next

- Operating the `plungeai_*` tools once connected: **plungeai-mcp-setup**.
- The `ocean-cli` command line the slash commands use: **plungeai-cli-setup** (install, login), **ocean-cli** (every verb).
- Writing code that calls `https://api.plungeai.com` directly: **plungeai-api-setup**.
- Picking MCP vs the One API for a given job: **choose-your-plungeai-door**.
- CNL workflow YAML authoring: **plungeai-workflows**.
- An unlisted but MCP-capable client, or the shared connect concepts (native
  remote vs. stdio bridge, key hygiene): **plungeai-mcp-setup**.
- Full guide: https://mcp.plungeai.com/docs#3-connecting-clients
