ThreadPage
All docs

MCP server

ThreadPage’s MCP server lets an assistant find, read, add and organize a person’s notes with the access that person chooses.

View as Markdown

On this page
  1. Server
  2. Connect
  3. What the server tells assistants
  4. Tools
  5. Tools change with access
  6. What each level sees: get_access
  7. Conventions
  8. Replace a note safely
  9. Repeat a write whose answer was lost
  10. Confirmations
  11. Errors
  12. Limits
  13. Next

Server

Server
URLhttps://thread.page/mcp
TransportStreamable HTTP, stateless, JSON responses
Sign-inOAuth in the browser. ThreadPage asks the person to choose access. Every level.
TokenAuthorization: Bearer tp_… from a Script or API connection, on Add to Inbox, Add only, Read only or Read and add. Edit and organize through MCP needs OAuth (403 oauth_required).
Discovery/.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server
Clients that can sign inClaude, ChatGPT, Codex, Claude Code

Add the URL to a client. Opened in a browser, or fetched without a token, it answers 401.

Connect

Connect
ClientHow
ClaudeIn ThreadPage, Settings → Connections → Apps, choose Connect an app → Claude app, then Add to Claude. Or in Claude, Customize → Connectors, Add custom connector, and paste the URL.
ChatGPTOn the web, choose + and Add custom MCP server, name it ThreadPage and paste the URL, then Create as a plugin and install it.
Codex, Claude CodeSee Coding agents.

Sign-in opens ThreadPage, where the person chooses the level and which threads and folders. The default for an assistant is Read and add. Step-by-step setup for each app is in Apps, and for Claude Code and Codex in Coding agents.

What the server tells assistants

When a client connects, the server sends instructions: how ThreadPage is organized and the rules for writing, editing and retrying. Some clients, such as Claude on the web and Claude Desktop, don’t pass them to the model.

get_guide with topic formatting answers every Markdown and document element; working answers the tools, editing, retries, limits and errors. The resources threadpage://instructions, threadpage://guide/formatting and threadpage://guide/working hold the same texts.

The ThreadPage skill gives an assistant the same guides ahead of time, which helps where instructions don’t reach the model. See Assistant guide.

Tools

Every tool has a title, a description, annotations (readOnlyHint, destructiveHint, idempotentHint) and strict arguments. Annotations help a client ask before a change; ThreadPage enforces the level on the server either way.

Tools
LevelTools
Add to Inboxget_access, create_note (to the Inbox only), get_operation, get_guide
Add onlyget_access, list_threads (titles), create_note, upload_note_image, get_operation, get_guide
Read onlyThe read tools: threads, folders, search, notes, versions, images, files and reminders
Read and addEvery tool. It adds notes, threads and reminders, and changes or trashes the notes it added. Other changes are refused.
Edit and organizeEvery tool, on any note, thread and folder in its scope

The full table, with each tool’s levels, annotations and the API operation that does the same:

