protogrid

Search / io.github.seunghan91/ainote

ainote

R1· needs a key

Agent-native notes, tasks, dev-docs, vaults, sync & handoffs. MCP + OpenAPI dual surface.

v1.3.2 · active · repository · website · descriptor JSON · versions

An agent can connect on its own if it already holds AINOTE_TOKEN.Remote endpoint behind a static API key or header. The registry never sees the value; the agent fills the placeholder.
Quality81good
Trust90of 100
Uptime, 30 days100%
Latency p50567 ms

Connect

8 clients · secrets stay placeholders
{
  "mcpServers": {
    "ainote": {
      "type": "http",
      "url": "https://api.ainote.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${AINOTE_TOKEN}"
      }
    }
  }
}
claude mcp add --transport http ainote https://api.ainote.dev/api/mcp --header "Authorization: Bearer ${AINOTE_TOKEN}"
[mcp_servers.ainote]
url = "https://api.ainote.dev/api/mcp"
bearer_token_env_var = "AINOTE_TOKEN"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ainote": {
      "type": "remote",
      "url": "https://api.ainote.dev/api/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer {env:AINOTE_TOKEN}"
      }
    }
  }
}
{
  "mcpServers": {
    "ainote": {
      "type": "http",
      "url": "https://api.ainote.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${AINOTE_TOKEN}"
      }
    }
  },
  "deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=ainote&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vYXBpLmFpbm90ZS5kZXYvYXBpL21jcCIsImhlYWRlcnMiOnsiQXV0aG9yaXphdGlvbiI6IkJlYXJlciAke0FJTk9URV9UT0tFTn0ifX0%3D"
}
{
  "servers": {
    "ainote": {
      "type": "http",
      "url": "https://api.ainote.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${AINOTE_TOKEN}"
      }
    }
  }
}
{
  "mcpServers": {
    "ainote": {
      "httpUrl": "https://api.ainote.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${AINOTE_TOKEN}"
      }
    }
  }
}
extensions:
  "ainote":
    enabled: true
    name: "ainote"
    type: streamable_http
    uri: "https://api.ainote.dev/api/mcp"
    headers:
      "Authorization": "Bearer ${AINOTE_TOKEN}"
    timeout: 300

Placeholders to fill from your own secret store: ${AINOTE_TOKEN}. The registry never accepts secret values.

Quality 81 / 100good

protocol88 · weight 25
  • pass
    protocol.modernsupports 2026-07-28 (server/discover)
  • pass
    protocol.statelessanswers without a session
  • pass
    protocol.transportstreamable HTTP
  • warn
    protocol.list_ttltools/list declares ttlMs 0, so clients re-fetch it on every use
authorizationn/a · weight 15
  • n/a
    auth.prm, auth.as_metadata, auth.cimdno remote uses OAuth
  • n/a
    auth.secret_in_urlno templated URL
tool hygiene86 · weight 30
  • pass
    tools.descriptionsevery tool has a description
  • warn
    tools.description_length1 tools have descriptions over 1,024 characters, which crowds the context
  • pass
    tools.schemasevery tool has an object input schema
  • pass
    tools.annotations34 of 34 tools declare readOnlyHint or destructiveHint
  • pass
    tools.directory_hintsevery tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
  • warn
    tools.token_costabout 12,559 tokens to load every tool
  • pass
    tools.api_dumptools are not a one-to-one API dump
stability75 · weight 15
  • warn
    stability.changes37 tool changes in 30 days
  • pass
    stability.rug_pullno tool changed its meaning under the same name
dependencies67 · weight 15
  • pass
    deps.known_vulnsno known advisory in 172 resolved packages
  • fail
    deps.mcp_sdk_version@modelcontextprotocol/sdk 1.30.1 has 1 known advisory (GHSA-6qxp-vccf-f47h); update @modelcontextprotocol/sdk to 1.31.0 or later
  • pass
    deps.resolvable@ainote/[email protected] resolved: 172 packages

34 tools, about 12,559 tokens to load them all · tool set a5564310e3e3 · tools last changed 2026-10-11 · checked 2026-10-19 10:20 UTC

