# MCP Tools Reference

Complete reference for all RemNote MCP tools available through the server.

## Overview

The RemNote MCP Server exposes tools that allow AI agents to interact with your RemNote knowledge base. Tools are
automatically available in any connected MCP client.

Tools with an `outputSchema` return machine-readable data in MCP `structuredContent` and also include the serialized
JSON in a top-level `content` text block for compatibility with older clients and transcripts. This follows the
[MCP tools specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools).

## Tool Summary

| Tool | Description | Use Case |
|------|-------------|----------|
| `remnote_create_note` | Create new notes or flashcards | Adding new knowledge, ideas, references, or flashcards. Supports hierarchical markdown, flashcard syntax, and exact tag Rem IDs. |
| `remnote_search` | Search knowledge base | Finding existing notes, exploring topics |
| `remnote_search_by_tag` | Search by exact tag Rem ID | Finding ancestor context for tagged notes |
| `remnote_read_note` | Read note content | Retrieving details, reading hierarchies |
| `remnote_list_children` | List direct child Rems | Cheap branch traversal without subtree rendering |
| `remnote_update_note` | Update note metadata | Renaming |
| `remnote_move_note` | Move a Rem safely | Dry-run-first hierarchy reorganization |
| `remnote_insert_children` | Insert child Rems | Ordered hierarchy maintenance, tag descriptions |
| `remnote_replace_children` | Replace direct child Rems | Explicitly approved destructive rewrites |
| `remnote_update_tags` | Mutate tags by exact Rem ID | Production tagging workflows |
| `remnote_append_journal` | Add to daily document | Journaling, logging, daily notes, optional exact tag Rem IDs |
| `remnote_read_table` | Read Advanced Tables | Fetching tabular rows, schema metadata, and filtered columns |
| `remnote_get_playbook` | Get operating playbook | Session preflight, traversal defaults, write safety guidance |
| `remnote_status` | Check connection health | Verifying setup, debugging |

## remnote_create_note

Create a new note/flashcard in RemNote with optional parent hierarchy and exact tag Rem IDs.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | string | No | The title of the note (optional if content is provided) |
| `content` | string | No | Child content as bullet points or hierarchical markdown |
| `parentId` | string | No | Parent Rem ID to nest this note under |
| `tagRemIds` | string[] | No | Exact tag Rem IDs to apply |

### Usage

**Create a simple note:**
```
Create a RemNote note titled "Project Ideas"
```

**Create with content:**
```
Create a note "Shopping List" with content:
- Milk
- Bread
- Eggs
```

**Create under a parent:**
```
Create a note "Chapter 1" under the note with ID abc123
```

**Create with tag Rem IDs:**
```
Create a note "Important Meeting" with tagRemIds ["workTagRemId", "urgentTagRemId"]
```

**Create a flashcard:**
```
Create a Concept card titled "Photosynthesis" with content "Photosynthesis :: Process by which plants make food"
```

**Create from an outline or hierarchical note:**
```
Create a markdown tree:
- Programming Languages
  - Python
  - JavaScript
    - React
    - Node
- Databases
```

**Create flashcards via markdown:**
Since this uses RemNote's native markdown parser, you can create flashcards inline using `::` for Concept cards and `;;` for Descriptor cards. This function fully supports RemNote's markdown-based flashcard creation.

For example, if you want to batch create flashcards, you can use the following format:

```
Create a markdown tree of biology terms, titled as "Energy Flow in Biology":
- Photosynthesis :: Process by which plants make food
- Cellular Respiration
  - Definition ;; The process of breaking down glucose for energy
```

For more usage, refer to https://help.remnote.com/en/articles/9252072-how-to-import-flashcards-from-text#h_fc1588b3b7

Returns an array of remIds containing the title (if provided) and each generated markdown line:

```json
{
  "remIds": ["abc123xyz", "def456xyz"],
  "titles": ["Project Ideas", "Child 1"]
}
```

### Tips