MCP tools by level
ToolLevelsChanges notesAPI operation
get_accessEdit and organize · Read and add · Read only · Add only · Add to InboxNoGET /connection
get_operationEdit and organize · Read and add · Read only · Add only · Add to InboxNoGET /operations/{operation_id}
list_threadsEdit and organize · Read and add · Read only · Add onlyNoGET /threads
get_threadEdit and organize · Read and add · Read onlyNoGET /threads/{thread_id} and GET /threads/{thread_id}/notes
create_threadEdit and organize · Read and addYesPOST /threads
update_threadEdit and organizeYesPATCH /threads/{thread_id}
archive_threadEdit and organizeYesPOST /threads/{thread_id}/archive
unarchive_threadEdit and organizeYesPOST /threads/{thread_id}/unarchive
trash_threadEdit and organizeYesPOST /threads/{thread_id}/trash
restore_threadEdit and organizeYesPOST /threads/{thread_id}/restore
move_threadEdit and organizeYesPOST /threads/{thread_id}/move
create_noteEdit and organize · Read and add · Add only · Add to InboxYesPOST /inbox/notes and POST /threads/{thread_id}/notes
upload_note_imageEdit and organize · Read and add · Add onlyYesPOST /threads/{thread_id}/images
get_noteEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}
update_noteEdit and organize · Read and addYesPUT /notes/{note_id}/content
update_note_propertiesEdit and organizeYesPATCH /notes/{note_id}
move_noteEdit and organize · Read and addYesPOST /notes/{note_id}/move
trash_noteEdit and organize · Read and addYesPOST /notes/{note_id}/trash
restore_noteEdit and organize · Read and addYesPOST /notes/{note_id}/restore
get_note_historyEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}/versions
get_note_versionEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}/versions/{version_id}
restore_note_versionEdit and organize · Read and addYesPOST /notes/{note_id}/versions/{version_id}/restore
read_note_attachmentEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}/images/{image_id}
read_note_fileEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}/files/{file_id}, GET /notes/{note_id}/files/{file_id}/preview and GET /notes/{note_id}/files/{file_id}/text
searchEdit and organize · Read and add · Read onlyNoGET /search
list_statusesEdit and organizeNoGET /statuses
list_foldersEdit and organize · Read and add · Read onlyNoGET /folders
create_folderEdit and organizeYesPOST /folders
rename_folderEdit and organizeYesPATCH /folders/{folder_id}
move_folderEdit and organizeYesPOST /folders/{folder_id}/move
trash_folderEdit and organizeYesPOST /folders/{folder_id}/trash
restore_folderEdit and organizeYesPOST /folders/{folder_id}/restore
list_remindersEdit and organize · Read and add · Read onlyNoGET /threads/{thread_id}/reminders
get_reminderEdit and organize · Read and add · Read onlyNoGET /notes/{note_id}/reminder and GET /threads/{thread_id}/reminder
set_reminderEdit and organize · Read and addYesPUT /notes/{note_id}/reminder and PUT /threads/{thread_id}/reminder
remove_reminderEdit and organize · Read and addYesDELETE /notes/{note_id}/reminder and DELETE /threads/{thread_id}/reminder
list_requestsEdit and organize · Read and addNoGET /requests
get_requestEdit and organize · Read and addNoGET /requests/{request_id}
claim_requestEdit and organize · Read and addYesPOST /requests/{request_id}/claim
report_request_statusEdit and organize · Read and addYesPOST /requests/{request_id}/status
complete_requestEdit and organize · Read and addYesPOST /requests/{request_id}/result
get_guideEdit and organize · Read and add · Read only · Add only · Add to InboxNoMCP only
delete_folder_containerEdit and organizeYesMCP only

Request tools (list_requests, get_request, claim_request, report_request_status, complete_request) appear for a connection that receives requests.

Tools change with access

tools/list is built from the grant’s scopes:

  • Read and add and Edit and organize hold the same scopes, so they list the same tools. A call Read and add may not make is refused with needs and manage_url. When the owner raises an assistant’s connection to Edit and organize, the same chat works. A tp_ token can’t use Edit and organize on /mcp: raised to it, the token keeps working on the API and stops on /mcp.
  • Read only lists no write tools, whatever the client asks for.
  • A raise that adds scopes, such as Read only to Read and add, needs a new tool list. Claude, Claude Code and Codex read it in a new session. ChatGPT reads it after Refresh in its Plugins settings.

A tool hidden by the level, called from an older list, gets the level’s refusal.

If the person asks for something your tools don’t do, call get_access and give them its manage_url. It opens the connection in ThreadPage with the next level proposed; it changes only the level, and nothing changes until the owner saves and confirms it’s them. The same sentence ends the get_access description and every level refusal, because some clients don’t pass the server’s instructions to the model.

What each level sees: get_access

get_access answers the object GET /connection answers (level, can, cannot, manage_url, shared_places and more), plus the grant’s token_scopes and the connection’s limits in capabilities.

