diff --git a/developer/personal-access-tokens.mdx b/developer/personal-access-tokens.mdx new file mode 100644 index 0000000..8036ed3 --- /dev/null +++ b/developer/personal-access-tokens.mdx @@ -0,0 +1,259 @@ +--- +title: "Personal Access Tokens" +description: "Create long-lived, scoped, revocable credentials that act as you — the recommended way to connect external agents and scripts to PipesHub" +icon: "id-badge" +--- + +A **Personal Access Token (PAT)** is a long-lived, scoped, revocable credential that you create for yourself. Unlike a session token, it doesn't expire after a day. Unlike an [OAuth 2.0 Application](/developer/oauth2), it authenticates as **you** — every request made with it respects your own per-user permissions, not an app's. + +Use a PAT when you want to connect something to PipesHub programmatically — most commonly, an MCP client (see [MCP Server Overview](/mcp/overview)) — without setting up an OAuth app or scraping a short-lived session token. + + + PATs are self-service: **any org member** can create their own, no administrator involvement required. + + +--- + +## Personal Access Tokens vs. OAuth Applications + +| | Personal Access Token | OAuth 2.0 Application | +|---|---|---| +| **Acts as** | You, the creator | The app itself. `client_credentials` has **no user identity** — don't use it where per-person permissions matter | +| **Who can create one** | Any org member | Administrators only | +| **Setup** | One click, no redirect URIs | Register an app, configure redirect URIs and grant types | +| **Best for** | Personal scripts, MCP clients, quick integrations | Third-party apps, multi-user integrations, machine-to-machine services | + +If you're connecting your own tooling and want it to see exactly what you can see, use a PAT. If you're building something other people in the org will authorize separately, use an [OAuth Application](/developer/oauth2). + +--- + +## Creating a Personal Access Token + +### Step 1: Open Personal Access Tokens + +1. Sign in to your PipesHub account +2. Navigate to **Workspace-settings** +3. Select **Personal Access Tokens** under the **Developer Settings** section + +### Step 2: Create a New Token + +Click **New token** and fill in: + +| Field | Required | Description | +|-------|----------|-------------| +| **Name** | Yes | A label to help you recognize the token later (e.g. `Claude Desktop`, `CI script`), 1–100 characters. | +| **Expiry** | No | `30`, `90`, or `365` days, or `Never`. Defaults to **30 days** if not set — a token minted without a second thought shouldn't default to the longest lifetime. | +| **Scopes** | No | Which permissions the token carries. Defaults to your instance's full configured MCP scope set if none are selected. Use **Select All** / **Clear all** to toggle every scope at once. | + + + A token with `Never` expiry has no automatic cutoff. Prefer a bounded expiry unless you have a specific, ongoing reason not to — you can always create a new token later. + + +### Step 3: Copy the Token + +PipesHub generates the token and shows it to you **exactly once**, along with a ready-to-paste block for connecting an MCP client: + +``` +PIPESHUB_MCP_URL=https://your-pipeshub-instance.com/mcp +PIPESHUB_MCP_TOKEN=phpat_eyJhbGciOiJIUzI1NiIs... +``` + + + Copy and store the token immediately. Only its hash is stored server-side — if you lose it, you'll need to revoke it and create a new one. + + + + The `phpat_` prefix is intentional and display-only — it makes personal access tokens easy to recognize in logs, config files, and secret-scanning tools, unlike a bare JWT. It's stripped automatically before the token is verified, so nothing else about how you use the token changes. + + If a `phpat_` token returns 401, your instance predates the prefix-stripping fix — upgrade PipesHub. Until you can, store the token without the `phpat_` prefix and add it back afterwards. + + +`PIPESHUB_MCP_TOKEN` is the same value you'll pass as `--bearer-auth` or in an `Authorization: Bearer` header below — the paste block just saves you from copying it twice. + + + This block is for MCP clients and the [local stdio server](/mcp/local-server). **QM expects different names**: the bare token as `PIPESHUB_TOKEN`, and the origin with no `/mcp` path as `PIPESHUB_BASE_URL`, on two personal keychain entries. Pasting this block into QM's keychain fails in a way that looks like a missing environment variable rather than a wrong one. + + +--- + +## Using a Personal Access Token + +Send it as a standard bearer token on any authenticated PipesHub API request, including the [MCP endpoint](/mcp/overview): + +```bash +curl -X POST https://your-pipeshub-instance.com/mcp \ + -H "Authorization: Bearer phpat_YOUR_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' +``` + +For the local stdio MCP server, or any MCP client that takes a bearer token (see [Local Server (Stdio)](/mcp/local-server)), pass the PAT as `YOUR_BEARER_TOKEN`: + +```bash +npx -y @pipeshub-ai/mcp start \ + --server-url PIPESHUB_INSTANCE_URL \ + --bearer-auth phpat_YOUR_TOKEN +``` + +A PAT reaches the same endpoints as a session token, and is verified the same way — just with a longer lifetime and no OAuth flow to obtain it. + +It is **not** equivalent to being logged in. Session tokens skip scope checks entirely; PATs are enforced against the scopes you granted. A PAT can only do what you selected when you created it, which is why granting fewer scopes is worth the extra moment. + +--- + +## Managing Your Tokens + +The **Personal Access Tokens** page lists every active token you've created, with its name, scopes, creation date, expiry (`Never` shown as-is, not a literal date), and last-used time. + +### Revoking a Token + +Click the revoke icon next to a token and confirm. Revocation takes effect **immediately** — any request using that token (including one already in flight) is rejected on its next verification. + + + Revocation is irreversible. Anything using the revoked token will need a new one. + + +--- + +## Admin Visibility and Revocation + +Because a PAT can live for months or years, an org admin needs a way to see and revoke tokens they didn't create themselves — for example, when someone leaves the org or a laptop is compromised. This is available today via the API (no dedicated admin UI page yet): + + +```bash List every active PAT in the org +curl -X GET "https://your-pipeshub-instance.com/api/v1/personal-access-tokens/admin?page=1&limit=100" \ + -H "Authorization: Bearer YOUR_SESSION_TOKEN" +``` + +```bash Revoke any user's token by id +curl -X DELETE https://your-pipeshub-instance.com/api/v1/personal-access-tokens/admin/TOKEN_ID \ + -H "Authorization: Bearer YOUR_SESSION_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"reason": "departed employee"}' +``` + + +Both endpoints require organization-admin privileges and return `400` for non-admins. The list is paginated (`page`, `limit`, up to 100 per page) and includes each token's owner — including tokens whose owner has since been removed from the org, which still appear so they can be cleaned up. + + + **Response shape:** the admin list is **not** the same shape as your own token list. It's wrapped in `data`/`pagination`, and each item carries owner fields the self-service list doesn't: + + ```json + { + "data": [ + { + "id": "665f1a2b3c4d5e6f7a8b9c0d", + "name": "Claude Desktop", + "scopes": ["kb:read", "semantic:write"], + "createdAt": "2026-05-01T12:00:00.000Z", + "expiresAt": "2026-05-31T12:00:00.000Z", + "lastUsedAt": "2026-06-10T08:15:00.000Z", + "userId": "665f0a1b2c3d4e5f6a7b8c9d", + "ownerEmail": "jane@example.com", + "ownerFullName": "Jane Doe", + "ownerDeleted": false + } + ], + "pagination": { "page": 1, "limit": 100, "total": 1, "totalPages": 1 } + } + ``` + + Your own `GET /api/v1/personal-access-tokens` returns `{ "tokens": [...] }` instead — a flat array with no `userId`/owner fields, since it's implicitly scoped to you. `ownerDeleted: true` means the token's owner has been removed from the org; `ownerEmail`/`ownerFullName` still reflect their last-known values in that case, for auditing. + + + + A deleted user's own personal access tokens stop authenticating automatically — this admin flow is for auditing and proactive cleanup, not something you need to remember to do on every offboarding. + + +--- + +## API Endpoints Reference + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/api/v1/personal-access-tokens` | `POST` | Create a new personal access token | +| `/api/v1/personal-access-tokens` | `GET` | List your own active tokens | +| `/api/v1/personal-access-tokens/{tokenId}` | `DELETE` | Revoke one of your own tokens | +| `/api/v1/personal-access-tokens/scopes` | `GET` | List the scopes available to grant, grouped by category | +| `/api/v1/personal-access-tokens/admin` | `GET` | **Admin only.** List every active token in the org, paginated | +| `/api/v1/personal-access-tokens/admin/{tokenId}` | `DELETE` | **Admin only.** Revoke any user's token by id | + +### Request Bodies + +**`POST /api/v1/personal-access-tokens`** + +```json +{ + "name": "Claude Desktop", + "scopes": ["kb:read", "semantic:write"], + "expiryDays": 30 +} +``` + +| Field | Required | Description | +|-------|----------|--------------| +| `name` | Yes | 1–100 characters | +| `scopes` | No | Defaults to your instance's full configured `MCP_SCOPES` set if omitted | +| `expiryDays` | No | `30`, `90`, `365`, or `"never"`. Defaults to `30` if omitted | + +**`DELETE /api/v1/personal-access-tokens/{tokenId}`** and **`DELETE .../admin/{tokenId}`** + +Both accept an optional body: + +```json +{ "reason": "rotated" } +``` + +`reason` is stored alongside the revocation for auditing — it's not required. + +--- + +## Security Notes + + + + + The raw token is shown only at creation time. Only its hash is stored — PipesHub can't show it to you again if you lose it. + + + + The `phpat_` prefix makes tokens easy to grep for in logs and files, and to catch with secret-scanning tools before they're committed somewhere they shouldn't be. + + + + New tokens default to 30 days. Choose `Never` deliberately, not by default. + + + + Revoking a token — by you or an admin — takes effect on the token's next use, not after some delay. + + + + +--- + +## FAQ + + + + +By default, a PAT gets your instance's full configured `MCP_SCOPES` set — the same scopes exposed to MCP clients (see [Customizing Default Scopes](/mcp/overview#customizing-default-scopes)). You can select a narrower set at creation time via the scope picker. + + + +A session token is issued when you log in and expires after a short, fixed window (24 hours) — it's meant for browser sessions, not long-running integrations. A PAT is created deliberately, can live far longer, and can be revoked independently without logging you out everywhere else. + + + +No, unless you're an org admin. Regular users can only see and revoke tokens they created themselves. Admins can list and revoke any user's token via the [admin API](#admin-visibility-and-revocation) for incident response. + + + +They stop authenticating immediately — PipesHub rejects a personal access token whose owning user has been deleted, the same way it would reject an expired one. + + + +There's no fixed limit on creation, but the list view shows up to 100 of your most recent active tokens. + + + diff --git a/docs.json b/docs.json index 8934e6d..3e7140e 100644 --- a/docs.json +++ b/docs.json @@ -325,6 +325,7 @@ "pages": [ "developer/getting-started", "developer/oauth2", + "developer/personal-access-tokens", "developer/api-reference" ] }, diff --git a/mcp/local-server.mdx b/mcp/local-server.mdx index 8e66d55..7009c29 100644 --- a/mcp/local-server.mdx +++ b/mcp/local-server.mdx @@ -10,7 +10,11 @@ Instead of connecting to PipesHub's remote MCP endpoint, you can run the MCP ser - Node.js 20+ installed - A PipesHub instance URL -- Authentication credentials: either a **Bearer token** (JWT) or **OAuth Client ID + Secret** +- Authentication credentials: a **[Personal Access Token](/developer/personal-access-tokens)** (recommended — no OAuth app setup needed) or **OAuth Client ID + Secret** + + + For the `--bearer-auth` flag used throughout this page, a [Personal Access Token](/developer/personal-access-tokens) is the easiest option: create one under **Developer Settings > Personal Access Tokens** and use it directly — no OAuth app, redirect URIs, or token exchange required. + ## Placeholders @@ -19,7 +23,7 @@ Replace these in all configurations below: | Placeholder | Description | Example | |---|---|---| | `PIPESHUB_INSTANCE_URL` | Your PipesHub instance URL | `https://app.pipeshub.com` | -| `YOUR_BEARER_TOKEN` | JWT Bearer token for authentication | `eyJhbGci...` | +| `YOUR_BEARER_TOKEN` | [Personal access token](/developer/personal-access-tokens) (or any other Bearer JWT) | `phpat_eyJhbGci...` | | `YOUR_CLIENT_ID` | OAuth app client ID | `clid_abc123...` | | `YOUR_CLIENT_SECRET` | OAuth app client secret | `clsec_xyz789...` | diff --git a/mcp/overview.mdx b/mcp/overview.mdx index e32d1d3..30c1c81 100644 --- a/mcp/overview.mdx +++ b/mcp/overview.mdx @@ -1,6 +1,6 @@ --- title: "MCP Server Overview" -description: "Connect MCP clients to the PipesHub MCP server using OAuth" +description: "Connect MCP clients to the PipesHub MCP server using OAuth or a personal access token" icon: "/logo/mcp.svg" --- @@ -17,7 +17,13 @@ This lets AI clients such as **Cursor**, **Claude Code**, **Gemini CLI**, **Clau ## Prerequisites - A running PipesHub instance (self-hosted or cloud) -- An OAuth app created in PipesHub (see [Step 1](#step-1-create-an-oauth-app) below) +- Either an OAuth app (see [Step 1](#step-1-create-an-oauth-app) below), **or** a [Personal Access Token](/developer/personal-access-tokens) — see the note below for which one to use + + + The **client setup guides below** (Cursor, Claude Code, Gemini CLI, Claude.ai, LibreChat) connect over OAuth — you'll need an OAuth app for those. + + For your own tooling, skip OAuth entirely: create a **[Personal Access Token](/developer/personal-access-tokens)** under **Developer Settings > Personal Access Tokens** and use it as a `Bearer` token — either directly against `/mcp`, as `--bearer-auth` with the [Local Server (Stdio)](/mcp/local-server) package, or with any MCP client you configure yourself with a custom `Authorization` header. + ## Step 1: Create an OAuth App @@ -71,7 +77,7 @@ Replace these placeholders in all client configurations: | `PIPESHUB_INSTANCE_URL` | Your PipesHub instance URL | `https://app.pipeshub.com` | | `YOUR_CLIENT_ID` | OAuth app client ID | `clid_abc123...` | | `YOUR_CLIENT_SECRET` | OAuth app client secret | `clsec_xyz789...` | -| `YOUR_BEARER_TOKEN` | JWT Bearer token (local stdio only) | `eyJhbGci...` | +| `YOUR_BEARER_TOKEN` | [Personal access token](/developer/personal-access-tokens) (local stdio only) | `phpat_eyJhbGci...` | The remote MCP endpoint URL is: `PIPESHUB_INSTANCE_URL/mcp`