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

# MCP Server

> Connect Claude Desktop, Cursor, and other MCP clients to Risotto to work with tickets, knowledge, runbooks, automation tools, access rules, and settings.

# Risotto MCP Server

Risotto exposes a [Model Context Protocol](https://modelcontextprotocol.io) server so MCP-compatible clients (Claude Desktop, Cursor, ChatGPT, and custom agents) can call into your Risotto workspace. The server has 120 tools. You can work with tickets, knowledge, users, departments, runbooks, automation tools, access rules, and organization settings. See [Available tools](#available-tools) for the full list.

Clients authenticate with **OAuth 2.1**. Your client runs a standard browser-based authorization flow, and each user signs in with their own Risotto identity, so tool calls are attributed and audited per person. Claude Desktop, Claude Code, Cursor, ChatGPT, the MCP Inspector, and any client that ships a built-in OAuth UI connect this way. Risotto API keys are not an authentication method for the MCP server.

<Info>
  OAuth clients self-register with Risotto the first time they connect — there
  is no "create OAuth client" step in the dashboard. You only need the server
  URL.
</Info>

## Prerequisites

* A Risotto account in the organization. Every organization role can connect. Your role limits the scopes that you can grant (see [Scopes and organization roles](#scopes-and-organization-roles)).
* An MCP-compatible client. OAuth requires a client that supports OAuth 2.1 + Dynamic Client Registration (Claude Desktop, recent Cursor, MCP Inspector, or any spec-compliant client).

## Find your MCP server URL

Each Risotto organization has its own MCP server URL of the form:

```text theme={null}
https://api.tryrisotto.com/o/<org_id>/mcp
```

Copy your organization's specific URL from [**Settings → Integrations → MCP**](https://dashboard.tryrisotto.com/settings/integrations/mcp) in the dashboard.

## Connect with OAuth

<Note>
  Org Admins and Managers can grant every scope. A Member can grant only the
  Member scopes. See [Scopes and organization
  roles](#scopes-and-organization-roles).
</Note>

<Steps>
  <Step title="Add the MCP server to your client">
    Most MCP clients only need the server URL — they handle registration and the consent flow automatically.

    <Tabs>
      <Tab title="Claude Desktop">
        Edit your Claude Desktop config file:

        * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
        * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

        ```json theme={null}
        {
          "mcpServers": {
            "risotto": {
              "transport": {
                "type": "http",
                "url": "YOUR_MCP_SERVER_URL"
              }
            }
          }
        }
        ```

        Replace `YOUR_MCP_SERVER_URL` with the URL from your dashboard. No client ID, client secret, or token URL is needed — Claude Desktop discovers everything from the server.

        Restart Claude Desktop after saving.
      </Tab>

      <Tab title="Cursor">
        Open **Cursor Settings → MCP → Add MCP server** and paste your MCP server URL from the dashboard.

        Save. Cursor will trigger the OAuth flow on first use.
      </Tab>

      <Tab title="ChatGPT">
        ChatGPT connects to Risotto as a custom MCP connector.

        <Note>
          Custom connectors require a ChatGPT **Pro, Team, or Enterprise** plan with **developer mode** enabled.
        </Note>

        In ChatGPT, go to **Settings → Connectors → Add custom connector** and paste your MCP server URL from the dashboard.

        ChatGPT runs the OAuth flow automatically — sign in with your Risotto account and approve the scopes you want. Risotto's tools then appear in ChatGPT's tool picker.
      </Tab>

      <Tab title="MCP Inspector">
        ```bash theme={null}
        npx @modelcontextprotocol/inspector YOUR_MCP_SERVER_URL
        ```

        The Inspector opens a browser tab for consent, then exposes a JSON-RPC console for poking at the server directly.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Sign in and grant scopes">
    The first time the client connects, a browser tab opens to a Risotto consent screen. Sign in with the same account you use for the dashboard and review the scopes the client is requesting. Clear the checkbox next to a scope to leave it out of the grant, then click **Allow**.

    The scopes you approve at this screen bound that specific client's access — they don't change your overall account permissions. The screen lists only the requested scopes that your organization role can hold.
  </Step>

  <Step title="Use the tools">
    Risotto's tools now appear in the client's tool picker. The access token issued at consent is refreshed automatically; you won't be re-prompted unless you revoke the client or the refresh window lapses.
  </Step>
</Steps>

### Available scopes

OAuth clients request scopes at consent time. A scope grants the tools listed under it in [Available tools](#available-tools).

| Scope | Grants |
| - | - |
| `tickets:read` | List and read tickets, comments, ticket insights, and ticket field definitions |
| `tickets:write` | Create, update, resolve, and escalate tickets, and add comments |
| `tickets:delete` | Reserved. No MCP tool uses this scope yet |
| `knowledge:read` | Search indexed knowledge, list knowledge sources, check a document's index |
| `users:read` | Find users and read their profiles and groups |
| `departments:read` | List departments (ID and name only without `config:read`) |
| `departments:write` | Create departments and change department settings |
| `runbooks:read` | Read runbooks and a ticket's runbook history |
| `runbooks:write` | Create, update, duplicate, and delete runbooks and forms, and read drafts, revisions, templates, forms, and the authoring guide |
| `tools:read` | List automation tools and tool templates, read script drafts and runs |
| `tools:write` | Create and update automation tools and script tools, set tool approval |
| `tools:execute` | Run and test automation tools and scripts |
| `custom_api_sources:read` | List custom API sources and browse the shipped API templates |
| `custom_api_sources:write` | Create custom API sources and stage, test, and promote endpoint drafts |
| `external_mcp_servers:read` | List connected external MCP servers |
| `external_mcp_servers:write` | Connect external MCP servers and import their tools |
| `applications:read` | List the applications that requestors can ask access to |
| `access_rules:read` | List access rules |
| `access_rules:write` | Create and update applications and access rules |
| `settings:read` | Read organization settings, request sources, and the IdP config |
| `settings:write` | Update organization settings, request routing, ticket fields, and Okta config |
| `artifacts:read` | List and read artifact pages |
| `artifacts:write` | Delete artifact pages |
| `audit:read` | Read the configuration audit log |
| `config:read` | Read Assistant settings, full department settings, and the automation opportunities report |
| `config:write` | Update Assistant settings |
| `triggers:read` | Reserved. No MCP tool uses this scope yet |
| `triggers:write` | Reserved. No MCP tool uses this scope yet |

<Tip>
  Follow least privilege. For a read-only assistant, approve `tickets:read`,
  `knowledge:read`, `users:read`, `departments:read`, `runbooks:read`, and
  `tools:read`. Add write or execute scopes only when a workflow needs them.
</Tip>

#### Scopes and organization roles

Your organization role limits the scopes that a client can hold:

* **Org Admin and Org Manager** can hold every scope.
* **Member** can hold `tickets:read`, `tickets:write`, `knowledge:read`, `users:read`, `departments:read`, `runbooks:read`, and `applications:read`.

At consent, a Member sees only the requested scopes in this list. If none of the requested scopes is in the list, the client gets `access_denied`. Risotto checks the role on every request. When an admin changes your role, your tokens get the scopes of the new role within 5 minutes. A user who leaves the organization gets `403`.

A Member also has these limits:

* A Member can act only as themselves. Risotto refuses a `create_ticket` for another requestor ("You can create tickets only for yourself"), an `add_comment` as another author ("You can comment only as yourself"), and a `search_knowledge` or `check_document_index_status` on behalf of another user ("You can search only with your own access").
* `search_knowledge` with a `dept_id` works only for a department where the Member can read tickets. Without `dept_id`, it searches only documents shared with the whole organization.
* `list_runbooks` and `get_runbook` return the org-wide runbooks and the runbooks of the Member's departments.

<Note>
  Ticket access via MCP respects the authenticated user's department membership
  and role, the same as the dashboard and chat — a `tickets:read` scope doesn't
  grant visibility into tickets outside the departments that user belongs to.
</Note>

### Manage authorized clients

From [**Settings → Integrations → MCP**](https://dashboard.tryrisotto.com/settings/integrations/mcp) in the dashboard you can:

* See every OAuth client that has registered against your organization, including the IP it was registered from and when it last made a request.
* Revoke a client — invalidates all of its tokens immediately. The client will be prompted to sign in again on its next request.

Revoking an OAuth client only affects that one client. Other authorized clients keep working.

## Available tools

The server registers 120 tools. Each tool needs one scope. `tools/list` returns only the tools whose scope your credential holds, with their input schemas. For example, a Member sees only the tools of the Member scopes, and an API key with narrow scopes sees only the tools of those scopes. Risotto also checks the scope when you call a tool, so a call to a tool outside your granted scopes fails with a missing-scope error.

Tool names below are the values you pass in `tools/call`. The dashboard Assistant is built on the same tools.

Where a ticket tool takes a `ticket_id`, you can pass the Risotto key (for example `IT-123`) or the key of the synced ticket in your ticketing system (for example the Jira key `ENG-123`). Risotto tries the Risotto key first, then the synced key. If more than one ticket has the same synced key, Risotto uses the newest ticket. Ticket results include `external_ticket_id` and `external_ticket_url`. Both are `null` when the ticket is not synced. `list_tickets` has no filter for the synced key, but its `search` argument matches the synced key.

Ticket results also include `priority`, as `{ value, is_suggested }` or `null`. `value` is `low`, `medium`, `high`, or `urgent`. `is_suggested` is `true` when the value is the priority that the AI suggested, and `false` when a person set it. The ticket tools cannot change the priority. See [Ticket priority](/integrations/webhooks#ticket-priority).

To find tickets about a topic, pass `search` to `list_tickets`. The search is not case-sensitive. It matches the ticket title, public comments, the requestor's email, the assignee's name, the name of the Slack channel where the ticket started, the synced key, and the ticket number (`123` or `IT-123`). Risotto combines `search` with the other filters. The dashboard **Search tickets** box matches the same fields.

<AccordionGroup>
  <Accordion title="Tickets and comments (8 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_tickets` | List, filter, and search tickets. Returns up to 100 tickets per page. | `tickets:read` |
    | `get_ticket` | Get one ticket with its comments and workflow state. | `tickets:read` |
    | `list_ticket_comments` | List the comments on a ticket. | `tickets:read` |
    | `create_ticket` | Create a ticket. The agent processes it like a ticket from chat. | `tickets:write` |
    | `update_ticket` | Update ticket fields. Only the fields you pass change. | `tickets:write` |
    | `add_comment` | Add a comment to a ticket. | `tickets:write` |
    | `resolve_ticket` | Mark a ticket as resolved. Also resolves the synced external ticket. | `tickets:write` |
    | `escalate_ticket` | Escalate a ticket to human support. Sends a Slack notification and stops the agent. | `tickets:write` |
  </Accordion>

  <Accordion title="Ticket insights (7 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `get_ticket_runbook_match_history` | Show which runbooks matched a ticket and why. | `tickets:read` |
    | `get_ticket_retrieval_history` | Show the knowledge that Risotto retrieved for a ticket. | `tickets:read` |
    | `get_ticket_agent_activity` | Show the agent's steps on a ticket in order. | `tickets:read` |
    | `list_ticket_runbook_history` | List the runbooks matched to a ticket and whether the agent followed them. | `runbooks:read` |
    | `get_automation_opportunities` | Report the requests Risotto could still automate, ranked by ticket volume. Also needs `tickets:read`. | `config:read` |
    | `list_ticket_custom_fields` | List the additional ticket fields defined for the organization. | `tickets:read` |
    | `create_ticket_custom_field` | Create an additional ticket field in a department. | `settings:write` |
  </Accordion>

  <Accordion title="Knowledge (3 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `search_knowledge` | Search indexed knowledge with semantic and keyword retrieval. | `knowledge:read` |
    | `list_knowledge_sources` | List the connected knowledge sources and their index IDs. | `knowledge:read` |
    | `check_document_index_status` | Check whether a document is in the index, by URL or title. | `knowledge:read` |
  </Accordion>

  <Accordion title="Users (3 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `find_users` | Search users by name or email. | `users:read` |
    | `get_user_profile` | Get a user's profile from the identity provider. | `users:read` |
    | `get_user_groups` | Get the identity provider groups a user belongs to. | `users:read` |
  </Accordion>

  <Accordion title="Departments and Tier 2 Assistant (10 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_departments` | List departments with descriptions, ticket prefixes, and member counts. Without `config:read`, returns only the ID and name. | `departments:read` |
    | `get_department` | Read every setting of one department. Without `config:read`, returns only the ID and name. | `departments:read` |
    | `create_department` | Create a department from a name and a description. | `departments:write` |
    | `update_department_setting` | Set one department setting, such as the name or description. | `departments:write` |
    | `update_department_ticket_sync_setting` | Set one Ticket Sync toggle for the department's external ticketing system. | `departments:write` |
    | `set_department_ticket_prefix` | Set the ticket prefix, for example `IT` in `IT-123`. | `departments:write` |
    | `set_department_agent_channel` | Set the Slack channel where Risotto posts escalations for the department. | `departments:write` |
    | `set_department_escalation_contact` | Set the person Risotto notifies when a ticket escalates. | `departments:write` |
    | `get_tier_2_assistant_config` | Read a department's Assistant settings: auto start and the investigation and execution instructions. | `config:read` |
    | `update_tier_2_assistant_config` | Set a department's Assistant auto start, investigation instructions, or execution instructions. Omitted settings stay unchanged. | `config:write` |
  </Accordion>

  <Accordion title="Runbooks, templates, and forms (17 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_runbooks` | List and filter runbooks. | `runbooks:read` |
    | `get_runbook` | Get a runbook's current version: conditions, instructions, and tool references. | `runbooks:read` |
    | `get_runbook_draft` | Get a runbook's pending draft revision. | `runbooks:write` |
    | `list_runbook_revisions` | List every version of a runbook, newest first. | `runbooks:write` |
    | `get_runbook_authoring_guide` | Get the runbook authoring guide as Markdown. | `runbooks:write` |
    | `create_runbook` | Create a runbook. It is active and indexed immediately. | `runbooks:write` |
    | `update_runbook` | Update one or more fields on a runbook. | `runbooks:write` |
    | `upsert_runbook_draft` | Stage or replace a pending draft revision on a runbook. | `runbooks:write` |
    | `duplicate_runbook` | Copy a runbook. The copy starts disabled with " (Copy)" in its title. | `runbooks:write` |
    | `delete_runbook` | Soft-delete a runbook. The version history is kept. | `runbooks:write` |
    | `list_runbook_templates` | List the curated runbook templates and whether your tools are ready for them. | `runbooks:write` |
    | `get_runbook_template` | Get a runbook template with its content. | `runbooks:write` |
    | `list_forms` | List the structured-input forms, newest first. | `runbooks:write` |
    | `get_form` | Get a form's fields and the runbooks that reference it. | `runbooks:write` |
    | `create_form` | Create a form for runbooks to collect answers from requestors. | `runbooks:write` |
    | `update_form` | Update a form. Omitted arguments stay unchanged. | `runbooks:write` |
    | `delete_form` | Delete a form. | `runbooks:write` |
  </Accordion>

  <Accordion title="Automation tools and scripts (17 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_tools` | List the organization's automation tools with their parameter schemas. | `tools:read` |
    | `list_tool_templates` | List the tool templates you can create a tool from. | `tools:read` |
    | `create_tool` | Create an automation tool from a template. | `tools:write` |
    | `update_tool` | Update a tool's enabled state, name, description, or approval setting. | `tools:write` |
    | `configure_tool_approval` | Record how executions of a tool must be approved. | `tools:write` |
    | `request_tool_credentials` | Report whether a tool has all required configuration. | `tools:write` |
    | `execute_tool` | Run an automation tool with the arguments you pass. See the warning below. | `tools:execute` |
    | `test_tool` | Run a tool against its live configuration and report the outcome. | `tools:execute` |
    | `create_script` | Create a script tool. It starts disabled with a skeleton code draft. | `tools:write` |
    | `get_script_draft` | Read a script tool's draft code, analysis, and diagnostics. | `tools:read` |
    | `update_script_draft` | Save a script tool's draft code. Risotto analyzes every save. | `tools:write` |
    | `test_script` | Run a script tool's draft code as a test execution. | `tools:execute` |
    | `get_script_run` | Read one script run's outcome and per-step trace. | `tools:read` |
    | `get_last_script_test_run` | Read the most recent test run for a script tool. | `tools:read` |
    | `publish_script` | Publish a script tool's draft as the live version. | `tools:write` |
    | `list_credentials` | List the names and types of the credentials in the vault. Never the values. | `tools:read` |
    | `request_vault_credential` | Ask for a new vault credential on a secure card. | `tools:write` |
  </Accordion>

  <Accordion title="Custom API sources and templates (22 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_custom_api_sources` | List the custom API sources (third-party REST integrations). | `custom_api_sources:read` |
    | `get_custom_api_source` | Inspect one source and its staged endpoint drafts. | `custom_api_sources:read` |
    | `find_api_spec_candidates` | Find a vendor's published API definition file on the web. | `custom_api_sources:read` |
    | `list_custom_api_templates` | List the vendor APIs Risotto ships a pinned specification for. | `custom_api_sources:read` |
    | `get_custom_api_template` | Inspect one template: its tag groups and endpoints. | `custom_api_sources:read` |
    | `search_custom_api_endpoints` | Search every shipped API specification for endpoints that match a description. | `custom_api_sources:read` |
    | `record_excluded_capability_request` | Record that you asked for an area that a template leaves out. | `custom_api_sources:read` |
    | `create_custom_api_source` | Create a custom API source. | `custom_api_sources:write` |
    | `create_custom_api_source_from_template` | Create a source from a template with all endpoints drafted. | `custom_api_sources:write` |
    | `update_custom_api_source` | Update a source's non-secret configuration. | `custom_api_sources:write` |
    | `ingest_openapi_spec` | Fetch an API definition by URL and stage every operation as a draft. | `custom_api_sources:write` |
    | `ingest_openapi_spec_content` | Stage every operation from a pasted API definition. | `custom_api_sources:write` |
    | `ingest_attached_file` | Stage operations from a file attached in the dashboard Assistant. | `custom_api_sources:write` |
    | `ingest_confirmed_web_spec` | Ground a source on a specification file found on the web. | `custom_api_sources:write` |
    | `stage_custom_api_drafts` | Stage hand-authored endpoint drafts on a source. | `custom_api_sources:write` |
    | `import_curl_endpoint` | Stage an endpoint draft parsed from a curl command. | `custom_api_sources:write` |
    | `discard_custom_api_draft` | Remove a staged endpoint draft. | `custom_api_sources:write` |
    | `test_custom_api_draft` | Run a staged draft against the real API before promotion. | `custom_api_sources:write` |
    | `validate_custom_api_draft` | Validate a staged read (GET) draft with one live test call. | `custom_api_sources:write` |
    | `promote_custom_api_drafts` | Promote staged read (GET) drafts into callable tools. | `custom_api_sources:write` |
    | `construct_custom_api_write_tool` | Turn a staged write draft into a disabled draft tool. | `custom_api_sources:write` |
    | `request_custom_api_credentials` | Report whether a source has its credentials. | `custom_api_sources:write` |
  </Accordion>

  <Accordion title="External MCP servers (8 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_external_mcp_servers` | List the connected external MCP servers. | `external_mcp_servers:read` |
    | `get_external_mcp_server` | Inspect one server: its tool catalog, drift, and imported tools. | `external_mcp_servers:read` |
    | `create_external_mcp_server` | Connect a third-party MCP server and discover its tool catalog. | `external_mcp_servers:write` |
    | `request_external_mcp_credentials` | Report whether a server has its bearer token. | `external_mcp_servers:write` |
    | `request_external_mcp_authorization` | Report whether a server's OAuth 2.1 authorization is complete. | `external_mcp_servers:write` |
    | `refresh_external_mcp_server` | Fetch a server's remote tool catalog again. | `external_mcp_servers:write` |
    | `import_external_mcp_tools` | Import chosen remote tools as automation tools. | `external_mcp_servers:write` |
    | `test_external_mcp_tool` | Call a remote tool on the live server before you import it. | `external_mcp_servers:write` |
  </Accordion>

  <Accordion title="Access management (8 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_applications` | List the applications that requestors can ask access to. | `applications:read` |
    | `list_access_rules` | List access rules with their state, application, limits, and approval. | `access_rules:read` |
    | `get_access_rule` | Get one access rule's full configuration. | `access_rules:read` |
    | `get_access_rule_authoring_guide` | Get the access-rule authoring guide as Markdown. | `access_rules:write` |
    | `create_applications` | Create up to 100 applications in one call. | `access_rules:write` |
    | `update_application` | Update an application's name, owner email, or keywords. | `access_rules:write` |
    | `create_access_rules` | Create up to 100 access rules in one call. New rules start disabled. | `access_rules:write` |
    | `update_access_rule` | Update one access rule. Omitted fields keep their value. | `access_rules:write` |
  </Accordion>

  <Accordion title="Organization settings, request sources, and identity provider (11 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `get_org_settings` | Read agent instructions, approval timers, auto-resolve days, and the notifications channel. | `settings:read` |
    | `update_org_setting` | Set one organization setting. | `settings:write` |
    | `find_slack_channels` | Find Slack channels by name. Returns IDs for the channel tools. | `settings:read` |
    | `set_slack_notifications_channel` | Set the Slack channel where Risotto posts admin notifications. | `settings:write` |
    | `list_request_sources` | List every request source with its routing department and settings. | `settings:read` |
    | `update_slack_channel_routing` | Update how a Slack channel routes requests. | `settings:write` |
    | `update_msteams_channel_routing` | Update how a Microsoft Teams channel routes requests. | `settings:write` |
    | `update_support_email_address` | Update the settings of a support email address. | `settings:write` |
    | `get_idp_configuration` | Read how the identity provider is configured. | `settings:read` |
    | `get_vendor_tenant_hosts` | Read the vendor site that each connection stores, such as your Atlassian site. | `settings:read` |
    | `request_okta_credentials` | Report whether the Okta connection is configured. | `settings:write` |
  </Accordion>

  <Accordion title="Artifacts and audit log (6 tools)">
    | Tool | What it does | Scope |
    | - | - | - |
    | `list_artifacts` | List the artifact pages (dynamic dashboards) with their URLs. | `artifacts:read` |
    | `get_artifact` | Get one artifact page, including its HTML. | `artifacts:read` |
    | `list_artifact_tools` | List the tools an artifact page can call. | `artifacts:read` |
    | `delete_artifact` | Delete an artifact page. Its audit log is kept. | `artifacts:write` |
    | `list_audit_events` | List configuration-change audit events. | `audit:read` |
    | `get_audit_event` | Get one audit event with its field-level diff. | `audit:read` |
  </Accordion>
</AccordionGroup>

<Warning>
  Grant `tools:execute` only to a user who may approve every tool it can reach.
  `execute_tool` runs the tool at once, also when the tool's approval setting is
  **Required** in the dashboard. Risotto records the call against the user who
  authorized the OAuth client.
</Warning>

<Note>
  Six tools collect secrets on a secure card in the dashboard Assistant:
  `request_tool_credentials`, `request_custom_api_credentials`,
  `request_external_mcp_credentials`, `request_external_mcp_authorization`,
  `request_okta_credentials`, and `request_vault_credential`. From an external
  MCP client they only report the current state. Enter the secret in the
  dashboard instead. `ingest_attached_file` reads a file uploaded in the
  dashboard Assistant and has no use from an external client.
</Note>

The set of tools grows as Risotto adds capabilities. Call `tools/list` against your endpoint to see the current list of tools that your scopes allow, with input schemas.

## Troubleshooting

<AccordionGroup>
  <Accordion title="401 Unauthorized">
    The bearer token is missing, malformed, expired, or revoked.

    * The client should refresh its token automatically. If it doesn't, remove and re-add the MCP server in the client to trigger a fresh consent flow.
    * If you configured the server with a Risotto API key instead of signing in, the response says so. Remove the key from the client's configuration and reconnect; the client prompts you to sign in with OAuth.
    * The `WWW-Authenticate` response header points to the OAuth discovery document — most clients use this automatically to recover. If you're building a custom client, follow that pointer.
  </Accordion>

  <Accordion title="403 insufficient_scope or access_denied">
    You are no longer in the organization, or none of the requested scopes is one that your role can hold.

    * A user who is not in the organization gets `403` with `insufficient_scope` ("Only org admins, managers, and members can use Risotto MCP.").
    * At consent, a Member whose client requests only scopes outside the [Member scopes](#scopes-and-organization-roles) goes back to the client with `access_denied`.
    * A `503` with `Retry-After: 30` means that Risotto could not read your role. Try again.
  </Accordion>

  <Accordion title="Consent screen redirects fail or loops">
    Risotto's Dynamic Client Registration follows [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) for **native/desktop clients**: they register either a `localhost` loopback redirect URI or a private-use URI scheme (like `cursor://`). Claude Desktop and the MCP Inspector use loopback; Cursor uses its `cursor://` scheme, and a single registration can mix native and web redirect URIs.

    Hosted clients like ChatGPT are different — they register their own public HTTPS redirect URI, which Risotto's DCR accepts. If you're building a custom **desktop** client, use a loopback or private-use-scheme redirect. If you're building a custom **hosted/web** client and registration is failing, double-check the redirect URI is a valid HTTPS URL your service controls.
  </Accordion>

  <Accordion title="Tool call returns a missing scope error">
    Scope failures come back as a successful JSON-RPC response whose `result.isError` is `true`, with a message naming the missing scope (for example, `tickets:read`).

    Revoke the client in the dashboard and reconnect — the consent screen lets you approve the additional scope. A Member cannot approve a scope outside the [Member scopes](#scopes-and-organization-roles). Ask an Org Admin for the Admin or Manager role.
  </Accordion>

  <Accordion title="429 Too Many Requests">
    You've hit Risotto's rate limit. `/mcp` requests are throttled per credential at 1,000 requests per hour by default, and OAuth token issuance is throttled per client.

    The response includes `Retry-After` and `X-RateLimit-*` headers showing the reset window. Back off until the window resets, or contact support if you consistently need higher limits.
  </Accordion>

  <Accordion title="Tools don't appear in the client">
    * Restart the client after editing its config file — most clients only read MCP config at startup.
    * Run the `curl` snippet above to confirm the endpoint is reachable.
    * `tools/list` returns only the tools that the credential's scopes allow. If a tool you expect is missing, check the scopes you granted, and for OAuth, check your organization role. See [Scopes and organization roles](#scopes-and-organization-roles).
  </Accordion>
</AccordionGroup>


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