basecamp-mcp 1.0.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.
- package/README.md +155 -0
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +13 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +19 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/tools/comments.d.ts +7 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +179 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/kanban.d.ts +6 -0
- package/dist/tools/kanban.d.ts.map +1 -0
- package/dist/tools/kanban.js +390 -0
- package/dist/tools/kanban.js.map +1 -0
- package/dist/tools/messages.d.ts +8 -0
- package/dist/tools/messages.d.ts.map +1 -0
- package/dist/tools/messages.js +300 -0
- package/dist/tools/messages.js.map +1 -0
- package/dist/tools/people.d.ts +6 -0
- package/dist/tools/people.d.ts.map +1 -0
- package/dist/tools/people.js +142 -0
- package/dist/tools/people.js.map +1 -0
- package/dist/tools/projects.d.ts +11 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +116 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/todos.d.ts +6 -0
- package/dist/tools/todos.d.ts.map +1 -0
- package/dist/tools/todos.js +223 -0
- package/dist/tools/todos.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/auth.d.ts +24 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/dist/utils/auth.js +62 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/contentOperations.d.ts +55 -0
- package/dist/utils/contentOperations.d.ts.map +1 -0
- package/dist/utils/contentOperations.js +109 -0
- package/dist/utils/contentOperations.js.map +1 -0
- package/dist/utils/errorHandlers.d.ts +11 -0
- package/dist/utils/errorHandlers.d.ts.map +1 -0
- package/dist/utils/errorHandlers.js +87 -0
- package/dist/utils/errorHandlers.js.map +1 -0
- package/dist/utils/serializers.d.ts +27 -0
- package/dist/utils/serializers.d.ts.map +1 -0
- package/dist/utils/serializers.js +19 -0
- package/dist/utils/serializers.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Board tools for Basecamp MCP server
|
|
3
|
+
*
|
|
4
|
+
* Includes special patch support for updating messages without passing full content
|
|
5
|
+
*/
|
|
6
|
+
import { asyncPagedToArray } from "basecamp-client";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { BasecampIdSchema } from "../schemas/common.js";
|
|
9
|
+
import { initializeBasecampClient } from "../utils/auth.js";
|
|
10
|
+
import { applyContentOperations, ContentOperationFields, htmlRules, validateContentOperations, } from "../utils/contentOperations.js";
|
|
11
|
+
import { handleBasecampError } from "../utils/errorHandlers.js";
|
|
12
|
+
import { serializePerson } from "../utils/serializers.js";
|
|
13
|
+
export function registerMessageTools(server) {
|
|
14
|
+
// basecamp_get_message
|
|
15
|
+
server.registerTool("basecamp_get_message", {
|
|
16
|
+
title: "Get Basecamp Message",
|
|
17
|
+
description: `Retrieve a single message from a Basecamp message board.`,
|
|
18
|
+
inputSchema: {
|
|
19
|
+
bucket_id: BasecampIdSchema.describe("Project/bucket ID containing the message"),
|
|
20
|
+
message_id: BasecampIdSchema.describe("Message ID to retrieve"),
|
|
21
|
+
},
|
|
22
|
+
annotations: {
|
|
23
|
+
readOnlyHint: true,
|
|
24
|
+
destructiveHint: false,
|
|
25
|
+
idempotentHint: true,
|
|
26
|
+
openWorldHint: true,
|
|
27
|
+
},
|
|
28
|
+
}, async (params) => {
|
|
29
|
+
try {
|
|
30
|
+
const client = await initializeBasecampClient();
|
|
31
|
+
const response = await client.messages.get({
|
|
32
|
+
params: { bucketId: params.bucket_id, messageId: params.message_id },
|
|
33
|
+
});
|
|
34
|
+
if (response.status !== 200 || !response.body) {
|
|
35
|
+
throw new Error(`Failed to fetch message: ${response.status}`);
|
|
36
|
+
}
|
|
37
|
+
const msg = response.body;
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: JSON.stringify({
|
|
43
|
+
id: msg.id,
|
|
44
|
+
subject: msg.title,
|
|
45
|
+
content: msg.content || "",
|
|
46
|
+
author: serializePerson(msg.creator),
|
|
47
|
+
created_at: msg.created_at,
|
|
48
|
+
updated_at: msg.updated_at,
|
|
49
|
+
url: msg.app_url,
|
|
50
|
+
}, null, 2),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// basecamp_list_messages
|
|
62
|
+
server.registerTool("basecamp_list_messages", {
|
|
63
|
+
title: "List Basecamp Messages",
|
|
64
|
+
description: `List messages in a Basecamp message board`,
|
|
65
|
+
inputSchema: {
|
|
66
|
+
bucket_id: BasecampIdSchema.describe("Project/bucket ID"),
|
|
67
|
+
message_board_id: BasecampIdSchema.describe("Message board ID"),
|
|
68
|
+
filter: z
|
|
69
|
+
.string()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("Optional regular expression to filter messages by title or content"),
|
|
72
|
+
},
|
|
73
|
+
annotations: {
|
|
74
|
+
readOnlyHint: true,
|
|
75
|
+
destructiveHint: false,
|
|
76
|
+
idempotentHint: true,
|
|
77
|
+
openWorldHint: true,
|
|
78
|
+
},
|
|
79
|
+
}, async (params) => {
|
|
80
|
+
try {
|
|
81
|
+
const client = await initializeBasecampClient();
|
|
82
|
+
const messages = await asyncPagedToArray({
|
|
83
|
+
fetchPage: client.messages.list,
|
|
84
|
+
request: {
|
|
85
|
+
params: {
|
|
86
|
+
bucketId: params.bucket_id,
|
|
87
|
+
messageBoardId: params.message_board_id,
|
|
88
|
+
},
|
|
89
|
+
query: {},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
// Apply filter if provided
|
|
93
|
+
let filteredMessages = messages;
|
|
94
|
+
if (params.filter) {
|
|
95
|
+
const regex = new RegExp(params.filter, "i");
|
|
96
|
+
filteredMessages = messages.filter((m) => regex.test(m.title) || regex.test(m.content || ""));
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: "text",
|
|
102
|
+
text: JSON.stringify(filteredMessages.map((m) => ({
|
|
103
|
+
id: m.id,
|
|
104
|
+
title: m.title,
|
|
105
|
+
creator: serializePerson(m.creator),
|
|
106
|
+
created_at: m.created_at,
|
|
107
|
+
})), null, 2),
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
return {
|
|
114
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
// basecamp_list_message_types
|
|
119
|
+
server.registerTool("basecamp_list_message_types", {
|
|
120
|
+
title: "List Basecamp Message Types",
|
|
121
|
+
description: `List available message types/categories for a Basecamp project`,
|
|
122
|
+
inputSchema: {
|
|
123
|
+
bucket_id: BasecampIdSchema.describe("Project/bucket ID"),
|
|
124
|
+
},
|
|
125
|
+
annotations: {
|
|
126
|
+
readOnlyHint: true,
|
|
127
|
+
destructiveHint: false,
|
|
128
|
+
idempotentHint: true,
|
|
129
|
+
openWorldHint: true,
|
|
130
|
+
},
|
|
131
|
+
}, async (params) => {
|
|
132
|
+
try {
|
|
133
|
+
const client = await initializeBasecampClient();
|
|
134
|
+
const response = await client.messageTypes.list({
|
|
135
|
+
params: {
|
|
136
|
+
bucketId: params.bucket_id,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
if (response.status !== 200 || !response.body) {
|
|
140
|
+
throw new Error(`Failed to fetch message types: ${response.status}`);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
content: [
|
|
144
|
+
{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: JSON.stringify(response.body.map((mt) => ({
|
|
147
|
+
id: mt.id,
|
|
148
|
+
name: mt.name,
|
|
149
|
+
icon: mt.icon,
|
|
150
|
+
created_at: mt.created_at,
|
|
151
|
+
updated_at: mt.updated_at,
|
|
152
|
+
})), null, 2),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return {
|
|
159
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
// basecamp_create_message
|
|
164
|
+
server.registerTool("basecamp_create_message", {
|
|
165
|
+
title: "Create Basecamp Message",
|
|
166
|
+
description: `Create a new message in a Basecamp message board.`,
|
|
167
|
+
inputSchema: {
|
|
168
|
+
bucket_id: BasecampIdSchema,
|
|
169
|
+
message_board_id: BasecampIdSchema,
|
|
170
|
+
subject: z.string().min(1).max(500).describe("Message subject/title"),
|
|
171
|
+
content: z
|
|
172
|
+
.string()
|
|
173
|
+
.optional()
|
|
174
|
+
.describe(`HTML message content. To mention people: <bc-attachment sgid="{ person.attachable_sgid }"></bc-attachment>`),
|
|
175
|
+
message_type_id: BasecampIdSchema.optional().describe("Optional message type/category ID"),
|
|
176
|
+
status: z
|
|
177
|
+
.enum(["active", "draft"])
|
|
178
|
+
.default("active")
|
|
179
|
+
.describe("Message status"),
|
|
180
|
+
},
|
|
181
|
+
annotations: {
|
|
182
|
+
readOnlyHint: false,
|
|
183
|
+
destructiveHint: false,
|
|
184
|
+
idempotentHint: false,
|
|
185
|
+
openWorldHint: true,
|
|
186
|
+
},
|
|
187
|
+
}, async (params) => {
|
|
188
|
+
try {
|
|
189
|
+
const client = await initializeBasecampClient();
|
|
190
|
+
const response = await client.messages.create({
|
|
191
|
+
params: {
|
|
192
|
+
bucketId: params.bucket_id,
|
|
193
|
+
messageBoardId: params.message_board_id,
|
|
194
|
+
},
|
|
195
|
+
body: {
|
|
196
|
+
subject: params.subject,
|
|
197
|
+
content: params.content,
|
|
198
|
+
category_id: params.message_type_id,
|
|
199
|
+
status: params.status,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
if (response.status !== 201 || !response.body) {
|
|
203
|
+
throw new Error(`Failed to create message`);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
content: [
|
|
207
|
+
{
|
|
208
|
+
type: "text",
|
|
209
|
+
text: `Message created successfully!\n\nID: ${response.body.id}\nSubject: ${response.body.title}\nURL: ${response.body.app_url}`,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
return {
|
|
216
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
server.registerTool("basecamp_update_message", {
|
|
221
|
+
title: "Update Basecamp Message",
|
|
222
|
+
description: `Update a message. Use partial content operations when possible to save on token usage. ${htmlRules}`,
|
|
223
|
+
inputSchema: {
|
|
224
|
+
bucket_id: BasecampIdSchema,
|
|
225
|
+
message_id: BasecampIdSchema,
|
|
226
|
+
subject: z
|
|
227
|
+
.string()
|
|
228
|
+
.min(1)
|
|
229
|
+
.max(500)
|
|
230
|
+
.optional()
|
|
231
|
+
.describe("New message subject"),
|
|
232
|
+
message_type_id: BasecampIdSchema.optional().describe("Optional message type/category ID"),
|
|
233
|
+
...ContentOperationFields,
|
|
234
|
+
},
|
|
235
|
+
annotations: {
|
|
236
|
+
readOnlyHint: false,
|
|
237
|
+
destructiveHint: false,
|
|
238
|
+
idempotentHint: false,
|
|
239
|
+
openWorldHint: true,
|
|
240
|
+
},
|
|
241
|
+
}, async (params) => {
|
|
242
|
+
try {
|
|
243
|
+
// Validate at least one operation is provided
|
|
244
|
+
validateContentOperations(params, ["subject", "message_type_id"]);
|
|
245
|
+
const client = await initializeBasecampClient();
|
|
246
|
+
let finalContent;
|
|
247
|
+
// Check if we need to fetch current content for partial operations
|
|
248
|
+
const hasPartialOps = params.content_append ||
|
|
249
|
+
params.content_prepend ||
|
|
250
|
+
params.search_replace;
|
|
251
|
+
if (hasPartialOps || params.content !== undefined) {
|
|
252
|
+
// Fetch current message if needed for partial operations
|
|
253
|
+
if (hasPartialOps) {
|
|
254
|
+
const currentResponse = await client.messages.get({
|
|
255
|
+
params: {
|
|
256
|
+
bucketId: params.bucket_id,
|
|
257
|
+
messageId: params.message_id,
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
if (currentResponse.status !== 200 || !currentResponse.body) {
|
|
261
|
+
throw new Error(`Failed to fetch current message for partial update: ${currentResponse.status}`);
|
|
262
|
+
}
|
|
263
|
+
const currentContent = currentResponse.body.content || "";
|
|
264
|
+
finalContent = applyContentOperations(currentContent, params);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Full content replacement
|
|
268
|
+
finalContent = params.content;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const response = await client.messages.update({
|
|
272
|
+
params: { bucketId: params.bucket_id, messageId: params.message_id },
|
|
273
|
+
body: {
|
|
274
|
+
...(params.subject ? { subject: params.subject } : {}),
|
|
275
|
+
...(finalContent !== undefined ? { content: finalContent } : {}),
|
|
276
|
+
...(params.message_type_id
|
|
277
|
+
? { category_id: params.message_type_id }
|
|
278
|
+
: {}),
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
if (response.status !== 200 || !response.body) {
|
|
282
|
+
throw new Error(`Failed to update message`);
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
content: [
|
|
286
|
+
{
|
|
287
|
+
type: "text",
|
|
288
|
+
text: `Message updated successfully!\n\nID: ${response.body.id}\nSubject: ${response.body.title}`,
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
return {
|
|
295
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/tools/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"people.d.ts","sourceRoot":"","sources":["../../src/tools/people.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2K3D"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* People tools for Basecamp MCP server
|
|
3
|
+
*/
|
|
4
|
+
import { asyncPagedToArray } from "basecamp-client";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { BasecampIdSchema } from "../schemas/common.js";
|
|
7
|
+
import { initializeBasecampClient } from "../utils/auth.js";
|
|
8
|
+
import { handleBasecampError } from "../utils/errorHandlers.js";
|
|
9
|
+
export function registerPeopleTools(server) {
|
|
10
|
+
server.registerTool("basecamp_get_me", {
|
|
11
|
+
title: "Get My Basecamp Profile",
|
|
12
|
+
description: "Get personal information for the authenticated user (me).",
|
|
13
|
+
annotations: {
|
|
14
|
+
readOnlyHint: true,
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: false,
|
|
18
|
+
},
|
|
19
|
+
}, async () => {
|
|
20
|
+
try {
|
|
21
|
+
const client = await initializeBasecampClient();
|
|
22
|
+
const response = await client.people.me({});
|
|
23
|
+
if (response.status !== 200 || !response.body) {
|
|
24
|
+
throw new Error("Failed to get personal info");
|
|
25
|
+
}
|
|
26
|
+
const me = response.body;
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: JSON.stringify({
|
|
32
|
+
id: me.id,
|
|
33
|
+
name: me.name,
|
|
34
|
+
email: me.email_address,
|
|
35
|
+
title: me.title,
|
|
36
|
+
attachable_sgid: me.attachable_sgid,
|
|
37
|
+
}, null, 2),
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
server.registerTool("basecamp_list_people", {
|
|
49
|
+
title: "List Basecamp People",
|
|
50
|
+
description: "List all people in the Basecamp account.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
filter: z
|
|
53
|
+
.string()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Optional regular expression to filter people by name, email, or title"),
|
|
56
|
+
},
|
|
57
|
+
annotations: {
|
|
58
|
+
readOnlyHint: true,
|
|
59
|
+
destructiveHint: false,
|
|
60
|
+
idempotentHint: true,
|
|
61
|
+
openWorldHint: true,
|
|
62
|
+
},
|
|
63
|
+
}, async (params) => {
|
|
64
|
+
try {
|
|
65
|
+
const client = await initializeBasecampClient();
|
|
66
|
+
const people = await asyncPagedToArray({
|
|
67
|
+
fetchPage: client.people.list,
|
|
68
|
+
request: { query: {} },
|
|
69
|
+
});
|
|
70
|
+
// Apply filter if provided
|
|
71
|
+
let filteredPeople = people;
|
|
72
|
+
if (params.filter) {
|
|
73
|
+
const regex = new RegExp(params.filter, "i");
|
|
74
|
+
filteredPeople = people.filter((p) => regex.test(p.name) ||
|
|
75
|
+
regex.test(p.email_address || "") ||
|
|
76
|
+
regex.test(p.title || ""));
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: JSON.stringify(filteredPeople.map((p) => ({
|
|
83
|
+
id: p.id,
|
|
84
|
+
name: p.name,
|
|
85
|
+
email: p.email_address,
|
|
86
|
+
title: p.title,
|
|
87
|
+
attachable_sgid: p.attachable_sgid,
|
|
88
|
+
})), null, 2),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
server.registerTool("basecamp_get_person", {
|
|
100
|
+
title: "Get Basecamp Person",
|
|
101
|
+
description: "Get details about a specific person.",
|
|
102
|
+
inputSchema: {
|
|
103
|
+
person_id: BasecampIdSchema,
|
|
104
|
+
},
|
|
105
|
+
annotations: {
|
|
106
|
+
readOnlyHint: true,
|
|
107
|
+
destructiveHint: false,
|
|
108
|
+
idempotentHint: true,
|
|
109
|
+
openWorldHint: true,
|
|
110
|
+
},
|
|
111
|
+
}, async (params) => {
|
|
112
|
+
try {
|
|
113
|
+
const client = await initializeBasecampClient();
|
|
114
|
+
const response = await client.people.get({
|
|
115
|
+
params: { personId: params.person_id },
|
|
116
|
+
});
|
|
117
|
+
if (response.status !== 200 || !response.body) {
|
|
118
|
+
throw new Error("Failed to get person");
|
|
119
|
+
}
|
|
120
|
+
const person = response.body;
|
|
121
|
+
return {
|
|
122
|
+
content: [
|
|
123
|
+
{
|
|
124
|
+
type: "text",
|
|
125
|
+
text: JSON.stringify({
|
|
126
|
+
id: person.id,
|
|
127
|
+
name: person.name,
|
|
128
|
+
email: person.email_address,
|
|
129
|
+
title: person.title,
|
|
130
|
+
}, null, 2),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
return {
|
|
137
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=people.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"people.js","sourceRoot":"","sources":["../../src/tools/people.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-related tools for Basecamp MCP server
|
|
3
|
+
*
|
|
4
|
+
* Projects are the foundation - they help users discover bucket IDs needed for other operations.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register all project-related tools with the MCP server
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerProjectTools(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/tools/projects.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4H5D"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-related tools for Basecamp MCP server
|
|
3
|
+
*
|
|
4
|
+
* Projects are the foundation - they help users discover bucket IDs needed for other operations.
|
|
5
|
+
*/
|
|
6
|
+
import { asyncPagedToArray } from "basecamp-client";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { BasecampIdSchema } from "../schemas/common.js";
|
|
9
|
+
import { initializeBasecampClient } from "../utils/auth.js";
|
|
10
|
+
import { handleBasecampError } from "../utils/errorHandlers.js";
|
|
11
|
+
/**
|
|
12
|
+
* Register all project-related tools with the MCP server
|
|
13
|
+
*/
|
|
14
|
+
export function registerProjectTools(server) {
|
|
15
|
+
// Tool: basecamp_list_projects
|
|
16
|
+
server.registerTool("basecamp_list_projects", {
|
|
17
|
+
title: "List Basecamp Projects",
|
|
18
|
+
description: `List all projects visible to the authenticated user in a Basecamp account. This tool returns active projects with their IDs, names, descriptions, and metadata. Use this to discover project/bucket IDs needed for accessing messages, todos, and other resources.`,
|
|
19
|
+
inputSchema: {
|
|
20
|
+
filter: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Optional regular expression to filter projects by name or description"),
|
|
24
|
+
},
|
|
25
|
+
annotations: {
|
|
26
|
+
readOnlyHint: true,
|
|
27
|
+
destructiveHint: false,
|
|
28
|
+
idempotentHint: true,
|
|
29
|
+
openWorldHint: true,
|
|
30
|
+
},
|
|
31
|
+
}, async (params) => {
|
|
32
|
+
try {
|
|
33
|
+
const client = await initializeBasecampClient();
|
|
34
|
+
// Fetch projects with pagination
|
|
35
|
+
const projects = await asyncPagedToArray({
|
|
36
|
+
fetchPage: client.projects.list,
|
|
37
|
+
request: {
|
|
38
|
+
query: {},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
// Apply filter if provided
|
|
42
|
+
let filteredProjects = projects;
|
|
43
|
+
if (params.filter) {
|
|
44
|
+
const regex = new RegExp(params.filter, "i");
|
|
45
|
+
filteredProjects = projects.filter((p) => regex.test(p.name) || regex.test(p.description || ""));
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: JSON.stringify(filteredProjects.map((p) => ({
|
|
52
|
+
id: p.id,
|
|
53
|
+
name: p.name,
|
|
54
|
+
description: p.description || "",
|
|
55
|
+
created_at: p.created_at,
|
|
56
|
+
updated_at: p.updated_at,
|
|
57
|
+
url: p.app_url,
|
|
58
|
+
})), null, 2),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
// Tool: basecamp_get_project
|
|
70
|
+
server.registerTool("basecamp_get_project", {
|
|
71
|
+
title: "Get Basecamp Project Details",
|
|
72
|
+
description: `Fetch detailed information about a specific Basecamp project. This tool retrieves complete project details including name, description, dock configuration, and metadata.
|
|
73
|
+
|
|
74
|
+
Examples:
|
|
75
|
+
- Use when: "Get details for project 12345"
|
|
76
|
+
- Use when: Need full project information including dock configuration`,
|
|
77
|
+
inputSchema: {
|
|
78
|
+
project_id: BasecampIdSchema.describe("Project ID to retrieve"),
|
|
79
|
+
},
|
|
80
|
+
annotations: {
|
|
81
|
+
readOnlyHint: true,
|
|
82
|
+
destructiveHint: false,
|
|
83
|
+
idempotentHint: true,
|
|
84
|
+
openWorldHint: true,
|
|
85
|
+
},
|
|
86
|
+
}, async (params) => {
|
|
87
|
+
try {
|
|
88
|
+
const client = await initializeBasecampClient();
|
|
89
|
+
const response = await client.projects.get({
|
|
90
|
+
params: { projectId: params.project_id },
|
|
91
|
+
});
|
|
92
|
+
if (response.status !== 200 || !response.body) {
|
|
93
|
+
throw new Error(`Failed to fetch project: ${response.status}`);
|
|
94
|
+
}
|
|
95
|
+
const project = response.body;
|
|
96
|
+
const jsonData = {
|
|
97
|
+
id: project.id,
|
|
98
|
+
name: project.name,
|
|
99
|
+
description: project.description || "",
|
|
100
|
+
created_at: project.created_at,
|
|
101
|
+
updated_at: project.updated_at,
|
|
102
|
+
url: project.app_url,
|
|
103
|
+
dock: project.dock || [],
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
content: [{ type: "text", text: JSON.stringify(jsonData, null, 2) }],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: "text", text: handleBasecampError(error) }],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/tools/projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todos.d.ts","sourceRoot":"","sources":["../../src/tools/todos.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0PzD"}
|