---
name: harbor-plugins
user-invocable: false
description: Provides the agent's safe path to the workspace's connected SaaS, API, MCP server, and database tools through Harbor. Use hrbr inspect to check source state, active tool count, exact tool ids, and JSON schemas before using hrbr exec.
---

# Harbor Plugins

## Use When

- User names a third-party product the agent should act through: Linear, Sentry, Slack, Gmail, GitHub, Notion, Postgres, Cloudflare, Vercel, Stripe, Posthog, Jira, etc.
- User asks "use X to do Y" where X is a connected service.
- User asks to inspect, list, search, or describe connected workspace tools.
- A previous plugin call failed with a schema or argument error; re-inspect with `hrbr inspect` before retrying.

## Current CLI Surface

The CLI no longer exposes separate `plugins` or `tools` commands. Use `hrbr inspect` for control-plane discovery and `hrbr exec` for execution.

```bash
# Source state
hrbr inspect 'return await hrbr.sources.list()'

# Cross-source tool discovery with schema
hrbr inspect 'return await hrbr.tools.search({ query: "<potential tool name>" })'

# Known-source tool discovery with schema
hrbr inspect 'return await hrbr.tools.search({ query: "<potential tool name>", source: "<namespace>" })'

# OAuth start for a source that requires it
hrbr inspect 'return await hrbr.sources.oauthStart({ namespace: "<namespace>" })'

# Call a ready tool
hrbr exec 'return await <namespace>.<tool>({ ... })'
```

No plugin/source/workspace/output flags are part of this surface. Use
`hrbr.workspace.switch({ target })`, `hrbr.sources.*`, and `hrbr.tools.search`
inside inspect code instead of `--workspace-id`, `--json`, `--human`, `--full`,
or plugin flags.

## Source State Contract

Only `ready` sources are callable from `hrbr exec`.

```txt
   state                     allowed next action
   ─────                     ───────────────────
   ready                     inspect tool schema, then call through hrbr exec
   requires_oauth            Connect first: run hrbr.sources.oauthStart({ namespace })
   reconnect_required        Connect first: run hrbr.sources.oauthStart({ namespace })
   no_tools                  inspect source state; refresh through Harbor web/API if needed
   needs_credentials         finish credential setup in the Harbor dashboard
   not_installed             Install first through Harbor dashboard/API (`sources action=install` in MCP/API-style setup), then re-inspect
   unknown                   re-run hrbr.sources.list() and stop if still ambiguous
```

If `sources.list()` shows fewer active tools than total tools, identify the non-ready source before calling anything. Do not call inactive tools.

## Tool Rules

- Search with an intended action, capability phrase, or likely function name before naming a tool in exec code. Do not paste the user's full request verbatim; distill it to phrases such as `create linear issue`, `search sentry issues`, `list github pull requests`, or a suspected provider function name.
- Use `source: "<namespace>"` when the user already named the product/source.
- Treat the search result's described schema as the source of truth for `signature`, `input_schema`, `output_schema`, rendered TypeScript types, `call_example`, `call`, and `shared_defs`.
- Use `call.example` or `js_var` + `js_name` in exec code. `tool_id`, raw `namespace`, and raw `name` are for lookup/debug, not copy-paste execution.
- Do not invent casing or punctuation. If the raw tool name contains underscores or dashes, still copy the camelCase `js_name` or `call.example` returned by Harbor.
- For REST/OpenAPI-style tools, read returned data according to `output_schema`; the useful object is often under `response.result.<field>`.
- After any failed exec call, re-run the inspect search and fix arguments against the live schema before retrying.

## Examples

Cross-source discovery:

```bash
hrbr inspect 'return await hrbr.sources.list()'
hrbr inspect 'return await hrbr.tools.search({ query: "create issue" })'
hrbr exec 'return await linear.createIssue({ teamId: "<id>", title: "..." })'
```

Known namespace:

```bash
hrbr inspect 'return await hrbr.tools.search({ query: "list issues", source: "linear-mcp" })'
hrbr exec 'return await linearMcp.listIssues({ limit: 20, query: "hrbr CLI", includeArchived: false })'
```

OAuth recovery:

```bash
hrbr inspect 'return await hrbr.sources.list()'
hrbr inspect 'return await hrbr.sources.oauthStart({ namespace: "<namespace>" })'
hrbr inspect 'return await hrbr.sources.list()'
hrbr inspect 'return await hrbr.tools.search({ query: "<potential tool name>" })'
```

Schema mismatch recovery:

```bash
hrbr inspect 'return await hrbr.tools.search({ query: "<potential tool name>" })'
hrbr exec 'return await <namespace>.<tool>({ /* corrected args */ })'
```

## Done Criteria

- The agent inspected source state when readiness mattered.
- The agent inspected the tool schema before the first call and after any argument/schema failure.
- Every exec call used `call.example` or the returned `js_var` + `js_name` plus the inspected argument shape.
- Non-ready sources were surfaced as setup state and were not called through `hrbr exec`.
- Returned results were shaped from the documented `output_schema`, not guessed from examples.
