Read Tools

All 11 read tools are available to every token regardless of scope.


prepare_context

Build a task-specific context pack before multi-page product or coding work. Context Pack v2 runs BM25 retrieval across titles and bodies, combines native OKF-aligned metadata and the page link graph, prefers exact-revision human reviews, and penalizes stale/deprecated knowledge. Matching is case- and accent-insensitive ("Çözüm" = "cozum") but lexical: pass keywords for synonyms and for a workspace written in another language than the task. See Keywords.

Parameter Type Required Default Description
task string ✓ Concrete task or question
keywords string[] Extra search terms, up to 24 × 60 characters: synonyms, and the workspace's own language when the task is written in another (English terms for a Turkish task). Ranked at half the weight of the task's own words
maxTokens number 2000 Approximate response budget (1000–16000)
maxConcepts number 6 Maximum concepts (1–16)
trustPolicy string prefer-human-reviewed any, prefer-human-reviewed, or human-reviewed-only
includeRelated boolean true Include title/ID graph neighbors of the top concepts for targeted follow-up

Returns — a remnus-context-pack-v2 JSON object with selected concept bodies, OKF-aligned type/status/trust/freshness metadata, per-concept selectionReason, truncation and token estimates, link-neighbor references, warnings, plus a short-lived contextRunId. The link-neighbor references (related, up to 6, titles and IDs only) come from the three best concepts' links, backlinks, parents and children — a page two of them point at comes first — and their room is set aside before the bodies are sized, so they fit inside maxTokens instead of being dropped when the bodies fill it. When most of the task's words appear nowhere in the workspace and no keyword matched, a warning names those words so the agent can call again with keywords. Concept content is explicitly labeled untrusted reference data and cannot override user/system instructions.

human-reviewed means an authenticated Remnus user reviewed the exact current title/body hash. An imported OKF human:* assertion is labeled external-human-asserted; it is never promoted to a local review merely because the file says so.

The contextRunId belongs to the current agent and workspace and expires after 30 minutes. Pass it to related write tools. Smart mode treats this as the recommended context-first flow; Strict mode rejects Remnus mutations without it. See Context-first MCP.

The budget applies to the compact JSON text returned by the tool. If a page cannot fit, its body is collapsed to an outline plus opening excerpt; if the pack still cannot fit, lower-ranked concepts are omitted and truncated becomes true.


search_workspace

Search the workspace by title and content. Matches standalone pages, databases, and database rows (each row is a page) on their title or body text.

Results come best match first: a full-text index ranks title matches above body matches, and each word matches by prefix (invit finds "invitation"; several words must all appear, in any order). Matching ignores case and accents: cozum finds "Çözüm Notları", istanbul finds "İstanbul Ofisi", espana finds "España". When the index finds nothing, or the query is shorter than three letters or written in a script without spaces (Chinese, Japanese, Thai), the search falls back to a plain substring match, so a fragment from the middle of a word is still found. For "what is relevant to this task", use prepare_context instead.

Parameters

Parameter Type Required Default Description
query string ✓ Words to find in item titles and content (case- and accent-insensitive)
limit number 10 Maximum results

Returns — { results: [...] }, where each result has:

Field Type Description
id string Item ID (pass to get_page)
type string page | database | database_row
title string Item title
breadcrumb string[] Location path from the workspace root to the item (for a database_row, ends with its parent database name)
matchedOn string Where the query matched: title (every word is in the title) | content
snippet string Matching content snippet (empty when the match was on the title)
databaseId string? Parent database ID, present for database_row results (pass to query_database)
parentId string? Parent item ID for nested sidebar items

list_workspace

List workspace items (pages and databases). Supports cursor-based pagination and optional parent filtering.

Parameters

Parameter Type Required Default Description
parentId string Parent item ID — omit for root items
limit number 100 Items per page
cursor string Pagination cursor from a previous nextCursor

