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
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Dependencies
node_modules/

# Internal docs (scraped API reference + implementation plan — not for public release)
/docs/
# Internal docs (scraped API reference — catalog is committed)
/docs/*
!/docs/docs-api-endpoints.json

# Build output
dist/
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## [1.3.0] — 2026-07-09

### Added

- Full Docs API v1 parity — 39 endpoints across articles, assets, categories, collections, redirects, and sites with matching CLI commands and MCP tools (61 MCP tools total, up from 29)
- Shared create-response parsing for `201` responses with empty bodies — Docs API `Location` header and Mailbox API `Resource-ID` header now yield `{ id, location }` on create
- Optional `reload=true` on Docs article/collection create (CLI `--reload`, MCP `reload` param) to return the full resource without a follow-up GET
- Multipart asset upload support (`docs asset create-article`, `docs asset create-settings`)
- Endpoint catalog at `docs/docs-api-endpoints.json` and `npm run scrape:docs-api` Playwright scraper to refresh it
- Coverage test ensuring catalog, CLI commands, and MCP tools stay in sync

### Changed

- Docs article list requires `--collection` or `--category` (matches API scoping)
- MCP Docs tools moved to `src/mcp-server-docs.js` via `registerDocsTools()`
- `create_conversation`, `create_customer`, and all Docs create MCP tools return resource IDs when the API provides them

## [1.2.2] — 2026-07-09

### Fixed
Expand Down
110 changes: 84 additions & 26 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,29 @@ To add it to a specific project instead, add to your project's `.mcp.json` (Clau
}
```

The MCP server exposes 29 tools covering all operations below. Use the MCP tools directly instead of shelling out to the CLI when available.
The MCP server exposes 61 tools covering Mailbox API and full Docs API operations. Use the MCP tools directly instead of shelling out to the CLI when available.

## MCP Tools

`auth_status`, `auth_login`, `auth_logout`, `list_conversations`, `get_conversation`, `create_conversation`, `update_conversation`, `delete_conversation`, `list_threads`, `reply_to_conversation`, `add_note`, `list_customers`, `get_customer`, `create_customer`, `update_customer`, `list_mailboxes`, `list_users`, `get_current_user`, `get_user_status`, `list_user_statuses`, `set_user_status`, `list_tags`, `list_articles`, `get_article`, `search_articles`, `create_article`, `update_article`, `delete_article`, `list_collections`, `get_collection`
**Auth:** `auth_status`, `auth_login`, `auth_logout`

All list tools (`list_conversations`, `list_threads`, `list_customers`, `list_mailboxes`, `list_users`, `list_user_statuses`, `list_tags`, `list_articles`, `search_articles`, `list_collections`) accept an optional `markdown: true` parameter to return a GitHub Flavored Markdown table instead of JSON — useful when displaying results directly to a user in the conversation.
**Inbox:** `list_conversations`, `get_conversation`, `create_conversation`, `update_conversation`, `delete_conversation`, `list_threads`, `reply_to_conversation`, `add_note`, `list_customers`, `get_customer`, `create_customer`, `update_customer`, `list_mailboxes`, `list_users`, `get_current_user`, `get_user_status`, `list_user_statuses`, `set_user_status`, `list_tags`

**Docs — Articles:** `list_articles`, `get_article`, `search_articles`, `list_related_articles`, `list_article_revisions`, `get_article_revision`, `create_article`, `upload_article`, `update_article`, `update_article_view_count`, `save_article_draft`, `delete_article_draft`, `delete_article`

**Docs — Collections:** `list_collections`, `get_collection`, `create_collection`, `update_collection`, `delete_collection`

**Docs — Categories:** `list_categories`, `get_category`, `create_category`, `update_category`, `update_category_order`, `delete_category`

**Docs — Redirects:** `list_redirects`, `get_redirect`, `find_redirect`, `create_redirect`, `update_redirect`, `delete_redirect`

**Docs — Sites:** `list_sites`, `get_site`, `create_site`, `update_site`, `delete_site`, `get_site_restrictions`, `update_site_restrictions`

**Docs — Assets:** `create_article_asset`, `create_settings_asset`

All list tools accept an optional `markdown: true` parameter to return a GitHub Flavored Markdown table instead of JSON — useful when displaying results directly to a user in the conversation.

Create tools return `{ id, location }` when the API responds with `201` and a `Location` or `Resource-ID` header. Pass `reload: true` on Docs article/collection create to receive the full resource in one call.

## Environment Variables

Expand Down Expand Up @@ -215,43 +231,85 @@ helpscout inbox webhook delete <id>

```
helpscout docs article list [options]
--collection <id>
--status <s> published (default) | notpublished
--collection <id> list articles in a collection (required unless --category)
--category <id> list articles in a category
--status <s> published (default) | notpublished
--page <n>
--all

helpscout docs article get <id>

helpscout docs article search [options]
--query <q> (required)
--collection <id>
--status <s>
--all
helpscout docs article search --query <q> [--collection <id>] [--status <s>] [--all]
helpscout docs article list-related <id> [--all]
helpscout docs article list-revisions <id> [--all]
helpscout docs article get-revision <articleId> <revisionId>

helpscout docs article create [options]
--collection <id> (required)
--name <title> (required)
--text <html>
--status <s> notpublished (default) | published

helpscout docs article update <id> [options]
--name <title>
--collection <id> (required)
--name <title> (required)
--text <html>
--status <s> published | notpublished

--status <s> notpublished (default) | published
--reload return full article JSON (reload=true query param)

helpscout docs article upload --collection <id> --name <title> [--text <html>] [--status <s>]
helpscout docs article update <id> [--name] [--text] [--status]
helpscout docs article update-view-count <id>
helpscout docs article save-draft <id>
helpscout docs article delete-draft <id>
helpscout docs article delete <id>
```

### Docs — Collections

```
helpscout docs collection list [options]
--site <id>
--visibility <v> public | private
--all

helpscout docs collection list [--site <id>] [--visibility public|private] [--all]
helpscout docs collection get <id>
helpscout docs collection create --site <id> --name <name> [--visibility] [--reload]
helpscout docs collection update <id> [--name] [--visibility]
helpscout docs collection delete <id>
```

### Docs — Categories

```
helpscout docs category list --collection <id> [--all]
helpscout docs category get <id>
helpscout docs category create --collection <id> --name <name> [--slug] [--order]
helpscout docs category update <id> [--name] [--slug] [--order]
helpscout docs category order --collection <id> --json '<[{id,order}]>'
helpscout docs category delete <id>
```

### Docs — Redirects

```
helpscout docs redirect list --site <id> [--all]
helpscout docs redirect get <id>
helpscout docs redirect find --site <id> --url <path>
helpscout docs redirect create --site <id> --from <path> --to <url>
helpscout docs redirect update <id> [--from] [--to]
helpscout docs redirect delete <id>
```

### Docs — Sites

```
helpscout docs site list [--all]
helpscout docs site get <id>
helpscout docs site create --title <title> --subdomain <name>
helpscout docs site update <id> [--title] [--subdomain]
helpscout docs site delete <id>
helpscout docs site restrictions get <siteId>
helpscout docs site restrictions update <siteId> --json '<{...}>'
```

### Docs — Assets

```
helpscout docs asset create-article --file <path> [--width] [--height]
helpscout docs asset create-settings --file <path>
```

Endpoint coverage is tracked in `docs/docs-api-endpoints.json`. Run `npm run scrape:docs-api` to refresh metadata from developer.helpscout.com.

## Common Patterns

Expand Down Expand Up @@ -291,6 +349,6 @@ helpscout docs article list --collection <collection-id> --all

```sh
helpscout docs article create --collection <collection-id> --name "My Article" --text "<p>Body here</p>"
# Returns the new article object including its id
# → { "id": "...", "location": "https://docsapi.helpscout.net/v1/articles/..." }
helpscout docs article update <new-id> --status published
```
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# helpscout CLI

A command-line tool for [Help Scout](https://www.helpscout.com), covering both the Mailbox API v2 (conversations, customers, users) and the Docs API v1 (articles, collections).
A command-line tool for [Help Scout](https://www.helpscout.com), covering the Mailbox API v2 (conversations, customers, users) and the full Docs API v1 (articles, collections, categories, redirects, sites, assets).

Designed for scripting, automation, and use by AI agents. Ships with an MCP server (`helpscout-mcp`) for direct integration with Claude Code, Claude Desktop, and Cursor. Outputs JSON by default when not in a terminal, pretty tables when it is.

Expand Down Expand Up @@ -172,30 +172,48 @@ helpscout docs article list --collection <collection-id> --all
# Search
helpscout docs article search --query "getting started"

# Create a draft, then publish
# Create a draft (returns id from Location header), then publish
helpscout docs article create \
--collection <collection-id> \
--name "New Feature Guide" \
--text "<p>Content here.</p>"

helpscout docs article update <id> --status published
# Or create with full body in one call
helpscout docs article create --collection <id> --name "Guide" --reload

# Delete
helpscout docs article update <id> --status published
helpscout docs article delete <id>
```

### Docs Collections
### Docs Collections, Categories, Redirects, Sites

```sh
helpscout docs collection list
helpscout docs collection get <id>
helpscout docs collection create --site <site-id> --name "FAQ"

helpscout docs category list --collection <collection-id>
helpscout docs category create --collection <id> --name "Getting Started"

helpscout docs redirect list --site <site-id>
helpscout docs redirect create --site <id> --from /old --to https://example.com/new

helpscout docs site list
helpscout docs site restrictions get <site-id>
```

### Docs Assets

```sh
helpscout docs asset create-article --file ./screenshot.png
helpscout docs asset create-settings --file ./logo.png
```

## Development

```sh
npm test # run tests
npm run lint # check for lint errors
npm test # run tests
npm run scrape:docs-api # refresh docs/docs-api-endpoints.json from Help Scout docs
npm run lint # check for lint errors
npm run lint:fix # auto-fix lint errors
npm run format # format with Prettier
npm run build # bundle to dist/helpscout and dist/helpscout-mcp
Expand Down
10 changes: 9 additions & 1 deletion bin/helpscout.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import { makeTagCommand } from '../src/commands/inbox/tags.js';
import { makeWebhookCommand } from '../src/commands/inbox/webhooks.js';
import { makeArticleCommand } from '../src/commands/docs/articles.js';
import { makeCollectionCommand } from '../src/commands/docs/collections.js';
import { makeCategoryCommand } from '../src/commands/docs/categories.js';
import { makeRedirectCommand } from '../src/commands/docs/redirects.js';
import { makeSiteCommand } from '../src/commands/docs/sites.js';
import { makeAssetCommand } from '../src/commands/docs/assets.js';

const program = new Command();

Expand Down Expand Up @@ -47,9 +51,13 @@ program.addCommand(inbox);

// ─── helpscout docs ───────────────────────────────────────────────────────────
const docsCmd = new Command('docs');
docsCmd.description('Docs API v1 — articles and collections');
docsCmd.description('Docs API v1 — articles, collections, categories, and more');
docsCmd.addCommand(makeArticleCommand());
docsCmd.addCommand(makeCollectionCommand());
docsCmd.addCommand(makeCategoryCommand());
docsCmd.addCommand(makeRedirectCommand());
docsCmd.addCommand(makeSiteCommand());
docsCmd.addCommand(makeAssetCommand());
program.addCommand(docsCmd);

// Global error handler — unhandled rejections shouldn't print a stack trace
Expand Down
Loading
Loading