- Use descriptive titles for better searchability
- Structure content with bullets (`-` or `•`) for RemNote hierarchy
- Use `parentId` to organize notes within existing hierarchies
- Use `tagRemIds` for production tagging workflows. Create or resolve the tag Rem first, then pass its exact Rem ID.
- Flashcards are created via markdown syntax in `content`, not separate create-note fields
- Tag Rem IDs apply to the created root Rem when `title` is provided, or to top-level created Rems when `title` is omitted


## remnote_search

Search your RemNote knowledge base with full-text search.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Search query text |
| `limit` | number | No | Maximum results to return (1-150, default: 50) |
| `cursor` | string | No | Opaque cursor from a previous `remnote_search` response |
| `contentMode` | string | No | Content mode: `none` (default), `markdown`, or `structured` |
| `view` | string | No | Output detail level: `compact`, `standard` (default), or `full` |
| `ancestorDepth` | number | No | Number of parent Rems to include, direct parent first |
| `depth` | number | No | Max child depth for rendered content (0-10, default: 1) |

### Usage

**Basic search:**
```
Search my RemNote for "machine learning"
```

**Search with more results:**
```
Search for "project management" and show up to 50 results
```

**Continue a paged search:**
```
Search again with the nextCursor from the previous remnote_search response
```

**Search with content:**
```
Search for "AI ethics" and include the note content
```

### Response

Returns matching notes plus paging metadata:

```json
{
  "results": [
    {
      "remId": "abc123",
      "title": "Machine Learning Basics and [[Neural Networks]]",
      "headline": "Machine Learning Basics and [[Neural Networks]]",
      "inlineRefs": [
        { "text": "Neural Networks", "targetRemId": "neuralNetworksRemId789", "kind": "rem" }
      ],
      "parentRemId": "parent987",
      "parentTitle": "AI Notes",
      "tags": [
        { "tagRemId": "mlTagRemId123", "name": "ml" },
        { "tagRemId": "referenceTagRemId456", "name": "reference" }
      ],
      "remType": "document"
    },
    {
      "remId": "def456",
      "title": "Deep Learning Overview",
      "headline": "Deep Learning Overview",
      "remType": "text"
    }
  ],
  "hasMore": true,
  "nextCursor": "search:v1:...",
  "truncated": false
}
```

**With content included:**
```json
{
  "results": [
    {
      "remId": "abc123",
      "title": "Machine Learning Basics",
      "headline": "Machine Learning Basics",
      "parentRemId": "parent987",
      "parentTitle": "AI Notes",
      "tags": [
        { "tagRemId": "mlTagRemId123", "name": "ml" },
        { "tagRemId": "referenceTagRemId456", "name": "reference" }
      ],
      "remType": "document",
      "content": "- Supervised learning\n- Unsupervised learning\n"
    }
  ]
}
```

### Tips

- Use specific terms for better results
- Increase `limit` for comprehensive searches
- Use `contentMode: "none"` (default) for faster searches when you only need titles
- Use `contentMode: "markdown"` when you need rendered child context
- Use `contentMode: "structured"` when you need nested child `remId`s for follow-up reads/navigation
- Use `nextCursor` while `hasMore` is true to continue a stable ordered search snapshot.
- Use `inlineRefs` when rendered titles/headlines contain `[[...]]` references and you need exact graph targets.
- For whole-KB orientation, start with `contentMode: "structured"`, `view: "compact"`, `depth: 1`, `childLimit: 500`
- Use `parentRemId` and `parentTitle` to show the direct parent.
- Use `ancestorDepth` when you need nearby hierarchy context. `ancestors` is parent-first and may include
  `ancestorsTruncated`.
- `tags` is optional and present when the matched Rem has readable tag identity metadata. Each tag includes
  `tagRemId` and `name`.

## remnote_search_by_tag

