Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- run: npm ci
- run: npm run typecheck
- run: npm run build
- run: npm test
- run: npm run format:check
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist
node_modules
package-lock.json
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"endOfLine": "auto"
}
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project will be documented in this file.

## [0.2.1]

### Changed

- **Node.js minimum version**: Raised from 20 to 22
- **README**: Added experimental disclaimer

### Added

- **CI workflow**: GitHub Actions — build, typecheck, and test on Ubuntu, macOS, and Windows (Node 22)

## [0.2.0]

### Security
Expand Down Expand Up @@ -53,6 +64,7 @@ Initial release. Full implementation from spec (`spec/intent.md`).
### Added

**CLI** (`todo` command)

- `todo setup` — interactive OAuth 2.0 PKCE authentication flow
- `todo serve` — start MCP server on stdio
- `todo lists` — list, create, update, delete task lists
Expand All @@ -62,27 +74,32 @@ Initial release. Full implementation from spec (`spec/intent.md`).
- `todo help` — usage reference

**MCP Server** (15 tools)

- `list-task-lists`, `create-task-list`, `update-task-list`, `delete-task-list`
- `list-tasks`, `create-task`, `update-task`, `delete-task`, `complete-task`
- `list-checklist-items`, `create-checklist-item`, `update-checklist-item`, `delete-checklist-item`

**Authentication**

- OAuth 2.0 Authorization Code with PKCE (public client — no client secret)
- AES-256-GCM encrypted token storage with PBKDF2 key derivation
- Automatic token refresh with mutex to prevent concurrent refresh races
- Environment variable override for CI/headless (`TODO_MCP_ACCESS_TOKEN`, `TODO_MCP_REFRESH_TOKEN`)

**Security**

- No client secret anywhere in the codebase
- Encrypted token persistence — never plaintext
- Minimal scopes: `Tasks.ReadWrite` + `offline_access` only
- No PII logging, no response body logging, no telemetry
- 2 runtime dependencies only (`@modelcontextprotocol/sdk`, `zod`)

**Tests**

- 115 unit tests across 7 test files (vitest)

**Documentation**

- Getting started guide
- Azure app registration (Portal + Azure CLI)
- CLI reference
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A **CLI-first** tool for managing Microsoft To Do tasks, with an optional MCP server for AI agents.

> **⚠️ Experimental** — This software is experimental and provided "as is" without warranty of any kind. Use at your own risk. See [LICENSE](LICENSE) for details.

## Install

```bash
Expand Down Expand Up @@ -58,4 +60,3 @@ Add to VS Code `settings.json` for Copilot integration:
## License

MIT

18 changes: 9 additions & 9 deletions docs/azure-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ This prints your **Application (client) ID**. Save it.

**`--sign-in-audience` options:**

| Value | Description |
|---|---|
| `PersonalMicrosoftAccount` | Personal Microsoft accounts only (@outlook.com, @hotmail.com, @live.com) |
| `AzureADandPersonalMicrosoftAccount` | Work/school + personal accounts |
| `AzureADMyOrg` | Single organization only |
| Value | Description |
| ------------------------------------ | ------------------------------------------------------------------------ |
| `PersonalMicrosoftAccount` | Personal Microsoft accounts only (@outlook.com, @hotmail.com, @live.com) |
| `AzureADandPersonalMicrosoftAccount` | Work/school + personal accounts |
| `AzureADMyOrg` | Single organization only |

### 2. Add Tasks.ReadWrite permission

Expand All @@ -88,10 +88,10 @@ Replace `<your-client-id>` with the ID from the previous step.

## Account Type Guidance

| Account type | Tenant value | Example domains |
|---|---|---|
| Personal accounts | `consumers` (the default) | @outlook.com, @hotmail.com, @live.com |
| Work/school accounts | `common` or your org's tenant ID | @yourcompany.com |
| Account type | Tenant value | Example domains |
| -------------------- | -------------------------------- | ------------------------------------- |
| Personal accounts | `consumers` (the default) | @outlook.com, @hotmail.com, @live.com |
| Work/school accounts | `common` or your org's tenant ID | @yourcompany.com |

To set the tenant explicitly:

Expand Down
84 changes: 42 additions & 42 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Full command reference for `@thingsai/todo-mcp-server`.

## Global Flags

| Flag | Description |
| ----------- | ------------------------------------------------ |
| Flag | Description |
| ----------- | ----------------------------------------------------------- |
| `--json` | Output in JSON format (available on all read/list commands) |
| `--version` | Show the version number |
| `--version` | Show the version number |

> **Note:** Unknown flags are rejected. The CLI uses strict argument parsing to prevent silent errors.

Expand Down Expand Up @@ -109,17 +109,17 @@ Use `--status` to filter by task status (`notStarted`, `inProgress`, `completed`

Create a task.

| Flag | Required | Description |
| ---------------- | -------- | --------------------------------------------------------------------------- |
| `--list <id>` | Yes | Task list ID |
| `--title <text>` | Yes | Task title |
| `--due <date>` | No | Due date (e.g. `2026-04-20`) |
| `--importance` | No | `low`, `normal`, or `high` |
| `--body <text>` | No | Task body / notes |
| `--reminder` | No | Reminder date-time (e.g. `2026-04-20T09:00:00Z`) |
| `--start <date>` | No | Start date |
| `--status` | No | `notStarted`, `inProgress`, `completed`, `waitingOnOthers`, or `deferred` |
| `--categories` | No | Comma-separated categories (e.g. `groceries,errands`) |
| Flag | Required | Description |
| ---------------- | -------- | ------------------------------------------------------------------------- |
| `--list <id>` | Yes | Task list ID |
| `--title <text>` | Yes | Task title |
| `--due <date>` | No | Due date (e.g. `2026-04-20`) |
| `--importance` | No | `low`, `normal`, or `high` |
| `--body <text>` | No | Task body / notes |
| `--reminder` | No | Reminder date-time (e.g. `2026-04-20T09:00:00Z`) |
| `--start <date>` | No | Start date |
| `--status` | No | `notStarted`, `inProgress`, `completed`, `waitingOnOthers`, or `deferred` |
| `--categories` | No | Comma-separated categories (e.g. `groceries,errands`) |

```bash
# Minimal
Expand All @@ -137,18 +137,18 @@ todo tasks create --list AAMkAD... --title "Buy milk" \