JSON
{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_access", "arguments": {}}}
What each level sees: get_access
levelcancannot
fullRead, add and edit notes, and organize threads and folders, including Archive and Trash.Can’t delete permanently.
read_addRead and search notes. Add notes, threads and reminders, and change or move to Trash the notes it added.Can’t change other notes.
readRead and search notes, including earlier versions.No changes.
appendAdd notes to threads you choose and see those threads’ titles.Can’t read notes.
inboxAdd notes to your Inbox.Can’t read notes.

Conventions

Conventions
ArgumentRule
operation_idEvery write takes one: a new UUID for each logical write, in any letter case. Send the same one when you repeat that write. The same ID with different arguments answers operation_id_reused.
expected_revision, context_receiptupdate_note and restore_note_version take both: the content_revision and the context_receipt from the same get_note. The tools that change an existing thread or folder, and update_note_properties, move_note, trash_note and restore_note, take expected_revision alone: the revision you last read. ThreadPage doesn’t compare it, and these writes apply in the order they arrive.
cursor, limitLists take limit (1 to 50) and answer next_cursor; pass it back as cursor. Read every page when the whole list matters.
contentA Markdown string, {"text": …}, {"markdown": …} or {"document": …}. Markdown up to 32 KiB, a note up to 256 KiB.

get_thread and search answer previews, and a truncated one is cut. Read a note with get_note before you quote, summarize or edit it.

Replace a note safely

1. Read the note in full. Keep its document, its content revision and the context receipt.

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_note",
    "arguments": {
      "note_id": "4c2f8e19-7a6b-4d3e-b1c0-95e8f2a7d364"
    }
  }
}

2. Change only what you were asked to in that document, and send it whole with a new operation_id. expected_revision is the content_revision you read.

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "update_note",
    "arguments": {
      "operation_id": "b8e1d4a2-6c3f-4e9b-a751-2d0f8c6e3b19",
      "note_id": "4c2f8e19-7a6b-4d3e-b1c0-95e8f2a7d364",
      "expected_revision": "$content_revision",
      "context_receipt": "$context_receipt",
      "content": {
        "document": "$document"
      }
    }
  }
}

Repeat a write whose answer was lost

1. Add a note. The answer is lost: a timeout, or the connection dropped.

JSON
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "create_note",
    "arguments": {
      "operation_id": "6e2a9c41-0b7d-4f53-8c1e-3a9d5f7b2c80",
      "thread_id": "0e7c4b2a-91d3-4f6e-8a25-3c1b9d7f4e60",
      "content": "## Release 412\n\n- [x] Tests passed\n- [ ] Tag the build"
    }
  }
}

2. Ask what happened to that operation_id. A receipt means the note exists: don't write again.

JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_operation",
    "arguments": {
      "operation_id": "6e2a9c41-0b7d-4f53-8c1e-3a9d5f7b2c80"
    }
  }
}

3. Or send the identical call again with the same operation_id. It answers the same receipt and adds no second note.

JSON
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "create_note",
    "arguments": {
      "operation_id": "6e2a9c41-0b7d-4f53-8c1e-3a9d5f7b2c80",
      "thread_id": "0e7c4b2a-91d3-4f6e-8a25-3c1b9d7f4e60",
      "content": "## Release 412\n\n- [x] Tests passed\n- [ ] Tag the build"
    }
  }
}

If the connection was disconnected or reconnected in between, get_operation can’t see the earlier write. Don’t replay it: ask the person to check in ThreadPage.

Confirmations

Moving a folder, or moving it to Trash with or without its contents, asks a confirmation when the folder holds threads:

  • A client that supports elicitation shows the question, such as Move “Clients” and its 4 threads to Trash?. Accept proceeds; any other answer is declined.
  • Without elicitation, the first call answers confirmation_required with details.confirm, the folder and how many threads and folders it holds. Send the same call with confirm within 10 minutes.

This guards an honest assistant against a mistake. It is not a security control; Trash and Restore from Trash… are.

Errors

A refused call answers a result with isError: true and JSON in its text: {"status": "rejected", "code", "message", "details"}, without retryable. The codes are the same as the API’s; a scope miss is unavailable. See Errors.

rate_limited means nothing was done: wait details.retry_after seconds and send the identical call with the same operation_id.

Limits

MCP calls count toward the same rate limits as the API.

Next