---
title: "Push 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)."
method: POST
path: "/api/mcp/tools/sync_push"
tags: ["sync"]
---

# Push 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).

`POST /api/mcp/tools/sync_push`

## Request

- Base URL: `https://api.ainote.dev`
- URL: `https://api.ainote.dev/api/mcp/tools/sync_push`
- Auth: API key in header `Authorization`

Push 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).

## Request body

- object
  - `path` string, required: Relative file path (e.g., 'global/MEMORY.md', 'launchcrew/firebase.md'). No leading slash, no '..'.
  - `content` string: Full file content (markdown text). Alternatively prefix with '__B64__:' followed by base64 payload for WAF bypass.
  - `content_b64` string: Optional: base64-encoded file content (use INSTEAD of `content`). For WAF-bypass on large bodies. Server decodes before storing. If both supplied, content_b64 wins.
  - `base_sha` string: Optional: git_sha the client last observed for this path. When present, server compares with current git_sha and returns -32009 conflict on mismatch (with current content for 3-way diff). Omit for legacy LWW behavior (response will include a `warning` field nudging clients to upgrade).
  - `device_id` string: Optional: client device identifier (e.g., from ~/.claude/ainote-sync/device.id). Stored on FileIndex so future conflict responses can report which device last wrote the path.
  - `force` boolean: Optional: when true, skip CAS check even if base_sha is supplied. Use only for intentional overwrites; presence is auditable via warning logs.
  - `resolves_conflict_id` string: Optional: UUID of a vault_conflicts row this push resolves. When supplied, server validates ownership/unresolved/path/sha and atomically marks the conflict as resolution=clean inside the same transaction as the file_indices write. Validation failure rolls back the whole push and returns -32009 stale_conflict_id.
  - `supports_superseded` boolean: Optional capability opt-in. When true AND resolves_conflict_id points at an already-resolved conflict whose (path, remote_sha) matches this push, the server returns a NORMAL 200 with resource_data {status:'superseded', reason:'resolved_elsewhere', applied:false, git_sha:<current remote>} instead of a -32009 error, so the client pulls to converge. Omit (default) to keep the legacy -32009 contract.

## Response `200`

Tool executed successfully

- ToolSuccessResponse: Successful tool invocation. `content` mirrors the MCP `tools/call` result shape: an array of content blocks (text and optionally a structured resource payload).
  - `content` object[]
    - `type` 'text' | 'resource'
    - `text` string

## Other responses

- `400`: Invalid arguments or business-rule violation
- `401`: Missing or invalid McpKey

---

[API](https://skmtc.dev/ainote/apis/ainote-mcp-openapi-mirror.md) · [All operations](https://skmtc.dev/ainote/apis/ainote-mcp-openapi-mirror/llms.txt) · [OpenAPI document](https://skmtc.dev/ainote/apis/ainote-mcp-openapi-mirror/revisions/f6c91d85e027?raw)