Update a task. All fields except `--list` and `--task` are optional. Pass an empty string to date fields to clear them.

| Flag | Required | Description |
| ---------------- | -------- | ------------------ |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--title` | No | New title |
| `--due` | No | New due date |
| `--importance` | No | New importance |
| `--body` | No | New body text |
| `--reminder` | No | New reminder |
| `--start` | No | New start date |
| `--status` | No | New status |
| `--categories` | No | New categories |
| Flag | Required | Description |
| -------------- | -------- | -------------- |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--title` | No | New title |
| `--due` | No | New due date |
| `--importance` | No | New importance |
| `--body` | No | New body text |
| `--reminder` | No | New reminder |
| `--start` | No | New start date |
| `--status` | No | New status |
| `--categories` | No | New categories |

```bash
todo tasks update --list AAMkAD... --task AAMkAD... --title "Buy oat milk"
Expand Down Expand Up @@ -192,11 +192,11 @@ todo checklist --list AAMkAD... --task AAMkAD... --json

Add a checklist item.

| Flag | Required | Description |
| ---------------- | -------- | ------------------ |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--text <text>` | Yes | Item display text |
| Flag | Required | Description |
| --------------- | -------- | ----------------- |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--text <text>` | Yes | Item display text |

```bash
todo checklist add --list AAMkAD... --task AAMkAD... --text "Check expiry date"
Expand All @@ -206,14 +206,14 @@ todo checklist add --list AAMkAD... --task AAMkAD... --text "Check expiry date"

Update a checklist item.

| Flag | Required | Description |
| ---------------- | -------- | ---------------------------- |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--item <id>` | Yes | Checklist item ID |
| `--text <text>` | No | New display text |
| `--checked` | No | Mark the item as checked |
| `--unchecked` | No | Mark the item as unchecked |
| Flag | Required | Description |
| --------------- | -------- | -------------------------- |
| `--list <id>` | Yes | Task list ID |
| `--task <id>` | Yes | Task ID |
| `--item <id>` | Yes | Checklist item ID |
| `--text <text>` | No | New display text |
| `--checked` | No | Mark the item as checked |
| `--unchecked` | No | Mark the item as unchecked |

```bash
todo checklist update --list AAMkAD... --task AAMkAD... --item AAMkAD... --checked
Expand Down Expand Up @@ -271,7 +271,7 @@ todo checklist --list AAMkAD... --task AAMkAD... --json

## Exit Codes

| Code | Meaning |
| ---- | ------------------------------------------------ |
| `0` | Success |
| Code | Meaning |
| ---- | -------------------------------------------------- |
| `0` | Success |
| `1` | Error (missing arguments, auth failure, API error) |
22 changes: 11 additions & 11 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ Configuration reference for `@thingsai/todo-mcp-server`.

## Environment Variables

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `TODO_MCP_CLIENT_ID` | Yes (for setup) | — | Azure AD Application (client) ID from your app registration |
| `TODO_MCP_TENANT` | No | `consumers` | Azure AD tenant. Options: `consumers` (personal accounts), `common` (personal + org), or a specific tenant ID |
| `TODO_MCP_ACCESS_TOKEN` | No | — | Use this access token directly, bypassing encrypted store. For CI/headless. |
| `TODO_MCP_REFRESH_TOKEN` | No | — | Used alongside `TODO_MCP_ACCESS_TOKEN` for token refresh in CI/headless scenarios |
| Variable | Required | Default | Description |
| ------------------------ | --------------- | ----------- | ------------------------------------------------------------------------------------------------------------- |
| `TODO_MCP_CLIENT_ID` | Yes (for setup) | — | Azure AD Application (client) ID from your app registration |
| `TODO_MCP_TENANT` | No | `consumers` | Azure AD tenant. Options: `consumers` (personal accounts), `common` (personal + org), or a specific tenant ID |
| `TODO_MCP_ACCESS_TOKEN` | No | — | Use this access token directly, bypassing encrypted store. For CI/headless. |
| `TODO_MCP_REFRESH_TOKEN` | No | — | Used alongside `TODO_MCP_ACCESS_TOKEN` for token refresh in CI/headless scenarios |

## Token Storage

Tokens are encrypted at rest using AES-256-GCM with a machine-derived key.

### Storage Locations

| Platform | Path |
|----------|------|
| Windows | `%APPDATA%\todo-mcp\tokens.enc` |
| macOS | `~/.config/todo-mcp/tokens.enc` |
| Linux | `~/.config/todo-mcp/tokens.enc` |
| Platform | Path |
| -------- | ------------------------------- |
| Windows | `%APPDATA%\todo-mcp\tokens.enc` |
| macOS | `~/.config/todo-mcp/tokens.enc` |
| Linux | `~/.config/todo-mcp/tokens.enc` |

### Encryption Details

Expand Down
Loading
Loading