Search by exact tag Rem ID. By default, returns resolved ancestor context targets and exposes direct matched Rems.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `tagRemId` | string | Yes | Exact tag Rem ID to search |
| `resultMode` | string | No | `context` (default) returns resolved context targets with `matchedRems`; `tagged` returns direct tagged Rems with context metadata |
| `limit` | number | No | Maximum results to return (1-150, default: 50) |
| `cursor` | string | No | Opaque cursor from a previous `remnote_search_by_tag` response |
| `timeoutMs` | number | No | Per-call bridge wait timeout in milliseconds (1-60000, default: 15000); does not cancel plugin-side work |
| `contentMode` | string | No | Content mode: `none` (default), `markdown`, or `structured` |
| `view` | string | No | Output detail level: `compact`, `standard` (default), or `full` |
| `ancestorDepth` | number | No | Number of parent Rems to include on results and `matchedRems`, direct parent first |
| `depth` | number | No | Max child depth for rendered content (0-10, default: 1) |

### Behavior

- For each tagged match, the bridge resolves the returned target to:
  1) nearest ancestor document/daily document,
  2) otherwise nearest non-document ancestor,
  3) otherwise the tagged note itself.
- `resultMode: "context"` preserves the navigation workflow and includes `matchedRems` for direct tag verification.
- `resultMode: "tagged"` returns the directly tagged Rems as top-level results and includes `contextRemId`,
  `contextTitle`, and `contextReason`.
- Tag names, `#name` inputs, and aliases are intentionally not resolved. Use the exact tag Rem ID to avoid ambiguity
  from duplicate names, renamed tags, or aliases.
- If `tagRemId` is valid input but does not resolve to a Rem, results are empty.
- Top-level output fields, content rendering, and cursor paging metadata are aligned with `remnote_search`.
- `cursor` is bound to `tagRemId` and `resultMode`; `context` and `tagged` cursors are not interchangeable.

### Usage

**Find notes by exact tag Rem ID:**
```text
Search by tagRemId "dailyTagRemId123"
```

**Find tagged results with content:**
```text
Search by tagRemId "projectReviewTagRemId123" and include structured content
```

## remnote_read_note

Read a specific note by its Rem ID, including child content.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `remId` | string | Yes | The Rem ID to read |
| `depth` | number | No | Depth of children to include in rendered content (0-10, default: 5) |
| `contentMode` | string | No | Content mode: `markdown` (default), `structured`, or `none` |
| `view` | string | No | Output detail level: `compact`, `standard` (default), or `full` |
| `ancestorDepth` | number | No | Number of parent Rems to include, direct parent first |

### Usage

**Read a note:**
```
Read the RemNote note with ID abc123
```

**Read with more depth:**
```
Read note def456 with depth 5 to include more nested children
```

**Read top-level only:**
```
Read note xyz789 with depth 0 (no children)
```

### Response

Returns note metadata plus optional rendered child content:

```json
{
  "remId": "abc123",
  "title": "Project Overview for [[Launch Plan]]",
  "headline": "Project Overview for [[Launch Plan]]",
  "inlineRefs": [
    { "text": "Launch Plan", "targetRemId": "launchPlanRemId789", "kind": "rem" }
  ],
  "parentRemId": "folder001",
  "parentTitle": "Work Projects",
  "tags": [
    { "tagRemId": "workTagRemId123", "name": "work" },
    { "tagRemId": "activeTagRemId456", "name": "active" }
  ],
  "remType": "document",
  "content": "- Goals\n  - Improve performance\n- Timeline\n",
  "contentProperties": {
    "childrenRendered": 3,
    "childrenTotal": 3,
    "contentTruncated": false
  }
}
```

In `contentMode: "structured"` mode, the response includes `contentStructured` (nested child nodes with `remId`s)
instead of markdown `content`.

### Tips

- Use `depth: 0` for just the note title (no children)
- Use `contentMode: "none"` when you only need metadata and parent context.
- Use `contentMode: "structured"` when you need nested child `remId`s for deterministic follow-up navigation.
- Use `inlineRefs` to follow inline Rem references without parsing `[[...]]` markdown text.
- `tags` is optional and present when the returned Rem has readable tag identity metadata. Each tag includes
  `tagRemId` and `name`.
