Keep MCP
Keep MCP is an MCP server for Google Keep that lets you search, read, create, update, organize, label, share, and manage notes and checklists.
Find notes with text and filters for labels, colors, pinned, trashed, or archived.
Get a single note by ID.
Create text notes and checklist notes, and add/update/delete checklist items.
Update note title/text, set color, pin/unpin, archive/unarchive, trash/restore, and delete notes.
List/create/delete labels and add/remove labels on notes.
List/add/remove note collaborators.
List note media blobs and direct media links.
By default, modification/destructive tools only work on notes carrying the keep-mcp label; UNSAFE_MODE=true bypasses this.
Enables interaction with Google Keep notes, providing capabilities to search for notes, create new notes, update existing notes, and mark notes for deletion. Notes created through the integration are automatically labeled for tracking purposes.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Keep MCP find my shopping list from yesterday"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
keep-mcp
MCP server for Google Keep
See CONTRIBUTING.md for contribution guidelines and required visual evidence.
How to use
Add the MCP server to your MCP servers:
"mcpServers": {
"keep-mcp-pipx": {
"command": "pipx",
"args": [
"run",
"keep-mcp"
],
"env": {
"GOOGLE_EMAIL": "Your Google Email",
"GOOGLE_MASTER_TOKEN": "Your Google Master Token - see README.md"
}
}
}Or with uvx:
"mcpServers": {
"keep-mcp": {
"command": "uvx",
"args": [
"keep-mcp"
],
"env": {
"GOOGLE_EMAIL": "Your Google Email",
"GOOGLE_MASTER_TOKEN": "Your Google Master Token - see README.md"
}
}
}Add your credentials:
GOOGLE_EMAIL: Your Google account email addressGOOGLE_MASTER_TOKEN: Your Google account master token
Obtain a Google master token
keep-mcp uses gkeepapi, which connects to Google Keep through an unofficial private API. A Google master token has full access to your account. Treat it like a password and never commit or share it.
You need Docker and a desktop browser.
Open https://accounts.google.com/EmbeddedSetup and sign in with the Google account you use for Keep.
Click I agree. The page may keep loading forever. Leave it open and continue.
Copy the
oauth_tokencookie:Chrome or Edge: Press F12, open the Application tab, then Cookies →
https://accounts.google.com.Firefox: Press F12, open the Storage tab, then Cookies →
https://accounts.google.com.
Find the row named
oauth_tokenand copy its value. It starts withoauth2_4/.Right away, run this in a terminal and paste your email and the cookie value when asked:
docker run --rm -it ghcr.io/astral-sh/uv:python3.13-bookworm-slim uv run --no-project --with gpsoauth python -c "import gpsoauth; r = gpsoauth.exchange_token(input('Email: '), input('oauth_token: '), '0123456789abcdef'); print(r.get('Token', r))"Without Docker, install uv and run the same command without the
docker run --rm -it ghcr.io/astral-sh/uv:python3.13-bookworm-slimpart.The command prints your master token. It starts with
aas_et/. Use it asGOOGLE_MASTER_TOKEN.
If it prints an error such as BadAuthentication instead, the cookie has expired. Repeat steps 1 to 4 to get a fresh one.
More details
gpsoauth's alternative flow describes the token exchange.gkeepapi's "Obtaining a Master Token" instructions describe the same exchange.
Older instructions may ask for your Google password or an app password and call perform_master_login(). That flow is unreliable and can return BadAuthentication. Use the browser-assisted flow above instead.
Related MCP server: Google Keep MCP
Features
Query and read tools
find: Search notes (case-insensitive by default) with optional filters for labels, colors, pinned, archived, trashed, creation/update date ranges (ISO 8601, UTC), and a result limit (default 50)get_note: Get a single note by ID
Creation and update tools
create_note: Create a new note with title and text (automatically adds keep-mcp label)create_list: Create a checklist noteupdate_note: Update a note's title and textadd_list_item: Add an item to a checklist noteupdate_list_item: Update checklist item text and checked statedelete_list_item: Delete a checklist item
Note state tools
set_note_color: Set a note color (valid values: DEFAULT, RED, ORANGE, YELLOW, GREEN, TEAL, BLUE, CERULEAN, PURPLE, PINK, BROWN, GRAY)pin_note: Pin or unpin a notearchive_note: Archive or unarchive a notetrash_note: Move a note to trashrestore_note: Restore a trashed/deleted notedelete_note: Mark a note for deletion
Labels, collaborators, and media tools
list_labels: List labelscreate_label: Create a labeldelete_label: Delete a labeladd_label_to_note: Add a label to a noteremove_label_from_note: Remove a label from a notelist_note_collaborators: List collaborator emails for a noteadd_note_collaborator: Add a collaborator email to a noteremove_note_collaborator: Remove a collaborator email from a notelist_note_media: List media blobs for a note (with media links)download_media: Download a note's media (images, drawings, audio) to a local directory through the authenticated session (the raw media links answer 403 to plain HTTP clients). Not available over Streamable HTTP, where the files would land on the server
By default, all destructive and modification operations are restricted to notes that have were created by the MCP server (i.e. have the keep-mcp label). Set UNSAFE_MODE to true to bypass this restriction.
"env": {
...
"UNSAFE_MODE": "true"
}Local development (uv + make)
If you prefer a JS-style workflow (npm i, npm start), use the included Makefile:
make install # like npm i
make start # like npm start
make test
make lintRun the real-account smoke test with credentials:
GOOGLE_EMAIL="you@example.com" \
GOOGLE_MASTER_TOKEN="..." \
make smokeEquivalent direct uv commands (without make):
UV_CACHE_DIR=/tmp/uv-cache uv venv --python 3.11 .venv
UV_CACHE_DIR=/tmp/uv-cache uv pip install --python .venv/bin/python -e .
UV_CACHE_DIR=/tmp/uv-cache uv run --no-sync --python .venv/bin/python -m serverTesting
Unit tests (default)
The project includes a lightweight unit test suite under tests/.
It validates:
note serialization shape for note and list objects (including labels, collaborators, media, and list items)
modification safety behavior (
keep-mcplabel requirement andUNSAFE_MODE=trueoverride)MCP tool behavior in
src/server/cli.pyusing mocked Keep client objects (tool happy paths and key error paths)
Run locally:
make testSmoke test against a real Keep account
For additional confidence, run a basic lifecycle smoke test against a dedicated test account:
GOOGLE_EMAIL="you@example.com" \
GOOGLE_MASTER_TOKEN="..." \
make smokeWhat it does:
create note
update note
pin/unpin
archive/unarchive
trash/restore
delete
This script is intended for manual verification and is not run in CI.
CI checks
GitHub Actions runs on every pull request and executes:
lint (
ruff check .)unit tests with coverage (
pytest -q --cov=src/server --cov-report=term-missing --cov-fail-under=70)bytecode sanity (
python -m compileall src)
Publishing
Automatic publish on merge to main (GitHub Actions)
This repo includes a release workflow at .github/workflows/release.yml that runs on every push to main (including merged PRs).
It will:
inspect commits since the last release tag (
vX.Y.Z)compute the next semantic version from Conventional Commit types
skip publishing when there are no releasable commit types
run lint and unit tests
build
dist/*publish to PyPI
create a GitHub release/tag
v<computed-version>with generated notes
Version bump rules:
major: commit subject with
!(example:feat!:orfix(api)!:) or commit body containingBREAKING CHANGEminor:
feat:patch:
fix:,perf:,revert:no release:
docs:,chore:,ci:,test:,refactor:(unless the commit is marked as breaking)
Required repository secret:
PYPI_API_TOKEN: a PyPI API token (recommended scope: this project only)
Manual publish
To publish manually to PyPI:
Update the version in
pyproject.tomlBuild the package:
pipx run buildUpload to PyPI:
pipx run twine upload --repository pypi dist/*
Run locally with MCP clients
This is useful when you want a client to run this server from your local checkout instead of PyPI.
Create a local virtualenv and install in editable mode:
cd /ABSOLUTE/PATH/TO/keep-mcp
make installAdd the server to your MCP client config.
config.toml clients (Codex, Goose, etc.)
[mcp_servers.keep_mcp]
command = "make"
args = ["-C", "/ABSOLUTE/PATH/TO/keep-mcp", "start"]
[mcp_servers.keep_mcp.env]
GOOGLE_EMAIL = "you@example.com"
GOOGLE_MASTER_TOKEN = "your-master-token"
UNSAFE_MODE = "false"JSON mcpServers clients (Claude Desktop, Cursor, Cline, etc.)
{
"mcpServers": {
"keep-mcp-local": {
"command": "make",
"args": ["-C", "/ABSOLUTE/PATH/TO/keep-mcp", "start"],
"env": {
"GOOGLE_EMAIL": "you@example.com",
"GOOGLE_MASTER_TOKEN": "your-master-token",
"UNSAFE_MODE": "false"
}
}
}
}Alternative (without make):
[mcp_servers.keep_mcp]
command = "uv"
args = [
"--directory", "/ABSOLUTE/PATH/TO/keep-mcp",
"run", "--no-sync", "--python", ".venv/bin/python",
"-m", "server"
]Notes:
Run
make installonce before starting from an MCP client.Only the repo root path is required (no absolute
/.venv/bin/pythonpath).Ensure
makeanduvare in yourPATH.Restart your MCP client after updating config files.
UNSAFE_MODEis optional; keep it"false"unless you explicitly want to modify non-keep-mcpnotes.
Running over Streamable HTTP
keep-mcp supports the MCP Streamable HTTP transport (/mcp endpoint) in addition to the default stdio transport:
# Start Streamable HTTP server on localhost (default: 127.0.0.1:8000)
keep-mcp --transport streamable-http
# Customize host or port
keep-mcp --transport streamable-http --host 127.0.0.1 --port 8000keep-mcp binds to 127.0.0.1 by default with DNS rebinding protection enabled. To expose the server to remote or web clients (such as Gemini web), place an authenticating proxy (such as mcp-auth-proxy) in front of the server.
Running in Docker
A Dockerfile is provided for running keep-mcp as a containerized Streamable HTTP server listening on port 8000.
Build the container image:
docker build -t keep-mcp .Run the container:
docker run -d \ -e GOOGLE_EMAIL="you@example.com" \ -e GOOGLE_MASTER_TOKEN="aas_et/..." \ -p 127.0.0.1:8000:8000 \ keep-mcp
The container has no built-in authentication. Publish it only to localhost (-p 127.0.0.1:8000:8000) or place it behind an authenticating reverse proxy if exposing it over a network.
Troubleshooting
If you get "DeviceManagementRequiredOrSyncDisabled" check https://admin.google.com/ac/devices/settings/general and turn "Turn off mobile management (Unmanaged)"
Available Tools
23 toolsadd_label_to_noteC
Add a label to a note.
Inputs: note_id (required), label_id (required). Returns: result
add_list_itemC
Add an item to a checklist note.
Inputs: note_id (required), text (required), checked. Returns: result
add_note_collaboratorC
Add a collaborator email to a note.
Inputs: note_id (required), email (required). Returns: result
archive_noteC
Archive or unarchive a note.
Inputs: note_id (required), archived. Returns: result
create_labelC
Create a label.
Inputs: name (required). Returns: result
create_listB
Create a new checklist note.
items should be objects like: {"text": "task", "checked": false}
Inputs: title, items. Returns: result
create_noteC
Create a new note with title and text.
Inputs: title, text. Returns: result
delete_labelB
Delete a label by ID.
Inputs: label_id (required). Returns: result
delete_list_itemC
Delete a checklist item.
Inputs: note_id (required), item_id (required). Returns: result
delete_noteC
Delete a note (mark for deletion).
Inputs: note_id (required). Returns: result
findB
Find notes using text and optional filters. labels should be label IDs. colors should be ColorValue strings (e.g. DEFAULT, RED, CERULEAN).
Inputs: query, labels, colors, pinned, +2 more. Returns: result
get_noteB
Get a note by ID.
Inputs: note_id (required). Returns: result
list_labelsA
List all labels.
Inputs: no named parameters. Returns: result
list_note_collaboratorsB
List collaborator emails for a note.
Inputs: note_id (required). Returns: result
list_note_mediaB
List note media blobs and direct media links when available.
Inputs: note_id (required). Returns: result
pin_noteC
Pin or unpin a note.
Inputs: note_id (required), pinned. Returns: result
remove_label_from_noteA
Remove a label from a note.
Inputs: note_id (required), label_id (required). Returns: result
remove_note_collaboratorC
Remove a collaborator email from a note.
Inputs: note_id (required), email (required). Returns: result
restore_noteB
Restore a trashed/deleted note.
Inputs: note_id (required). Returns: result
set_note_colorA
Set a note color. Valid values: DEFAULT (white), RED, ORANGE, YELLOW, GREEN, TEAL, BLUE, CERULEAN (dark blue), PURPLE, PINK, BROWN, GRAY.
Inputs: note_id (required), color (required). Returns: result
trash_noteC
Move a note to trash.
Inputs: note_id (required). Returns: result
update_list_itemB
Update checklist item text and/or checked state.
Inputs: note_id (required), item_id (required), text, checked. Returns: result
update_noteC
Update a note's properties.
Inputs: note_id (required), title, text. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 23 tools
Each tool has a clearly distinct purpose, covering notes, labels, checklist items, collaboration, and media. There is minimal overlap; for example, archive, trash, delete, and restore are all separate actions. An agent can reliably select the correct tool.
Most tools follow a consistent verb_noun pattern with snake_case (e.g., add_label_to_note, create_note). Minor inconsistency: 'find' is a bare verb instead of 'find_notes', and 'create_list' creates a checklist note rather than using 'create_checklist'. Overall, the pattern is predictable.
23 tools is slightly above the typical 3-15 range but reasonable for a full-featured note-taking server. Each tool captures a specific operation, and the count is not overwhelming for the domain.
CRUD operations are covered for notes, labels, and checklist items. However, there is no tool to list all notes (only find with text search), and no explicit tool to unarchive or unpin (toggle behavior), which could cause agent failures if not inferred. Notable gaps exist.
Maintenance
Related MCP Connectors
Google Keep MCP, read and edit your notes, lists, labels and collaborators. Connect with your Google
Google Keep-style notes app with an MCP server for AI agents to read/write notes.
Read and write your Caliu notes from any MCP client: search, create, tag, remind, attach files.
Notes, files, GitHub, and Drive through one MCP connection.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables users to create, search, and retrieve Google Keep notes via natural language commands.ISC
- FlicenseBqualityDmaintenanceA Model Context Protocol server that connects Google Keep to Claude, enabling full note management capabilities including search, CRUD, checklists, labels, and more.20-
- FlicenseAqualityDmaintenanceMCP server for Google Keep that enables managing notes, checklists, and labels through tools like search, create, update, and delete.182-
- AlicenseAqualityCmaintenanceEnables Claude or Cursor to read Google Keep notes and checklists, add items, and check or uncheck them via MCP over HTTP with OAuth.71MIT