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

# Knowledge & attachments

> Reference for the 21 MCP tools that attach knowledge base entries and binary file attachments to ideations, refinements, specs, and cards — including the host-side file_path / file_url loaders that keep large documents out of LLM context.

# Knowledge & attachments

Pulse exposes **21 of its 216 MCP tools** for context attached alongside the structured ADLC artifacts:

* **Knowledge base entries** — text snippets, design docs, API specs, analysis notes — attached to ideation, refinement, spec, or card. **18 tools** (`server.py:4131–4281`, `:7565–7825`, `:10777–10974`, `:11074–11280`).
* **Binary file attachments** — files on cards. **3 tools** (`server.py:3166–3317`).

Both share an important runtime trick: large documents and binary files can be loaded **server-side** via `file_path` or `file_url` rather than base64-passed through the model. The bytes never enter the LLM context, saving tokens and avoiding round-trip corruption.

Source-of-truth citations: `okto-pulse-feature-inventory.md:272–289` (attachments + comments sub-section), `:290–314` (ideation knowledge), `:395–410` (card knowledge), `:353–370` (spec knowledge), `:446–456` (refinement knowledge).

***

## Knowledge bases vs. attachments

|                  | Knowledge entries                                                                                             | Attachments                                                                    |
| ---------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **Stored on**    | Inline JSONB on the parent (or a dedicated table for spec/ideation/refinement)                                | Filesystem under `~/.okto-pulse/uploads/` with metadata in `attachments` table |
| **Content type** | UTF-8 text (Markdown by default)                                                                              | Any MIME type (binaries OK)                                                    |
| **Attached to**  | Ideation, refinement, spec, card                                                                              | Card only                                                                      |
| **Propagation**  | Ideation KEs auto-propagate to derived refinements/specs; spec KEs copy to cards via `copy_knowledge_to_card` | None — attachments stay on the card they were uploaded to                      |
| **Loaders**      | `content` (inline) / `file_path` (host) / `file_url`                                                          | `content_base64` / `file_path` / `file_url`                                    |
| **Permission**   | `Permissions.SPECS_UPDATE` (most), `Permissions.CARDS_UPDATE` (card knowledge)                                | `Permissions.ATTACHMENTS_UPLOAD` / `_DELETE` / `BOARD_READ`                    |

Use **knowledge entries** when an agent needs to *read* the content while reasoning. Use **attachments** for binaries (PDFs, images, raw datasets) the agent needs to reference but not parse — or for any payload outside the text envelope.

***

## Knowledge entries

Every parent type follows the same shape: `add` / `list` / `get` / `delete`. Cards add a fifth tool — `update` — because card knowledge is mutable inline JSONB.

### Tool reference by parent

#### Ideation (`server.py:4131–4281`)

| Tool                                   | Line | Purpose                                                                                                  |
| -------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------- |
| `okto_pulse_list_ideation_knowledge`   | 4131 | List entries on an ideation.                                                                             |
| `okto_pulse_get_ideation_knowledge`    | 4167 | Get one entry by ID.                                                                                     |
| `okto_pulse_add_ideation_knowledge`    | 4193 | Add an entry (text, file ref, URL). **Auto-propagates** to refinements/specs derived from this ideation. |
| `okto_pulse_delete_ideation_knowledge` | 4249 | Delete an entry.                                                                                         |

#### Refinement (`server.py:11074–11280`)

| Tool                                     | Line  | Purpose                       |
| ---------------------------------------- | ----- | ----------------------------- |
| `okto_pulse_list_refinement_knowledge`   | 11074 | List entries on a refinement. |
| `okto_pulse_get_refinement_knowledge`    | 11118 | Get one entry.                |
| `okto_pulse_add_refinement_knowledge`    | 11160 | Add an entry.                 |
| `okto_pulse_delete_refinement_knowledge` | 11235 | Delete an entry.              |

#### Spec (`server.py:10777–10974`)

| Tool                               | Line  | Purpose                 |
| ---------------------------------- | ----- | ----------------------- |
| `okto_pulse_list_spec_knowledge`   | 10777 | List entries on a spec. |
| `okto_pulse_get_spec_knowledge`    | 10821 | Get one entry.          |
| `okto_pulse_add_spec_knowledge`    | 10863 | Add an entry.           |
| `okto_pulse_delete_spec_knowledge` | 10938 | Delete an entry.        |

#### Card (`server.py:7565–7825`)