Returns — { items: [...], hasMore: boolean, nextCursor?: string }, where each item has { id, type, title, databaseId? } plus parentId and icon when they are set (a root item simply has no parentId).

Token tip — for orientation the workspace map is cheaper and needs no pagination: read the digest resource, or the cached .remnus/workspace-map.md in a project set up with remnus init. Reach for list_workspace when you need one branch of the tree, not the shape of the whole thing.


get_page

Get the content of a workspace page, database row or dashboard. Auto-detects the type — no flags needed.

Parameters

Parameter Type Required Default Description
pageId string ✓ Workspace item ID or database row ID
mode "full" | "outline" "full" "outline" collapses the body to headings + the first line of each section — a token-cheap skim for long pages

Returns — { id, title, content, properties, type }. In outline mode the response also carries mode: "outline" and fullContentChars (the size of the full body), so you can decide whether a "full" re-fetch is worth it.

Token tip — on long pages, skim with mode: "outline" first (~80% smaller), then fetch "full" only when the outline shows the page is relevant. The workspace map prints each page's body size, so you can choose outline mode before the first read rather than after.

Dashboards — a dashboard comes back as { id, type: "dashboard", title, icon, url, spec }: its block spec as an object (not an escaped string), plus the in-app url. In outline mode spec is replaced by blocks: [{ id, type, title }] — all you need to pick ids for update_dashboard. There is no comment thread, so includeComments adds nothing. get_pages shapes dashboards the same way.


get_pages

Batch version of get_page — fetch a specific, already-known list of page/row IDs in one call, for example IDs returned by search_workspace, get_related_pages, or get_changes_since. IDs can span multiple databases or mix standalone pages with database rows.

Parameters

Parameter Type Required Default Description
pageIds string[] ✓ Page/row IDs to fetch (max 50)
mode "full" | "outline" "full" Same as get_page — applied to every fetched page

Returns — { results: [{ id, ok, page?, error? }] }. One missing or inaccessible ID does not fail the whole call — check each entry's ok field; page is present when ok is true (same shape as get_page's return value), error when it's false.

When to use this vs. query_database — if the rows you want all live in one database, query_database with filters/fields is a single query and is cheaper than N lookups. Reach for get_pages when the IDs are already known and don't share one database (or mix page/database-row types).


get_database_schema

Get the column schema and saved views of a database, without fetching rows. Use this before query_database to learn column names and IDs, or before create_database_view / update_database_view / delete_database_view to see existing view ids and config shape.

Parameters

Parameter Type Required Description
databaseId string ✓ Database ID (from list_workspace or search_workspace)

Returns — { name, schema: [{ id, name, type, options? }], views: [{ id, name, config, icon?, iconColor? }] } (views always has at least one entry — a database with no saved views implicitly has a default Table view).


query_database

Get the schema and rows of a database. Row markdown bodies are omitted by default — add "content" to fields to include them, or get_page a single row. Supports property filters, field projection, and cursor-based pagination.

Parameters

Parameter Type Required Default Description
databaseId string ✓ Database ID
limit number 50 Rows per page
filters object Filter rows by property value
fields string[] Only return these columns (matched by column id or name, case-insensitive); row titles are always included. Add "content" to include row markdown bodies — they are omitted by default, with or without a projection
cursor string Pagination cursor

Filters

Pass a JSON object where each key is a column ID and each value is the property value to match. Use get_database_schema to discover column IDs.

{
  "filters": {
    "col_abc123": "Done",
    "col_def456": ["Tag1", "Tag2"]
  }
}

Use a string for select columns and an array for multi_select columns.

Field projection

When you only need a few columns (e.g. checking statuses on a board), pass fields to cut the payload further — unrequested properties are dropped (row bodies are already omitted by default), and the returned schema is trimmed to match:

{
  "databaseId": "…",
  "fields": ["Status", "Priority"]
}

