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

# MCP Server

> Connect AI assistants and MCP clients to Hyperstack. How sign-in, scopes and errors work, and every tool the server offers.

The Hyperstack MCP server lets AI assistants and other MCP clients work in your organization. It uses the [Model Context Protocol](https://modelcontextprotocol.io). The assistant calls tools to read and manage credentials, groups, designs, recipients and more.

The server URL is:

```text theme={null}
https://api.thehyperstack.com/mcp
```

To connect a specific assistant step by step, see [AI Assistants](/docs/tutorials/advanced-setup/ai-assistants). This page is for developers who build or set up an MCP client.

## How it works

* The assistant acts as the member who connected it, in one organization. It has that member's roles and the organization's plan features, and nothing more.
* Roles are checked on every tool call. If an admin changes the member's roles, the next call uses the new roles.
* Each tool runs the same Studio endpoint that the matching Studio page uses. The same rules, limits and audit logs apply.
* A connection is not an API key. The [REST API](/docs/api-guide/overview) refuses MCP tokens.

## Transport

| Item | Value |
| - | - |
| Transport | Streamable HTTP |
| Endpoint | `POST https://api.thehyperstack.com/mcp` |
| Sessions | None. The server is stateless: each request stands alone. |
| Responses | JSON. The server does not stream. |

Send the access token in the `Authorization` header of every request, and accept both JSON and event streams:

```text theme={null}
Authorization: Bearer ACCESS_TOKEN
Accept: application/json, text/event-stream
```

A request with no token, or with a token that is not valid, gets a `401`. The `WWW-Authenticate` header points to the discovery document, so the client can start sign-in:

```text theme={null}
WWW-Authenticate: Bearer error="invalid_token", error_description="Authentication required", resource_metadata="https://api.thehyperstack.com/.well-known/oauth-protected-resource/mcp"
```

## Authentication

The server uses OAuth 2.1 with the authorization code flow and PKCE. Most MCP clients do all of this for you once you give them the server URL.

### Endpoints

| Endpoint | Use |
| - | - |
| `/.well-known/oauth-protected-resource/mcp` | Names the authorization server for the MCP endpoint. |
| `/.well-known/oauth-authorization-server` | The authorization server metadata. |
| `/register` | Dynamic client registration. |
| `/authorize` | Starts sign-in. Sends the user to the Hyperstack consent page. |
| `/token` | Exchanges the code for tokens, and refreshes the access token. |
| `/revoke` | Revokes a token, which ends the connection. |

All endpoints are on `https://api.thehyperstack.com`.

### Client registration

Clients register themselves at `/register`. You don't need to ask Hyperstack for a client ID.

* `grant_types` must include `authorization_code`. Add `refresh_token` to refresh.
* `response_types` must include `code`.
* `token_endpoint_auth_method` can be `none` (a public client with no secret), `client_secret_post` or `client_secret_basic`. If you leave it out, you get `client_secret_post` and a client secret. `private_key_jwt` is not supported.
* PKCE uses `S256` only.

### Tokens

| Token | Lifetime |
| - | - |
| Authorization code | 10 minutes, and works only once. |
| Access token | 1 hour. |
| Refresh token | 90 days from when it was issued, and works only once. |

When the access token expires, get a new one with the refresh token. Each refresh also returns a new refresh token, valid for another 90 days. Store it and use it for the next refresh, because the old one stops working. If you send the same refresh token again within 60 seconds (for example, two refreshes at once, or a retry after a lost response), it still works. The connection lasts as long as it is used. If no refresh happens for 90 days, the member must connect again.

To end a connection from your client, send the access token or the refresh token to `/revoke`. Either one ends the whole connection.

### The consent page

`/authorize` sends the member to a Hyperstack page. There they:

1. Sign in, if they are not signed in already.
2. See the assistant's name, the access it asks for, and where they will be sent back to.
3. Pick the organization the assistant can work in. The page shows the member's roles in each organization.
4. Click **Allow** or **Deny**.

The consent link works for 10 minutes. If the member clicks **Deny**, the client gets `error=access_denied`.

## Scopes

A client asks for scopes when it registers or when it starts sign-in. If it asks for none, it gets all three. The consent page shows the scopes. The member allows or denies them all together.

| Scope | Allows |
| - | - |
| `read` | Read credentials, groups, designs, recipients, insights and settings. |
| `issue` | Issue, update, publish, resend, suspend, unsuspend and revoke credentials. |
| `manage` | Create and change groups, designs, attributes, email templates, recipients, reviews, pathways, directories, app settings and organization settings. |

A scope never adds to the member's roles. To issue a credential, the connection needs the `issue` scope **and** the member needs the Issuer role.

## Manage connections

Admins see every connection of the organization in the Studio, under **Settings → AI assistants**. Each row shows the assistant, the member who connected it and when.

* Click **Disconnect** to end a connection at once. The next request with its token gets a `401`.
* When a member leaves the organization, their connections stop working.

What an assistant does is written to the [audit logs](/docs/tutorials/advanced-setup/audit-logs) as the member who connected it, the same as when that member uses the Studio. Connecting and disconnecting an assistant are logged too.

## Confirmation before changes

The server gives every client these instructions:

* Issuing creates credentials **under review**. Nothing is sent yet.
* Publishing emails each recipient and uses one credit per new recipient (by email). A recipient who is already covered uses no credit.
* Before it publishes, suspends, revokes or changes anything in bulk, the assistant must tell the user exactly what will happen and get a clear yes.

Tools also carry MCP annotations: read-only tools are marked read-only, and tools such as `revoke_credentials` are marked destructive. Clients can use these to ask the user before a call.

> [!WARNING]
>
> `publish_credentials` emails recipients and uses credits. `resend_credentials` emails recipients. After `set_auto_issue` turns auto-issue on, each course completion issues a credential, emails the learner and uses a credit. `revoke_credentials` can't be undone.

## Tools

Each tool needs one scope, a role, and sometimes a plan feature. The **Admin** role includes every other role. Call `get_organization` to see the member's roles and the plan's features.

There are no tools to delete groups, designs or credentials, to change billing, or to manage API keys.

### Organization

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `get_organization` | `read` | Any member | The organization, the member's roles, the plan and its features, and the installed apps. |
| `get_organization_settings` | `read` | Admin | The profile on **Settings → General**: name, about, contact email, website and social links. |
| `update_organization_settings` | `manage` | Admin | Changes the profile. Only the fields sent change. It can't change the organization's slug. |
| `list_team` | `read` | Admin | The members with their roles, and pending invitations. |
| `list_departments` | `read` | Admin, `departments` feature | The departments, each with its own team and credit allowance. |
| `get_billing` | `read` | Billing | The plan, renewal dates, and credits used and left. |

### Credential groups

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_groups` | `read` | Issuer | Groups, newest first. Shows live or archived groups, and searches title, key or code. |
| `get_group` | `read` | Issuer | One group with its designs, email template and settings. |
| `get_group_form_options` | `read` | Issuer | The email templates, merge tags and plan features a new group can use. |
| `create_group` | `manage` | Issuer | Creates a group. Needs a title, a description and a certificate or badge design. |
| `update_group` | `read` and `manage` | Issuer | Changes a group. Only the fields sent change. Issued credentials are not reissued. |
| `duplicate_group` | `manage` | Issuer | Copies a group, with or without copies of its designs. |
| `archive_groups` | `manage` | Issuer | Archives groups. Their credentials stay valid. |
| `unarchive_groups` | `manage` | Issuer | Brings archived groups back. |

### Designs

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_designs` | `read` | Designer | Certificate and badge designs, newest first. Filters by type or archived, and searches name or key. |
| `list_design_choices` | `read` | Issuer or Designer | The live designs of one type, to use as a group's certificate or badge. |
| `preview_design` | `read` | Designer | Renders a design as HTML. Fills merge tags with the values you send. |
| `get_design_template` | `read` | Designer | A template from the design editor's gallery, as design JSON. |
| `duplicate_design` | `manage` | Designer | Copies a design with its files. |
| `archive_design` | `manage` | Designer | Archives a design. Groups that use it keep working. |
| `unarchive_design` | `manage` | Designer | Brings an archived design back. |

### Attributes

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_attributes` | `read` | Admin | The custom attributes with their merge tags, and the types the plan offers. |
| `create_attribute` | `manage` | Admin | Adds a custom attribute. The merge tag is made from its name. |
| `delete_attribute` | `manage` | Admin | Deletes an attribute. Issued values stay, but the merge tag stops filling. |

### Credentials

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_credentials` | `read` | Issuer | Credentials, a page at a time. Filters by tab (all, suspended, revoked, expired, under review), search, group and publish date. |
| `get_credential_filters` | `read` | Issuer | The groups the credential list can filter by. |
| `get_credential` | `read` | Issuer | One credential: recipient, status, dates, public URL, attributes and engagement. |
| `get_credential_timeline` | `read` | Issuer | A credential's history: issue, publish, edits, emails sent and the holder's activity. |
| `get_issuing_options` | `read` | Issuer | The groups, credential attributes and credits available for issuing. |
| `check_duplicate_recipients` | `read` | Issuer | Which emails already hold a credential in a group. |
| `issue_credentials` | `issue` | Issuer | Creates credentials in a group, under review. No email is sent and no credit is used yet. Refused if there are fewer credits than rows. |
| `update_credential` | `issue` | Issuer | Edits one credential. No email is sent. A revoked credential can't be edited. |
| `get_update_sheet` | `read` | Issuer, `credential_update` feature | The rows for a bulk update of selected credentials. |
| `preview_credential_changes` | `read` | Issuer, `credential_update` feature | Shows what a bulk update would change, without saving. |
| `modify_credentials` | `issue` | Issuer, `credential_update` feature | Saves a bulk update. Nothing is saved if any row has an error. No email is sent. |
| `publish_credentials` | `issue` | Issuer | Publishes credentials under review. **Emails recipients and uses credits.** |
| `resend_credentials` | `issue` | Issuer | **Emails** the selected credentials to their recipients again. |
| `suspend_credentials` | `issue` | Issuer, `credential_suspension` feature | Suspends credentials. Their pages stop verifying until unsuspended. |
| `unsuspend_credentials` | `issue` | Issuer | Lifts a suspension. |
| `revoke_credentials` | `issue` | Issuer | **Revokes credentials for good.** This can't be undone. |
| `export_credentials` | `read` | Issuer, `credential_export` feature | The data of selected credentials, with links to their certificate and badge files. The export is logged. |

The bulk tools (`publish_credentials` to `export_credentials`) take either a list of credential `keys`, or `all_matching: true` with the same filters as `list_credentials`.

### Recipients

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_recipients` | `read` | Admin | Everyone the organization has issued to, newest first. Searches name, email or identifier. |
| `get_recipient` | `read` | Issuer | One recipient: details, credential statuses, engagement and attributes. |
| `list_recipient_credentials` | `read` | Issuer | The credentials issued to one recipient. |
| `update_recipient_attributes` | `manage` | Issuer | Sets a recipient's attribute values. Replaces all editable values. |

### Reviews

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_student_reviews` | `read` | Any member | Reviews recipients left on your groups. Filters by search, dates, group, rating and flag. |
| `get_student_review_summary` | `read` | Any member | The review count, average rating, flagged count and count per rating. |
| `get_student_review_filters` | `read` | Any member | The groups that have reviews. |
| `flag_student_review` | `manage` | Issuer | Flags or unflags a review. A flagged review is hidden from the group's public page. |

### Insights

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `get_dashboard` | `read` | Any member | The dashboard figures: credentials issued, pending review, views, social traffic and more. |
| `get_insights` | `read` | Marketing, `general_analytics` feature | Totals, the previous period, a series over time, traffic sources and countries for a date range. |
| `get_realtime_insights` | `read` | Marketing, `general_analytics` feature | Credential views in the last 30 minutes. |

### Email templates

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_email_templates` | `read` | Marketing or Issuer, `custom_email_content` feature | The email templates, with the groups that use each one. |
| `get_email_template` | `read` | Marketing or Issuer | One template's subject, body and merge tags. Without a key, the defaults for a new one. |
| `create_email_template` | `manage` | Marketing or Issuer | Creates a template. |
| `update_email_template` | `manage` | Marketing or Issuer | Replaces a template's name, subject, body and LinkedIn button setting. |

### Pathways

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_pathways` | `read` | Admin | The credential pathways, newest first. |
| `get_pathway` | `read` | Admin | One pathway with its editor JSON. |
| `list_pathway_groups` | `read` | Admin | The groups a pathway block can name, found by keyword. |
| `create_pathway` | `manage` | Admin | Creates a pathway from editor JSON. |
| `update_pathway` | `manage` | Admin | Replaces a pathway's name and editor JSON. |

### Directories

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_directories` | `read` | Admin, `directories` feature | The earners directories, with their public and embed URLs. |
| `get_directory_form` | `read` | Admin, `directories` feature | The groups a new directory can list, and a new random slug. |
| `get_directory` | `read` | Admin, `directories` feature | One directory's settings. |
| `create_directory` | `manage` | Admin, `directories` feature | Creates a directory. A public one is visible to anyone at its URL. |
| `update_directory` | `manage` | Admin, `directories` feature | Replaces a directory's settings. Changing the slug changes its URLs. |

### Apps

These tools work with apps from the marketplace. Install and connect an app in the Studio first.

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_extensions` | `read` | Admin | The apps in the marketplace, and which are installed. |
| `get_extension` | `read` | Admin | One app: features, plan access and install state. |
| `list_courses` | `read` | Admin | The courses in the connected Docebo or Thinkific account, with the group each maps to. |
| `set_course_mapping` | `manage` | Admin | Maps an LMS course to a credential group. |
| `set_auto_issue` | `manage` | Admin | Turns auto-issue on course completion on or off. **When on, each completion of a mapped course issues a credential, emails the learner and uses a credit.** |
| `sync_courses` | `manage` | Admin | Creates a mapped group for each LMS course that has none. |
| `list_meetings` | `read` | Admin | Recent meetings and webinars in the connected Zoom or Webex account. |
| `list_meeting_participants` | `read` | Admin | A meeting's participants, the groups you can issue from, and the credits left. |
| `issue_to_participants` | `issue` | Admin | Creates credentials under review for meeting participants. Participants without an email are skipped. |

### Audit logs

| Tool | Scope | Needs | What it does |
| - | - | - | - |
| `list_audit_logs` | `read` | Admin, `audit_logs` feature, Audit Logs app | Audit log entries, newest first. Filters by search, dates, area and person. |
| `list_audit_log_filters` | `read` | Admin, `audit_logs` feature, Audit Logs app | The areas and people the log can filter by. |
| `get_audit_log` | `read` | Admin, `audit_logs` feature, Audit Logs app | One audit log entry in full. |

## Resources and prompts

The server also offers three resources that clients can attach as context:

| Resource | Content |
| - | - |
| `hyperstack://organization` | The organization, the member's roles, the plan and its features. |
| `hyperstack://groups` | The first page of credential groups. |
| `hyperstack://groups/{key}` | One credential group. |

And three prompts, ready-made tasks a client can offer:

| Prompt | Arguments | Task |
| - | - | - |
| `issue_credentials_from_list` | `group`, `recipients` | Issue credentials to a pasted list of names and emails, with a check before issuing and before publishing. |
| `credential_report` | `start`, `end` | A short report of credentials issued and engagement for a period. |
| `set_up_new_credential` | `name`, `description` (optional) | Create a credential group for a new course, event or achievement. |

## Errors

When a tool fails, the call returns a normal MCP result with `isError: true`. The text says what went wrong and starts with the tool's name:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [
      { "type": "text", "text": "Error executing tool get_group: Group not found" }
    ],
    "isError": true
  }
}
```

The server tells assistants to report these errors to the user, and not to retry.

| Cause | Message after the tool name |
| - | - |
| The connection lacks the scope | `This connection was not granted the "issue" scope (issue, update, resend, suspend and revoke credentials). Connect Hyperstack again and allow it.` |
| The member lacks the role | `You do not have permission to do this.` |
| The plan lacks the feature | `Your plan doesn't include this feature.` |
| A key or ID matches nothing | A not-found message, such as `Group not found` or `Design not found`. |
| A field is not valid | The reason, and the field with its problem, such as `Title should not be empty`. |
| The Studio is paused for an unpaid invoice | `Your Studio is paused until the overdue invoice is paid. Your issued credentials, public pages and wallets aren't affected.` |

Keys come from other tools. List or search first, then use the key in the result.

Arguments that don't match a tool's input schema also return `isError: true`, with the details.

A connection that was revoked, or whose member left the organization, gets a `401` on every request, and its refresh token is refused. Connect again to get a new connection.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.