| Tool                                | Line | Purpose                                                                                                                        |
| ----------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------ |
| `okto_pulse_copy_knowledge_to_card` | 7565 | Copy spec KEs to a card as inline KEs. Empty `knowledge_ids` copies all. Sets `source = "copied_from_spec:<spec_id>:<kb_id>"`. |
| `okto_pulse_add_card_knowledge`     | 7658 | Attach a KE directly to a card (no spec needed).                                                                               |
| `okto_pulse_list_card_knowledge`    | 7721 | List entries on a card. Returns full content.                                                                                  |
| `okto_pulse_get_card_knowledge`     | 7741 | Get one entry.                                                                                                                 |
| `okto_pulse_update_card_knowledge`  | 7760 | Update a card KE in place.                                                                                                     |
| `okto_pulse_delete_card_knowledge`  | 7808 | Delete a card KE.                                                                                                              |

### Three ways to load content

`add_ideation_knowledge`, `add_refinement_knowledge`, and `add_spec_knowledge` all take a `content` / `file_path` / `file_url` triplet. Provide **exactly one** — the others stay empty.

| Field       | When to use                                                          | Token cost in agent context                        |
| ----------- | -------------------------------------------------------------------- | -------------------------------------------------- |
| `content`   | Small inline snippets — runbooks, short ADRs, code stubs ≤ a few KB. | Full content — counts against your context window. |
| `file_path` | Local UTF-8 text file on the MCP server host (absolute path).        | Path string only — bytes load server-side.         |
| `file_url`  | HTTP(S)-reachable UTF-8 text document.                               | URL string only — server fetches the bytes.        |

```text theme={null}
Input to okto_pulse_add_spec_knowledge:
  board_id:    "brd_abc123"
  spec_id:     "spec_XYZ"
  title:       "Stripe webhook contract"
  description: "Stripe's documented webhook events we rely on for payment lifecycle."
  mime_type:   "text/markdown"
  file_url:    "https://internal.docs/stripe-webhook-contract.md"

Output:
{
  "success": true,
  "knowledge": {
    "id":        "kb_001",
    "title":     "Stripe webhook contract",
    "mime_type": "text/markdown"
  }
}
```

<Note>
  File content is loaded **once at attachment time** and persisted on the parent. Subsequent edits to the source URL do not auto-refresh the entry — re-add (or for cards, `update_card_knowledge`) to capture changes.
</Note>

### Card knowledge is mutable

Specs/ideations/refinements treat knowledge as append-then-delete. Cards are different: `okto_pulse_update_card_knowledge` lets agents revise an entry in place — useful for evolving implementation notes captured during a card's lifetime.

```text theme={null}
Input to okto_pulse_update_card_knowledge:
  board_id: "brd_abc123"
  card_id:  "card_001"
  knowledge_id: "kb_d4f3a1b2c0"
  title:    "Implementation notes — payment retry"
  content:  "Decided to use exponential backoff with jitter (3, 6, 12s) ..."

Output:
{
  "success": true,
  "knowledge": { "id": "kb_d4f3a1b2c0", "title": "...", "content": "..." }
}
```

### Spec → card propagation

When a sprint slices a spec into cards, attach the relevant knowledge to each card so the implementer's view is self-contained. `copy_knowledge_to_card` deep-copies entries from the source spec onto `Card.knowledge_bases` with stable provenance.

```text theme={null}
Input to okto_pulse_copy_knowledge_to_card:
  board_id:      "brd_abc123"
  spec_id:       "spec_XYZ"
  card_id:       "card_001"
  knowledge_ids: ["kb_001", "kb_004"]

Output:
{
  "success":       true,
  "copied":        2,
  "knowledge_ids": ["cardkb_kb_001", "cardkb_kb_004"],
  "total_on_card": 2
}
```

The `source` field of each copied KE is set to `copied_from_spec:<spec_id>:<kb_id>` so traceability is preserved through the lineage. Re-running the copy is idempotent — entries already attached (matched on `id` or `source`) are skipped.

`knowledge_ids` accepts a native list (preferred), a JSON array string, or pipe-separated values. **Comma-only strings are rejected** — see `okto_pulse.core.mcp.helpers.coerce_to_list_str`.

***

## File attachments

Three tools, all card-scoped (`server.py:3166–3317`).

