Skip to content
Rinhelp
Esc
navigateopen⌘Jpreview
On this page

Connect MCP and CLI

Connect an OAuth MCP client or the Rinhelp CLI and use every current operator operation.

Connect an MCP client or use the Rinhelp CLI to manage your Rinhelp workspace. Both expose the operations listed below. Your access token selects the workspace; never pass organization_id.

Connect MCP

Add https://mcp.rinhelp.com/mcp as a remote HTTP MCP server in a client that supports OAuth. Complete the browser authorization for the rinhelp.operator scope.

After connecting, call account.whoami and confirm the returned organization and role before making changes. MCP clients discover the current operation list through tools/list; the reference on this page is generated from that same shared catalog.

Legacy /sse connections are unsupported. Use the /mcp endpoint and a client with OAuth support.

Use the CLI

The current CLI is shipped in the Rinhelp repository, not published as an npm package. From a source checkout, install the workspace dependencies and run the CLI entry point:

git clone https://github.com/wilbertliu/rinhelp.git
cd rinhelp
pnpm install
pnpm --filter @rinhelp/cli exec node bin/rinhelp.mjs login

login opens browser OAuth, asks for the rinhelp.operator scope, and stores credentials locally. Stored credentials refresh when the saved credential contains refresh metadata. Use another endpoint with --mcp:

pnpm --filter @rinhelp/cli exec node bin/rinhelp.mjs login --mcp https://mcp.example.com/mcp

For the examples below, run the command with pnpm --filter @rinhelp/cli exec node bin/rinhelp.mjs from the checkout, or make that entry point available as rinhelp on your PATH.

rinhelp --json account.whoami
rinhelp ops
rinhelp sources.start_crawl --help
rinhelp --json inbox.list_items --input '{}'

Use exactly one input style per command:

  • --input '<json object>' for inline JSON.
  • --input-file <path> for a file, or --input-file - for stdin.
  • Field flags such as --conversation-id and --idempotency-key.

Do not mix input JSON with field flags. rinhelp logout removes saved credentials. RINHELP_ACCESS_TOKEN can supply an access token instead of saved credentials; that environment value does not carry the saved issuer/client metadata used for automatic refresh.

The CLI returns exit code 0 for success, 1 for another operator or transport failure, 2 for invalid input or usage, 3 when login is required or a credential is expired, and 4 when the operation is forbidden. With --json, successful calls print { "ok": true, "op": "...", "output": ... }; operator errors print { "ok": false, "error": { "code": "...", "message": "..." } }. Unexpected runtime failures can still write to stderr and exit 1.

Operation behavior to know first

  • Crawls return run_id immediately. Pass it as source_id to sources.show and poll until ready or failed.
  • widget.preview returns one completed ephemeral answer, not a stream.
  • email.setup returns the exact PostShiba forwarding destination. The merchant keeps the support mailbox, configures forwarding, and keeps a mailbox copy; Rinhelp does not change MX. email.verify sends a test, then email.show reports whether forwarding is verified or failed.
  • inbox.list lists conversations. inbox.list_items includes conversations and pending refunds. Pass control=closed to select closed work.
  • inbox.reply posts a teammate reply. The first reply claims the thread; it does not impersonate the visitor.
  • Refund requests do not execute refunds. Obtain a deliberate human decision before calling inbox.approve_action; that call executes a pending Shopify refund. inbox.reject_action rejects it without executing. Get action_id from the refund item’s refund.id in inbox.list_items.
  • Generate one idempotency_key per intent and reuse it on retry with the same input. The CLI does not generate keys. For a failed refund approval, reuse the same key; do not retry an unconfirmed Shopify result.
  • team.invite and team.cancel_invite require the owner role. The role required by every operation appears below.

Current operations

This reference contains all 23 current operations (1 account, 4 sources, 3 widget, 3 email, 7 inbox, 3 team, 2 shopify). The names are the same in MCP and the CLI. It is generated from the shared operator catalog, so this page does not document a second API.

account.whoami

Return the signed-in operator (user, organization, role).

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {}
}

sources.list

List crawl/index runs for this organization.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "cursor": {
      "type": "string"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    }
  }
}

sources.start_crawl

Start a site crawl (async). Returns run_id immediately. Poll sources.show. Same idempotency_key + url + org replays the same run.

  • Role: member
  • Retry: idempotency_key

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["url", "idempotency_key"],
  "properties": {
    "url": {
      "type": "string",
      "format": "uri"
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

sources.show

Get one ingest run and its pages. Crawl is async; poll until ready or failed.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["source_id"],
  "properties": {
    "source_id": {
      "type": "string",
      "minLength": 1
    }
  }
}

sources.show_page

Get one crawled page and its chunks.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["page_id"],
  "properties": {
    "page_id": {
      "type": "string",
      "minLength": 1
    }
  }
}

widget.show

Widget config, publishable key, and install snippet for this org.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {}
}

widget.update_config

