@cpenned/mcp 0.9.0 → 0.10.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 CHANGED
@@ -15,8 +15,9 @@ Set via environment variables:
15
15
  | `OPEN_BRAIN_CLIENT_TYPE` | no | `X-Client` stamped on the audit log (default `mcp`) |
16
16
 
17
17
  The key's scopes gate the tools: resource tools need `<resource>:read|write`,
18
- review tools `reviews:*`, settings tools `settings:read|write`, and
19
- `find_tasks` / `ai_triage` need `ai:invoke`. `list_shares`/`list_shared_tasks`
18
+ review tools `reviews:*`, settings tools `settings:read|write`, history tools
19
+ `history:read` (plus `history:write` and the entity's write scope for
20
+ `revert_change`), and `find_tasks` / `ai_triage` need `ai:invoke`. `list_shares`/`list_shared_tasks`
20
21
  additionally need the key to have been minted with `includeGrants: true` (via
21
22
  `create_key`'s `includeGrants` flag or the web app) - without it, a key only
22
23
  ever sees the vault's own data, even with `*`.
@@ -186,6 +187,16 @@ Point the `args` at the absolute `packages/mcp/dist/index.js` path with
186
187
  - **Profile**: `get_profile`, `update_profile` (`displayName`, 1-60 chars,
187
188
  and/or `notifications: {emailOnMention?, emailOnAssign?}` to turn mention and
188
189
  assignment emails on or off; avatar upload is web-only).
190
+ - **History** (every change from every surface, with before/after values):
191
+ `list_history` (filters `entityType`, `entityId`, `source`, `actor`,
192
+ `since`/`until` as epoch ms or ISO, `batchId`, `limit` 1-200, `cursor`;
193
+ only entity types the key can read), `get_history_entry`, `revert_change`
194
+ (`{id}` or `{batchId}` for a whole bulk action, `force?`). An update revert
195
+ restores fields still equal to their `after` value and reports the rest as
196
+ conflicts unless `force`; reverting a create soft-deletes, reverting a delete
197
+ restores, tag/link adds and removes invert. The result's `batchId` reverts
198
+ the revert (redo). System rows, recurrence spawns, settings, keys, webhooks
199
+ and attachments are not revertable (400).
189
200
  - **Key management**: `create_key` (optional `includeGrants` so the minted key
190
201
  can see gardens shared with its owner - only settable if the calling key
191
202
  itself has it), `list_keys`, `rotate_key`, `revoke_key`
package/dist/config.js CHANGED
@@ -3,6 +3,21 @@
3
3
  export function normalizeBaseUrl(baseUrl) {
4
4
  return baseUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
5
5
  }
6
+ // The API key travels in every request's Authorization header, so it only goes
7
+ // over HTTPS. Plain http is allowed for a local backend (localhost) only.
8
+ export function assertSecureBaseUrl(baseUrl) {
9
+ let url;
10
+ try {
11
+ url = new URL(baseUrl);
12
+ }
13
+ catch {
14
+ throw new Error(`Invalid API URL: ${baseUrl}`);
15
+ }
16
+ const local = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
17
+ if (url.protocol === "https:" || (url.protocol === "http:" && local))
18
+ return;
19
+ throw new Error(`Refusing to send your API key to ${url.origin}: the API URL must use https (http only for localhost).`);
20
+ }
6
21
  export function loadConfig(env = process.env) {
7
22
  const baseUrl = env.OPEN_BRAIN_API_URL;
8
23
  const apiKey = env.OPEN_BRAIN_API_KEY;
@@ -12,6 +27,7 @@ export function loadConfig(env = process.env) {
12
27
  if (!apiKey) {
13
28
  throw new Error("OPEN_BRAIN_API_KEY is required");
14
29
  }
30
+ assertSecureBaseUrl(baseUrl);
15
31
  return {
16
32
  baseUrl: normalizeBaseUrl(baseUrl),
17
33
  apiKey,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAmBA,uEAAuE;AACvE,qBAAqB;AACrB,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,CAAC;IACvC,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO;QACL,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;QAClC,MAAM;QACN,UAAU,EAAE,GAAG,CAAC,sBAAsB,IAAI,KAAK;QAC/C,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;KAC3D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAmBA,uEAAuE;AACvE,qBAAqB;AACrB,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,+EAA+E;AAC/E,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzE,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC;QAAE,OAAO;IAC7E,MAAM,IAAI,KAAK,CACb,oCAAoC,GAAG,CAAC,MAAM,yDAAyD,CACxG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,CAAC;IACvC,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO;QACL,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;QAClC,MAAM;QACN,UAAU,EAAE,GAAG,CAAC,sBAAsB,IAAI,KAAK;QAC/C,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;KAC3D,CAAC;AACJ,CAAC"}
package/dist/tools/api.js CHANGED
@@ -5,6 +5,7 @@ import { registerCalendarTools } from "./calendar.js";
5
5
  import { registerCommentTools } from "./comments.js";
6
6
  import { registerGardenTools } from "./gardens.js";
7
7
  import { registerHabitTools } from "./habits.js";
8
+ import { registerHistoryTools } from "./history.js";
8
9
  import { registerKeyTools } from "./keys.js";
9
10
  import { registerListTools } from "./lists.js";
10
11
  import { registerPeopleTools } from "./people.js";
@@ -37,5 +38,6 @@ export function registerApiTools(server, client) {
37
38
  registerSettingsTools(server, client);
38
39
  registerShareTools(server, client);
39
40
  registerProfileTools(server, client);
41
+ registerHistoryTools(server, client);
40
42
  }
41
43
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/tools/api.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,MAAuB;IACzE,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/tools/api.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,MAAuB;IACzE,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,93 @@
1
+ // Change history tools. Every write to the vault (from any surface) is recorded
2
+ // with before/after values; list_history browses it and revert_change undoes a
3
+ // change or a whole batch. Reverting a revert is a redo.
4
+ import { z } from "zod";
5
+ import { apiPath } from "../client.js";
6
+ import { runTool } from "../result.js";
7
+ import { idField } from "./schemas.js";
8
+ export const historyEntityTypeEnum = z.enum([
9
+ "task",
10
+ "project",
11
+ "garden",
12
+ "tag",
13
+ "person",
14
+ "list",
15
+ "apiKey",
16
+ "attachment",
17
+ "webhook",
18
+ "vault",
19
+ "readingListItem",
20
+ "stravaActivity",
21
+ "habit",
22
+ "book",
23
+ "calendarEvent",
24
+ "calendarConnection",
25
+ "taskComment",
26
+ ]);
27
+ const timeField = z
28
+ .union([z.number(), z.string()])
29
+ .describe("Epoch milliseconds or an ISO date/time, e.g. 2026-11-04 or 2026-11-04T09:00:00Z");
30
+ const listHistorySchema = z.object({
31
+ entityType: historyEntityTypeEnum.optional(),
32
+ entityId: z.string().optional().describe("Only changes to this entity"),
33
+ source: z
34
+ .string()
35
+ .optional()
36
+ .describe("Surface that made the change: web, mac, ios, mcp, cli, raycast, api, ai, chat, email, meld, integration, system, strava, linear"),
37
+ actor: z
38
+ .string()
39
+ .optional()
40
+ .describe('Who made it: an API key id, a user id, "ai", "email" or "system"'),
41
+ since: timeField.optional(),
42
+ until: timeField.optional(),
43
+ batchId: z
44
+ .string()
45
+ .optional()
46
+ .describe("Only the changes of one bulk/multi-entity action"),
47
+ limit: z.number().int().min(1).max(200).optional().describe("Page size, default 50"),
48
+ cursor: z.string().optional().describe("nextCursor from a previous page"),
49
+ });
50
+ export function listHistory(client, args) {
51
+ return client.get("/v1/history", { ...args });
52
+ }
53
+ const getHistoryEntrySchema = z.object({ id: idField.describe("History entry id") });
54
+ export function getHistoryEntry(client, args) {
55
+ return client.get(apiPath `/v1/history/${args.id}`);
56
+ }
57
+ const revertChangeSchema = z.object({
58
+ id: idField.optional().describe("History entry id to revert"),
59
+ batchId: idField
60
+ .optional()
61
+ .describe("Revert every change of one batch instead (a bulk or multi-entity action)"),
62
+ force: z
63
+ .boolean()
64
+ .optional()
65
+ .describe("Overwrite fields that changed since this entry (conflicts). Default false skips them."),
66
+ });
67
+ export function revertChange(client, args) {
68
+ const body = args.force === undefined ? {} : { force: args.force };
69
+ if (args.batchId && !args.id)
70
+ return client.post(apiPath `/v1/history/batches/${args.batchId}/revert`, body);
71
+ if (args.id && !args.batchId)
72
+ return client.post(apiPath `/v1/history/${args.id}/revert`, body);
73
+ throw new Error("Pass exactly one of id or batchId");
74
+ }
75
+ export function registerHistoryTools(server, client) {
76
+ server.registerTool("list_history", {
77
+ title: "List change history",
78
+ description: "Recent changes across the vault, newest first: { items, hasMore, nextCursor }. Each entry has id, entityType, entityId, action, summary, actor, source, at (epoch ms), fields, before/after (changed fields only; a missing key means unset), batchId, revertOf, revertedBy and revertable. Only entity types this key can read are returned. Filter by entity, type, source, actor, time window or batch.",
79
+ inputSchema: listHistorySchema.shape,
80
+ }, (args) => runTool(() => listHistory(client, args)));
81
+ server.registerTool("get_history_entry", {
82
+ title: "Get history entry",
83
+ description: "One change history entry by id, with its before/after values.",
84
+ inputSchema: getHistoryEntrySchema.shape,
85
+ }, (args) => runTool(() => getHistoryEntry(client, args)));
86
+ server.registerTool("revert_change", {
87
+ title: "Revert change",
88
+ description: "Undo one change (id) or every change of a batch (batchId). Updates write back `before` for each field still equal to `after`; fields edited since are conflicts and skipped unless force. Reverting a create soft-deletes (tasks/projects canceled, gardens/people/habits archived, tags/saved lists hard-deleted); reverting a delete restores; tag/link adds and removes invert. Returns { batchId, results, entries }: per-entity status (reverted, partial, conflict, noop, skipped), reverted fields, conflicts, skipped and newEntityId when a hard-deleted record returns under a new id. Revert the returned batchId to redo. Some changes are not revertable (system rows, recurrence spawns, settings, keys, webhooks, attachments) and fail with 400. Needs history:write plus the entity's write scope.",
89
+ inputSchema: revertChangeSchema.shape,
90
+ annotations: { destructiveHint: true },
91
+ }, (args) => runTool(() => revertChange(client, args)));
92
+ }
93
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/tools/history.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/tools/views.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,+FAA+F;AAC/F,6EAA6E;AAC7E,yCAAyC;AAGzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAwB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC9C,EAAE,EAAE,CAAC;SACF,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,wGAAwG,CACzG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAEH,MAAM,UAAU,OAAO,CAAC,MAAuB,EAAE,IAAiB;IAChE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAA,aAAa,IAAI,CAAC,IAAI,EAAE,EAAE;QACjD,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IAChF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,MAAuB,EAAE,IAAoB;IACtE,OAAO,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAEvD,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,IAAkB;IACtE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAA,eAAe,IAAI,CAAC,QAAQ,SAAS,CAAC,CAAC;AAClE,CAAC;AACD,MAAM,UAAU,mBAAmB,CAAC,MAAuB,EAAE,IAAkB;IAC7E,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAA,eAAe,IAAI,CAAC,QAAQ,iBAAiB,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAE7D,MAAM,UAAU,gBAAgB,CAAC,MAAuB,EAAE,IAA0B;IAClF,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAA,aAAa,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CACjC,MAAuB,EACvB,IAA6B;IAE7B,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAA,gBAAgB,IAAI,CAAC,SAAS,WAAW,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAuB;IAC1E,MAAM,CAAC,YAAY,CACjB,UAAU,EACV;QACE,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,8DAA8D;QAC3E,WAAW,EAAE,aAAa,CAAC,KAAK;KACjC,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAC/C,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,8IAA8I;QAChJ,WAAW,EAAE,gBAAgB,CAAC,KAAK;KACpC,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAClD,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,gFAAgF;QAClF,WAAW,EAAE,cAAc,CAAC,KAAK;KAClC,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CACpD,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,iEAAiE;QAC9E,WAAW,EAAE,cAAc,CAAC,KAAK;KAClC,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAC3D,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EACT,6EAA6E;QAC/E,WAAW,EAAE,sBAAsB,CAAC,KAAK;KAC1C,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CACxD,CAAC;IACF,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,mCAAmC;QAChD,WAAW,EAAE,yBAAyB,CAAC,KAAK;KAC7C,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAC3D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"views.js","sourceRoot":"","sources":["../../src/tools/views.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cpenned/mcp",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "MCP server for Open Brain - a thin adapter over the /v1 HTTP API.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "dependencies": {
49
49
  "@mcp-ui/server": "^6.1.0",
50
50
  "@modelcontextprotocol/sdk": "^1.29.0",
51
- "zod": "^3.23.8"
51
+ "zod": "^4.6.7"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^22.0.0",
@@ -241,6 +241,15 @@ pre-guessing constraints.
241
241
  `notifications: {emailOnMention, emailOnAssign}`), `update_profile
242
242
  {displayName?, notifications?: {emailOnMention?, emailOnAssign?}}` (pass at
243
243
  least one; display name 1-60 chars; avatar upload is web-only).
244
+ - **History** (every write from every surface, with before/after values):
245
+ `list_history` (filters `entityType`, `entityId`, `source`, `actor`,
246
+ `since`/`until` as epoch ms or ISO date/time, `batchId`, `limit` 1-200
247
+ default 50, `cursor`; newest first, `{ items, hasMore, nextCursor }`),
248
+ `get_history_entry {id}`, `revert_change {id}` or `revert_change
249
+ {batchId}` (plus `force?`). Entries carry `summary` (human line),
250
+ `actor`, `source`, `at`, `fields`, `before`/`after` (changed fields only;
251
+ a missing key means unset), `batchId`, `revertOf`, `revertedBy`,
252
+ `revertable`. See the undo workflow below.
244
253
  - **Keys**: `create_key` (optional `includeGrants` to let the new key see
245
254
  gardens shared with its owner - only settable if the calling key itself
246
255
  has it), `list_keys`, `rotate_key`, `revoke_key`. `rotate_key` and
@@ -331,6 +340,21 @@ pre-guessing constraints.
331
340
  link it to a person at the same time, pass `tagIds`/`personIds` inline
332
341
  instead of following up with separate calls.
333
342
 
343
+ - **Undo a change** → `list_history` filtered by `entityId` (or `since`)
344
+ to find the entry, check `revertable`, then `revert_change {id}`. A bulk or
345
+ multi-entity action shares one `batchId`; undo all of it with
346
+ `revert_change {batchId}`. Update reverts write `before` back only for
347
+ fields whose current value still equals `after`; fields edited since come
348
+ back as `conflicts` (`{field, expected, current}`) and are left alone.
349
+ Show the user the conflicts and only re-run with `force: true` if they want
350
+ them overwritten. Reverting a create soft-deletes (tasks/projects
351
+ canceled, gardens/people/habits archived, books/reading/Strava deleted;
352
+ tags and saved lists are hard-deleted), reverting a delete restores (a
353
+ hard-deleted tag/saved list returns under `newEntityId`), tag/link
354
+ add/remove invert. The result is `{ batchId, results, entries }` with a
355
+ per-entity `status` (`reverted`, `partial`, `conflict`, `noop`,
356
+ `skipped`). To redo, revert the returned `batchId`.
357
+
334
358
  ## Gotchas
335
359
 
336
360
  - Tools act on the vault behind the configured API key. If the user's web tasks
@@ -339,7 +363,10 @@ pre-guessing constraints.
339
363
  - Scopes gate tools: resource tools need `<resource>:read|write` (people tools
340
364
  `people:read|write`, settings tools `settings:read|write`, reading list tools
341
365
  `reading:read|write`, Strava tools `strava:read|write`, book tools
342
- `books:read|write`, calendar tools `calendar:read|write`), review tools
366
+ `books:read|write`, calendar tools `calendar:read|write`), history tools
367
+ `history:read` (rows only for entity types the key can also read) and
368
+ `revert_change` `history:write` plus the write scope of each entity it
369
+ touches, review tools
343
370
  `reviews:*`, `find_tasks` needs `ai:invoke` + `tasks:read`, `ai_triage` needs
344
371
  `ai:invoke` + `tasks:write`, `reading:write`, `habits:write`, and
345
372
  `books:write` (it can create any of those), the `*_key` tools need `keys:manage`. A missing scope returns a
@@ -348,6 +375,10 @@ pre-guessing constraints.
348
375
  web-only flow, `POST /v1/uploads` before setting `coverStorageId`), but a
349
376
  key used for that flow needs `books:write` alongside `tasks:write`/
350
377
  `projects:write`.
378
+ - `revert_change` fails with a 400 "Invalid revert" for changes that are not
379
+ revertable (`revertable: false`: system rows, recurrence spawns, settings,
380
+ keys, webhooks, attachments, oversized values). Check the flag before
381
+ offering an undo.
351
382
  - `sync_strava_activities` requires a Strava account already connected (via
352
383
  the web UI's Settings page) — it does nothing useful if nobody has
353
384
  authorized the app yet.