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

# Tool reference

> The five tools the Lucent MCP server exposes to agents — four read tools and one write tool.

All five tools are registered under the MCP server at
`https://app.lucenthq.com/api/mcp` and scoped automatically to the
organization that owns the bearer token. There is no way to pass an
`orgId` argument — your token IS the scope.

Every tool returns a single JSON-stringified payload in a `text` content
block. The shapes below are what you'll see once the client parses that
JSON.

Every tool also accepts an optional `prompt` argument: the user request
that caused the tool call. Clients should pass it through when they can —
it gives the audit trail context for why an agent read or changed
something.

## `list_signals`

List signals configured for the organization, with match counts and
last-match timestamps.

**Arguments**

| Name    | Type    | Default | Description                        |
| ------- | ------- | ------- | ---------------------------------- |
| `limit` | integer | `50`    | Max rows to return. Range `1–200`. |

**Returns**

```json theme={null}
[
  {
    "id": "d3f0a2c4-...",
    "name": "Empty cart after checkout",
    "prompt": "Flag any session where the cart empties unexpectedly...",
    "runMode": "ongoing",
    "status": "active",
    "createdAt": "2026-03-14T22:10:04.512Z",
    "matchCount": 17,
    "lastMatchAt": "2026-04-14T08:41:22.103Z"
  }
]
```

Ordered by `createdAt` descending. `matchCount` is a LEFT JOIN count of
rows in `signal_instances`; `lastMatchAt` is the most recent instance
timestamp or `null` if the signal has never matched.

## `list_issues`

List issues for the organization, optionally filtered by status.

**Arguments**

| Name     | Type                                                                | Default | Description                        |
| -------- | ------------------------------------------------------------------- | ------- | ---------------------------------- |
| `limit`  | integer                                                             | `25`    | Max rows to return. Range `1–200`. |
| `status` | `"unresolved"` \| `"ticket_created"` \| `"ignored"` \| `"resolved"` | —       | Filter by issue status.            |

**Returns**

```json theme={null}
[
  {
    "id": "87b3a6b6-5af5-438b-a39c-eff148a68ccb",
    "title": "Payment processing fails with generic server error message during checkout",
    "description": "Users are unable to complete the booking process...",
    "status": "unresolved",
    "priority": "critical",
    "previewUrl": "https://.../issue-screenshots/87b3a6b6.png",
    "createdAt": "2026-02-24T10:32:19.066Z",
    "sessionCount": 1,
    "linearIssueUrl": null,
    "linearIssueIdentifier": null
  }
]
```

Ordered by `createdAt` descending. `sessionCount` is the number of session
replays that triggered this issue. `linearIssueUrl` and
`linearIssueIdentifier` are populated when the issue has been promoted to
a Linear ticket, otherwise `null`.

## `get_issue`

Fetch a single issue by ID, scoped to the organization.

**Arguments**

| Name      | Type                     | Description                     |
| --------- | ------------------------ | ------------------------------- |
| `issueId` | string (uuid) — required | The UUID of the issue to fetch. |

**Returns**

```json theme={null}
{
  "id": "87b3a6b6-5af5-438b-a39c-eff148a68ccb",
  "title": "Payment processing fails with generic server error message during checkout",
  "description": "Users are unable to complete the booking process...",
  "stepsToReplicate": "1. Add a listing to the cart\n2. Proceed to checkout\n3. Fill in valid payment details\n4. Click 'Complete booking'\n...",
  "status": "unresolved",
  "priority": "critical",
  "previewUrl": "https://.../issue-screenshots/87b3a6b6.png",
  "aiVerified": true,
  "createdAt": "2026-02-24T10:32:19.066Z",
  "updatedAt": "2026-02-24T10:32:19.066Z",
  "linearIssueUrl": null,
  "linearIssueIdentifier": null
}
```

Returns `isError: true` with a "No issue found with id {issueId}" message
if the issue doesn't exist or belongs to a different organization.

Unlike `list_issues`, `get_issue` includes `stepsToReplicate` and
`aiVerified` — heavier fields that aren't worth returning in bulk.

## `update_issue`

Update an issue's status — mark it resolved after a fix ships, ignore a
false positive, or reopen a regression. This is the only write tool, and
the only one that requires the `write:issues` scope.

**Arguments**

| Name      | Type                                                                           | Description                      |
| --------- | ------------------------------------------------------------------------------ | -------------------------------- |
| `issueId` | string (uuid) — required                                                       | The UUID of the issue to update. |
| `status`  | `"unresolved"` \| `"ticket_created"` \| `"ignored"` \| `"resolved"` — required | The new status.                  |

**Returns**

The updated issue, in the same shape as `get_issue`.

Returns `isError: true` with `Missing required scope: write:issues` if the
token lacks the scope, or `No issue found with id {issueId}` if the issue
doesn't exist or belongs to a different organization.

The same operation is available over REST as
[`PATCH /api/v1/issues/{issueId}`](/api-reference/update-issue-status).

## `list_insights`

List the most recent insights (periodic session summaries) for the
organization.

**Arguments**

| Name    | Type    | Default | Description                        |
| ------- | ------- | ------- | ---------------------------------- |
| `limit` | integer | `25`    | Max rows to return. Range `1–100`. |

**Returns**

```json theme={null}
[
  {
    "id": "f2b1c0e8-...",
    "createdAt": "2026-04-14T00:00:00.000Z",
    "intervalStart": "2026-04-07T00:00:00.000Z",
    "intervalEnd": "2026-04-14T00:00:00.000Z",
    "sessionsCount": 342,
    "content": {
      "positive": [...],
      "negative": [...]
    }
  }
]
```

Ordered by `createdAt` descending. Each row covers the window from
`intervalStart` to `intervalEnd` and summarizes `sessionsCount` sessions
that completed in that window. The `content` field is the structured AI
summary — shape varies by insight type.

## Limits and defaults

| Tool            | Default limit | Max limit |
| --------------- | ------------- | --------- |
| `list_signals`  | 50            | 200       |
| `list_issues`   | 25            | 200       |
| `list_insights` | 25            | 100       |
| `get_issue`     | —             | —         |
| `update_issue`  | —             | —         |

If you need more than the max for a single tool call, filter by `status`
(for `list_issues`) or fetch specific records individually.

## Scopes

| Scope          | Tools                                                                                   |
| -------------- | --------------------------------------------------------------------------------------- |
| `read:lucent`  | `list_signals`, `list_issues`, `get_issue`, `list_insights`. Included with every token. |
| `write:issues` | `update_issue`.                                                                         |

API keys get `write:issues` by checking **Allow issue status updates** at
creation; keys without it can use the four read tools but `update_issue`
returns a missing-scope error. OAuth clients must request `write:issues`
explicitly — the default OAuth scope is `read:lucent`.

## Organization isolation

Every tool call compiles to a SQL query with `WHERE org_id = ?` where
`org_id` comes exclusively from the bearer token's auth context. No
tool accepts an organization argument from the client, and `get_issue`
compounds the ID check with the org check so an issue UUID from another
organization will never resolve.

If you need access to a different organization, sign in to that
organization in the dashboard and mint a new token there.