Tool changes

  • sync_readchangedinput schema
  • vault_syncchangeddescription, input schema
    before

    Wrapper around vault file sync. action=list|pull|push to work against the primary vault. list/pull are paginated — narrow with `path`/`since` and follow `next_cursor` instead of pulling the whole vault. For push: WAF-bypass via `content_b64` or `content: '__B64__:...'` prefix (mirrors sync_push).

    after · 80% of words in common

    Wrapper around vault file sync. action=list|pull|push to work against the primary vault. list/pull are paginated — narrow with `path`/`since` and follow `next_cursor` instead of pulling the whole vault. To fetch specific files, pull with `paths` (up to 100 exact paths, one call). For push: WAF-bypass via `content_b64` or `content: '__B64__:...'` prefix (mirrors sync_push).

  • auth_keyremoved

    Obtain an MCP key. action: login | signup (consolidated surface — same handlers as the legacy tools) Required per action — login: email, password | signup: email, password.

  • memory_readchangedtitle
  • handoff_readchangedtitle
  • graph_writechangedtitle, description, annotations
    before

    Add or update a graph entity (non-destructive). action: add | update. Deletion is a separate tool (graph_soft_delete). (consolidated surface — same handlers as the legacy tools) Required per action — add: node_type, alias, payload, device_id | update: node_id, device_id, field_updates.

    after · 94% of words in common

    Add or update a graph entity. action: add | update. Deletion is a separate tool (graph_soft_delete). (consolidated surface — same handlers as the legacy tools) Required per action — add: node_type, alias, payload, device_id | update: node_id, device_id, field_updates.

  • graph_readchangedtitle
  • env_sync_writechangedtitle
  • env_sync_readchangedtitle
  • vault_readchangedtitle

Showing the latest 10. Full history: list_changes · trend: quality JSON.

Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.

Trust 90 / 100

provenance90
liveness100
freshness65
hygiene100

+repository +namespace-matches-repo +website +reachable +uptime-100% ~updated-158d-ago

Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.

Dependencies

@ainote/[email protected] npm171 dependencies, resolved · MCP SDK @modelcontextprotocol/sdk 1.30.1 · advisories checked 2026-10-19

advisoryseveritypackagefixed in
GHSA-6qxp-vccf-f47hMCP TypeScript SDK: OAuth client could send credentials to an authorization server chosen by the MCP serverhigh@modelcontextprotocol/[email protected]MCP SDK, directfixed in 1.31.0

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.

Endpoints

remoteauthreachableuptime 30dp50protocollast ok
https://api.ainote.dev/api/mcp streamable-httpapi_key ${AINOTE_TOKEN}yes100%567 ms2026-07-282026-10-19
packageregistryversionruntimesecrets
@ainote/mcpnpm1.3.2–AINOTE_API_KEY

Tools (34)

