---
title: skill_list
description: List your organization's ad-ops playbooks (Skills) by slug, name, and description.
---

Lists the **Skills** (ad-ops playbooks) in your organization, newest first. Returns each Skill's `slug`, `name`, and `description` only — never the body. This is progressive disclosure: the agent picks the right Skill from its description, then loads the full instructions with [`skill_get`](/mcp/tools/skill-get).

## Input

The active organization is resolved from your OAuth token.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | `number` | no | The greatest number of rows in the answer, from 1 to 500. The default is 100. |
| `cursor` | `string` | no | The `nextCursor` of the previous answer. Omit it to get the first page. |

## Output

`{ skills: [...], nextCursor? }`. Each Skill is `{ slug, name, description }`. Soft-deleted Skills are excluded. When `nextCursor` is present, more Skills exist: call `skill_list` again with `cursor` set to that value.

## Example

> _"What ad-ops playbooks do I have?"_

```ts
skill_list({});
// → { skills: [{ slug: 'weekly-meta-audit', name: 'Weekly Meta Audit', description: '…' }, …] }
```

:::info[Slug is the handle]

The `slug` is the stable per-organization handle you pass to [`skill_get`](/mcp/tools/skill-get), [`skill_update`](/mcp/tools/skill-update), and [`skill_delete`](/mcp/tools/skill-delete). Bodies are intentionally omitted here — fetch them on demand.

:::

## Errors

- `invalid_cursor` — the `cursor` is not a `nextCursor` of this tool, with the same arguments. Send it with no change, or omit it.
- `401` or `403` — see [Errors](/mcp/errors), which every tool shares. This one needs `skill:read`.

## Reference

List the active organization's ad-ops playbooks (Skills) as slug + name + description, newest first. Bodies are not returned — fetch a Skill's instructions with skill_get once you've picked one. The answer holds at most `limit` rows (default 100, maximum 500). When it carries `nextCursor`, more rows exist: call this tool again with the same arguments and `cursor` set to that value. When it carries no `nextCursor`, you have every row.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `cursor` | string, at least 1 character | no | The `nextCursor` of the previous page. Omit it to get the first page. Send it with no change, and with the same filters as the request that answered it: a cursor from a different query gets a 400 `invalid_cursor`. Do not build or change a cursor. |
| `limit` | integer, 1 to 500 | no | The greatest number of rows on the page, from 1 to 500. The default is 100. A greater value gets a 400, with `error` of `invalid_request`. Default: `100`. |

### Failure codes

A failed call has `isError` set, and `structuredContent.error` holds one of these codes. [Errors](/mcp/errors) describes the shape of a failed call.

- `invalid_cursor`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `skill:read`. [Auth & scopes](/mcp/auth) lists each scope.

### Annotations

A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.

- **Read-only.** The tool changes nothing.
- **Closed world.** The tool reads and writes the data of AdCrunch only.
