nudge
by davesleal
README.md
# nudge
[](https://www.npmjs.com/package/nudge-mcp)
[](LICENSE)
[](https://modelcontextprotocol.io)
> Your AI assistant, acting like a friend who actually remembers what you said you'd do.
**nudge** is an open-source [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that connects Claude — or any MCP-compatible AI — to your todo app. Instead of a cold productivity dashboard, you get a friend checking in naturally.
```
"hey, you've had 'call the accountant' on your list for 4 days 👀"
"nothing due today, you're all clear"
"added 'dentist appointment' for Friday"
```
No server to run. No first-person AI narration. Just a nudge.
---
## Install
### Quickest — setup wizard
```bash
npx nudge-mcp-init
```
Walks you through picking your todo app, entering credentials, and wiring up Claude Desktop automatically. Done in under a minute.
### Manual — Claude Desktop (no server needed)
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"nudge": {
"command": "npx",
"args": ["nudge-mcp"]
}
}
}
```
Restart Claude Desktop. That's it — Claude now has access to your tasks and will bring them up naturally.
> Claude Desktop launches nudge as a subprocess. Nothing runs in the background when you're not using Claude.
### Global install
```bash
npm install -g nudge-mcp
nudge-mcp
```
### No install (try it)
```bash
npx nudge-mcp
```
---
## Supported backends
| App | Config type | Notes |
|---|---|---|
| Local JSON file | `local` | Default — zero config needed |
| Markdown checklist | `local` | Any `- [ ] task` format |
| Todoist | `todoist` | Full read + write via REST API |
| Notion | `notion` | Read + write via database |
| Linear | `linear` | Issues assigned to you, full read + write |
| GitHub Issues | `github` | Issues assigned to you, full read + write |
| Apple Reminders | `reminders` | macOS only — no API key, reads directly |
| Anything else | `local` | Sync/export to a JSON or `.md` file |
Want to add an adapter? See [CONTRIBUTING.md](CONTRIBUTING.md).
---
## Configuration
Create `~/.nudge/config.json` — or skip it entirely to use the zero-config local default.
### Local JSON (default — no config file needed)
Tasks live at `~/.nudge/todos.json`:
```json
[
{ "id": "1", "title": "Call the accountant", "done": false, "due": "2026-03-03", "priority": "high" },
{ "id": "2", "title": "Buy birthday gift", "done": true },
{ "id": "3", "title": "Dentist appointment", "done": false, "tags": ["health"] }
]
```
### Markdown checklist
```json
{
"adapter": { "type": "local", "filePath": "~/Documents/tasks.md", "format": "markdown" }
}
```
```markdown
- [ ] Call the accountant
- [x] Buy birthday gift
- [ ] Dentist appointment
```
### Todoist
```json
{
"adapter": { "type": "todoist", "apiKey": "your_token_here" }
}
```
Or set the env var: `TODOIST_API_KEY=your_token npx nudge-mcp`
Get your token: Todoist → Settings → Integrations → Developer
### Notion
```json
{
"adapter": {
"type": "notion",
"apiKey": "secret_xxx",
"databaseId": "your_database_id"
}
}
```
Your database needs: `Name` (title), `Done` (checkbox), and optionally `Due` (date), `Priority` (select: Low / Medium / High), `Tags` (multi-select).
Setup: create an internal integration at [notion.so/my-integrations](https://www.notion.so/my-integrations), then share your database with it.
### Apple Reminders
```json
{
"adapter": {
"type": "reminders",
"list": "To Do"
}
}
```
No API key needed — reads directly from the Reminders app via AppleScript. macOS only.
`list` is optional. If omitted, nudge reads all lists. If you have a lot of reminders or multiple iCloud accounts, specifying a list is faster and more reliable.
**Troubleshooting:**
- **First run** — macOS will prompt for Automation permission. Click Allow when asked, or go to System Settings → Privacy & Security → Automation and enable Reminders for your terminal.
- **iCloud sync issues** — if you get a "Can't get" error, open Reminders.app and wait for it to fully sync before trying again.
- **Timeouts with large lists** — add `"list": "To Do"` (or whichever list you use most) to your config to limit the scope.
- **List name must match exactly** — including capitalisation. Run `osascript -e 'tell application "Reminders" to get name of every list'` in Terminal to see your exact list names.
---
## Tools
nudge exposes these tools to any connected AI:
| Tool | What it does |
|---|---|
| `check_tasks` | "Did I ever call the dentist?" — fuzzy matched |
| `get_pending_today` | What's still open and due today |
| `list_todos` | Full list, with filters (overdue, tag, priority, done) |
| `get_stats` | Honest summary — done, pending, overdue |
| `search_todos` | Find tasks by keyword |
| `create_todo` | "Remind me to call Dave on Friday" → adds it |
| `mark_complete` | "Done with the report" → ticks it off |
| `mark_incomplete` | "Actually I didn't finish that" → reopens it |
nudge also ships a **suggested system prompt** (as an MCP prompt resource named `nudge-persona`) that gives the AI the right tone: warm, honest, not preachy. Claude Desktop can pick this up automatically.
---
## Connecting apps without a native adapter
**Apple Shortcuts** — build a shortcut that exports tasks as JSON to `~/.nudge/todos.json` on a schedule.
**Zapier / Make** — add a step that writes task updates to the file whenever something changes in your app.
**Obsidian / Logseq** — point `filePath` at your daily note and use `format: "markdown"`.
**Any CLI app** — add a cron: `0 * * * * myapp export --format json > ~/.nudge/todos.json`
---
## Writing a new adapter
Each adapter is a single file in `src/adapters/`. Implement two required methods and you're done:
```typescript
import { Todo, NewTodo, TodoAdapter } from "../types.js";
export class MyAppAdapter implements TodoAdapter {
name = "myapp";
async listTodos(): Promise<Todo[]> {
// fetch from your app's API
return [];
}
async getTodo(id: string): Promise<Todo | null> {
return null;
}
// Optional — enables create_todo tool
async createTodo(input: NewTodo): Promise<Todo> { ... }
// Optional — enables mark complete/incomplete
async markComplete(id: string): Promise<void> { ... }
async markIncomplete(id: string): Promise<void> { ... }
}
```
Then register it in `src/index.ts` in `buildAdapter()`. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
---
## Roadmap
- [x] `nudge init` — interactive setup wizard
- [x] Apple Reminders adapter (macOS, via AppleScript)
- [x] Linear adapter
- [x] GitHub Issues adapter
- [x] `mark_complete` / `mark_incomplete` tools
- [ ] Asana / Microsoft To Do adapter
- [ ] Webhook listener for real-time push (tasks trigger the AI)
- [ ] Scheduled nudge mode (daily check-in without opening Claude)
---
## Contributing
PRs and issues are welcome — especially new adapters. See [CONTRIBUTING.md](CONTRIBUTING.md).
## License
[MIT](LICENSE) © Dave Leal
TDQS
A3.9/5.0
Scored across 8 tools
Disambiguation4/5
Tools are mostly distinct but check_tasks and search_todos overlap in searching, and list_todos with filters overlaps with get_pending_today and get_stats, causing mild ambiguity.
Naming Consistency5/5
All tool names follow a consistent verb_noun snake_case pattern (e.g., create_todo, mark_complete), making them predictable and easy to distinguish.
Tool Count5/5
With 8 tools, the set is well-scoped for a task management assistant, covering core operations without being overwhelming.
Completeness4/5
The set covers CRUD operations except for task deletion, and lacks editing capabilities, but the core lifecycle (create, read, update status) is present.
Maintenance
ActivityInactive
ResponsivenessNo issues