basecamp-mcp 1.1.2 → 1.2.1

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.
Files changed (79) hide show
  1. package/dist/index.d.ts +7 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +16 -7
  4. package/dist/index.js.map +1 -1
  5. package/dist/schemas/common.d.ts +9 -1
  6. package/dist/schemas/common.d.ts.map +1 -1
  7. package/dist/schemas/common.js +10 -2
  8. package/dist/schemas/common.js.map +1 -1
  9. package/dist/tools/activity.d.ts +6 -4
  10. package/dist/tools/activity.d.ts.map +1 -1
  11. package/dist/tools/activity.js +13 -285
  12. package/dist/tools/activity.js.map +1 -1
  13. package/dist/tools/auth.d.ts.map +1 -1
  14. package/dist/tools/auth.js +5 -11
  15. package/dist/tools/auth.js.map +1 -1
  16. package/dist/tools/campfires.d.ts +13 -0
  17. package/dist/tools/campfires.d.ts.map +1 -0
  18. package/dist/tools/campfires.js +221 -0
  19. package/dist/tools/campfires.js.map +1 -0
  20. package/dist/tools/checkins.d.ts.map +1 -1
  21. package/dist/tools/checkins.js +10 -74
  22. package/dist/tools/checkins.js.map +1 -1
  23. package/dist/tools/comments.d.ts.map +1 -1
  24. package/dist/tools/comments.js +9 -44
  25. package/dist/tools/comments.js.map +1 -1
  26. package/dist/tools/files.d.ts +21 -0
  27. package/dist/tools/files.d.ts.map +1 -0
  28. package/dist/tools/files.js +659 -0
  29. package/dist/tools/files.js.map +1 -0
  30. package/dist/tools/kanban.d.ts.map +1 -1
  31. package/dist/tools/kanban.js +84 -146
  32. package/dist/tools/kanban.js.map +1 -1
  33. package/dist/tools/messages.d.ts.map +1 -1
  34. package/dist/tools/messages.js +31 -71
  35. package/dist/tools/messages.js.map +1 -1
  36. package/dist/tools/people.d.ts.map +1 -1
  37. package/dist/tools/people.js +5 -19
  38. package/dist/tools/people.js.map +1 -1
  39. package/dist/tools/projects.d.ts.map +1 -1
  40. package/dist/tools/projects.js +4 -16
  41. package/dist/tools/projects.js.map +1 -1
  42. package/dist/tools/todos.d.ts.map +1 -1
  43. package/dist/tools/todos.js +82 -86
  44. package/dist/tools/todos.js.map +1 -1
  45. package/dist/utils/auth.d.ts +7 -2
  46. package/dist/utils/auth.d.ts.map +1 -1
  47. package/dist/utils/auth.js +19 -11
  48. package/dist/utils/auth.js.map +1 -1
  49. package/dist/utils/contentOperations.d.ts +2 -2
  50. package/dist/utils/credentials.d.ts.map +1 -1
  51. package/dist/utils/credentials.js.map +1 -1
  52. package/dist/utils/errorHandlers.d.ts.map +1 -1
  53. package/dist/utils/errorHandlers.js +53 -29
  54. package/dist/utils/errorHandlers.js.map +1 -1
  55. package/dist/utils/oauth.d.ts +1 -0
  56. package/dist/utils/oauth.d.ts.map +1 -1
  57. package/dist/utils/oauth.js +18 -0
  58. package/dist/utils/oauth.js.map +1 -1
  59. package/dist/utils/pagination.d.ts +43 -0
  60. package/dist/utils/pagination.d.ts.map +1 -0
  61. package/dist/utils/pagination.js +72 -0
  62. package/dist/utils/pagination.js.map +1 -0
  63. package/dist/utils/parseSince.d.ts +11 -0
  64. package/dist/utils/parseSince.d.ts.map +1 -0
  65. package/dist/utils/parseSince.js +48 -0
  66. package/dist/utils/parseSince.js.map +1 -0
  67. package/dist/utils/serializers.d.ts +17 -2
  68. package/dist/utils/serializers.d.ts.map +1 -1
  69. package/dist/utils/serializers.js +16 -0
  70. package/dist/utils/serializers.js.map +1 -1
  71. package/package.json +5 -3
  72. package/dist/tools/documents.d.ts +0 -11
  73. package/dist/tools/documents.d.ts.map +0 -1
  74. package/dist/tools/documents.js +0 -453
  75. package/dist/tools/documents.js.map +0 -1
  76. package/dist/tools/uploads.d.ts +0 -9
  77. package/dist/tools/uploads.d.ts.map +0 -1
  78. package/dist/tools/uploads.js +0 -319
  79. package/dist/tools/uploads.js.map +0 -1