- Start traversal with `contentMode: "structured"`, `depth: 1`, `childLimit: 500`, then deepen selected branches.
- Use `depth: 1-3` for common hierarchies
- Use `depth: 4-10` for deep nested structures
- Higher depth may be slower for large hierarchies

## remnote_update_note

Update note metadata. This tool is intentionally limited to title changes.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `remId` | string | Yes | The Rem ID to update |
| `title` | string | Yes | New title for the note |

**Notes:**

- Use `remnote_insert_children` for ordered child creation.
- Use `remnote_replace_children` for explicitly approved direct-child replacement.
- Use `remnote_update_tags` for exact-ID tag mutation.
- Use `remnote_move_note` for dry-run-first hierarchy reparenting.

### Usage

**Rename a note:**
```
Rename note abc123 to "Updated Project Name"
```

## remnote_list_children

List direct children under a parent without rendering a whole subtree. Use this for cheap hierarchy traversal before
deepening selected branches with `remnote_read_note`.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `parentRemId` | string | Yes | Parent Rem ID |
| `limit` | number | No | Maximum direct children (1-150, default: 50) |
| `cursor` | string | No | Opaque cursor from a previous page |
| `view` | string | No | `compact` (default), `standard`, or `full` |
| `ancestorDepth` | number | No | Number of parent Rems to include for each child, direct parent first |

## remnote_move_note

Move an existing Rem and its whole subtree under a new parent. The tool defaults to `dryRun: true`; rerun with
`dryRun: false` only after the proposed move is approved. Pass `expectedOldParentRemId` when the move was proposed from
a previous read so stale hierarchy context is rejected.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `remId` | string | Yes | Rem ID to move |
| `newParentRemId` | string | Yes | New parent Rem ID |
| `position` | `"first" \| "last" \| "before" \| "after"` | No | Placement under the new parent (default: `last`) |
| `siblingRemId` | string | For `before`/`after` | Sibling Rem ID used for relative placement |
| `dryRun` | boolean | No | Preview only by default |
| `expectedOldParentRemId` | string | No | Reject if the current direct parent differs |
| `ancestorDepth` | number | No | Number of parent Rems to include before/after the move |

## remnote_insert_children

Insert new child Rems under a parent without replacing existing children.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `parentRemId` | string | Yes | Parent Rem ID |
| `content` | string | Yes | Markdown content to insert as child Rems |
| `position` | `"first" \| "last" \| "before" \| "after"` | Yes | Insert position |
| `siblingRemId` | string | For `before`/`after` | Sibling Rem ID to insert before or after |

Use this for tag description nodes, for example:

```
Insert under tag cEZH8DJYED3RQIB7k at first:
description: Use for Codex app/CLI/skills/ExecPlans notes.
```

## remnote_replace_children

Replace all direct children under a parent Rem. This is destructive because existing child Rem IDs are removed.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `parentRemId` | string | Yes | Parent Rem ID whose direct children will be replaced |
| `content` | string | Yes | Markdown replacement content; empty string clears direct children |

Bridge policy can reject this tool when `acceptReplaceOperation=false`.

## remnote_update_tags

Add or remove tags using exact tag Rem IDs.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `remId` | string | Yes | Rem ID whose tags should change |
| `addTagRemIds` | string[] | No | Exact tag Rem IDs to add |
| `removeTagRemIds` | string[] | No | Exact tag Rem IDs to remove |

Use this for production tagging workflows. Name-based tag mutation is intentionally absent from the write tool surface
because same-name Rems can exist in different branches.

## remnote_append_journal

Append content to today's daily document in RemNote with optional exact tag Rem IDs.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `content` | string | Yes | Content to append to today's daily document |
| `timestamp` | boolean | No | Include timestamp (default: true) |
| `tagRemIds` | string[] | No | Exact tag Rem IDs to apply |

### Usage

**Add journal entry:**
```
Add to my journal: "Completed the MCP integration today"
```

