@lcajigasm/things3-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luis Cajigas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # things3-mcp
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40lcajigasm%2Fthings3-mcp)](https://www.npmjs.com/package/@lcajigasm/things3-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that connects Claude to [Things 3](https://culturedcode.com/things/) on macOS. Ask Claude to add to-dos and projects, search, open lists, and read your Today/Upcoming/Inbox — all from a Claude conversation.
7
+
8
+ > **Unofficial project.** Not affiliated with, endorsed by, or supported by Cultured Code. Things 3 is a trademark of Cultured Code GmbH & Co. KG.
9
+
10
+ ## How it works
11
+
12
+ Things 3 doesn't expose a network API, so this server uses two different mechanisms:
13
+
14
+ - **Writing** (`add_todo`, `add_project`, `update_todo`, `update_project`, `search`, `show`) opens Things' [URL scheme](https://culturedcode.com/things/help/url-scheme/) in the background via `open -g things:///...`. This requires Things 3 to be running.
15
+ - **Reading** (`list_today`, `list_upcoming`, `list_projects`, `list_inbox`, `get_todo`) queries Things' local SQLite database directly, in read-only mode. The URL scheme has no way to read data back, so this is the only option.
16
+
17
+ ## Prerequisites
18
+
19
+ - **macOS** with **Things 3** installed and running
20
+ - **Node.js 18+**
21
+ - To use `update_todo` / `update_project`: enable Things URLs in **Things → Settings → General → Enable Things URLs** and copy the auth token shown there
22
+
23
+ This server is macOS-only and talks to a local app and a local file — it is not a remote/OAuth-capable MCP server and cannot be hosted or used from another machine.
24
+
25
+ ## Installation
26
+
27
+ ### Claude Desktop
28
+
29
+ Add the following to `~/Library/Application Support/Claude/claude_desktop_config.json`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "things3": {
35
+ "command": "npx",
36
+ "args": ["-y", "@lcajigasm/things3-mcp"],
37
+ "env": {
38
+ "THINGS_AUTH_TOKEN": "your-token-here"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Omit `THINGS_AUTH_TOKEN` if you don't need `update_todo` / `update_project`. Restart Claude Desktop afterwards.
46
+
47
+ ### Claude Code
48
+
49
+ ```bash
50
+ claude mcp add things3 --env THINGS_AUTH_TOKEN=your-token-here -- npx -y @lcajigasm/things3-mcp
51
+ ```
52
+
53
+ ### From source
54
+
55
+ ```bash
56
+ git clone https://github.com/lcajigasm/things3-mcp.git
57
+ cd things3-mcp
58
+ npm install
59
+ npm run build
60
+ ```
61
+
62
+ Then point Claude Desktop at the built file:
63
+
64
+ ```json
65
+ {
66
+ "mcpServers": {
67
+ "things3": {
68
+ "command": "node",
69
+ "args": ["/absolute/path/to/things3-mcp/dist/index.js"],
70
+ "env": {
71
+ "THINGS_AUTH_TOKEN": "your-token-here"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Environment variables
79
+
80
+ | Variable | Required | Description |
81
+ |---|---|---|
82
+ | `THINGS_AUTH_TOKEN` | Only for `update_todo` / `update_project` | Auth token from Things → Settings → General → Enable Things URls. Never logged or echoed back by this server. |
83
+
84
+ ## Available tools
85
+
86
+ ### Writing (via URL scheme)
87
+
88
+ | Tool | Description |
89
+ |---|---|
90
+ | `add_todo` | Create a to-do: title, notes, `when` (today/tomorrow/evening/someday/date), deadline, tags, checklist items, destination list. |
91
+ | `add_project` | Create a project: title, notes, area, tags, initial to-dos. |
92
+ | `update_todo` | Update a to-do by id. Requires `THINGS_AUTH_TOKEN`. |
93
+ | `update_project` | Update a project by id. Requires `THINGS_AUTH_TOKEN`. |
94
+ | `search` | Open Things and search for a term. |
95
+ | `show` | Open a built-in list (Today, Upcoming, Anytime, Someday, Logbook, Inbox) or a specific project/area/to-do by id. |
96
+
97
+ ### Reading (via local database, read-only)
98
+
99
+ | Tool | Description |
100
+ |---|---|
101
+ | `list_today` | To-dos scheduled for Today. |
102
+ | `list_upcoming` | To-dos scheduled for a future date or with an upcoming deadline. |
103
+ | `list_projects` | Open (incomplete, non-trashed) projects. |
104
+ | `list_inbox` | Unclassified to-dos in the Inbox. |
105
+ | `get_todo` | Full detail for one to-do by id, including its checklist. |
106
+
107
+ ## Example prompts
108
+
109
+ - "Add a to-do 'Renew passport' with a deadline of 2026-09-01"
110
+ - "Create a project called 'Q3 planning' in my Work area with to-dos for budget, hiring, roadmap"
111
+ - "What's on my plate today?"
112
+ - "What's coming up in the next few weeks?"
113
+ - "Show me everything sitting in my Inbox"
114
+ - "Mark to-do abc-123 as completed"
115
+ - "Open Things and search for 'invoice'"
116
+
117
+ ## Limitations
118
+
119
+ - macOS + Things 3 only. No Windows/Linux/iOS support, no remote/hosted mode.
120
+ - Writing is fire-and-forget: the URL scheme doesn't return the created item's id, so `add_todo`/`add_project` can't tell you the new id directly (use `search` or `list_inbox` to find it afterwards).
121
+ - Reading queries Things' internal SQLite schema, which is undocumented and could change in future Things versions.
122
+ - `update_todo`/`update_project` need `THINGS_AUTH_TOKEN`; without it those two tools return an error, everything else still works.
123
+
124
+ ## Troubleshooting
125
+
126
+ **"things3-mcp only works on macOS"**
127
+ This server calls `open -g things:///...` and reads a macOS-only app container path — there's no way around this.
128
+
129
+ **"Could not find the Things 3 database"**
130
+ Make sure Things 3 is installed and has been opened at least once (the database is created on first launch).
131
+
132
+ **"THINGS_AUTH_TOKEN environment variable is required"**
133
+ Only `update_todo`/`update_project` need it. Get it from Things → Settings → General → Enable Things URLs, then add it to your MCP config's `env` block.
134
+
135
+ **Claude doesn't see the Things 3 tools**
136
+ - Restart Claude Desktop after editing the config file
137
+ - Validate the JSON in `claude_desktop_config.json` (a trailing comma will break it)
138
+ - Run `npx @lcajigasm/things3-mcp` manually in a terminal to check for Node errors
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ npm install
144
+ npm run dev # watch mode via tsx
145
+ npm run build # compile to dist/
146
+ ```
147
+
148
+ ## License
149
+
150
+ MIT — see [LICENSE](LICENSE). Not affiliated with Cultured Code.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env node
2
+ import { execFile } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import path from "node:path";
6
+ import { promisify } from "node:util";
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import Database from "better-sqlite3";
10
+ import { z } from "zod";
11
+ const execFileAsync = promisify(execFile);
12
+ // ---------------------------------------------------------------------------
13
+ // Configuration
14
+ // ---------------------------------------------------------------------------
15
+ if (process.platform !== "darwin") {
16
+ console.error("things3-mcp only works on macOS — Things 3 is a macOS-only app.");
17
+ process.exit(1);
18
+ }
19
+ const AUTH_TOKEN = process.env.THINGS_AUTH_TOKEN;
20
+ const DB_PATH = path.join(homedir(), "Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac/Things Database.thingsdatabase/main.sqlite");
21
+ // ---------------------------------------------------------------------------
22
+ // Things URL scheme (write operations)
23
+ // ---------------------------------------------------------------------------
24
+ class ThingsError extends Error {
25
+ }
26
+ function buildThingsUrl(action, params) {
27
+ const pairs = [];
28
+ for (const [key, value] of Object.entries(params)) {
29
+ if (value === undefined || value === null || value === "")
30
+ continue;
31
+ pairs.push(`${key}=${encodeURIComponent(String(value))}`);
32
+ }
33
+ return `things:///${action}${pairs.length ? "?" + pairs.join("&") : ""}`;
34
+ }
35
+ async function openThingsUrl(url) {
36
+ try {
37
+ await execFileAsync("open", ["-g", url]);
38
+ }
39
+ catch (err) {
40
+ const msg = err instanceof Error ? err.message : String(err);
41
+ throw new ThingsError(`Failed to open Things URL: ${msg}`);
42
+ }
43
+ }
44
+ function requireAuthToken() {
45
+ if (!AUTH_TOKEN) {
46
+ throw new ThingsError("THINGS_AUTH_TOKEN environment variable is required for update operations. " +
47
+ "Get it from Things → Settings → General → Enable Things URLs.");
48
+ }
49
+ return AUTH_TOKEN;
50
+ }
51
+ function toolResult(data) {
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2),
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ function errorResult(err) {
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ return { content: [{ type: "text", text: `Error: ${message}` }] };
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Things date encoding
67
+ // ---------------------------------------------------------------------------
68
+ // Things packs startDate/deadline into a single integer as
69
+ // (year << 16) | (month << 12) | (day << 7), which conveniently also sorts
70
+ // correctly as a plain integer.
71
+ function encodeThingsDate(date) {
72
+ const year = date.getFullYear();
73
+ const month = date.getMonth() + 1;
74
+ const day = date.getDate();
75
+ return (year << 16) | (month << 12) | (day << 7);
76
+ }
77
+ function decodeThingsDate(value) {
78
+ if (value === null)
79
+ return null;
80
+ const year = value >> 16;
81
+ const month = (value >> 12) & 0xf;
82
+ const day = (value >> 7) & 0x1f;
83
+ return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
84
+ }
85
+ // Core Data timestamps are seconds since 2001-01-01, not the Unix epoch.
86
+ const CORE_DATA_EPOCH_OFFSET = 978307200;
87
+ function decodeCoreDataDate(value) {
88
+ if (value === null)
89
+ return null;
90
+ return new Date((value + CORE_DATA_EPOCH_OFFSET) * 1000).toISOString();
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // SQLite (read operations)
94
+ // ---------------------------------------------------------------------------
95
+ let db = null;
96
+ function getDb() {
97
+ if (db)
98
+ return db;
99
+ if (!existsSync(DB_PATH)) {
100
+ throw new ThingsError(`Could not find the Things 3 database at "${DB_PATH}". ` +
101
+ "Make sure Things 3 is installed and has been opened at least once.");
102
+ }
103
+ db = new Database(DB_PATH, { readonly: true, fileMustExist: true });
104
+ return db;
105
+ }
106
+ const STATUS_LABELS = {
107
+ 0: "open",
108
+ 2: "canceled",
109
+ 3: "completed",
110
+ };
111
+ function formatTaskRow(row) {
112
+ return {
113
+ id: row.uuid,
114
+ title: row.title,
115
+ notes: row.notes || undefined,
116
+ status: STATUS_LABELS[row.status] ?? String(row.status),
117
+ when: decodeThingsDate(row.startDate) ?? undefined,
118
+ deadline: decodeThingsDate(row.deadline) ?? undefined,
119
+ completedAt: decodeCoreDataDate(row.stopDate) ?? undefined,
120
+ tags: row.tags ? row.tags.split(", ") : undefined,
121
+ project: row.project ?? undefined,
122
+ area: row.area ?? undefined,
123
+ };
124
+ }
125
+ const TASK_SELECT = `
126
+ SELECT
127
+ t.uuid, t.title, t.notes, t.status, t.startDate, t.deadline, t.stopDate,
128
+ (SELECT group_concat(tag.title, ', ')
129
+ FROM TMTaskTag tt JOIN TMTag tag ON tt.tags = tag.uuid
130
+ WHERE tt.tasks = t.uuid) AS tags,
131
+ p.title AS project,
132
+ a.title AS area
133
+ FROM TMTask t
134
+ LEFT JOIN TMTask p ON t.project = p.uuid
135
+ LEFT JOIN TMArea a ON t.area = a.uuid
136
+ `;
137
+ // ---------------------------------------------------------------------------
138
+ // MCP Server
139
+ // ---------------------------------------------------------------------------
140
+ const server = new McpServer({
141
+ name: "things3-mcp",
142
+ version: "1.0.0",
143
+ });
144
+ // --- Write tools -----------------------------------------------------------
145
+ server.tool("add_todo", "Create a new to-do in Things 3.", {
146
+ title: z.string().describe("The to-do's title (required)"),
147
+ notes: z.string().optional().describe("Notes for the to-do"),
148
+ when: z
149
+ .string()
150
+ .optional()
151
+ .describe("When to schedule it: 'today', 'tomorrow', 'evening', 'someday', or a YYYY-MM-DD date"),
152
+ deadline: z.string().optional().describe("Deadline as a YYYY-MM-DD date"),
153
+ tags: z.array(z.string()).optional().describe("Tags to apply (must already exist in Things)"),
154
+ checklistItems: z.array(z.string()).optional().describe("Checklist item titles to add"),
155
+ list: z.string().optional().describe("Name of the destination project or area"),
156
+ }, async ({ title, notes, when, deadline, tags, checklistItems, list }) => {
157
+ try {
158
+ const url = buildThingsUrl("add", {
159
+ title,
160
+ notes,
161
+ when,
162
+ deadline,
163
+ tags: tags?.join(","),
164
+ "checklist-items": checklistItems?.join("\n"),
165
+ list,
166
+ });
167
+ await openThingsUrl(url);
168
+ return toolResult({ status: "ok", url });
169
+ }
170
+ catch (err) {
171
+ return errorResult(err);
172
+ }
173
+ });
174
+ server.tool("add_project", "Create a new project in Things 3.", {
175
+ title: z.string().describe("The project's title (required)"),
176
+ notes: z.string().optional().describe("Notes for the project"),
177
+ area: z.string().optional().describe("Name of the destination area"),
178
+ tags: z.array(z.string()).optional().describe("Tags to apply (must already exist in Things)"),
179
+ todos: z.array(z.string()).optional().describe("Titles of initial to-dos to create inside the project"),
180
+ }, async ({ title, notes, area, tags, todos }) => {
181
+ try {
182
+ const url = buildThingsUrl("add-project", {
183
+ title,
184
+ notes,
185
+ area,
186
+ tags: tags?.join(","),
187
+ "to-dos": todos?.join("\n"),
188
+ });
189
+ await openThingsUrl(url);
190
+ return toolResult({ status: "ok", url });
191
+ }
192
+ catch (err) {
193
+ return errorResult(err);
194
+ }
195
+ });
196
+ server.tool("update_todo", "Update an existing to-do in Things 3. Requires THINGS_AUTH_TOKEN to be set.", {
197
+ id: z.string().describe("The to-do's id (required)"),
198
+ title: z.string().optional().describe("New title"),
199
+ notes: z.string().optional().describe("New notes (replaces existing notes)"),
200
+ when: z.string().optional().describe("New schedule: 'today', 'tomorrow', 'evening', 'someday', or a YYYY-MM-DD date"),
201
+ deadline: z.string().optional().describe("New deadline as a YYYY-MM-DD date"),
202
+ tags: z.array(z.string()).optional().describe("Replace all tags with this set"),
203
+ checklistItems: z.array(z.string()).optional().describe("Replace the checklist with these items"),
204
+ completed: z.boolean().optional().describe("Mark as completed"),
205
+ canceled: z.boolean().optional().describe("Mark as canceled"),
206
+ }, async ({ id, tags, checklistItems, ...rest }) => {
207
+ try {
208
+ const token = requireAuthToken();
209
+ const url = buildThingsUrl("update", {
210
+ id,
211
+ "auth-token": token,
212
+ ...rest,
213
+ tags: tags?.join(","),
214
+ "checklist-items": checklistItems?.join("\n"),
215
+ });
216
+ await openThingsUrl(url);
217
+ return toolResult({ status: "ok" });
218
+ }
219
+ catch (err) {
220
+ return errorResult(err);
221
+ }
222
+ });
223
+ server.tool("update_project", "Update an existing project in Things 3. Requires THINGS_AUTH_TOKEN to be set.", {
224
+ id: z.string().describe("The project's id (required)"),
225
+ title: z.string().optional().describe("New title"),
226
+ notes: z.string().optional().describe("New notes (replaces existing notes)"),
227
+ area: z.string().optional().describe("Move the project to this area"),
228
+ tags: z.array(z.string()).optional().describe("Replace all tags with this set"),
229
+ completed: z.boolean().optional().describe("Mark as completed"),
230
+ canceled: z.boolean().optional().describe("Mark as canceled"),
231
+ }, async ({ id, tags, ...rest }) => {
232
+ try {
233
+ const token = requireAuthToken();
234
+ const url = buildThingsUrl("update-project", {
235
+ id,
236
+ "auth-token": token,
237
+ ...rest,
238
+ tags: tags?.join(","),
239
+ });
240
+ await openThingsUrl(url);
241
+ return toolResult({ status: "ok" });
242
+ }
243
+ catch (err) {
244
+ return errorResult(err);
245
+ }
246
+ });
247
+ server.tool("search", "Open Things 3 and search for a term.", {
248
+ query: z.string().describe("The search term"),
249
+ }, async ({ query }) => {
250
+ try {
251
+ const url = buildThingsUrl("search", { query });
252
+ await openThingsUrl(url);
253
+ return toolResult({ status: "ok" });
254
+ }
255
+ catch (err) {
256
+ return errorResult(err);
257
+ }
258
+ });
259
+ server.tool("show", "Open a built-in list (Today, Upcoming, Anytime, Someday, Logbook, Inbox) or a project/area by id in Things 3.", {
260
+ list: z.string().optional().describe("Built-in list name, e.g. 'today', 'upcoming', 'anytime', 'someday', 'logbook', 'inbox'"),
261
+ id: z.string().optional().describe("Id of a specific project, area, or to-do to open"),
262
+ }, async ({ list, id }) => {
263
+ try {
264
+ if (!list && !id) {
265
+ throw new ThingsError("Provide either 'list' or 'id'.");
266
+ }
267
+ const url = buildThingsUrl("show", { list, id });
268
+ await openThingsUrl(url);
269
+ return toolResult({ status: "ok" });
270
+ }
271
+ catch (err) {
272
+ return errorResult(err);
273
+ }
274
+ });
275
+ // --- Read tools --------------------------------------------------------
276
+ server.tool("list_today", "List to-dos scheduled for Today.", {}, async () => {
277
+ try {
278
+ const rows = getDb()
279
+ .prepare(`${TASK_SELECT}
280
+ WHERE t.type = 0 AND t.trashed = 0 AND t.status = 0
281
+ AND t.start = 1 AND t.startDate IS NOT NULL
282
+ ORDER BY t."index" ASC`)
283
+ .all();
284
+ return toolResult(rows.map(formatTaskRow));
285
+ }
286
+ catch (err) {
287
+ return errorResult(err);
288
+ }
289
+ });
290
+ server.tool("list_upcoming", "List to-dos scheduled for a future date or with an upcoming deadline.", {
291
+ limit: z.number().int().min(1).max(200).default(50).describe("Max number of results (default 50)"),
292
+ }, async ({ limit }) => {
293
+ try {
294
+ const todayEncoded = encodeThingsDate(new Date());
295
+ const rows = getDb()
296
+ .prepare(`${TASK_SELECT}
297
+ WHERE t.type = 0 AND t.trashed = 0 AND t.status = 0
298
+ AND (
299
+ (t.startDate IS NOT NULL AND t.startDate > @today)
300
+ OR (t.deadline IS NOT NULL AND t.deadline >= @today)
301
+ )
302
+ ORDER BY COALESCE(t.startDate, t.deadline) ASC
303
+ LIMIT @limit`)
304
+ .all({ today: todayEncoded, limit });
305
+ return toolResult(rows.map(formatTaskRow));
306
+ }
307
+ catch (err) {
308
+ return errorResult(err);
309
+ }
310
+ });
311
+ server.tool("list_projects", "List open (non-trashed, incomplete) projects.", {}, async () => {
312
+ try {
313
+ const rows = getDb()
314
+ .prepare(`${TASK_SELECT}
315
+ WHERE t.type = 1 AND t.trashed = 0 AND t.status = 0
316
+ ORDER BY t."index" ASC`)
317
+ .all();
318
+ return toolResult(rows.map(formatTaskRow));
319
+ }
320
+ catch (err) {
321
+ return errorResult(err);
322
+ }
323
+ });
324
+ server.tool("list_inbox", "List unclassified to-dos in the Inbox.", {}, async () => {
325
+ try {
326
+ const rows = getDb()
327
+ .prepare(`${TASK_SELECT}
328
+ WHERE t.type = 0 AND t.trashed = 0 AND t.status = 0 AND t.start = 0
329
+ ORDER BY t."index" ASC`)
330
+ .all();
331
+ return toolResult(rows.map(formatTaskRow));
332
+ }
333
+ catch (err) {
334
+ return errorResult(err);
335
+ }
336
+ });
337
+ server.tool("get_todo", "Get full details for a single to-do by id, including its checklist.", {
338
+ id: z.string().describe("The to-do's id"),
339
+ }, async ({ id }) => {
340
+ try {
341
+ const row = getDb()
342
+ .prepare(`${TASK_SELECT} WHERE t.uuid = @id AND t.type = 0`)
343
+ .get({ id });
344
+ if (!row) {
345
+ throw new ThingsError(`No to-do found with id "${id}".`);
346
+ }
347
+ const checklist = getDb()
348
+ .prepare(`SELECT title, status FROM TMChecklistItem WHERE task = @id ORDER BY "index" ASC`)
349
+ .all({ id });
350
+ return toolResult({
351
+ ...formatTaskRow(row),
352
+ checklist: checklist.map((item) => ({
353
+ title: item.title,
354
+ status: STATUS_LABELS[item.status] ?? String(item.status),
355
+ })),
356
+ });
357
+ }
358
+ catch (err) {
359
+ return errorResult(err);
360
+ }
361
+ });
362
+ // ---------------------------------------------------------------------------
363
+ // Start
364
+ // ---------------------------------------------------------------------------
365
+ async function main() {
366
+ const transport = new StdioServerTransport();
367
+ await server.connect(transport);
368
+ console.error("Things 3 MCP server running on stdio");
369
+ }
370
+ main().catch((err) => {
371
+ console.error("Fatal error:", err);
372
+ process.exit(1);
373
+ });
374
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@lcajigasm/things3-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server connecting Claude to Things 3 on macOS via its URL scheme (write) and local database (read)",
5
+ "type": "module",
6
+ "bin": {
7
+ "things3-mcp": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsx watch src/index.ts",
12
+ "start": "node dist/index.js"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "keywords": [
18
+ "mcp",
19
+ "things",
20
+ "things3",
21
+ "claude",
22
+ "task-management",
23
+ "todo",
24
+ "productivity",
25
+ "model-context-protocol"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/lcajigasm/things3-mcp.git"
30
+ },
31
+ "homepage": "https://github.com/lcajigasm/things3-mcp#readme",
32
+ "bugs": {
33
+ "url": "https://github.com/lcajigasm/things3-mcp/issues"
34
+ },
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "os": [
40
+ "darwin"
41
+ ],
42
+ "engines": {
43
+ "node": ">=18"
44
+ },
45
+ "dependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.12.0",
47
+ "better-sqlite3": "^12.11.1",
48
+ "zod": "^3.24.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/better-sqlite3": "^7.6.12",
52
+ "@types/node": "^22.0.0",
53
+ "tsx": "^4.19.0",
54
+ "typescript": "^5.8.0"
55
+ },
56
+ "allowScripts": {
57
+ "better-sqlite3@12.11.1": true
58
+ }
59
+ }