@@ -1,19 +1,25 @@
1
1
  /**
2
2
  * TODO tools for Basecamp MCP server
3
3
  */
4
- import { asyncPagedToArray } from "basecamp-client";
5
4
  import { z } from "zod";
6
5
  import { BasecampIdSchema } from "../schemas/common.js";
7
6
  import { initializeBasecampClient } from "../utils/auth.js";
8
7
  import { applyContentOperations, ContentOperationFields, htmlRules, validateContentOperations, } from "../utils/contentOperations.js";
9
8
  import { handleBasecampError } from "../utils/errorHandlers.js";
10
9
  import { serializePerson } from "../utils/serializers.js";
10
+ /**
11
+ * Optional date field for todos. Accepts an ISO date (YYYY-MM-DD) or an empty
12
+ * string. Empty/omitted leaves the date unset on create and clears it on update.
13
+ */
14
+ const TodoDateSchema = z
15
+ .string()
16
+ .regex(/^(\d{4}-\d{2}-\d{2})?$/, "Date must be in YYYY-MM-DD format or empty")
17
+ .optional();
11
18
  export function registerTodoTools(server) {
12
19
  server.registerTool("basecamp_get_todoset", {
13
20
  title: "Get Basecamp Todo Set",
14
21
  description: "Get todo set container for a project. Returns todo lists and groups.",
15
22
  inputSchema: {
16
- bucket_id: BasecampIdSchema,
17
23
  todoset_id: BasecampIdSchema,
18
24
  },
19
25
  annotations: {
@@ -25,23 +31,8 @@ export function registerTodoTools(server) {
25
31
  }, async (params) => {
26
32
  try {
27
33
  const client = await initializeBasecampClient();
28
- const responseTodoSet = await client.todoSets.get({
29
- params: { bucketId: params.bucket_id, todosetId: params.todoset_id },
30
- });
31
- if (responseTodoSet.status !== 200 || !responseTodoSet.body) {
32
- throw new Error("Failed to fetch todo set");
33
- }
34
- const todoLists = await asyncPagedToArray({
35
- fetchPage: client.todoLists.list,
36
- request: {
37
- params: {
38
- bucketId: params.bucket_id,
39
- todosetId: params.todoset_id,
40
- },
41
- query: {},
42
- },
43
- });
44
- const todoSet = responseTodoSet.body;
34
+ const todoSet = await client.todosets.get(params.todoset_id);
35
+ const todoLists = await client.todolists.list(params.todoset_id);
45
36
  return {
46
37
  content: [
47
38
  {
@@ -73,7 +64,6 @@ export function registerTodoTools(server) {
73
64
  title: "List Basecamp Todos",
74
65
  description: "List todos in a todo list. Filter by status: 'active' or 'archived'.",
75
66
  inputSchema: {
76
- bucket_id: BasecampIdSchema,
77
67
  todolist_id: BasecampIdSchema,
78
68
  status: z.enum(["active", "archived"]).default("active").optional(),
79
69
  completed: z.literal(true).optional(),
@@ -87,27 +77,43 @@ export function registerTodoTools(server) {
87
77
  }, async (params) => {
88
78
  try {
89
79
  const client = await initializeBasecampClient();
90
- const todos = await asyncPagedToArray({
91
- fetchPage: client.todos.list,
92
- request: {
93
- params: {
94
- bucketId: params.bucket_id,
95
- todolistId: params.todolist_id,
96
- },
97
- query: { status: params.status, completed: params.completed },
98
- },
99
- });
80
+ const listOptions = {
81
+ status: params.status,
82
+ completed: params.completed,
83
+ };
84
+ // Todos directly under the list (i.e. not inside any group).
85
+ const ungroupedTodos = await client.todos.list(params.todolist_id, listOptions);
86
+ // A todo list can be split into groups ("sections"). Todos that live in
87
+ // a group are NOT returned by todos.list(listId) — they only come back
88
+ // from todos.list(groupId). Without this, lists that use sections return
89
+ // an empty result even though they contain todos (GitHub issue #7).
90
+ const groups = await client.todolistGroups.list(params.todolist_id);
91
+ const groupedResults = await Promise.all(groups.map(async (group) => {
92
+ const groupTodos = await client.todos.list(group.id, listOptions);
93
+ const groupName = group.title || group.name || null;
94
+ return groupTodos.map((t) => ({ todo: t, group: groupName }));
95
+ }));
96
+ const todos = [
97
+ ...ungroupedTodos.map((t) => ({
98
+ todo: t,
99
+ group: null,
100
+ })),
101
+ ...groupedResults.flat(),
102
+ ];
100
103
  return {
101
104
  content: [
102
105
  {
103
106
  type: "text",
104
107
  text: JSON.stringify({
105
108
  count: todos.length,
106
- todos: todos.map((t) => ({
109
+ todos: todos.map(({ todo: t, group }) => ({
107
110
  id: t.id,
108
111
  title: t.content,
109
112
  completed: t.completed,
110
- assignees: t.assignees.map(serializePerson),
113
+ due_on: t.due_on,
114
+ starts_on: t.starts_on,
115
+ group,
116
+ assignees: (t.assignees || []).map(serializePerson),
111
117
  })),
112
118
  }, null, 2),
113
119
  },
@@ -124,7 +130,6 @@ export function registerTodoTools(server) {
124
130
  title: "Create Basecamp Todo",
125
131
  description: `Create a new todo item in a todo list. ${htmlRules}`,
126
132
  inputSchema: {
127
- bucket_id: BasecampIdSchema,
128
133
  todolist_id: BasecampIdSchema,
129
134
  title: z.string().min(1),
130
135
  content: z.string().optional(),
@@ -132,6 +137,12 @@ export function registerTodoTools(server) {
132
137
  .array(BasecampIdSchema)
133
138
  .optional()
134
139
  .describe("Array of person IDs to assign to this todo"),
140
+ due_on: TodoDateSchema.describe("Due date in YYYY-MM-DD format. Pass an empty string to leave the due date unset."),
141
+ starts_on: TodoDateSchema.describe("Start date in YYYY-MM-DD format (for a date range; requires due_on). Pass an empty string to leave it unset."),
142
+ notify: z
143
+ .boolean()
144
+ .optional()
145
+ .describe("Whether to notify the assignees about this todo"),
135
146
  },
136
147
  annotations: {
137
148
  readOnlyHint: false,
@@ -142,25 +153,19 @@ export function registerTodoTools(server) {
142
153
  }, async (params) => {
143
154
  try {
144
155
  const client = await initializeBasecampClient();
145
- const response = await client.todos.create({
146
- params: {
147
- bucketId: params.bucket_id,
148
- todolistId: params.todolist_id,
149
- },
150
- body: {
151
- content: params.title,
152
- description: params.content,
153
- assignee_ids: params.assignee_ids,
154
- },
156
+ const todo = await client.todos.create(params.todolist_id, {
157
+ content: params.title,
158
+ description: params.content,
159
+ assigneeIds: params.assignee_ids,
160
+ ...(params.due_on ? { dueOn: params.due_on } : {}),
161
+ ...(params.starts_on ? { startsOn: params.starts_on } : {}),
162
+ ...(params.notify !== undefined ? { notify: params.notify } : {}),
155
163
  });
156
- if (response.status !== 201 || !response.body) {
157
- throw new Error("Failed to create todo");
158
- }
159
164
  return {
160
165
  content: [
161
166
  {
162
167
  type: "text",
163
- text: `Todo created!\n\nID: ${response.body.id}\nContent: ${response.body.content}`,
168
+ text: `Todo created!\n\nID: ${todo.id}\nContent: ${todo.content}${todo.due_on ? `\nDue: ${todo.due_on}` : ""}${todo.starts_on ? `\nStarts: ${todo.starts_on}` : ""}`,
164
169
  },
165
170
  ],
166
171
  };
@@ -175,7 +180,6 @@ export function registerTodoTools(server) {
175
180
  title: "Complete Basecamp Todo",
176
181
  description: "Mark a todo as completed.",
177
182
  inputSchema: {
178
- bucket_id: BasecampIdSchema,
179
183
  todo_id: BasecampIdSchema,
180
184
  },
181
185
  annotations: {
@@ -187,9 +191,7 @@ export function registerTodoTools(server) {
187
191
  }, async (params) => {
188
192
  try {
189
193
  const client = await initializeBasecampClient();
190
- await client.todos.complete({
191
- params: { bucketId: params.bucket_id, todoId: params.todo_id },
192
- });
194
+ await client.todos.complete(params.todo_id);
193
195
  return {
194
196
  content: [{ type: "text", text: "Todo marked as completed!" }],
195
197
  };
@@ -204,7 +206,6 @@ export function registerTodoTools(server) {
204
206
  title: "Uncomplete Basecamp Todo",
205
207
  description: "Mark a todo as incomplete (undo completion).",
206
208
  inputSchema: {
207
- bucket_id: BasecampIdSchema,
208
209
  todo_id: BasecampIdSchema,
209
210
  },
210
211
  annotations: {
@@ -216,9 +217,7 @@ export function registerTodoTools(server) {
216
217
  }, async (params) => {
217
218
  try {
218
219
  const client = await initializeBasecampClient();
219
- await client.todos.uncomplete({
220
- params: { bucketId: params.bucket_id, todoId: params.todo_id },
221
- });
220
+ await client.todos.uncomplete(params.todo_id);
222
221
  return {
223
222
  content: [{ type: "text", text: "Todo marked as incomplete!" }],
224
223
  };
@@ -233,13 +232,18 @@ export function registerTodoTools(server) {
233
232
  title: "Update Basecamp Todo",
234
233
  description: `Update a todo item. Use partial content operations when possible to save on token usage. ${htmlRules}`,
235
234
  inputSchema: {
236
- bucket_id: BasecampIdSchema,
237
235
  todo_id: BasecampIdSchema,
238
236
  title: z.string().optional().describe("New todo title"),
239
237
  assignee_ids: z
240
238
  .array(BasecampIdSchema)
241
239
  .optional()
242
240
  .describe("Array of person IDs to assign to this todo"),
241
+ due_on: TodoDateSchema.describe("Due date in YYYY-MM-DD format. Pass an empty string to clear the due date."),
242
+ starts_on: TodoDateSchema.describe("Start date in YYYY-MM-DD format (for a date range; requires due_on). Pass an empty string to clear it."),
243
+ notify: z
244
+ .boolean()
245
+ .optional()
246
+ .describe("Whether to notify the assignees about this todo"),
243
247
  ...ContentOperationFields,
244
248
  },
245
249
  annotations: {
@@ -251,27 +255,25 @@ export function registerTodoTools(server) {
251
255
  }, async (params) => {
252
256
  try {
253
257
  // Validate at least one operation is provided
254
- validateContentOperations(params, ["title", "assignee_ids"]);
258
+ validateContentOperations(params, [
259
+ "title",
260
+ "assignee_ids",
261
+ "due_on",
262
+ "starts_on",
263
+ "notify",
264
+ ]);
255
265
  const client = await initializeBasecampClient();
256
266
  // Fetch current todo to get existing values
257
- const currentResponse = await client.todos.get({
258
- params: {
259
- bucketId: params.bucket_id,
260
- todoId: params.todo_id,
261
- },
262
- });
263
- if (currentResponse.status !== 200 || !currentResponse.body) {
264
- throw new Error(`Failed to fetch current todo: ${currentResponse.status}`);
265
- }
267
+ const currentTodo = await client.todos.get(params.todo_id);
266
268
  // Determine final title (maps to Basecamp's content field)
267
- const finalTitle = params.title ?? currentResponse.body.content;
269
+ const finalTitle = params.title ?? currentTodo.content;
268
270
  // Determine final content (maps to Basecamp's description field)
269
271
  let finalContent;
270
272
  const hasPartialOps = params.content_append ||
271
273
  params.content_prepend ||
272
274
  params.search_replace;
273
275
  if (hasPartialOps) {
274
- const currentContent = currentResponse.body.description || "";
276
+ const currentContent = currentTodo.description || "";
275
277
  const result = applyContentOperations(currentContent, params);
276
278
  if (result === undefined) {
277
279
  throw new Error("Content operations resulted in undefined content");
@@ -282,29 +284,23 @@ export function registerTodoTools(server) {
282
284
  // Full content replacement
283
285
  finalContent = params.content;
284
286
  }
285
- const response = await client.todos.update({
286
- params: {
287
- bucketId: params.bucket_id,
288
- todoId: params.todo_id,
289
- },
290
- body: {
291
- content: finalTitle,
292
- ...(finalContent !== undefined
293
- ? { description: finalContent }
294
- : {}),
295
- ...(params.assignee_ids !== undefined
296
- ? { assignee_ids: params.assignee_ids }
297
- : {}),
298
- },
287
+ const todo = await client.todos.update(params.todo_id, {
288
+ content: finalTitle,
289
+ ...(finalContent !== undefined ? { description: finalContent } : {}),
290
+ ...(params.assignee_ids !== undefined
291
+ ? { assigneeIds: params.assignee_ids }
292
+ : {}),
293
+ ...(params.due_on !== undefined ? { dueOn: params.due_on } : {}),
294
+ ...(params.starts_on !== undefined
295
+ ? { startsOn: params.starts_on }
296
+ : {}),
297
+ ...(params.notify !== undefined ? { notify: params.notify } : {}),
299
298
  });
300
- if (response.status !== 200 || !response.body) {
301
- throw new Error("Failed to update todo");
302
- }
303
299
  return {
304
300
  content: [
305
301
  {
306
302
  type: "text",
307
- text: `Todo updated!\n\nID: ${response.body.id}\nContent: ${response.body.content}`,
303
+ text: `Todo updated!\n\nID: ${todo.id}\nContent: ${todo.content}${todo.due_on ? `\nDue: ${todo.due_on}` : ""}${todo.starts_on ? `\nStarts: ${todo.starts_on}` : ""}`,
308
304
  },
309
305
  ],
310
306
  };
@@ -1 +1 @@
1
- {"version":3,"file":"todos.js","sourceRoot":"","sources":["../../src/tools/todos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"todos.js","sourceRoot":"","sources":["../../src/tools/todos.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
- import { type Client } from "basecamp-client";
2
- export declare function initializeBasecampClient(): Promise<Client>;
1
+ import { type BasecampClient } from "@37signals/basecamp";
2
+ /**
3
+ * Return a valid bearer token, refreshing (and caching) one if necessary.
4
+ * Throws if the user is not logged in.
5
+ */
6
+ export declare function getBearerToken(): Promise<string>;
7
+ export declare function initializeBasecampClient(): Promise<BasecampClient>;
3
8
  export declare function clearTokenCache(): void;
4
9
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,MAAM,EAAkB,MAAM,iBAAiB,CAAC;AAM3E,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAqBhE;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,qBAAqB,CAAC;AAMhF;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAiBtD;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,cAAc,CAAC,CAaxE;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -1,23 +1,31 @@
1
- import { buildClient, getBearerToken } from "basecamp-client";
1
+ import { createBasecampClient } from "@37signals/basecamp";
2
2
  import { readCredentials } from "./credentials.js";
3
- import { getClientCredentials } from "./oauth.js";
3
+ import { getClientCredentials, refreshAccessToken } from "./oauth.js";
4
4
  let cachedBearerToken = null;
5
- export async function initializeBasecampClient() {
5
+ /**
6
+ * Return a valid bearer token, refreshing (and caching) one if necessary.
7
+ * Throws if the user is not logged in.
8
+ */
9
+ export async function getBearerToken() {
6
10
  const creds = await readCredentials();
7
11
  if (!creds) {
8
12
  throw new Error("Not logged in. Use basecamp_login to authenticate.");
9
13
  }
10
- const { clientId, clientSecret } = getClientCredentials();
11
14
  if (!cachedBearerToken) {
12
- cachedBearerToken = await getBearerToken({
13
- clientId,
14
- clientSecret,
15
- refreshToken: creds.refreshToken,
16
- });
15
+ const { clientId, clientSecret } = getClientCredentials();
16
+ cachedBearerToken = await refreshAccessToken(creds.refreshToken, clientId, clientSecret);
17
+ }
18
+ return cachedBearerToken;
19
+ }
20
+ export async function initializeBasecampClient() {
21
+ const creds = await readCredentials();
22
+ if (!creds) {
23
+ throw new Error("Not logged in. Use basecamp_login to authenticate.");
17
24
  }
18
- return buildClient({
19
- bearerToken: cachedBearerToken,
25
+ const accessToken = await getBearerToken();
26
+ return createBasecampClient({
20
27
  accountId: creds.accountId,
28
+ accessToken,
21
29
  });
22
30
  }
23
31
  export function clearTokenCache() {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC7C,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAE1D,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,iBAAiB,GAAG,MAAM,cAAc,CAAC;YACxC,QAAQ;YACR,YAAY;YACZ,YAAY,EAAE,KAAK,CAAC,YAAY;SAChC,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,WAAW,CAAC;QAClB,WAAW,EAAE,iBAAiB;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;KAC1B,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC9B,iBAAiB,GAAG,IAAI,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEtE,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,EAAE,CAAC;QAC1D,iBAAiB,GAAG,MAAM,kBAAkB,CAC1C,KAAK,CAAC,YAAY,EAClB,QAAQ,EACR,YAAY,CACb,CAAC;IACJ,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAE3C,OAAO,oBAAoB,CAAC;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,iBAAiB,GAAG,IAAI,CAAC;AAC3B,CAAC"}
@@ -16,11 +16,11 @@ export declare const ContentOperationFields: {
16
16
  find: z.ZodString;
17
17
  replace: z.ZodString;
18
18
  }, "strip", z.ZodTypeAny, {
19
- replace: string;
20
19
  find: string;
21
- }, {
22
20
  replace: string;
21
+ }, {
23
22
  find: string;
23
+ replace: string;
24
24
  }>, "many">>;
25
25
  };
26
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CAClB,CAAC;AASF,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAanE;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AASF,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAanE;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAO1C,MAAM,gBAAgB,GAAG,IAAI,CAC5B,OAAO,EAAE,EACT,SAAS,EACT,cAAc,EACd,kBAAkB,CAClB,CAAC;AAEF,MAAM,UAAU,kBAAkB;IACjC,OAAO,gBAAgB,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACpC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAkB;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACtC,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACR,oCAAoC;IACrC,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAO1C,MAAM,gBAAgB,GAAG,IAAI,CAC3B,OAAO,EAAE,EACT,SAAS,EACT,cAAc,EACd,kBAAkB,CACnB,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAkB;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandlers.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA8E1D"}
1
+ {"version":3,"file":"errorHandlers.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwC1D"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Error handling utilities for Basecamp API
3
3
  */
4
+ import { isBasecampError } from "@37signals/basecamp";
4
5
  /**
5
6
  * Convert Basecamp API errors to helpful, actionable error messages for LLMs.
6
7
  *
@@ -8,38 +9,20 @@
8
9
  * @returns Human-readable error message with guidance
9
10
  */
10
11
  export function handleBasecampError(error) {
12
+ // Structured errors thrown by the official SDK carry a code, message, and
13
+ // (often) an actionable hint. Prefer those, falling back to status-based
14
+ // guidance below when no HTTP status is available.
15
+ if (isBasecampError(error)) {
16
+ if (error.httpStatus) {
17
+ return statusMessage(error.httpStatus, error.message, error.hint);
18
+ }
19
+ const hint = error.hint ? ` ${error.hint}` : "";
20
+ return `Error [${error.code}]: ${error.message}.${hint}`;
21
+ }
11
22
  // Handle HTTP response errors
12
23
  if (error && typeof error === "object" && "status" in error) {
13
24
  const status = error.status;
14
- switch (status) {
15
- case 400:
16
- return ("Error: Bad request. Check that all required parameters are provided and formatted correctly. " +
17
- extractErrorDetails(error));
18
- case 401:
19
- return ("Error: Authentication failed. Your access token may have expired. " +
20
- "Try restarting the server to refresh the token, or check your BASECAMP_REFRESH_TOKEN is valid.");
21
- case 403:
22
- return ("Error: Access denied. You don't have permission to access this resource. " +
23
- "Check that you're using the correct account ID and that your Basecamp user has access to this project/resource.");
24
- case 404:
25
- return ("Error: Resource not found. The requested resource (message, todo, project, etc.) doesn't exist or has been deleted. " +
26
- "Verify the ID is correct and the resource hasn't been moved to trash.");
27
- case 422:
28
- return ("Error: Validation failed. The request data didn't pass Basecamp's validation rules. " +
29
- extractErrorDetails(error) +
30
- " Check the data format and required fields.");
31
- case 429:
32
- return ("Error: Rate limit exceeded. Too many requests have been made to the Basecamp API. " +
33
- "Please wait a moment before trying again.");
34
- case 500:
35
- case 502:
36
- case 503:
37
- case 504:
38
- return ("Error: Basecamp server error. The Basecamp API is experiencing issues. " +
39
- "Please try again in a moment.");
40
- default:
41
- return `Error: API request failed with status ${status}. ${extractErrorDetails(error)}`;
42
- }
25
+ return statusMessage(status, extractErrorDetails(error));
43
26
  }
44
27
  // Handle network/connection errors
45
28
  if (error && typeof error === "object" && "code" in error) {
@@ -56,6 +39,47 @@ export function handleBasecampError(error) {
56
39
  // Generic error fallback
57
40
  return `Error: ${error instanceof Error ? error.message : String(error)}`;
58
41
  }
42
+ /**
43
+ * Map an HTTP status code to actionable guidance for LLMs.
44
+ *
45
+ * @param status - HTTP status code
46
+ * @param details - Extra details to append (from SDK message or response body)
47
+ * @param hint - Optional actionable hint from the SDK error
48
+ * @returns Human-readable error message with guidance
49
+ */
50
+ function statusMessage(status, details = "", hint = "") {
51
+ const suffix = [details, hint].filter(Boolean).join(" ");
52
+ const tail = suffix ? ` ${suffix}` : "";
53
+ switch (status) {
54
+ case 400:
55
+ return ("Error: Bad request. Check that all required parameters are provided and formatted correctly." +
56
+ tail);
57
+ case 401:
58
+ return ("Error: Authentication failed. Your access token may have expired. " +
59
+ "Try restarting the server to refresh the token, or check your BASECAMP_REFRESH_TOKEN is valid.");
60
+ case 403:
61
+ return ("Error: Access denied. You don't have permission to access this resource. " +
62
+ "Check that you're using the correct account ID and that your Basecamp user has access to this project/resource.");
63
+ case 404:
64
+ return ("Error: Resource not found. The requested resource (message, todo, project, etc.) doesn't exist or has been deleted. " +
65
+ "Verify the ID is correct and the resource hasn't been moved to trash.");
66
+ case 422:
67
+ return ("Error: Validation failed. The request data didn't pass Basecamp's validation rules." +
68
+ tail +
69
+ " Check the data format and required fields.");
70
+ case 429:
71
+ return ("Error: Rate limit exceeded. Too many requests have been made to the Basecamp API. " +
72
+ "Please wait a moment before trying again.");
73
+ case 500:
74
+ case 502:
75
+ case 503:
76
+ case 504:
77
+ return ("Error: Basecamp server error. The Basecamp API is experiencing issues. " +
78
+ "Please try again in a moment.");
79
+ default:
80
+ return `Error: API request failed with status ${status}.${tail}`;
81
+ }
82
+ }
59
83
  /**
60
84
  * Extract additional error details from API response if available.
61
85
  *
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandlers.js","sourceRoot":"","sources":["../../src/utils/errorHandlers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errorHandlers.js","sourceRoot":"","sources":["../../src/utils/errorHandlers.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ export declare function getClientCredentials(): {
2
2
  clientId: string;
3
3
  clientSecret: string;
4
4
  };
5
+ export declare function refreshAccessToken(refreshToken: string, clientId: string, clientSecret: string): Promise<string>;
5
6
  export declare function performBasecampOAuthLogin(): Promise<{
6
7
  accessToken: string;
7
8
  refreshToken: string;
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/utils/oauth.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,IAAI;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACrB,CAWA;AAwID,wBAAsB,yBAAyB,IAAI,OAAO,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC,CAqBD;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,qBAAqB,CAC1C,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,EAAE,CAAC,CAiB5B"}
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/utils/oauth.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,IAAI;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,CAWA;AA8CD,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AA+FD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAqBD;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,EAAE,CAAC,CAe5B"}
@@ -47,6 +47,24 @@ async function exchangeCodeForTokens(code, clientId, clientSecret) {
47
47
  const data = (await response.json());
48
48
  return { accessToken: data.access_token, refreshToken: data.refresh_token };
49
49
  }
50
+ export async function refreshAccessToken(refreshToken, clientId, clientSecret) {
51
+ const response = await fetch(TOKEN_URL, {
52
+ method: "POST",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify({
55
+ type: "refresh",
56
+ refresh_token: refreshToken,
57
+ client_id: clientId,
58
+ client_secret: clientSecret,
59
+ }),
60
+ });
61
+ if (!response.ok) {
62
+ const body = await response.text();
63
+ throw new Error(`Token refresh failed (${response.status}): ${body}`);
64
+ }
65
+ const data = (await response.json());
66
+ return data.access_token;
67
+ }
50
68
  const SUCCESS_HTML = `<!DOCTYPE html>
51
69
  <html>
52
70
  <head><title>Basecamp MCP</title></head>