**Add without timestamp:**
```
Add to my journal without timestamp: "Project milestone reached"
```

**Add with tag Rem IDs:**
```
Add to my journal with tagRemIds ["dailyLogTagRemId"]: "Completed the MCP integration today"
```

### Response

Returns confirmation:

```json
{
  "success": true,
  "date": "2024-01-15",
  "timestamp": "10:30:45",
  "content": "Completed the MCP integration today"
}
```

### Tips

- Entries are added to today's daily document (created automatically if it doesn't exist)
- Use `timestamp: true` (default) for timestamped entries
- Use `timestamp: false` for plain entries
- Great for logging daily activities, thoughts, or progress notes

## remnote_read_table

Read an Advanced Table by exact title or Rem ID and return structured column and row data.

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `tableTitle` | string | Conditionally | Exact Advanced Table title |
| `tableRemId` | string | Conditionally | Table Rem ID |
| `limit` | number | No | Maximum rows to return (1-150, default: 50) |
| `offset` | number | No | Zero-based row offset for pagination (default: 0) |
| `propertyFilter` | string[] | No | Only include these property/column names |

Provide exactly one of `tableTitle` or `tableRemId`.

### Usage

**Read a table by name:**
```
Read the RemNote table "Projects"
```

**Read a table by Rem ID:**
```
Use remnote_read_table with tableRemId "abc123def"
```

**Limit rows for a large table:**
```
Read the first 10 rows from table "Projects"
```

**Filter to selected columns:**
```
Read table "Projects" but only return the columns "Status" and "Owner"
```

Returns the table identity, column schema, row values keyed by `propertyId`, and pagination metadata:

```json
{
  "tableId": "abc123def",
  "tableName": "Projects",
  "columns": [
    { "propertyId": "prop1", "name": "Status", "type": "single_select" }
  ],
  "rows": [
    {
      "remId": "row1",
      "name": "Project Alpha",
      "values": { "prop1": "In Progress" }
    }
  ],
  "totalRows": 12,
  "rowsReturned": 1
}
```

### Tips

- Prefer table Rem IDs when you need deterministic lookup across renamed tables.
- Use `propertyFilter` to reduce payload size for wide tables.
- Use `limit` and `offset` together for incremental reads of large tables.

## remnote_get_playbook

Return a compact operational playbook for MCP agents.

Use this tool when an agent needs built-in guidance for:

- status-first session preflight recommendations,
- hierarchy traversal presets for whole-KB navigation,
- tag navigation vs strict direct-tag verification guidance,
- `markdown` vs `structured` content-mode decisions,
- write/replace safety checks.

### Parameters

None.

### Usage

```text
Get the RemNote MCP playbook
```

Or:

```text
Call remnote_get_playbook and follow its navigation defaults
```

### Response

Returns a structured playbook object, including:

- `decisionTree` - short natural-language operating decisions.
- `navigationPresets.orientation` - recommended traversal defaults (`structured`, `depth: 1`, `childLimit: 500`).
- `contentModes` - when to use `structured` vs `markdown` vs `none`.
- Search paging guidance - continue `remnote_search` / `remnote_search_by_tag` with `nextCursor` while `hasMore` is
  true.
- `remnote_search_by_tag` guidance - when to use default context results, `matchedRems`, `resultMode: "tagged"`, or a
  bounded `timeoutMs` fallback.
- `writePolicy` - how to interpret `acceptWriteOperations` / `acceptReplaceOperation` and exact-ID tag writes.
- `currentStatus` - live `remnote_status` snapshot when available.

### Tips

- Treat this as guidance, not rigid policy.
- Use the playbook's write guidance to choose between metadata updates, ordered child insertion, destructive replacement,
  and exact-ID tag writes without overloading `remnote_update_note`.
- Call `remnote_status` once per session (recommended) and before high-risk writes.
- For whole-KB orientation, start shallow and ID-first:
  - `structured` mode, `depth: 1`, `childLimit: 500`.

## remnote_status

Check connection status, compatibility warnings, and write-policy capabilities.