Patch widget config (greeting, title, colors, position). Omitted fields keep their current values.

  • Role: member
  • Retry: idempotent

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "minProperties": 1,
  "properties": {
    "primary_color": {
      "type": "string"
    },
    "position": {
      "type": "string",
      "enum": ["bottom-right", "bottom-left"]
    },
    "title": {
      "type": "string"
    },
    "greeting": {
      "type": "string"
    }
  }
}

widget.preview

Run one ephemeral preview question against the corpus. Returns the completed answer, not a stream.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["message"],
  "properties": {
    "message": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000
    }
  }
}

email.show

Show the merchant support address, exact PostShiba forwarding target, and setup state. This does not change MX or send mail.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {}
}

email.setup

Create or reuse the PostShiba receive target for support_email. The merchant keeps the mailbox and forwards into the returned address; Rinhelp does not change MX.

  • Role: member
  • Retry: idempotent
  • Hint: open-world operation.

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["support_email"],
  "properties": {
    "support_email": {
      "type": "string",
      "minLength": 1
    }
  }
}

email.verify

Send one forwarding test to the configured support address. This starts verification; call email.show until status is verified. Requires idempotency_key and reuse it on retry.

  • Role: member
  • Retry: idempotency_key
  • Hint: open-world operation.

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["idempotency_key"],
  "properties": {
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

inbox.list

List visitor conversations in the shared inbox. Default is queued and live chats. Pass control=closed to list resolved live chats. Use inbox.list_items for mixed inbox items.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "cursor": {
      "type": "string"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "control": {
      "type": "string",
      "enum": ["closed"]
    }
  }
}

inbox.list_items

List the inbox work queue (conversations and pending refunds), the same items as the console. Default is the open queue. Pass control=closed for resolved chats and closed refunds. Use a refund_action item’s refund.id as action_id for inbox.approve_action or inbox.reject_action.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "cursor": {
      "type": "string"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "control": {
      "type": "string",
      "enum": ["closed"]
    }
  }
}

inbox.show

Get one conversation and its messages. Poll this instead of opening a live WebSocket.

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["conversation_id"],
  "properties": {
    "conversation_id": {
      "type": "string",
      "minLength": 1
    }
  }
}

inbox.reply

Post a teammate reply (first reply claims the thread). Requires idempotency_key. Does not impersonate the visitor.

  • Role: member
  • Retry: idempotency_key

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["conversation_id", "message", "idempotency_key"],
  "properties": {
    "conversation_id": {
      "type": "string",
      "minLength": 1
    },
    "message": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

inbox.end_live

End live chat on a conversation.

  • Role: member
  • Retry: idempotent

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["conversation_id"],
  "properties": {
    "conversation_id": {
      "type": "string",
      "minLength": 1
    }
  }
}

team.show

List members. Pending invitations included only for owners (same as the console).

  • Role: member
  • Retry: safe

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "properties": {}
}

team.invite

Invite a member by email (owners only, role=member only). A pending invite for the same org+email is returned, not duplicated.

  • Role: owner
  • Retry: idempotent

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["email"],
  "properties": {
    "email": {
      "type": "string",
      "minLength": 1
    }
  }
}

team.cancel_invite

Cancel a pending invitation (owners only).

  • Role: owner
  • Retry: idempotent
  • Hint: destructive operation.

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["invitation_id"],
  "properties": {
    "invitation_id": {
      "type": "string",
      "minLength": 1
    }
  }
}

shopify.request_refund

Request a Shopify refund for an order (lookup only; does not execute). Requires idempotency_key. Reuse the same key to replay the same request. Amount omitted requests the full refundable balance.

  • Role: member
  • Retry: idempotent

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["order_number", "email", "idempotency_key"],
  "properties": {
    "order_number": {
      "type": "string",
      "minLength": 1
    },
    "email": {
      "type": "string",
      "minLength": 1
    },
    "amount": {
      "type": "string",
      "minLength": 1
    },
    "reason": {
      "type": "string",
      "minLength": 1
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

shopify.lookup_order

Look up a Shopify order by order number and email. Returns the widget status and tracking, or not_found / shop_unavailable. Requires idempotency_key. Reuse the same key to replay the same lookup.

  • Role: member
  • Retry: idempotency_key

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["order_number", "email", "idempotency_key"],
  "properties": {
    "order_number": {
      "type": "string",
      "minLength": 1
    },
    "email": {
      "type": "string",
      "minLength": 1
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

inbox.approve_action

Approve a pending refund action and execute the Shopify refund. List inbox.list_items first and pass the refund.id as action_id. Reuse the same idempotency_key if the refund failed. Do not retry an unconfirmed Shopify result.

  • Role: member
  • Retry: idempotent
  • Hint: destructive operation.

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["action_id", "idempotency_key"],
  "properties": {
    "action_id": {
      "type": "string",
      "minLength": 1
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

inbox.reject_action

Reject a pending refund action without executing a Shopify refund. Requires action_id and idempotency_key.

  • Role: member
  • Retry: idempotent

Input schema

{
  "type": "object",
  "additionalProperties": false,
  "required": ["action_id", "idempotency_key"],
  "properties": {
    "action_id": {
      "type": "string",
      "minLength": 1
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  }
}

Was this page helpful?