@cpenned/mcp 0.8.4 → 0.9.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/README.md +34 -7
- package/dist/client.js +40 -6
- package/dist/client.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/server.js +16 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/api.js +41 -0
- package/dist/tools/api.js.map +1 -0
- package/dist/tools/attachments.js +43 -0
- package/dist/tools/attachments.js.map +1 -0
- package/dist/tools/books.js +24 -18
- package/dist/tools/books.js.map +1 -1
- package/dist/tools/comments.js +63 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/gardens.js +8 -7
- package/dist/tools/gardens.js.map +1 -1
- package/dist/tools/habits.js +26 -18
- package/dist/tools/habits.js.map +1 -1
- package/dist/tools/index.js +2 -34
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/keys.js +23 -7
- package/dist/tools/keys.js.map +1 -1
- package/dist/tools/lists.js +6 -5
- package/dist/tools/lists.js.map +1 -1
- package/dist/tools/people.js +17 -15
- package/dist/tools/people.js.map +1 -1
- package/dist/tools/profile.js +18 -6
- package/dist/tools/profile.js.map +1 -1
- package/dist/tools/projects.js +14 -8
- package/dist/tools/projects.js.map +1 -1
- package/dist/tools/reading.js +11 -10
- package/dist/tools/reading.js.map +1 -1
- package/dist/tools/render.js +11 -2
- package/dist/tools/render.js.map +1 -1
- package/dist/tools/schemas.js +6 -1
- package/dist/tools/schemas.js.map +1 -1
- package/dist/tools/shares.js +4 -3
- package/dist/tools/shares.js.map +1 -1
- package/dist/tools/strava.js +13 -9
- package/dist/tools/strava.js.map +1 -1
- package/dist/tools/tags.js +8 -7
- package/dist/tools/tags.js.map +1 -1
- package/dist/tools/tasks.js +17 -11
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/ui.js +34 -13
- package/dist/tools/ui.js.map +1 -1
- package/dist/tools/views.js +12 -10
- package/dist/tools/views.js.map +1 -1
- package/package.json +1 -1
- package/skills/open-brain-mcp/SKILL.md +61 -18
package/dist/tools/views.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
// Opinionated read tools: computed views and the review system. Views are
|
|
2
|
-
// timezone-aware (tz overrides the
|
|
2
|
+
// timezone-aware (tz overrides the host timezone the server sends); review tools cover the due
|
|
3
3
|
// queue, garden deep-review, forcing a garden into review, and marking items
|
|
4
4
|
// reviewed (which restarts their clock).
|
|
5
5
|
import { z } from "zod";
|
|
6
|
+
import { apiPath } from "../client.js";
|
|
6
7
|
import { runTool } from "../result.js";
|
|
8
|
+
import { idField } from "./schemas.js";
|
|
7
9
|
const getViewSchema = z.object({
|
|
8
10
|
view: z.enum(["today", "upcoming", "overdue"]),
|
|
9
11
|
tz: z
|
|
10
12
|
.string()
|
|
11
13
|
.optional()
|
|
12
|
-
.describe("IANA timezone (e.g. America/New_York); defaults to the
|
|
14
|
+
.describe("IANA timezone (e.g. America/New_York); defaults to the timezone of the machine running this MCP server"),
|
|
13
15
|
limit: z.number().int().positive().optional(),
|
|
14
16
|
cursor: z.string().optional(),
|
|
15
17
|
});
|
|
16
18
|
export function getView(client, args) {
|
|
17
|
-
return client.get(`/v1/views/${args.view}`, {
|
|
19
|
+
return client.get(apiPath `/v1/views/${args.view}`, {
|
|
18
20
|
tz: args.tz,
|
|
19
21
|
limit: args.limit,
|
|
20
22
|
cursor: args.cursor,
|
|
@@ -27,20 +29,20 @@ const getReviewsSchema = z.object({
|
|
|
27
29
|
export function getReviews(client, args) {
|
|
28
30
|
return client.get("/v1/reviews", { gardenId: args.gardenId, limit: args.limit });
|
|
29
31
|
}
|
|
30
|
-
const gardenIdSchema = z.object({ gardenId:
|
|
32
|
+
const gardenIdSchema = z.object({ gardenId: idField });
|
|
31
33
|
export function reviewGarden(client, args) {
|
|
32
|
-
return client.get(`/v1/gardens/${args.gardenId}/review`);
|
|
34
|
+
return client.get(apiPath `/v1/gardens/${args.gardenId}/review`);
|
|
33
35
|
}
|
|
34
36
|
export function requestGardenReview(client, args) {
|
|
35
|
-
return client.post(`/v1/gardens/${args.gardenId}/request-review`);
|
|
37
|
+
return client.post(apiPath `/v1/gardens/${args.gardenId}/request-review`);
|
|
36
38
|
}
|
|
37
|
-
const markTaskReviewedSchema = z.object({ taskId:
|
|
39
|
+
const markTaskReviewedSchema = z.object({ taskId: idField });
|
|
38
40
|
export function markTaskReviewed(client, args) {
|
|
39
|
-
return client.post(`/v1/tasks/${args.taskId}/reviewed`);
|
|
41
|
+
return client.post(apiPath `/v1/tasks/${args.taskId}/reviewed`);
|
|
40
42
|
}
|
|
41
|
-
const markProjectReviewedSchema = z.object({ projectId:
|
|
43
|
+
const markProjectReviewedSchema = z.object({ projectId: idField });
|
|
42
44
|
export function markProjectReviewed(client, args) {
|
|
43
|
-
return client.post(`/v1/projects/${args.projectId}/reviewed`);
|
|
45
|
+
return client.post(apiPath `/v1/projects/${args.projectId}/reviewed`);
|
|
44
46
|
}
|
|
45
47
|
export function registerViewTools(server, client) {
|
|
46
48
|
server.registerTool("get_view", {
|
package/dist/tools/views.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/tools/views.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E
|
|
1
|
+
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/tools/views.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -122,7 +122,9 @@ pre-guessing constraints.
|
|
|
122
122
|
`assignee: "me"|"unassigned"|<userId>` filters the home vault by assignee),
|
|
123
123
|
`get_task`, `update_task` (drives status), `delete_task`, batch
|
|
124
124
|
`create_tasks`/`update_tasks`, `add_task_tags`/`remove_task_tags`.
|
|
125
|
-
`create_task`/`
|
|
125
|
+
`create_task`/`create_tasks` accept an initial `status` (default `todo`;
|
|
126
|
+
e.g. `backlog` to park it). `create_task`/`update_task` accept `eventId` to
|
|
127
|
+
link a synced calendar event
|
|
126
128
|
(read-only mirror); `eventId: null` on update unlinks it.
|
|
127
129
|
`create_task`/`create_tasks`/`update_task`/`update_tasks` also accept
|
|
128
130
|
`assigneeUserId` (a user id, `"me"`, or `null` to unassign) - only
|
|
@@ -132,6 +134,7 @@ pre-guessing constraints.
|
|
|
132
134
|
`sharedFrom` marker).
|
|
133
135
|
- **Projects**: `create_project`, `list_projects`, `get_project`,
|
|
134
136
|
`update_project`, `delete_project`, `create_projects`/`update_projects`.
|
|
137
|
+
`create_project(s)` accept an initial `status` (default `todo`).
|
|
135
138
|
Project reads carry `taskCounts {open, done}` (canceled in neither) and
|
|
136
139
|
`nextTaskId` (first open task by manual order; `get_task` it to see what's
|
|
137
140
|
next), so progress needs no extra task listing.
|
|
@@ -145,8 +148,8 @@ pre-guessing constraints.
|
|
|
145
148
|
(null clears a field, e.g. `contactInterval: null`; `archived: false`
|
|
146
149
|
restores), `delete_person` (archives, links kept), `mark_contacted`
|
|
147
150
|
(optional `at` backdates the touch), `add_person_links`/`remove_person_links`
|
|
148
|
-
(`{id, taskIds?, projectIds?, gardenIds?, readingListItemIds?,
|
|
149
|
-
people?}
|
|
151
|
+
(`{id, taskIds?, projectIds?, gardenIds?, readingListItemIds?, habitIds?,
|
|
152
|
+
bookIds?, people?}`: `people` is `[{id, label?}]` for person-to-person connections;
|
|
150
153
|
symmetric, shown on both people, re-link with a new label to change it or
|
|
151
154
|
`label: null` to clear it; unlink takes the same shape, ids only for
|
|
152
155
|
`people`). `create_task(s)` accept `personIds` inline; `list_tasks` filters
|
|
@@ -159,9 +162,10 @@ pre-guessing constraints.
|
|
|
159
162
|
`archived`/`deleted` toggle independently of status), `delete_reading_item`
|
|
160
163
|
(true soft delete, hidden everywhere; restore with `update_reading_item
|
|
161
164
|
{deleted: false}`), `add_reading_tags`/`remove_reading_tags`.
|
|
162
|
-
- **Habits**: `create_habit`, `list_habits
|
|
165
|
+
- **Habits**: `create_habit`, `list_habits` (pages; pass `cursor`), `get_habit`, `update_habit`,
|
|
163
166
|
`archive_habit`/`unarchive_habit`, `complete_habit` (`quantity?`, `durationMinutes?`,
|
|
164
|
-
`force?` skips time window), `remove_habit_completion` (by `completionId` or `day
|
|
167
|
+
`force?` skips time window), `remove_habit_completion` (by `completionId` or `day`;
|
|
168
|
+
a `day` lookup reaches back through the newest 200 check-ins),
|
|
165
169
|
`reorder_habits`, `add_habit_tags`/`remove_habit_tags`.
|
|
166
170
|
Schedules: `{kind: daily}`, `{kind: weekly, times, byWeekday?}`, `{kind: monthly, times}`,
|
|
167
171
|
`{kind: every_n_days, interval}`. Optional `graceDays` (daily streak tolerance),
|
|
@@ -191,20 +195,37 @@ pre-guessing constraints.
|
|
|
191
195
|
`delete_book` (soft delete, cover blob kept, restore with `{deleted:
|
|
192
196
|
false}`), `add_book_tags`/`remove_book_tags`, `log_book_session` (`day?`,
|
|
193
197
|
`pagesRead?`, `minutes?`, `endPage?`, `notes?`; retroactive OK, multiple
|
|
194
|
-
sessions per day
|
|
198
|
+
sessions per day; `pagesRead` alone continues from the current page and
|
|
199
|
+
moves it forward), `remove_book_session` (never retroactively un-satisfies
|
|
195
200
|
a habit day), `refresh_book_metadata` (`overwrite?` to replace non-empty
|
|
196
201
|
fields). Person links via `add_person_links`/`remove_person_links` with
|
|
197
202
|
`bookIds`.
|
|
198
203
|
- **Saved lists** (named, reusable task-list filters): `list_saved_lists`,
|
|
199
204
|
`create_saved_list`, `update_saved_list`, `delete_saved_list`.
|
|
200
|
-
- **
|
|
205
|
+
- **Comments**: `list_task_comments {taskId}` (oldest first, max 200, plus
|
|
206
|
+
`participants`: the people in the task's garden who can be @mentioned,
|
|
207
|
+
`{userId, displayName, avatarUrl, role}`), `add_task_comment {taskId, body,
|
|
208
|
+
mentions?}`, `edit_task_comment {taskId, commentId, body, mentions?}`
|
|
209
|
+
(author only), `delete_task_comment {taskId, commentId}` (author or garden
|
|
210
|
+
owner). Each comment has `body` (Markdown with mention tokens), `text`
|
|
211
|
+
(tokens rendered as `@Name`), `mentions` (user ids), `canEdit`,
|
|
212
|
+
`canDelete`, and `editedAt` once edited. Tasks carry `commentCount`
|
|
213
|
+
(omitted when 0). Needs `tasks:read` / `tasks:write`.
|
|
214
|
+
- **Attachments** (read-only; upload is web/app-only): `list_task_attachments
|
|
215
|
+
{taskId}`, `get_attachment {id}` (metadata), `get_attachment_url {id,
|
|
216
|
+
variant?}` (short-lived signed URL; `variant` is `served` (default),
|
|
217
|
+
`original`, or `thumbnail`). Needs `tasks:read`.
|
|
218
|
+
- **Views & reviews**: `get_view` (today/upcoming/overdue, timezone-aware;
|
|
219
|
+
without `tz` it uses the timezone of the machine running the MCP server),
|
|
201
220
|
`get_reviews` (due queue), `review_garden` (deep review),
|
|
202
221
|
`request_garden_review`, `mark_task_reviewed`, `mark_project_reviewed`.
|
|
203
222
|
- **AI**: `find_tasks` (hybrid keyword + semantic search), `ai_triage`
|
|
204
223
|
(brain dump → garden-assigned tasks, recurring habits, reading-list
|
|
205
224
|
saves/edits/cancels, and books - see Workflows).
|
|
206
|
-
- **UI (read-only)**: `ui_view`, `ui_review_queue`, `ui_garden_board
|
|
207
|
-
`ui://` HTML resources.
|
|
225
|
+
- **UI (read-only)**: `ui_view`, `ui_review_queue`, `ui_garden_board`,
|
|
226
|
+
`ui_habits` return `ui://` HTML resources. `ui_view` and `ui_habits` take a
|
|
227
|
+
`cursor`; when a page is cut short the result adds a text note with the
|
|
228
|
+
cursor for the next page.
|
|
208
229
|
- **Settings**: `get_settings`, `update_settings` (the default review period
|
|
209
230
|
applied to new tasks/projects; `defaultReviewInterval: null` disables it;
|
|
210
231
|
`defaultTimezone`, an IANA string, is also settable - it's what date-only
|
|
@@ -216,11 +237,15 @@ pre-guessing constraints.
|
|
|
216
237
|
owner, participants - empty unless the key has `includeGrants`),
|
|
217
238
|
`list_shared_tasks {shareId, status?, includeCanceled?}` (that garden's
|
|
218
239
|
tasks, capped at 500).
|
|
219
|
-
- **Profile**: `get_profile` (user id, display name, avatar URL
|
|
220
|
-
`
|
|
240
|
+
- **Profile**: `get_profile` (user id, display name, avatar URL,
|
|
241
|
+
`notifications: {emailOnMention, emailOnAssign}`), `update_profile
|
|
242
|
+
{displayName?, notifications?: {emailOnMention?, emailOnAssign?}}` (pass at
|
|
243
|
+
least one; display name 1-60 chars; avatar upload is web-only).
|
|
221
244
|
- **Keys**: `create_key` (optional `includeGrants` to let the new key see
|
|
222
245
|
gardens shared with its owner - only settable if the calling key itself
|
|
223
|
-
has it), `list_keys`, `rotate_key`, `revoke_key`.
|
|
246
|
+
has it), `list_keys`, `rotate_key`, `revoke_key`. `rotate_key` and
|
|
247
|
+
`revoke_key` refuse the key this MCP server itself authenticates with (it
|
|
248
|
+
would lock the server out); rotate or revoke that one from the CLI or web app.
|
|
224
249
|
|
|
225
250
|
## Workflows
|
|
226
251
|
|
|
@@ -235,16 +260,20 @@ pre-guessing constraints.
|
|
|
235
260
|
archives it, reversibly, independent of status) — it matches existing
|
|
236
261
|
items by exact title, so an unmatched or ambiguous reference comes back as a
|
|
237
262
|
reading-list clarification rather than a silent no-op or a task.
|
|
238
|
-
- **Plan today** → `get_view today`.
|
|
239
|
-
day boundary is
|
|
263
|
+
- **Plan today** → `get_view today`. It defaults to this machine's timezone;
|
|
264
|
+
pass the user's IANA `tz` if they are somewhere else so the day boundary is
|
|
265
|
+
correct.
|
|
240
266
|
- **Add a task** → need a garden: `list_gardens` first, then `create_task` with
|
|
241
267
|
`gardenId`. Set `deadline` for "today"/hard dates — that's what lands it in
|
|
242
268
|
the Today view. `create_task`/`create_tasks` accept `tagIds`, `recurrence`,
|
|
243
269
|
`deferDate`, `deadline`, and `habitId` (completing the task checks in the
|
|
244
270
|
habit) **inline** — set them at creation, never create-then-patch.
|
|
245
271
|
`deferDate`/`deadline` are calendar days `"YYYY-MM-DD"` (no timezone); inputs
|
|
246
|
-
also accept relative tokens (`"today"`, `"tomorrow"`, `"+3d"`
|
|
247
|
-
|
|
272
|
+
also accept relative tokens (`"today"`, `"tomorrow"`, `"+3d"`, `"friday"`,
|
|
273
|
+
`"next week"`; a weekday is its next occurrence after today), so no
|
|
274
|
+
client-side date math. The local (stdio) server sends the machine's
|
|
275
|
+
timezone, so relative tokens resolve in the user's zone; the hosted server
|
|
276
|
+
falls back to the vault timezone. Returned values are always `"YYYY-MM-DD"`.
|
|
248
277
|
- **Recurring task** → set `recurrence` at creation:
|
|
249
278
|
`{mode, frequency, interval, byWeekday?}`. `mode`: `on_schedule` (next = prior
|
|
250
279
|
due + interval; self-heals missed days) or `on_completion` (next = completed +
|
|
@@ -281,6 +310,19 @@ pre-guessing constraints.
|
|
|
281
310
|
pagesRead}` as pages are read (auto-promotes `want_to_read` to `reading`)
|
|
282
311
|
→ `update_book {id, status: "read"}` when finished (stamps `finishedDay`
|
|
283
312
|
and force-completes a linked page-goal habit for that day).
|
|
313
|
+
- **Comment on a task / loop someone in** → `list_task_comments {taskId}` to
|
|
314
|
+
read the thread and see who can be mentioned, then `add_task_comment {taskId,
|
|
315
|
+
body, mentions: ["Sam"]}`. `mentions` takes participant user ids or display
|
|
316
|
+
names (case-insensitive, leading `@` ok): a plain `@Sam` already in the
|
|
317
|
+
body becomes a mention token, otherwise the token is prepended; an unknown
|
|
318
|
+
name is a 400, so check `participants` first. You can also write the token
|
|
319
|
+
inline: `@[Display Name](userId)`; a token for someone outside the task's
|
|
320
|
+
garden becomes plain `@Name` text. Anyone who can see the task can comment,
|
|
321
|
+
including watch-only guests of a shared garden (the key needs
|
|
322
|
+
`includeGrants` for shared tasks). Mentioned people, and people newly
|
|
323
|
+
assigned a task, get an email from the server (never the caller), unless
|
|
324
|
+
they turned it off via `update_profile {notifications: {emailOnMention:
|
|
325
|
+
false}}` (or `emailOnAssign`).
|
|
284
326
|
- **Find something** → `find_tasks` (handles fuzzy/semantic queries; narrow to a
|
|
285
327
|
due window with `deadlineBefore` / `deadlineAfter`, inclusive day bounds,
|
|
286
328
|
e.g. `"2026-07-10"` or `"+1w"`).
|
|
@@ -298,8 +340,9 @@ pre-guessing constraints.
|
|
|
298
340
|
`people:read|write`, settings tools `settings:read|write`, reading list tools
|
|
299
341
|
`reading:read|write`, Strava tools `strava:read|write`, book tools
|
|
300
342
|
`books:read|write`, calendar tools `calendar:read|write`), review tools
|
|
301
|
-
`reviews:*`, `find_tasks
|
|
302
|
-
`ai:invoke
|
|
343
|
+
`reviews:*`, `find_tasks` needs `ai:invoke` + `tasks:read`, `ai_triage` needs
|
|
344
|
+
`ai:invoke` + `tasks:write`, `reading:write`, `habits:write`, and
|
|
345
|
+
`books:write` (it can create any of those), the `*_key` tools need `keys:manage`. A missing scope returns a
|
|
303
346
|
403 tool error. Keys minted before a feature shipped won't carry its scope
|
|
304
347
|
unless they hold `*`. There is no upload tool here (cover uploads are a
|
|
305
348
|
web-only flow, `POST /v1/uploads` before setting `coverStorageId`), but a
|