### Parameters

None.

### Usage

```
Check the RemNote connection status
```

Or:
```
Use remnote_status to verify the bridge is working
```

### Response

Returns connection health and policy capabilities:

```json
{
  "connected": true,
  "serverVersion": "0.8.0",
  "pluginVersion": "0.3.2",
  "acceptWriteOperations": true,
  "acceptReplaceOperation": false,
  "statistics": {
    "requestsSent": 142,
    "responsesReceived": 141,
    "errors": 1,
    "uptime": "2h 34m"
  }
}
```

**If disconnected:**
```json
{
  "connected": false,
  "error": "RemNote plugin not connected"
}
```

### Tips

- Use this to verify your setup after installation
- Call once per session before normal operations (recommended)
- Check after configuration changes
- Check before write operations when safety/capability matters
- Useful for debugging connection and compatibility issues
- See [Troubleshooting Guide](troubleshooting.md) if status shows disconnected

## Conversational Usage

AI agents automatically select the appropriate tool based on natural language commands. You don't need to specify tool
names.

### Examples

**Natural command → Tool used**

| User says | AI uses |
|-----------|---------|
| "Create a note about X" | `remnote_create_note` |
| "Search for Y" | `remnote_search` |
| "Show me note abc123" | `remnote_read_note` |
| "Add Z to note def456" | `remnote_insert_children` |
| "Log today's progress" | `remnote_append_journal` |
| "How should I navigate this KB?" | `remnote_get_playbook` |
| "Is RemNote connected?" | `remnote_status` |

### Complex Workflows

AI agents can chain multiple tools:

**"Find my project management notes and create a summary"**

1. `remnote_search` - Search for "project management"
2. `remnote_read_note` - Read each result
3. `remnote_create_note` - Create summary note

**"Update my tasks note with today's completed items"**

1. `remnote_search` - Find "tasks" note
2. `remnote_read_note` - Read current tasks
3. `remnote_insert_children` - Insert completed items

## Error Handling

### Common Errors

**Note not found:**
```json
{
  "error": "Note with ID abc123 not found"
}
```

**Invalid parameters:**
```json
{
  "error": "Parameter 'limit' must be between 1 and 100"
}
```

**Connection error:**
```json
{
  "error": "RemNote plugin not connected"
}
```

### Troubleshooting

- **Note not found:** Verify the Rem ID is correct (use search to find it)
- **Invalid parameters:** Check parameter types and ranges
- **Connection errors:** See [Troubleshooting Guide](troubleshooting.md#plugin-wont-connect)
- **Timeout errors:** Check RemNote app is running and plugin is connected

## Best Practices

### Creating Notes

- Use descriptive titles for better searchability
- Structure content hierarchically with bullet points
- Use `tagRemIds` for exact tag assignment; name-based tag mutation is intentionally avoided in production writes
- Set parent relationships to maintain organization

### Searching

- Start with broad searches, then refine
- Use `contentMode: "none"` for title-only searches (faster)
- Use `contentMode: "markdown"` or `"structured"` when you need content analysis
- Increase `limit` for comprehensive searches

### Reading Notes

- Use appropriate `depth` based on hierarchy complexity
- Lower depths are faster for shallow structures
- Higher depths capture more context for nested content

### Updating Notes

- Use descriptive titles after renaming
- Use `remnote_update_tags` with exact tag Rem IDs for tag changes
- Use `remnote_insert_children` for additive content and `remnote_replace_children` only when destructive replacement is explicitly intended

### Journaling

- Use timestamps for time-tracking
- Use plain entries for topic-based organization
- Log regularly for better knowledge capture

## Related Documentation

- [Configuration Guide](configuration.md) - Set up MCP clients
- [Installation Guide](installation.md) - Install the server
- [Troubleshooting](troubleshooting.md) - Common issues
- [Demo](../demo.md) - See tools in action

## Need Help?

- [GitHub Issues](https://github.com/robert7/remnote-mcp-server/issues) - Report bugs or ask questions
