---
name: paper-ask
version: 1.1.0
description: /paper-ask, what do I know about, search my vault for, from my notes, based on my vault, ask my paper vault
allowed-tools: Read Glob Grep
---

# paper-ask

Answer a question by searching the user's `paper-*` MCP vault, reading relevant notes, and synthesizing an answer with `[[wikilink]]` citations.

This is the read-side counterpart to `paper-save`. It treats the vault as the source of truth for "what do I know" questions and refuses to hallucinate when the vault is empty on a topic.

## When to invoke

- `/paper-ask <question>`
- "what do I know about X"
- "search my vault for X"
- "from my notes, …"
- "based on my vault, …"

## Server selection

Same as `paper-save`. Pattern-match `mcp__paper-[a-z0-9-]+__`. If both personal and global are bound, default to the last-used server. Allow explicit override:

- `paper-ask global <question>` → forces global vault
- `paper-ask personal <question>` → forces personal vault

If neither was used in this session yet, default to personal.

## Three modes

| Mode | Tool budget | When to use |
|---|---|---|
| `quick` | 1× `search_notes` → return top 3 with snippets | Browsing, "what notes do I have on X" |
| `standard` (default) | 1× `search_notes` + 3-5× `read_note` → synthesize with citations | Most questions |
| `deep` | search + read + `get_backlinks` per top hit → multi-source synthesis with gap analysis | "Compare …", "Everything I know about …" |
| `exhaustive` | uncapped — explicit opt-in | User explicitly says "uncapped" or "exhaustive" |

Mode selection heuristic:
- If user prefixes with `quick `, `deep `, or `exhaustive ` → use that mode.
- Otherwise default to `standard`.

### Cross-vault deep mode (both personal and global bound)

When both servers are bound AND mode is `deep`:
- Cap total reads to **12** (≤ 6 per side).
- Cap total `get_backlinks` calls to **4**.
- Search both sides in parallel: `mcp__paper-personal__search_notes` + `mcp__paper-global__search_notes`.
- Label each citation with its source: `[[Title]] (global)` vs `[[Title]] (personal)`.

If the user wants no caps, they explicitly say "exhaustive" — no caps apply.

## Workflow

### 1. Search (no separate probe)

Do NOT probe `get_vault` first — that tool exists only on personal servers, not on the global vault (`/api/mcp/global`), so a probe breaks every global-mode query. Confirm the binding with the first real call instead: `search_notes({ query: <user question>, limit: 10 })`. A `401` on this call triggers the OAuth-refresh flow in the error matrix below.

If search returns `search_unavailable: true` (Meilisearch is down on the server side), warn the user once:

> Note: full-text search is degraded. Falling back to folder listing — results may be less precise.

Then call `list_notes({ folder: "notes" })` and use simple title-substring match.

### 2. Quick mode

Return the top 3 results with their snippets. Format:

```
- [[Title 1]] — <snippet>
- [[Title 2]] — <snippet>
- [[Title 3]] — <snippet>
```

Stop here.

### 3. Standard mode

For the top 3-5 search hits, call `read_note({ idOrPath })` and load the body + frontmatter.

Synthesize an answer (3-8 sentences) where every factual claim cites a wikilink: `[[Title of source]]`.

Format:
```
<concise synthesis with [[Title 1]] and [[Title 2]] citations>

Sources:
- [[Title 1]] (created YYYY-MM-DD)
- [[Title 2]] (created YYYY-MM-DD)
```

### 4. Deep mode

Standard mode +:
- For each of the top 3 hits, also call `get_backlinks({ noteId })` to find related notes.
- Read up to 2 additional backlinked notes per source.
- Identify contradictions across sources — flag them as `> ⚠ Contradiction: [[A]] says X, [[B]] says Y`.
- End with a "Gaps" section listing things the vault doesn't cover.

### 5. Empty-vault handling

If `search_notes` returns 0 hits AND `list_notes` for the most plausible folder is also empty:

> Your vault doesn't have any notes on this topic. I can answer from general knowledge if you want, but the answer wouldn't be grounded in your second brain. Say "use general knowledge" to proceed, or "save this answer" if you'd like me to write a starter note first.

Do NOT silently fall through to training-data answers when the user scoped the question to "my vault".

## Citation rule

Every factual claim cites the source note as a wikilink: `[[Title]]`. This is the form that resolves on paper.farzai.com via `src/lib/markdown/wikilinks.ts`.

Do not paraphrase a single source as if it were multiple. If only one note discusses the topic, the answer should cite that one note multiple times — not pretend to draw from many.

## Error matrix

| Error | Action |
|---|---|
| `401 unauthorized` | Check the `WWW-Authenticate` header. If `resource_metadata=...` is present, Claude Code handles the OAuth refresh — retry the call once. If the retry also 401s, direct the user to `/app/connections` to reconnect. |
| `429 rate_limited` | Wait, retry once. If still 429, downgrade mode (deep → standard, standard → quick). |
| `search_unavailable: true` | Warn once, fall back to `list_notes` + title-substring match. |
| `note_not_found` mid-read | Skip that result, continue with the remaining. |

## Examples

User: "/paper-ask deep what do I know about cache invalidation"

You:
1. `search_notes({ query: "cache invalidation", limit: 10 })` → 6 hits.
2. Read top 3 hits via `read_note`.
3. For each, `get_backlinks` → 2 more relevant notes read.
4. Synthesize:
   > Three approaches surface in my notes: TTL-based ([[Cache TTL strategies]]), event-driven ([[Event-sourced caching]]), and lazy ([[Lazy invalidation patterns]]). [[Event-sourced caching]] notes a contradiction with [[Cache TTL strategies]] about staleness windows — see ⚠ below.
   > ...
5. Output the synthesis + sources + gaps.

User: "what does the global vault say about MCP" (both servers bound, `paper-global` last used)

You:
1. Default server = `paper-global`.
2. `mcp__paper-global__search_notes({ query: "MCP", limit: 10 })`.
3. Mode default = standard.
4. Read top 3, synthesize, label each citation with `(global)`.