On a typical board this returns ~82% fewer tokens than a query that also pulls row bodies — and the body-free default is already ~74% of that saving on its own.

Returns — { schema, rows, hasMore, nextCursor? } (schema trimmed to the requested fields when projecting)


list_members

List all members of the workspace with their roles and join dates.

Parameters — none

Returns — array of { userId, email, name, role, joinedAt }


query_audit_log

Query the MCP agent activity audit log for the current workspace.

The log reaches back as far as the workspace owner's plan keeps it — 7 days on Free, 30 on Startup, 90 on Professional, 365 on Enterprise. An earlier from finds nothing older; upgrading the plan makes the older history visible again right away.

Parameters

Parameter Type Required Default Description
tool string Filter by tool name (e.g. "create_page")
status "success" | "error" Filter by call status
from string Start of date range — ISO 8601 (e.g. "2025-01-01T00:00:00Z")
to string End of date range — ISO 8601
limit number 50 Maximum results

Returns — array of audit log entries with tool, status, targetType, targetId, createdAt, agentName (the agent's brand id, if set), and tokenName (the token's label).


get_changes_since

Get a compact, chronological list of everything that changed in the workspace since a given time or a previous call's cursor — pages/databases edited, database rows edited, and items deleted. Built for recurring agents (a daily report, a standup summary, a memory refresh) so they can sync incrementally instead of re-reading the whole workspace on every run.

Parameters

Parameter Type Required Default Description
since string ISO 8601 timestamp — only return changes after this time. Ignored when cursor is provided
cursor string Pagination cursor from a previous response's nextCursor — takes priority over since for resuming a sync
limit number 100 Maximum changes per page

Returns — { changes: [...], hasMore: boolean, nextCursor?: string }, where each change has:

Field Type Description
id string Item ID (pass to get_page or query_database)
type string page | database | database_row
title string Item title (last known title for deleted items)
changeType string created | updated | deleted
updatedAt string When the change happened (ISO 8601) — for deleted, when the deletion happened
databaseId string? Parent database ID, present for database_row entries

nextCursor is always returned, even when hasMore is false and even when nothing changed — that is the value to keep for the next call. (It used to be present only mid-pagination, which left a one-page bootstrap with nothing to save.)

Starting from the map, not from a crawl — the digest resource and the cached .remnus/workspace-map.md both begin with a cursor: line taken before the map was built. Read the map once, then pass that cursor here: you get the delta since the map, not the tree again. Only when you have no map at all is a full bootstrap (omit both since and cursor) the right first call — every item then comes back as created.

Re-reported entries — a cursor that lands on the current second is deliberately inclusive of that second, since timestamps are second-granular and another agent may still be writing into it. An entry can therefore appear once more on the following call; dedupe by id rather than assuming exactly-once delivery.

{ "changes": [
  { "id": "…", "type": "page", "title": "Sprint Notes", "changeType": "updated", "updatedAt": "2026-07-04T09:12:00.000Z" },
  { "id": "…", "type": "database_row", "title": "Fix login bug", "changeType": "created", "updatedAt": "2026-07-04T10:03:00.000Z", "databaseId": "…" },
  { "id": "…", "type": "page", "title": "Old Draft", "changeType": "deleted", "updatedAt": "2026-07-04T11:20:00.000Z" }
], "hasMore": false, "nextCursor": "eyJ0cyI6MTc…" }

What counts as a change — a page's own content edit, a database's schema edit, a database row's title/content/property edit, or moving/renaming an item. Deletions are tracked separately as tombstones, so a deleted item still shows up here (with its last known title) even though it no longer exists.

Note on old data — a handful of rows created before this app consistently stamped timestamps may have no reliable "last changed" time; those are only ever reported once, on a full crawl (no since/cursor), and won't reappear on later incremental calls.


