MCP server

An MCP endpoint for assistants and agents to read and write a workspace's notes, tasks and routines.

Connecting

POST https://is.underwhelm.ing/mcp is a streamable HTTP MCP endpoint without a server-to-client stream: each request carries one JSON-RPC message and is answered in full. It accepts only bearer tokens, never the browser's session cookie.

Make a token in the app under Settings → Devices. Give it only the scopes the client needs. Add the workspace id in X-Aquamarine-Account; it can be left out when you have one workspace or the token is scoped.

{
  "mcpServers": {
    "aquamarine": {
      "type": "http",
      "url": "https://is.underwhelm.ing/mcp",
      "headers": {
        "Authorization": "Bearer <token>",
        "X-Aquamarine-Account": "<workspace id>"
      }
    }
  }
}

To check a token by hand:

curl https://is.underwhelm.ing/mcp \
  -H "Authorization: Bearer <token>" \
  -H "X-Aquamarine-Account: <workspace id>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A call needing a scope the token lacks is refused with HTTP 403 and { "error", "scopes" } before it reaches the server. tools/list and resources/templates/list show only what the token can use. The scopes are the same as the REST API's.

Tools

notes_list read:notes

List active notes, newest first, without bodies. query searches titles and bodies.

  • query string
  • limit integer 1–200

notes_get read:notes

A note with its body, tags and links.

  • id string, required · The record's id

notes_create write:notes

Create a note.

  • title string, required
  • body string · Markdown; Obsidian frontmatter is kept
  • parent_id string · The record's id
  • tags array of string · Tag names; replaces the record's tags

notes_update write:notes

Change a note's title, body, parent or tags.

  • id string, required · The record's id
  • title string
  • body string · Markdown; Obsidian frontmatter is kept
  • parent_id string · The record's id
  • tags array of string · Tag names; replaces the record's tags

notes_publication_get read:notes

A note's publication, or null, and the links that would not work for visitors if it were published now.

  • id string, required · The record's id

notes_publish publish:notes

Publish a note, or republish it with its current text. Keeps the URL and settings. When links would not work for visitors it fails with the list; call again with confirm: true to publish anyway.

  • id string, required · The record's id
  • confirm boolean
  • display object · What the public page shows; each key is true or false
  • password string · 4 to 72 characters; an empty string removes it
  • expires_at string · ISO 8601 time; an empty string clears it
  • slug string · Lowercase a-z, 0-9 and dashes, 3 to 80 characters; the old address redirects here
  • domain_id string · A verified custom domain's id; an empty string is the main address

notes_unpublish publish:notes

Take a published note offline. When other published notes link to it, it fails with their list; call again with confirm_takedown: true.

  • id string, required · The record's id
  • confirm_takedown boolean

tasks_list read:tasks

List top-level tasks. status is inbox, planned or done; date lists the tasks scheduled on a day.

  • status one of inbox, planned, done
  • date string · YYYY-MM-DD

tasks_get read:tasks

A task with its subtasks.

  • id string, required · The record's id

tasks_create write:tasks

Create a task.

  • title string, required
  • notes string · Markdown
  • priority integer 0–3
  • due_on string · YYYY-MM-DD
  • scheduled_at string · ISO 8601 time
  • duration_minutes integer
  • project_id string · The record's id
  • page_id string · The record's id
  • parent_id string · The record's id
  • tags array of string · Tag names; replaces the record's tags

tasks_update write:tasks

Change a task's fields.

  • id string, required · The record's id
  • title string
  • notes string · Markdown
  • priority integer 0–3
  • due_on string · YYYY-MM-DD
  • scheduled_at string · ISO 8601 time
  • duration_minutes integer
  • project_id string · The record's id
  • page_id string · The record's id
  • parent_id string · The record's id
  • tags array of string · Tag names; replaces the record's tags

tasks_complete write:tasks

Mark a task done.

  • id string, required · The record's id

tasks_reopen write:tasks

Reopen a done task.

  • id string, required · The record's id

routines_list read:routines

List active routines with their steps.

routines_get read:routines

A routine with its steps and the id of its running run.

  • id string, required · The record's id

routines_start write:routines

Start a routine, or answer the run already going.

  • id string, required · The record's id
  • finish_by string · ISO 8601 time to finish by

search Any read: scope

Search notes, tasks, projects and routines; only the families the token can read are searched.

  • query string, required

Resources

resources/list lists the 200 most recently changed notes to a token holding read:notes. Each record family is also a resource template:

aquamarine://notes/{id} read:notes

One note as JSON, the same shape the REST API answers.

aquamarine://tasks/{id} read:tasks

One task as JSON, the same shape the REST API answers.

aquamarine://routines/{id} read:routines

One routine as JSON, the same shape the REST API answers.