mi_note_mcp is a Xiaomi Cloud Notes server implementation based on the Model Context Protocol (MCP). It lets MCP-capable assistants (e.g. Claude, ChatGPT desktop) read, search, create, and manage your cloud notes directly. The project caches API responses locally and provides Markdown/XML conversion so that LLMs can work with note content seamlessly.
- Read, search & cache: List, search, and view note details with automatic local caching to reduce repeated network requests.
- Full note editing: Create, update, delete, and move notes with automatic sync of resource state.
- Folder management: List, create, rename, and delete folders, and view notes by folder.
- Rich text conversion: Convert between Markdown and Xiaomi’s internal note XML, preserving checklists, images, bold, etc.
- Image upload: Upload local images to Xiaomi cloud and get reusable
minote://image/{fileId}links. - MCP resources: Expose note and folder resource URIs for context and navigation.
- Bun ≥ 1.1 (1.2.23 used for development)
- A Xiaomi account that can access https://i.mi.com/note
- Node.js/TypeScript tooling (for development and type-checking only)
bun installBefore starting the server, create a config file. Default path is ~/.mi-note-mcp.json, or set MI_NOTE_MCP_CONFIG to another path.
Example config:
{
"serviceToken": "YOUR_SERVICE_TOKEN",
"userId": "YOUR_USER_ID",
"passToken": "optional, improves login stability",
"slh": "optional",
"ph": "optional",
"deviceId": "optional, align with web client",
"cUserId": "optional",
"uLocale": "zh_CN",
"syncInterval": 30000,
"baseUrl": "https://i.mi.com"
}To obtain values: log in to Xiaomi Cloud Notes in a browser and copy the Cookie headers (e.g. serviceToken, userId, passToken) from DevTools; keep them valid. syncInterval is in milliseconds and controls how often background incremental sync runs.
bun run index.tsWhen it’s ready, the terminal prints mi-note-mcp server started. Then register mi_note_mcp as a local MCP server in your client and set the command and working directory as instructed.
| Tool ID | Description | Main parameters |
|---|---|---|
list_notes |
List all cached notes | none |
get_note |
Get note Markdown by ID | id |
create_note |
Create a note and return resource link | content, title?, folderId? |
update_note |
Update note content and metadata | id, content, title?, folderId? |
delete_note |
Delete or permanently delete a note | id, purge? |
move_note |
Move a note to a folder | noteId, folderId |
search_notes |
Search by keyword in title and snippet | keyword, limit? |
upload_image |
Upload image and return minote://image/{fileId} |
path, mimeType? (stdio); contentBase64 on Worker |
list_folders |
List all folders | none |
create_folder |
Create a folder | subject, parentId? |
update_folder |
Rename a folder | id, subject |
delete_folder |
Delete or permanently delete a folder | id, purge? |
| Resource URI | Content | Notes |
|---|---|---|
minote://notes |
Overview list of all notes | Supports resource list change notifications |
minote://notes/{id} |
Markdown content of a note | Cached and kept up to date |
minote://folders |
Folder overview | List refreshes with sync |
minote://folders/{id}/notes |
Notes in a folder | Use with move_note to browse and organize |
- On first start, full data is fetched via
/note/full/pageand cached in memory. - Incremental sync runs on the interval set by
syncInterval(default 30s) to update notes and folders. - After write operations, tools refresh the cache and trigger resource updates so MCP clients see changes immediately.
- You can force a refresh in code via
NotesCache.refresh()(most tools already call it when needed).
-
Type-check (recommended before commit):
bun run tsc --noEmit --skipLibCheck
-
Unit tests:
npm run test(Vitest: config, OAuth state, cache. See
test/.)
For local/stdio MCP, run bun run index.ts. For the remote Worker (OAuth), see wrangler.jsonc and Cloudflare Access for SaaS; tool descriptions and env are in worker-configuration.d.ts and the solution doc under docs/solutions/security-issues/.
- Config file not found: Ensure
~/.mi-note-mcp.jsonexists orMI_NOTE_MCP_CONFIGpoints to the correct path. - 401/403: Usually means
serviceTokenoruserId(or other cookies) have expired; copy them again from the web app and update the config. - Image upload fails: Check that the file exists, MIME type is correct, and the host can reach
i.mi.com.
When adding tools or resources, reuse the existing client and cache logic and keep the code simple (KISS/YAGNI).