| Tool                           | Line | Purpose                                                                                      |
| ------------------------------ | ---- | -------------------------------------------------------------------------------------------- |
| `okto_pulse_upload_attachment` | 3166 | Upload a file to a card. Provide exactly one of `content_base64` / `file_path` / `file_url`. |
| `okto_pulse_list_attachments`  | 3239 | List all attachments on a card with id, filename, mime\_type, size, uploader, timestamp.     |
| `okto_pulse_delete_attachment` | 3283 | Delete an attachment by ID.                                                                  |

### Three loaders, same trade-offs as knowledge

| Field            | When to use                                                         | Token cost in agent context         |
| ---------------- | ------------------------------------------------------------------- | ----------------------------------- |
| `content_base64` | Small files (≤ a few hundred KB) the agent already holds in memory. | Full base64 in the request — heavy. |
| `file_path`      | Binary on the MCP server host filesystem.                           | Path string only.                   |
| `file_url`       | HTTP(S)-reachable file.                                             | URL string only.                    |

```text theme={null}
Input to okto_pulse_upload_attachment:
  board_id:  "brd_abc123"
  card_id:   "card_001"
  filename:  "checkout-flow-pdf.pdf"
  mime_type: "application/pdf"
  file_path: "/tmp/checkout-flow-pdf.pdf"

Output:
{
  "success": true,
  "attachment": {
    "id":        "att_7f3a91b4c0d2",
    "filename":  "checkout-flow-pdf.pdf",
    "mime_type": "application/pdf",
    "size":      482301
  }
}
```

`okto_pulse_list_attachments` is read-only (`Permissions.BOARD_READ`); both `upload` and `delete` require their own scoped permissions. A blocked agent gets `FORBIDDEN` — adjust the preset in **Board → Agents → Edit**.

```text theme={null}
Input to okto_pulse_list_attachments:
  board_id: "brd_abc123"
  card_id:  "card_001"

Output:
[
  {
    "id":          "att_7f3a91b4c0d2",
    "filename":    "checkout-flow-pdf.pdf",
    "mime_type":   "application/pdf",
    "size":        482301,
    "uploaded_by": "agent_design",
    "created_at":  "2026-05-07T18:42:11+00:00"
  }
]
```

***

## Permissions summary

| Action                                               | Permission flag                                      |
| ---------------------------------------------------- | ---------------------------------------------------- |
| Add / delete knowledge on ideation, refinement, spec | `Permissions.SPECS_UPDATE`                           |
| Add / update / delete knowledge on card              | `Permissions.CARDS_UPDATE`                           |
| List / get knowledge (any parent)                    | `Permissions.BOARD_READ`                             |
| Upload attachment                                    | `Permissions.ATTACHMENTS_UPLOAD`                     |
| Delete attachment                                    | `Permissions.ATTACHMENTS_DELETE`                     |
| List attachments                                     | `Permissions.BOARD_READ`                             |
| Copy knowledge spec → card                           | `Permissions.CARDS_UPDATE` (the destination governs) |

See [Permissions](/concepts/pipeline) for the registry and presets.

***

## Errors

Standard MCP error envelope. Codes that hit this domain:

| Code               | Most common cause                                                                                                                                                                    |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `VALIDATION_ERROR` | Empty `title` or `content` on add; multiple loaders supplied; invalid `file_path` (not absolute, not UTF-8, doesn't exist on the MCP host); `file_url` returned non-text or non-200. |
| `NOT_FOUND`        | Parent entity (ideation/refinement/spec/card) belongs to a different board, or the knowledge/attachment ID does not exist.                                                           |
| `FORBIDDEN`        | Agent's preset does not allow the permission named in the table above.                                                                                                               |
| `RATE_LIMITED`     | `file_url` fetches share the host-side HTTP client's rate budget — back off and retry.                                                                                               |

```json theme={null}
{
  "error": "VALIDATION_ERROR",
  "message": "Provide exactly one of content, file_path, or file_url.",
  "detail": {}
}
```

***

## Next steps

<CardGroup cols={2}>
  <Card title="Architecture & mockups" href="/reference/mcp/architecture-mockups">
    Visual design artifacts — entities, interfaces, diagrams, screen mockups.
  </Card>

  <Card title="Comments & questions" href="/reference/mcp/comments-questions">
    Free-text comments, choice questions, and Q\&A across every entity type.
  </Card>

  <Card title="MCP reference index" href="/reference/mcp">
    All 216 tools across 8 domains.
  </Card>

  <Card title="ADLC pipeline" href="/concepts/sdlc-flow">
    Where knowledge and attachments flow through the pipeline.
  </Card>
</CardGroup>