assumption_writedestructiveCreate or update an assumption under a project (L2 intent layer). Omit `id` to create, pass it to update. There is no delete tool. 🔴 `verdict` is REJECTED with an error if passed — verdict is confirmed only through a human judgment decision (see judgment_submit). This tool can only shape the assumption itself: what is being assumed, how critical it is, and what evidence would settle it.
delete_dev_docdestructiveSoft-delete a dev document by title or UUID. Reversible from trash. Pass `category` when multiple docs share the same title across subcategories (memory/claude/cursor/env/docs).
delete_taskdestructiveSoft-delete a task by ID. Destructive but reversible within 30 days (TaskCleanupJob purges trash daily at 2am KST). Returns 404 if the task does not exist or is not owned by the authenticated user.
dev_docs_readread-onlyRead dev docs. action: get | list | categories | pull (consolidated surface — same handlers as the legacy tools)
dev_doc_writedestructiveCreate or update a dev doc. action: create | update. Deletion is a separate tool (delete_dev_doc). (consolidated surface — same handlers as the legacy tools) Required per action — create: title, content | update: content.
env_sync_readread-onlyRead env-sync state. action: devices | drift | status | txn_pull. Secret reads are a separate tool (env_sync.secret_pull). (consolidated surface — same handlers as the legacy tools)
env_sync.secret_pullread-onlyPull an encrypted secret blob. Response is ciphertext_b64 only — server never sees and never returns plaintext.
env_sync.secret_pushPush a new client-encrypted secret. Ciphertext only — server never sees plaintext. Recipients must include the pushing device's own pubkey.
env_sync.secret_rotatedestructiveRotate a secret: soft-delete the old node, create a new live node with the same alias and the new ciphertext+recipients. 7-day grace before hard delete of old ciphertext bytes.
env_sync_txn_pushdestructiveIngest a batched envelope of client-recorded env_sync mutations. HLC-skew gated, partial-success on conflict.
env_sync_txn_rollbackdestructiveInverse-apply a prior env_sync transaction. Safety gates: ownership, idempotency, descendant-conflict (force opt-out).
env_sync_writeNon-destructive env-sync writes. action: enroll | request_share | heartbeat. Secret push/rotate are separate tools. (consolidated surface — same handlers as the legacy tools) Required per action — enroll: alias, age_pubkey, enrollment_token | request_share: target_device_id, secret_shares, device_id | heartbeat: device_id, installed_skills_hash, installed_hooks_hash.
get_setup_guideread-onlyGet instructions for setting up AI Note MCP in Claude Desktop, Cursor, or other MCP clients. No authentication required.
graph_readread-onlyRead knowledge-graph nodes. action: get | list (consolidated surface — same handlers as the legacy tools)
graph_soft_deletedestructiveSoft-delete an env_sync graph node (sets deleted_at; .live scope hides it from reads). Idempotent — re-deleting a deleted node is a no-op success.
graph_writedestructiveAdd or update a graph entity. action: add | update. Deletion is a separate tool (graph_soft_delete). (consolidated surface — same handlers as the legacy tools) Required per action — add: node_type, alias, payload, device_id | update: node_id, device_id, field_updates.
handoff_readread-onlyRead session handoffs. action: get | list (consolidated surface — same handlers as the legacy tools) Required per action — get: project, topic.
handoff_savedestructiveSave a session handoff note for cross-device / cross-session continuation. Stored at handoffs/{project}-{topic}-{YYYY-MM-DD}.txt in the user's primary vault. Use the optional `time` param (HHMM, KST) to disambiguate multiple handoffs saved on the same day — it is appended to the topic slug (e.g. topic='phase-d', time='1555' → handoffs/{project}-phase-d-1555-{date}.txt).
judgment_listread-onlyList the authenticated user's own judgments (L3 layer) — use this to check your own blocking status (risk_tier 1 pending = execution blocked). Default order matches the /command queue: risk_tier ascending, then arrival order.
judgment_submitRequest a human judgment (L3 layer) by attaching evidence — approval, evidence, or verdict. This is the ONLY door an agent has into the judgment queue. 🔴 `decision` is REJECTED with an error if passed — judgments are always created with decision='pending'. Only a human decides them (from the /command queue). Use judgment_list afterwards to check whether this judgment has since been decided. risk_tier controls urgency: 1=destructive (blocks execution until decided), 2=reversible (may auto-proceed after a wait window), 3=informational (auto-expires after 24h).
list_papersread-onlyList notes/papers from AI Note. Supports keyword search across title and content, category filtering, pagination, and sorting. Returns id/title/content_preview/category_id/created_at. Use this when the user asks 'find my note about X', 'what did I write on Y', or wants to search their knowledge base.
memory_readread-onlyRead agent memory. action: get | search (consolidated surface — same handlers as the legacy tools) Required per action — get: source | search: query.
project_readread-onlyList the authenticated user's projects (L2 intent layer), or fetch one by id. Each entry includes riskiest_assumption — the single highest-priority unverified assumption (or, if all are verified, the highest-criticality one).
project_writedestructiveCreate or update a project (L2 intent layer). Omit `id` to create, pass it to update. There is no delete tool — use status: 'archived' to retire a project.
sync_audit_layer5Record the result of a client-side Layer 5 codex review (sync.py merge gate) as a vault_events row. Body of the review is NOT stored — only an HMAC digest of the summary so operators can correlate without exposing review content. Opt-in: server skips writes (still returns success) unless ENV['AINOTE_LAYER5_AUDIT']='on' AND a versioned HMAC secret is configured. Used by the sync.py SessionStart hook + merge command to surface 'why was this blocked?' across multi-PC sessions.
sync_deletedestructiveDelete a file from the primary vault. Optional CAS via base_sha to detect concurrent multi-PC writes. Protected paths (global/memory/, global/skills/, global/planning/, global/intent/, global/claude-config/, handoffs/) require base_sha or explicit force:true (audited). Idempotent: deleting a non-existent path returns success with deleted:false.
sync_pushdestructivePush a markdown file into the primary vault. Optional CAS via base_sha to detect concurrent multi-PC writes (Layer 3 of multi-PC sync plan). WAF-bypass tip: large bodies (~10KB+) that get false-positive blocked at Cloudflare can be sent via `content_b64` (base64-encoded) OR `content` prefixed with `__B64__:` instead. When the push CREATES a new .md file, the response may carry `dedup_candidates` — existing memory files that look similar (keyword + title similarity, no LLM). It is an advisory, not a rejection: YOU decide to merge into one of them (re-push that path), drop this write as a duplicate (skip), or keep it as a new memory (store).
sync_push_batchdestructivePush MANY files into the primary vault in ONE call. Use this instead of looping sync_push whenever you have more than a couple of changed paths — the cost of sync_push is round trips, not bytes. Per-item semantics are identical to sync_push (Layer 3 base_sha CAS, superseded contract, content_b64 WAF fallback). Partial success is normal and returns HTTP 200: read `results[]` and match entries by `path`, NOT by position. A conflict result always carries `remote_sha` + `conflict_reason` so you can go straight to sync_merge. Request-level failures (duplicate paths in one batch, idempotency key reused with a different payload, >200 items, >4MB) return 4xx and apply NOTHING. Each item MUST carry `content_sha` (SHA1 hex of the decoded body, same algorithm as git_sha) — it powers both the integrity check and the retry-safe `skipped_identical` result. Newly created .md items may carry `dedup_candidates` (same merge/skip/store advisory as sync_push); a batch creating more than 10 new files skips the check entirely and reports `dedup_skipped: "bulk"`.
sync_readread-onlyRead-only vault sync operations. action: list | pull | diff | merge | conflicts. Writes (push/delete) are separate tools — they carry CAS semantics. (consolidated surface — same handlers as the legacy tools) Required per action — diff: path | merge: path, base_text, local_text.
tasks_readread-onlyRead tasks and task categories. action: tasks | categories (consolidated surface — same handlers as the legacy tools)
task_writedestructiveCreate or update a task. action: create | update. Deletion is a separate tool (delete_task). (consolidated surface — same handlers as the legacy tools) Required per action — create: content | update: id.
vault_createCreate a new private vault as a GitHub repository under the user's account. Requires the user to have completed the GitHub App install flow first.
vault_readread-onlyRead vault metadata. action: list | clone | status (consolidated surface — same handlers as the legacy tools) Required per action — clone: name.
vault_syncdestructiveWrapper around vault file sync. action=list|pull|push to work against the primary vault. list/pull are paginated — narrow with `path`/`since` and follow `next_cursor` instead of pulling the whole vault. To fetch specific files, pull with `paths` (up to 100 exact paths, one call). For push: WAF-bypass via `content_b64` or `content: '__B64__:...'` prefix (mirrors sync_push).

