@manudota/artist-mcp 1.5.2-staging.72 → 1.5.2

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/dist/calendar.js CHANGED
@@ -374,6 +374,20 @@ const draftFrom = (params) => {
374
374
  if (new Date(end).getTime() < new Date(start).getTime()) {
375
375
  throw failure('The event ends before it starts.');
376
376
  }
377
+ // Equal ends are the subtler half, and they differ by kind.
378
+ //
379
+ // Google treats an all-day `end.date` as exclusive: a gig on the 11th ends on
380
+ // the 12th. `end` equal to `start` is an empty range, which Google refuses —
381
+ // and a model that does not know the convention writes it without hesitating.
382
+ // A timed event of zero length is not a gig either. Refused here rather than
383
+ // surfacing as a Google 400 that says nothing about what to do.
384
+ if (end === start) {
385
+ throw failure(allDay
386
+ ? `An all-day event ends on the following day: Google reads the end date as ` +
387
+ `exclusive, so a single day on ${start} is start ${start}, end ` +
388
+ `${new Date(new Date(start).getTime() + 86_400_000).toISOString().slice(0, 10)}.`
389
+ : 'The event starts and ends at the same moment. Give it a duration.');
390
+ }
377
391
  return {
378
392
  calendar_id: calendarId,
379
393
  summary: text(params.summary, 'summary', true),
package/dist/config.d.ts CHANGED
@@ -6,6 +6,22 @@ export declare const ENTRY_NAME = "artist-notes";
6
6
  * that read this file except against the developer's own Claude Desktop config,
7
7
  * which a test suite has no business touching.
8
8
  */
9
+ /**
10
+ * Where Claude Desktop keeps its config on Windows, which is not one place.
11
+ *
12
+ * A packaged install — the one that appears under `AppData\Local\Packages` —
13
+ * has a **virtualised** `%APPDATA%`. Desktop reads
14
+ * `…\Packages\Claude_<id>\LocalCache\Roaming\Claude\`, while this process
15
+ * is an ordinary Node program whose `%APPDATA%` is the real `Roaming` folder.
16
+ * Writing to the obvious path therefore produced two config files that were
17
+ * each internally consistent and never the same one: `init` and `status` agreed
18
+ * with each other about a grant that Claude Desktop had never seen.
19
+ *
20
+ * Found the hard way, and the symptom is maddening — every check passes and the
21
+ * tools do not appear — so the packaged location wins when it exists rather
22
+ * than being offered as a fallback.
23
+ */
24
+ export declare const windowsConfigPath: (home: string) => string;
9
25
  export declare const configPath: () => string;
10
26
  type Config = {
11
27
  mcpServers?: Record<string, unknown>;
package/dist/config.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /** Locating and editing the Claude Desktop config, without trampling it. */
2
2
  import { homedir, platform } from "node:os";
3
3
  import { join } from "node:path";
4
+ import { existsSync, readdirSync } from "node:fs";
4
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
5
6
  import { dirname } from "node:path";
6
7
  export const ENTRY_NAME = "artist-notes";
@@ -10,6 +11,45 @@ export const ENTRY_NAME = "artist-notes";
10
11
  * that read this file except against the developer's own Claude Desktop config,
11
12
  * which a test suite has no business touching.
12
13
  */
14
+ /**
15
+ * Where Claude Desktop keeps its config on Windows, which is not one place.
16
+ *
17
+ * A packaged install — the one that appears under `AppData\Local\Packages` —
18
+ * has a **virtualised** `%APPDATA%`. Desktop reads
19
+ * `…\Packages\Claude_<id>\LocalCache\Roaming\Claude\`, while this process
20
+ * is an ordinary Node program whose `%APPDATA%` is the real `Roaming` folder.
21
+ * Writing to the obvious path therefore produced two config files that were
22
+ * each internally consistent and never the same one: `init` and `status` agreed
23
+ * with each other about a grant that Claude Desktop had never seen.
24
+ *
25
+ * Found the hard way, and the symptom is maddening — every check passes and the
26
+ * tools do not appear — so the packaged location wins when it exists rather
27
+ * than being offered as a fallback.
28
+ */
29
+ export const windowsConfigPath = (home) => {
30
+ const roaming = process.env.APPDATA ?? join(home, "AppData", "Roaming");
31
+ const plain = join(roaming, "Claude", "claude_desktop_config.json");
32
+ const packagesRoot = process.env.LOCALAPPDATA ?? join(home, "AppData", "Local");
33
+ try {
34
+ const packages = readdirSync(join(packagesRoot, "Packages"))
35
+ .filter((name) => /^Claude_/i.test(name))
36
+ .map((name) => join(packagesRoot, "Packages", name, "LocalCache", "Roaming", "Claude", "claude_desktop_config.json"));
37
+ // An existing packaged config is the one Desktop reads. If more than one
38
+ // package directory exists, prefer one that already holds a config over an
39
+ // empty shell left by an uninstall.
40
+ const written = packages.find((candidate) => existsSync(candidate));
41
+ if (written)
42
+ return written;
43
+ // A packaged install with no config yet: still the right place to write,
44
+ // since the plain path would be ignored.
45
+ if (packages.length > 0 && !existsSync(plain))
46
+ return packages[0];
47
+ }
48
+ catch {
49
+ // No Packages directory at all — an ordinary install. Fall through.
50
+ }
51
+ return plain;
52
+ };
13
53
  export const configPath = () => {
14
54
  const override = process.env.ARTIST_MCP_CONFIG;
15
55
  if (override)
@@ -19,7 +59,7 @@ export const configPath = () => {
19
59
  case "darwin":
20
60
  return join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
21
61
  case "win32":
22
- return join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
62
+ return windowsConfigPath(home);
23
63
  default:
24
64
  // Claude Desktop ships on macOS and Windows only; this keeps the error
25
65
  // legible rather than writing a config nothing will ever read.
package/dist/init.js CHANGED
@@ -2,6 +2,7 @@ import { resolve } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { DEFAULT_EDITABLE_DIRECTORY, describeSeed, seedEditablePack } from "./agents.js";
4
4
  import { isStagingVersion, packageVersion } from "./client.js";
5
+ import { sep } from "node:path";
5
6
  import { configPath, ENTRY_NAME, readConfig, writeConfig } from "./config.js";
6
7
  import { connectedProviders } from "./dispatch.js";
7
8
  import { describeGrants, setGrants } from "./grants.js";
@@ -65,6 +66,12 @@ export const runInit = async ({ local = false, editableDir, grants = [], } = {})
65
66
  config.mcpServers = servers;
66
67
  await writeConfig(path, config);
67
68
  console.log(`\nWrote "${ENTRY_NAME}" to ${path}`);
69
+ if (path.includes(`${sep}Packages${sep}`)) {
70
+ // Worth naming. A packaged Windows install virtualises %APPDATA%, so the
71
+ // obvious path is a different file that Claude Desktop never opens — and
72
+ // writing there fails invisibly: every check passes and no tool appears.
73
+ console.log(" (packaged Claude install — this is the config it reads)");
74
+ }
68
75
  if (seeded) {
69
76
  console.log("");
70
77
  describeSeed(seeded);
package/dist/server.js CHANGED
@@ -103,7 +103,7 @@ const selectNotebook = async (call, notebook, tool) => {
103
103
  : null;
104
104
  return { pages, scope };
105
105
  };
106
- const serverVersion = '1.5.2-staging.72'; // x-release-please-version
106
+ const serverVersion = '1.5.2'; // x-release-please-version
107
107
  const errorResult = (err) => {
108
108
  const message = err instanceof GraphError ? err.message : `Unexpected error: ${err}`;
109
109
  return { content: [{ type: "text", text: message }], isError: true };
@@ -809,7 +809,11 @@ const createServer = async (call) => {
809
809
  start: z
810
810
  .string()
811
811
  .describe("YYYY-MM-DD for an all-day event, or an RFC3339 date-time such as 2026-10-16T20:00:00"),
812
- end: z.string().describe("The same kind as start: both dates, or both date-times"),
812
+ end: z
813
+ .string()
814
+ .describe("The same kind as start: both dates, or both date-times. For an all-day " +
815
+ "event Google reads this as EXCLUSIVE, so a gig on 2028-09-11 is " +
816
+ "start 2028-09-11, end 2028-09-12"),
813
817
  time_zone: z
814
818
  .string()
815
819
  .optional()
@@ -870,7 +874,10 @@ const createServer = async (call) => {
870
874
  source_page: z
871
875
  .string()
872
876
  .optional()
873
- .describe("The OneNote page this came from, recorded locally so the write can be traced back"),
877
+ .describe("The page id from list_notes or read_note, so the write can be traced back " +
878
+ "weeks later. The id, not the title: a notebook can hold two pages with " +
879
+ "the same or nearly the same name, which is exactly when tracing matters. " +
880
+ "Add the title after it if you like"),
874
881
  }, async (params) => {
875
882
  try {
876
883
  const { created, link, calendar_id, written } = await call("create_calendar_event", params);
@@ -936,7 +943,8 @@ const createServer = async (call) => {
936
943
  source_page: z
937
944
  .string()
938
945
  .optional()
939
- .describe("The OneNote page this relates to, recorded locally"),
946
+ .describe("The page id from list_notes or read_note, not the title — a title does not " +
947
+ "identify a page in a notebook holding near-duplicates"),
940
948
  }, async (params) => {
941
949
  try {
942
950
  const { deleted, calendar_id } = await call("delete_calendar_event", params);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manudota/artist-mcp",
3
- "version": "1.5.2-staging.72",
3
+ "version": "1.5.2",
4
4
  "description": "MCP server that reads your OneNote notes, with optional Gmail and Calendar as supporting evidence, via a hosted connection.",
5
5
  "repository": {
6
6
  "type": "git",