Get a page's knowledge-graph neighborhood in one compact call: its parent, child pages, outgoing links (pages its body references), backlinks (pages whose bodies reference it), — for database rows — sibling rows in the same database, and the repository files it rests on. Titles and IDs only, no page bodies, so orienting around a page costs a fraction of re-reading it and its neighbors; follow up with get_page on the ones that matter.

It also answers the reverse question for code: pass resource (a file or folder path) instead of pageId to get the pages whose knowledge sources cite that file — the decisions, gotchas and systems written against it. Ask it before changing a file. See By file.

The link graph is derived from page content: inline @-mention links and child blocks (both embedded sub-pages and "Link to page" references) are extracted on every save, so the graph is always current — no separate indexing step.

Parameters — pass exactly one of them.

Parameter Type Required Default Description
pageId string Page ID — a standalone page, database, or database row (same IDs get_page accepts)
resource string A repository file or folder path (src/auth.ts, src/lib/, or the absolute path your editor uses) — see By file

Returns (with pageId) — { page, parent, children, outgoingLinks, backlinks, siblings, sources? }:

Field Type Description
page object The subject — { id, title, type }
parent object? Parent item (for a database row, the database it belongs to); null at workspace root
children array Items nested under this page in the sidebar tree
outgoingLinks array Pages this page's body references (children already listed above are excluded)
backlinks array Pages whose bodies reference this page (the parent is excluded)
siblings object? { total, items: [{ id, title }] } — other rows in the same database (first 10); only for database rows, null otherwise
sources string[]? The files (or URLs) the page's knowledge metadata cites, as written — present only when there are any

Every entry in parent/children/outgoingLinks/backlinks is { id, title, type, databaseId?, linkKind? } — type is page | database | database_row, databaseId is present on database entries (pass it to query_database / get_database_schema), and linkKind says how the reference was made (page_link = inline @-mention, child_block = embedded or linked block).

{
  "page": { "id": "…", "title": "Auth Refactor Plan", "type": "page" },
  "parent": { "id": "…", "title": "Engineering", "type": "page" },
  "children": [ { "id": "…", "title": "Session Notes", "type": "page" } ],
  "outgoingLinks": [ { "id": "…", "title": "Login Bug", "type": "database_row", "linkKind": "page_link" } ],
  "backlinks": [ { "id": "…", "title": "Sprint Board", "type": "database", "databaseId": "…", "linkKind": "child_block" } ],
  "siblings": null
}

Typical use — after search_workspace or get_changes_since surfaces a page, call get_related_pages before reading bodies: it tells you what context exists around the page (specs it links to, tasks that reference it, its place in the tree) so you only get_page the neighbors you actually need.

By file (resource)

{ "resource": "src/lib/auth/session.ts" } returns the pages, databases and rows whose knowledge sources cite that path — the ones calibration labels with the repo files a concept rests on (knowledge.sources[].resource on create_page, bulk_create_pages, create_database, update_page):

{
  "resource": "src/lib/auth/session.ts",
  "pages": [
    { "id": "…", "title": "Auth decisions", "type": "page", "match": "exact", "source": "src/lib/auth/session.ts#L10-L40" },
    { "id": "…", "title": "Session gotchas", "type": "database_row", "databaseId": "…", "match": "exact", "source": "src/lib/auth/session.ts" },
    { "id": "…", "title": "Auth system", "type": "page", "match": "folder", "source": "src/lib/auth/" }
  ],
  "total": 3
}
match Means
exact The page cites this file (or folder). Line anchors (#L10-L40, :42), ./ and backslashes are ignored, and an absolute path matches by its repo-relative end — so the path your editor uses works as is
folder The page cites a folder the file is in
inside You asked about a folder, and the page cites something inside it

Closest match first, then pages before databases before rows, up to 25 (total counts all). Matching ignores case. A URL source matches only the same URL. An empty pages means no page cites the file; a note says so when no page in the workspace records sources at all — then the answer is "unknown", not "nothing written about it".

We use cookies We use analytics cookies to understand how Remnus is used and improve it. Privacy Policy