Schemas: list_tools.

Similar MCP servers

Official server.json
{
  "name": "io.github.seunghan91/ainote",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "remotes": [
    {
      "url": "https://api.ainote.dev/api/mcp",
      "type": "streamable-http",
      "headers": [
        {
          "name": "Authorization",
          "format": "string",
          "isSecret": true,
          "isRequired": true,
          "description": "McpKey <YOUR_KEY> -- same key as the AINOTE_API_KEY env var for the stdio transport."
        }
      ]
    }
  ],
  "version": "1.3.2",
  "packages": [
    {
      "version": "1.3.2",
      "transport": {
        "type": "stdio"
      },
      "identifier": "@ainote/mcp",
      "registryType": "npm",
      "environmentVariables": [
        {
          "name": "AINOTE_API_KEY",
          "format": "string",
          "isSecret": true,
          "isRequired": true,
          "description": "64-character ainote MCP key. Issue one via `npx @ainote/mcp signup` (RFC 8628 device flow), or in a Claude session by calling signup_and_get_key, or at https://app.ainote.dev -> Settings -> MCP keys."
        }
      ]
    }
  ],
  "repository": {
    "url": "https://github.com/seunghan91/ainote",
    "source": "github"
  },
  "websiteUrl": "https://docs.ainote.dev",
  "description": "Agent-native notes, tasks, dev-docs, vaults, sync & handoffs. MCP + OpenAPI dual surface."
}