Skip to main content

roamresearch-client-py

Roam Research client. Programmable. CLI. SDK. MCP.

For developers who automate. For LLMs that need graph access. Smart diff keeps UIDs intact. References survive. Minimal API calls.

Install

pip install roamresearch-client-py

# standalone
uv tool install roamresearch-client-py

Setup

export ROAM_API_TOKEN="your-token"
export ROAM_API_GRAPH="your-graph"

Or rr init creates ~/.config/roamresearch-client-py/config.toml:

[roam]
api_token = "your-token"
api_graph = "your-graph"

[mcp]
host = "127.0.0.1"
port = 9000
topic_node = ""

[batch]
size = 100
max_retries = 3

[logging]
level = "WARNING"
httpx_level = "WARNING"

Env vars take precedence.

CLI

Get

rr get "Page Title"
rr get "((block-uid))"
rr get "Page Title" --debug

Search

rr search "keyword"
rr search "term1" "term2"
rr search "term" --tag "#TODO"
rr search --tag "[[Project]]"
rr search "term" --page "Page" -i -n 50

Save

Create or update. Preserves UIDs.

rr save -t "Page" -f content.md
echo "# Hello" | rr save -t "Page"

Refs

rr refs "Page Title"
rr refs "block-uid"

Todos

rr todos
rr todos --done
rr todos --page "Work" -n 100

Query

rr q '[:find ?title :where [?e :node/title ?title]]'
rr q '[:find ?t :in $ ?p :where ...]' --args "Page"

MCP

rr mcp
rr mcp --port 9100
rr mcp --token <T> --graph <G>

Endpoints (default host 127.0.0.1, port 9000):

  • Streamable HTTP: http://127.0.0.1:9000/mcp
  • SSE:
    • Event stream: http://127.0.0.1:9000/sse
    • Client messages: http://127.0.0.1:9000/messages

Optional OAuth 2.0 (config-only; no users/DB):

  • Protected Resource Metadata (RFC 9728):
    • http://127.0.0.1:9000/.well-known/oauth-protected-resource
    • http://127.0.0.1:9000/.well-known/oauth-protected-resource/mcp
    • http://127.0.0.1:9000/mcp/.well-known/oauth-protected-resource
  • Authorization Server Metadata (RFC 8414):
    • http://127.0.0.1:9000/.well-known/oauth-authorization-server
    • http://127.0.0.1:9000/.well-known/oauth-authorization-server/mcp
    • http://127.0.0.1:9000/mcp/.well-known/oauth-authorization-server
  • Token endpoint: http://127.0.0.1:9000/oauth/token
  • Authorization endpoint (for authorization_code + PKCE): http://127.0.0.1:9000/authorize

Enable in ~/.config/roamresearch-client-py/config.toml:

[oauth]
enabled = true
require_auth = true
allow_access_token_query = false
signing_secret = "change-me-long-random"

[[oauth.clients]]
id = "claude"
secret = ""  # empty for public client (authorization_code + PKCE)
scopes = ["mcp"]
redirect_uris = ["https://claude.ai/api/mcp/auth_callback"]

Notes:

  • Disable/skip OAuth: set [oauth].enabled = false (default). No oauth.clients needed.
  • oauth.clients is a static allowlist of OAuth2 clients; secret is required for client_credentials and optional for authorization_code (PKCE public clients).
  • Multiple clients are supported by adding multiple [[oauth.clients]] sections.

Browser CORS / preflight:

  • Some browser MCP clients will send OPTIONS /sse preflight requests. Configure allowed origins via:
    • mcp.cors_allow_origins (comma-separated) or mcp.cors_allow_origin_regex
    • mcp.cors_auto_allow_origin_from_host = true (default) allows same-origin requests based on the request Host (recommended when behind nginx that sets Host/X-Forwarded-Proto).

SDK

Connect

from roamresearch_client_py import RoamClient

async with RoamClient() as client:
    pass

async with RoamClient(api_token="...", graph="...") as client:
    pass

Write

async with client.create_block("Root") as blk:
    blk.write("Child 1")
    blk.write("Child 2")
    with blk:
        blk.write("Grandchild")
    blk.write("Child 3")

Read

page = await client.get_page_by_title("Page")
block = await client.get_block_by_uid("uid")
daily = await client.get_daily_page()

Search

results = await client.search_blocks(["python", "async"], limit=50)
todos = await client.search_by_tag("#TODO", limit=50)
refs = await client.find_references("block-uid")
refs = await client.find_page_references("Page Title")
todos = await client.search_todos(status="TODO", page_title="Work")

Update

await client.update_block_text("uid", "New text")

result = await client.update_page_markdown("Page", "## New\n- Item", dry_run=False)
# result['stats'] = {'creates': 0, 'updates': 2, 'moves': 0, 'deletes': 0}
# result['preserved_uids'] = ['uid1', 'uid2']

Query

result = await client.q('[:find ?title :where [?e :node/title ?title]]')

Batch

Atomic operations.

from roamresearch_client_py.client import (
    create_page, create_block, update_block, remove_block, move_block
)

actions = [
    create_page("New Page"),
    create_block("Text", parent_uid="page-uid"),
    update_block("uid", "Updated"),
    move_block("uid", parent_uid="new-parent", order=0),
    remove_block("old-uid"),
]
await client.batch_actions(actions)

MCP Tools

Tool Description
save_markdown Create/update page
get Fetch as markdown
search Text + tag search
query Raw Datalog
find_references Block/page refs
search_todos TODO/DONE items
update_markdown Smart diff update
{"title": "Notes", "markdown": "## Topic\n- Point"}
{"terms": ["python"], "tag": "TODO", "limit": 20}
{"identifier": "Page", "markdown": "## New", "dry_run": true}

Internals

Smart Diff — Match by content. Preserve UIDs. Detect moves. Minimize calls.

Markdown ↔ Roam — Bidirectional. Headings, lists, tables, code, inline.

Task Queue — SQLite. Background. Retry. JSONL logs.

Requirements

  • Python 3.10+
  • Roam API token

License

MIT

Metadata

Release files for roamresearch-client-py 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for roamresearch-client-py 0.4.1
File Size Uploaded
roamresearch_client_py-0.4.1.tar.gz 47.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for roamresearch-client-py 0.4.1
File Interpreter ABI Platform
roamresearch_client_py-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 98.3 kB

Release files / roamresearch_client_py-0.4.1.tar.gz

Download URL roamresearch_client_py-0.4.1.tar.gz
Size 47.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8d718141f988749318e250467fea5a02f65410888dd6e43ee41ba4a2dbf73e27
BLAKE2b-256 checksum
How to use checksums
284585d768dca113101113ea3f82b6029e419752d46e5dd677a190d2cc9a11d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 6, 2026.

Transparency log

Release files / roamresearch_client_py-0.4.1-py3-none-any.whl

Download URL roamresearch_client_py-0.4.1-py3-none-any.whl
Size 51.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
98739295d2d2b671d3190f6d467e098bc816843ca98c8154bff08092c5548de8
BLAKE2b-256 checksum
How to use checksums
61db0af8729e2cd9b3677af7618c25f991e246a669df1ebccb66eada39b767e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page