@nestr/mcp 0.1.8
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/LICENSE +21 -0
- package/README.md +228 -0
- package/build/api/client.d.ts +211 -0
- package/build/api/client.d.ts.map +1 -0
- package/build/api/client.js +279 -0
- package/build/api/client.js.map +1 -0
- package/build/http.d.ts +25 -0
- package/build/http.d.ts.map +1 -0
- package/build/http.js +810 -0
- package/build/http.js.map +1 -0
- package/build/index.d.ts +15 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +62 -0
- package/build/index.js.map +1 -0
- package/build/oauth/config.d.ts +70 -0
- package/build/oauth/config.d.ts.map +1 -0
- package/build/oauth/config.js +86 -0
- package/build/oauth/config.js.map +1 -0
- package/build/oauth/flow.d.ts +113 -0
- package/build/oauth/flow.d.ts.map +1 -0
- package/build/oauth/flow.js +233 -0
- package/build/oauth/flow.js.map +1 -0
- package/build/oauth/storage.d.ts +65 -0
- package/build/oauth/storage.d.ts.map +1 -0
- package/build/oauth/storage.js +222 -0
- package/build/oauth/storage.js.map +1 -0
- package/build/server.d.ts +11 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +383 -0
- package/build/server.js.map +1 -0
- package/build/tools/index.d.ts +1049 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +711 -0
- package/build/tools/index.js.map +1 -0
- package/package.json +58 -0
- package/web/index.html +595 -0
- package/web/styles.css +700 -0
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tools for Nestr
|
|
3
|
+
* Defines all available tools and their handlers
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
// Fields to keep for compact list responses (reduces token usage)
|
|
7
|
+
const COMPACT_FIELDS = {
|
|
8
|
+
// Common fields for all nests
|
|
9
|
+
base: ["_id", "title", "purpose"],
|
|
10
|
+
// Additional fields for roles
|
|
11
|
+
role: ["accountabilities", "domains"],
|
|
12
|
+
// Additional fields for users
|
|
13
|
+
user: ["_id", "username", "profile"],
|
|
14
|
+
// Additional fields for labels
|
|
15
|
+
label: ["_id", "title"],
|
|
16
|
+
};
|
|
17
|
+
// Strip verbose fields from API responses for list operations
|
|
18
|
+
function compactResponse(data, type = "nest") {
|
|
19
|
+
// Handle wrapped response: { status, meta, data: [...] }
|
|
20
|
+
if (data && typeof data === "object" && "data" in data && Array.isArray(data.data)) {
|
|
21
|
+
const wrapped = data;
|
|
22
|
+
return {
|
|
23
|
+
...wrapped,
|
|
24
|
+
data: compactResponse(wrapped.data, type),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Guard: if not an array, return as-is
|
|
28
|
+
if (!Array.isArray(data)) {
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
const allowedFields = new Set([
|
|
32
|
+
...COMPACT_FIELDS.base,
|
|
33
|
+
...(type === "role" ? COMPACT_FIELDS.role : []),
|
|
34
|
+
...(type === "user" ? COMPACT_FIELDS.user : []),
|
|
35
|
+
...(type === "label" ? COMPACT_FIELDS.label : []),
|
|
36
|
+
]);
|
|
37
|
+
return data.map((item) => {
|
|
38
|
+
const compact = {};
|
|
39
|
+
for (const key of Object.keys(item)) {
|
|
40
|
+
if (allowedFields.has(key)) {
|
|
41
|
+
compact[key] = item[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return compact;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Tool input schemas using Zod
|
|
48
|
+
export const schemas = {
|
|
49
|
+
listWorkspaces: z.object({
|
|
50
|
+
search: z.string().optional().describe("Search query to filter workspaces"),
|
|
51
|
+
limit: z.number().optional().describe("Maximum number of results"),
|
|
52
|
+
}),
|
|
53
|
+
getWorkspace: z.object({
|
|
54
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
55
|
+
}),
|
|
56
|
+
search: z.object({
|
|
57
|
+
workspaceId: z.string().describe("Workspace ID to search in"),
|
|
58
|
+
query: z.string().describe("Search query"),
|
|
59
|
+
limit: z.number().optional().default(20).describe("Maximum results (default 20)"),
|
|
60
|
+
}),
|
|
61
|
+
getNest: z.object({
|
|
62
|
+
nestId: z.string().describe("Nest ID"),
|
|
63
|
+
}),
|
|
64
|
+
getNestChildren: z.object({
|
|
65
|
+
nestId: z.string().describe("Parent nest ID"),
|
|
66
|
+
}),
|
|
67
|
+
createNest: z.object({
|
|
68
|
+
parentId: z.string().describe("Parent nest ID (workspace, circle, or project)"),
|
|
69
|
+
title: z.string().describe("Title of the new nest"),
|
|
70
|
+
purpose: z.string().optional().describe("Purpose or description"),
|
|
71
|
+
labels: z.array(z.string()).optional().describe("Label IDs to apply"),
|
|
72
|
+
users: z.array(z.string()).optional().describe("User IDs to assign (required for tasks/projects to associate with a person)"),
|
|
73
|
+
}),
|
|
74
|
+
updateNest: z.object({
|
|
75
|
+
nestId: z.string().describe("Nest ID to update"),
|
|
76
|
+
title: z.string().optional().describe("New title"),
|
|
77
|
+
purpose: z.string().optional().describe("New purpose"),
|
|
78
|
+
parentId: z.string().optional().describe("New parent ID (move nest to different location, e.g., move inbox item to a project)"),
|
|
79
|
+
fields: z.record(z.unknown()).optional().describe("Field updates (e.g., status)"),
|
|
80
|
+
users: z.array(z.string()).optional().describe("User IDs to assign"),
|
|
81
|
+
data: z.record(z.unknown()).optional().describe("Data updates (e.g., { botContext: '# Context...' })"),
|
|
82
|
+
}),
|
|
83
|
+
deleteNest: z.object({
|
|
84
|
+
nestId: z.string().describe("Nest ID to delete"),
|
|
85
|
+
}),
|
|
86
|
+
addComment: z.object({
|
|
87
|
+
nestId: z.string().describe("Nest ID to comment on"),
|
|
88
|
+
body: z.string().describe("Comment text (supports @mentions)"),
|
|
89
|
+
}),
|
|
90
|
+
listCircles: z.object({
|
|
91
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
92
|
+
limit: z.number().optional().describe("Maximum results"),
|
|
93
|
+
}),
|
|
94
|
+
getCircleRoles: z.object({
|
|
95
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
96
|
+
circleId: z.string().describe("Circle ID"),
|
|
97
|
+
}),
|
|
98
|
+
listRoles: z.object({
|
|
99
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
100
|
+
limit: z.number().optional().describe("Maximum results"),
|
|
101
|
+
}),
|
|
102
|
+
getInsights: z.object({
|
|
103
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
104
|
+
includeSubCircles: z.boolean().optional().describe("Include metrics from sub-circles"),
|
|
105
|
+
}),
|
|
106
|
+
listUsers: z.object({
|
|
107
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
108
|
+
search: z.string().optional().describe("Search by name or email"),
|
|
109
|
+
}),
|
|
110
|
+
listLabels: z.object({
|
|
111
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
112
|
+
search: z.string().optional().describe("Search query"),
|
|
113
|
+
}),
|
|
114
|
+
getProjects: z.object({
|
|
115
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
116
|
+
limit: z.number().optional().describe("Maximum results"),
|
|
117
|
+
}),
|
|
118
|
+
getComments: z.object({
|
|
119
|
+
nestId: z.string().describe("Nest ID to get comments from"),
|
|
120
|
+
depth: z.number().optional().describe("Comment thread depth (default: all)"),
|
|
121
|
+
}),
|
|
122
|
+
getCircle: z.object({
|
|
123
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
124
|
+
circleId: z.string().describe("Circle ID"),
|
|
125
|
+
}),
|
|
126
|
+
getUser: z.object({
|
|
127
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
128
|
+
userId: z.string().describe("User ID"),
|
|
129
|
+
}),
|
|
130
|
+
getLabel: z.object({
|
|
131
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
132
|
+
labelId: z.string().describe("Label ID"),
|
|
133
|
+
}),
|
|
134
|
+
getInsightHistory: z.object({
|
|
135
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
136
|
+
metricId: z.string().describe("Metric ID from getInsights"),
|
|
137
|
+
from: z.string().optional().describe("Start date (ISO format)"),
|
|
138
|
+
to: z.string().optional().describe("End date (ISO format)"),
|
|
139
|
+
limit: z.number().optional().describe("Maximum data points"),
|
|
140
|
+
}),
|
|
141
|
+
getWorkspaceApps: z.object({
|
|
142
|
+
workspaceId: z.string().describe("Workspace ID"),
|
|
143
|
+
}),
|
|
144
|
+
// Inbox tools (require OAuth token)
|
|
145
|
+
listInbox: z.object({
|
|
146
|
+
completedAfter: z.string().optional().describe("Include completed items from this date (ISO format). If omitted, only non-completed items are returned."),
|
|
147
|
+
}),
|
|
148
|
+
createInboxItem: z.object({
|
|
149
|
+
title: z.string().describe("Title of the inbox item (what you captured)"),
|
|
150
|
+
description: z.string().optional().describe("Additional details or context"),
|
|
151
|
+
}),
|
|
152
|
+
getInboxItem: z.object({
|
|
153
|
+
nestId: z.string().describe("Inbox item ID"),
|
|
154
|
+
}),
|
|
155
|
+
updateInboxItem: z.object({
|
|
156
|
+
nestId: z.string().describe("Inbox item ID"),
|
|
157
|
+
title: z.string().optional().describe("Updated title"),
|
|
158
|
+
description: z.string().optional().describe("Updated description"),
|
|
159
|
+
completed: z.boolean().optional().describe("Mark as completed (processed)"),
|
|
160
|
+
data: z.record(z.unknown()).optional().describe("Custom data storage"),
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
163
|
+
// Tool definitions for MCP
|
|
164
|
+
export const toolDefinitions = [
|
|
165
|
+
{
|
|
166
|
+
name: "nestr_list_workspaces",
|
|
167
|
+
description: "List all Nestr workspaces you have access to",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
search: { type: "string", description: "Search query to filter workspaces" },
|
|
172
|
+
limit: { type: "number", description: "Maximum number of results" },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "nestr_get_workspace",
|
|
178
|
+
description: "Get details of a specific workspace including its purpose and member count",
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
183
|
+
},
|
|
184
|
+
required: ["workspaceId"],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "nestr_search",
|
|
189
|
+
description: "Search for nests within a workspace. Supports operators: label:role (filter by type), assignee:me, completed:false, has:due, depth:1, project->status:Current (field values). Combine with spaces for AND, commas for OR. Examples: 'label:project assignee:me', 'label:role', 'marketing label:todo'",
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
workspaceId: { type: "string", description: "Workspace ID to search in" },
|
|
194
|
+
query: { type: "string", description: "Search query with optional operators (e.g., 'label:role', 'assignee:me completed:false')" },
|
|
195
|
+
limit: { type: "number", description: "Maximum results (default 20)" },
|
|
196
|
+
},
|
|
197
|
+
required: ["workspaceId", "query"],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: "nestr_get_nest",
|
|
202
|
+
description: "Get details of a specific nest (task, project, role, etc.)",
|
|
203
|
+
inputSchema: {
|
|
204
|
+
type: "object",
|
|
205
|
+
properties: {
|
|
206
|
+
nestId: { type: "string", description: "Nest ID" },
|
|
207
|
+
},
|
|
208
|
+
required: ["nestId"],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "nestr_get_nest_children",
|
|
213
|
+
description: "Get child nests (sub-tasks, sub-projects) of a nest",
|
|
214
|
+
inputSchema: {
|
|
215
|
+
type: "object",
|
|
216
|
+
properties: {
|
|
217
|
+
nestId: { type: "string", description: "Parent nest ID" },
|
|
218
|
+
},
|
|
219
|
+
required: ["nestId"],
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "nestr_create_nest",
|
|
224
|
+
description: "Create a new nest (task, project, etc.) under a parent. Set users to assign to people - placing under a role does NOT auto-assign.",
|
|
225
|
+
inputSchema: {
|
|
226
|
+
type: "object",
|
|
227
|
+
properties: {
|
|
228
|
+
parentId: { type: "string", description: "Parent nest ID (workspace, circle, or project)" },
|
|
229
|
+
title: { type: "string", description: "Title of the new nest" },
|
|
230
|
+
purpose: { type: "string", description: "Purpose or description" },
|
|
231
|
+
labels: {
|
|
232
|
+
type: "array",
|
|
233
|
+
items: { type: "string" },
|
|
234
|
+
description: "Label IDs to apply (e.g., 'project', 'todo')",
|
|
235
|
+
},
|
|
236
|
+
users: {
|
|
237
|
+
type: "array",
|
|
238
|
+
items: { type: "string" },
|
|
239
|
+
description: "User IDs to assign (required for tasks/projects to associate with a person)",
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
required: ["parentId", "title"],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: "nestr_update_nest",
|
|
247
|
+
description: "Update properties of an existing nest. Use parentId to move a nest (e.g., inbox item to a project). Use data.botContext to store AI context (markdown format) that persists across sessions.",
|
|
248
|
+
inputSchema: {
|
|
249
|
+
type: "object",
|
|
250
|
+
properties: {
|
|
251
|
+
nestId: { type: "string", description: "Nest ID to update" },
|
|
252
|
+
title: { type: "string", description: "New title" },
|
|
253
|
+
purpose: { type: "string", description: "New purpose" },
|
|
254
|
+
parentId: { type: "string", description: "New parent ID (move nest to different location)" },
|
|
255
|
+
fields: {
|
|
256
|
+
type: "object",
|
|
257
|
+
description: "Field updates (e.g., {status: 'done'})",
|
|
258
|
+
},
|
|
259
|
+
users: {
|
|
260
|
+
type: "array",
|
|
261
|
+
items: { type: "string" },
|
|
262
|
+
description: "User IDs to assign",
|
|
263
|
+
},
|
|
264
|
+
data: {
|
|
265
|
+
type: "object",
|
|
266
|
+
description: "Data updates (e.g., { botContext: '# Context\\n...' } for AI memory)",
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
required: ["nestId"],
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "nestr_delete_nest",
|
|
274
|
+
description: "Delete a nest (use with caution)",
|
|
275
|
+
inputSchema: {
|
|
276
|
+
type: "object",
|
|
277
|
+
properties: {
|
|
278
|
+
nestId: { type: "string", description: "Nest ID to delete" },
|
|
279
|
+
},
|
|
280
|
+
required: ["nestId"],
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: "nestr_add_comment",
|
|
285
|
+
description: "Add a comment to a nest. Use @username to mention someone.",
|
|
286
|
+
inputSchema: {
|
|
287
|
+
type: "object",
|
|
288
|
+
properties: {
|
|
289
|
+
nestId: { type: "string", description: "Nest ID to comment on" },
|
|
290
|
+
body: { type: "string", description: "Comment text (supports @mentions)" },
|
|
291
|
+
},
|
|
292
|
+
required: ["nestId", "body"],
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: "nestr_list_circles",
|
|
297
|
+
description: "List all circles (teams/departments) in a workspace",
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
302
|
+
limit: { type: "number", description: "Maximum results" },
|
|
303
|
+
},
|
|
304
|
+
required: ["workspaceId"],
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: "nestr_get_circle_roles",
|
|
309
|
+
description: "Get all roles within a specific circle, including accountabilities",
|
|
310
|
+
inputSchema: {
|
|
311
|
+
type: "object",
|
|
312
|
+
properties: {
|
|
313
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
314
|
+
circleId: { type: "string", description: "Circle ID" },
|
|
315
|
+
},
|
|
316
|
+
required: ["workspaceId", "circleId"],
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: "nestr_list_roles",
|
|
321
|
+
description: "List all roles in a workspace",
|
|
322
|
+
inputSchema: {
|
|
323
|
+
type: "object",
|
|
324
|
+
properties: {
|
|
325
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
326
|
+
limit: { type: "number", description: "Maximum results" },
|
|
327
|
+
},
|
|
328
|
+
required: ["workspaceId"],
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: "nestr_get_insights",
|
|
333
|
+
description: "Get self-organization and team health metrics. Includes: role-awareness (how well people use their roles), governance participation, circle meeting output, plus task completion rates, overdue items, and activity stats. Pro accounts can access these metrics at circle and user level; other accounts get workspace-level insights only.",
|
|
334
|
+
inputSchema: {
|
|
335
|
+
type: "object",
|
|
336
|
+
properties: {
|
|
337
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
338
|
+
includeSubCircles: { type: "boolean", description: "Include metrics from sub-circles" },
|
|
339
|
+
},
|
|
340
|
+
required: ["workspaceId"],
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: "nestr_list_users",
|
|
345
|
+
description: "List members of a workspace",
|
|
346
|
+
inputSchema: {
|
|
347
|
+
type: "object",
|
|
348
|
+
properties: {
|
|
349
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
350
|
+
search: { type: "string", description: "Search by name or email" },
|
|
351
|
+
},
|
|
352
|
+
required: ["workspaceId"],
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: "nestr_list_labels",
|
|
357
|
+
description: "List available labels in a workspace",
|
|
358
|
+
inputSchema: {
|
|
359
|
+
type: "object",
|
|
360
|
+
properties: {
|
|
361
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
362
|
+
search: { type: "string", description: "Search query" },
|
|
363
|
+
},
|
|
364
|
+
required: ["workspaceId"],
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
name: "nestr_get_projects",
|
|
369
|
+
description: "List all projects in a workspace. Check fields['project.status'] for status: Future (planned), Current (active), Waiting (blocked), Done (completed). The 'due' field contains the project due date.",
|
|
370
|
+
inputSchema: {
|
|
371
|
+
type: "object",
|
|
372
|
+
properties: {
|
|
373
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
374
|
+
limit: { type: "number", description: "Maximum results" },
|
|
375
|
+
},
|
|
376
|
+
required: ["workspaceId"],
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
name: "nestr_get_comments",
|
|
381
|
+
description: "Get comments and discussion history on a nest. Useful for understanding context, decisions made, and team communication around a task or project.",
|
|
382
|
+
inputSchema: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
nestId: { type: "string", description: "Nest ID to get comments from" },
|
|
386
|
+
depth: { type: "number", description: "Comment thread depth (default: all)" },
|
|
387
|
+
},
|
|
388
|
+
required: ["nestId"],
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
name: "nestr_get_circle",
|
|
393
|
+
description: "Get details of a specific circle including its purpose, domains, and accountabilities. Circles are self-governing teams in Holacracy/Sociocracy.",
|
|
394
|
+
inputSchema: {
|
|
395
|
+
type: "object",
|
|
396
|
+
properties: {
|
|
397
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
398
|
+
circleId: { type: "string", description: "Circle ID" },
|
|
399
|
+
},
|
|
400
|
+
required: ["workspaceId", "circleId"],
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
name: "nestr_get_user",
|
|
405
|
+
description: "Get details of a specific user including their profile, roles, and contact info. Useful for @mentions and understanding who is responsible for what.",
|
|
406
|
+
inputSchema: {
|
|
407
|
+
type: "object",
|
|
408
|
+
properties: {
|
|
409
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
410
|
+
userId: { type: "string", description: "User ID" },
|
|
411
|
+
},
|
|
412
|
+
required: ["workspaceId", "userId"],
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
name: "nestr_get_label",
|
|
417
|
+
description: "Get details of a specific label. Labels define what type a nest is (e.g., 'project', 'todo', 'role', 'circle', 'meeting').",
|
|
418
|
+
inputSchema: {
|
|
419
|
+
type: "object",
|
|
420
|
+
properties: {
|
|
421
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
422
|
+
labelId: { type: "string", description: "Label ID" },
|
|
423
|
+
},
|
|
424
|
+
required: ["workspaceId", "labelId"],
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
name: "nestr_get_insight_history",
|
|
429
|
+
description: "Get historical trend data for a specific metric. Use after getInsights to see how metrics like role-awareness, governance participation, or completion rates have changed over time.",
|
|
430
|
+
inputSchema: {
|
|
431
|
+
type: "object",
|
|
432
|
+
properties: {
|
|
433
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
434
|
+
metricId: { type: "string", description: "Metric ID from getInsights" },
|
|
435
|
+
from: { type: "string", description: "Start date (ISO format)" },
|
|
436
|
+
to: { type: "string", description: "End date (ISO format)" },
|
|
437
|
+
limit: { type: "number", description: "Maximum data points" },
|
|
438
|
+
},
|
|
439
|
+
required: ["workspaceId", "metricId"],
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "nestr_get_workspace_apps",
|
|
444
|
+
description: "List enabled apps/features in a workspace. Shows which Nestr modules are active (e.g., goals, metrics, notes, feed). Check this before using features - if an app is disabled, its related tools won't return useful data.",
|
|
445
|
+
inputSchema: {
|
|
446
|
+
type: "object",
|
|
447
|
+
properties: {
|
|
448
|
+
workspaceId: { type: "string", description: "Workspace ID" },
|
|
449
|
+
},
|
|
450
|
+
required: ["workspaceId"],
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
// Inbox tools (require OAuth token - won't work with workspace API keys)
|
|
454
|
+
{
|
|
455
|
+
name: "nestr_list_inbox",
|
|
456
|
+
description: "List items in the user's inbox. The inbox is a collection point for 'stuff' that needs processing - ideas, tasks, notes captured quickly without organizing. Requires OAuth token (won't work with workspace API keys).",
|
|
457
|
+
inputSchema: {
|
|
458
|
+
type: "object",
|
|
459
|
+
properties: {
|
|
460
|
+
completedAfter: { type: "string", description: "Include completed items from this date (ISO format). If omitted, only non-completed items are returned." },
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: "nestr_create_inbox_item",
|
|
466
|
+
description: "Quick capture: add an item to the user's inbox for later processing. Use for capturing thoughts, ideas, or tasks without worrying about where they belong. Requires OAuth token.",
|
|
467
|
+
inputSchema: {
|
|
468
|
+
type: "object",
|
|
469
|
+
properties: {
|
|
470
|
+
title: { type: "string", description: "Title of the inbox item (what you captured)" },
|
|
471
|
+
description: { type: "string", description: "Additional details or context" },
|
|
472
|
+
},
|
|
473
|
+
required: ["title"],
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
name: "nestr_get_inbox_item",
|
|
478
|
+
description: "Get details of a specific inbox item. Requires OAuth token.",
|
|
479
|
+
inputSchema: {
|
|
480
|
+
type: "object",
|
|
481
|
+
properties: {
|
|
482
|
+
nestId: { type: "string", description: "Inbox item ID" },
|
|
483
|
+
},
|
|
484
|
+
required: ["nestId"],
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
name: "nestr_update_inbox_item",
|
|
489
|
+
description: "Update an inbox item. Set completed:true when processed. To move out of inbox (clarify/organize), use nestr_update_nest to change parentId to a project, role, or other location. Requires OAuth token.",
|
|
490
|
+
inputSchema: {
|
|
491
|
+
type: "object",
|
|
492
|
+
properties: {
|
|
493
|
+
nestId: { type: "string", description: "Inbox item ID" },
|
|
494
|
+
title: { type: "string", description: "Updated title" },
|
|
495
|
+
description: { type: "string", description: "Updated description" },
|
|
496
|
+
completed: { type: "boolean", description: "Mark as completed (processed)" },
|
|
497
|
+
data: { type: "object", description: "Custom data storage" },
|
|
498
|
+
},
|
|
499
|
+
required: ["nestId"],
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
];
|
|
503
|
+
// Tool handlers
|
|
504
|
+
export async function handleToolCall(client, name, args) {
|
|
505
|
+
try {
|
|
506
|
+
switch (name) {
|
|
507
|
+
case "nestr_list_workspaces": {
|
|
508
|
+
const parsed = schemas.listWorkspaces.parse(args);
|
|
509
|
+
const workspaces = await client.listWorkspaces({
|
|
510
|
+
search: parsed.search,
|
|
511
|
+
limit: parsed.limit,
|
|
512
|
+
cleanText: true,
|
|
513
|
+
});
|
|
514
|
+
return formatResult(compactResponse(workspaces));
|
|
515
|
+
}
|
|
516
|
+
case "nestr_get_workspace": {
|
|
517
|
+
const parsed = schemas.getWorkspace.parse(args);
|
|
518
|
+
const workspace = await client.getWorkspace(parsed.workspaceId, true);
|
|
519
|
+
return formatResult(workspace);
|
|
520
|
+
}
|
|
521
|
+
case "nestr_search": {
|
|
522
|
+
const parsed = schemas.search.parse(args);
|
|
523
|
+
const results = await client.searchWorkspace(parsed.workspaceId, parsed.query, { limit: parsed.limit, cleanText: true });
|
|
524
|
+
return formatResult(compactResponse(results));
|
|
525
|
+
}
|
|
526
|
+
case "nestr_get_nest": {
|
|
527
|
+
const parsed = schemas.getNest.parse(args);
|
|
528
|
+
const nest = await client.getNest(parsed.nestId, true);
|
|
529
|
+
return formatResult(nest);
|
|
530
|
+
}
|
|
531
|
+
case "nestr_get_nest_children": {
|
|
532
|
+
const parsed = schemas.getNestChildren.parse(args);
|
|
533
|
+
const children = await client.getNestChildren(parsed.nestId, true);
|
|
534
|
+
return formatResult(compactResponse(children));
|
|
535
|
+
}
|
|
536
|
+
case "nestr_create_nest": {
|
|
537
|
+
const parsed = schemas.createNest.parse(args);
|
|
538
|
+
const nest = await client.createNest({
|
|
539
|
+
parentId: parsed.parentId,
|
|
540
|
+
title: parsed.title,
|
|
541
|
+
purpose: parsed.purpose,
|
|
542
|
+
labels: parsed.labels,
|
|
543
|
+
users: parsed.users,
|
|
544
|
+
});
|
|
545
|
+
return formatResult({ message: "Nest created successfully", nest });
|
|
546
|
+
}
|
|
547
|
+
case "nestr_update_nest": {
|
|
548
|
+
const parsed = schemas.updateNest.parse(args);
|
|
549
|
+
const nest = await client.updateNest(parsed.nestId, {
|
|
550
|
+
title: parsed.title,
|
|
551
|
+
purpose: parsed.purpose,
|
|
552
|
+
parentId: parsed.parentId,
|
|
553
|
+
fields: parsed.fields,
|
|
554
|
+
users: parsed.users,
|
|
555
|
+
data: parsed.data,
|
|
556
|
+
});
|
|
557
|
+
return formatResult({ message: "Nest updated successfully", nest });
|
|
558
|
+
}
|
|
559
|
+
case "nestr_delete_nest": {
|
|
560
|
+
const parsed = schemas.deleteNest.parse(args);
|
|
561
|
+
await client.deleteNest(parsed.nestId);
|
|
562
|
+
return formatResult({ message: `Nest ${parsed.nestId} deleted successfully` });
|
|
563
|
+
}
|
|
564
|
+
case "nestr_add_comment": {
|
|
565
|
+
const parsed = schemas.addComment.parse(args);
|
|
566
|
+
const post = await client.createPost(parsed.nestId, parsed.body);
|
|
567
|
+
return formatResult({ message: "Comment added successfully", post });
|
|
568
|
+
}
|
|
569
|
+
case "nestr_list_circles": {
|
|
570
|
+
const parsed = schemas.listCircles.parse(args);
|
|
571
|
+
const circles = await client.listCircles(parsed.workspaceId, {
|
|
572
|
+
limit: parsed.limit,
|
|
573
|
+
cleanText: true,
|
|
574
|
+
});
|
|
575
|
+
return formatResult(compactResponse(circles, "role"));
|
|
576
|
+
}
|
|
577
|
+
case "nestr_get_circle_roles": {
|
|
578
|
+
const parsed = schemas.getCircleRoles.parse(args);
|
|
579
|
+
const roles = await client.getCircleRoles(parsed.workspaceId, parsed.circleId, { cleanText: true });
|
|
580
|
+
return formatResult(compactResponse(roles, "role"));
|
|
581
|
+
}
|
|
582
|
+
case "nestr_list_roles": {
|
|
583
|
+
const parsed = schemas.listRoles.parse(args);
|
|
584
|
+
const roles = await client.listRoles(parsed.workspaceId, {
|
|
585
|
+
limit: parsed.limit,
|
|
586
|
+
cleanText: true,
|
|
587
|
+
});
|
|
588
|
+
return formatResult(compactResponse(roles, "role"));
|
|
589
|
+
}
|
|
590
|
+
case "nestr_get_insights": {
|
|
591
|
+
const parsed = schemas.getInsights.parse(args);
|
|
592
|
+
const insights = await client.getInsights(parsed.workspaceId, {
|
|
593
|
+
includeSubCircles: parsed.includeSubCircles,
|
|
594
|
+
});
|
|
595
|
+
return formatResult(insights);
|
|
596
|
+
}
|
|
597
|
+
case "nestr_list_users": {
|
|
598
|
+
const parsed = schemas.listUsers.parse(args);
|
|
599
|
+
const users = await client.listUsers(parsed.workspaceId, {
|
|
600
|
+
search: parsed.search,
|
|
601
|
+
});
|
|
602
|
+
return formatResult(compactResponse(users, "user"));
|
|
603
|
+
}
|
|
604
|
+
case "nestr_list_labels": {
|
|
605
|
+
const parsed = schemas.listLabels.parse(args);
|
|
606
|
+
const labels = await client.listLabels(parsed.workspaceId, {
|
|
607
|
+
search: parsed.search,
|
|
608
|
+
});
|
|
609
|
+
return formatResult(compactResponse(labels, "label"));
|
|
610
|
+
}
|
|
611
|
+
case "nestr_get_projects": {
|
|
612
|
+
const parsed = schemas.getProjects.parse(args);
|
|
613
|
+
const projects = await client.getWorkspaceProjects(parsed.workspaceId, {
|
|
614
|
+
limit: parsed.limit,
|
|
615
|
+
cleanText: true,
|
|
616
|
+
});
|
|
617
|
+
return formatResult(compactResponse(projects));
|
|
618
|
+
}
|
|
619
|
+
case "nestr_get_comments": {
|
|
620
|
+
const parsed = schemas.getComments.parse(args);
|
|
621
|
+
const comments = await client.getNestPosts(parsed.nestId, {
|
|
622
|
+
depth: parsed.depth,
|
|
623
|
+
});
|
|
624
|
+
return formatResult(comments);
|
|
625
|
+
}
|
|
626
|
+
case "nestr_get_circle": {
|
|
627
|
+
const parsed = schemas.getCircle.parse(args);
|
|
628
|
+
const circle = await client.getCircle(parsed.workspaceId, parsed.circleId, true);
|
|
629
|
+
return formatResult(circle);
|
|
630
|
+
}
|
|
631
|
+
case "nestr_get_user": {
|
|
632
|
+
const parsed = schemas.getUser.parse(args);
|
|
633
|
+
const user = await client.getUser(parsed.workspaceId, parsed.userId);
|
|
634
|
+
return formatResult(user);
|
|
635
|
+
}
|
|
636
|
+
case "nestr_get_label": {
|
|
637
|
+
const parsed = schemas.getLabel.parse(args);
|
|
638
|
+
const label = await client.getLabel(parsed.workspaceId, parsed.labelId);
|
|
639
|
+
return formatResult(label);
|
|
640
|
+
}
|
|
641
|
+
case "nestr_get_insight_history": {
|
|
642
|
+
const parsed = schemas.getInsightHistory.parse(args);
|
|
643
|
+
const history = await client.getInsightHistory(parsed.workspaceId, parsed.metricId, {
|
|
644
|
+
from: parsed.from,
|
|
645
|
+
to: parsed.to,
|
|
646
|
+
limit: parsed.limit,
|
|
647
|
+
});
|
|
648
|
+
return formatResult(history);
|
|
649
|
+
}
|
|
650
|
+
case "nestr_get_workspace_apps": {
|
|
651
|
+
const parsed = schemas.getWorkspaceApps.parse(args);
|
|
652
|
+
const apps = await client.getWorkspaceApps(parsed.workspaceId);
|
|
653
|
+
return formatResult(apps);
|
|
654
|
+
}
|
|
655
|
+
// Inbox tools (require OAuth token)
|
|
656
|
+
case "nestr_list_inbox": {
|
|
657
|
+
const parsed = schemas.listInbox.parse(args);
|
|
658
|
+
const items = await client.listInbox({
|
|
659
|
+
completedAfter: parsed.completedAfter,
|
|
660
|
+
});
|
|
661
|
+
return formatResult(compactResponse(items));
|
|
662
|
+
}
|
|
663
|
+
case "nestr_create_inbox_item": {
|
|
664
|
+
const parsed = schemas.createInboxItem.parse(args);
|
|
665
|
+
const item = await client.createInboxItem({
|
|
666
|
+
title: parsed.title,
|
|
667
|
+
description: parsed.description,
|
|
668
|
+
});
|
|
669
|
+
return formatResult({ message: "Inbox item created successfully", item });
|
|
670
|
+
}
|
|
671
|
+
case "nestr_get_inbox_item": {
|
|
672
|
+
const parsed = schemas.getInboxItem.parse(args);
|
|
673
|
+
const item = await client.getInboxItem(parsed.nestId, true);
|
|
674
|
+
return formatResult(item);
|
|
675
|
+
}
|
|
676
|
+
case "nestr_update_inbox_item": {
|
|
677
|
+
const parsed = schemas.updateInboxItem.parse(args);
|
|
678
|
+
const item = await client.updateInboxItem(parsed.nestId, {
|
|
679
|
+
title: parsed.title,
|
|
680
|
+
description: parsed.description,
|
|
681
|
+
completed: parsed.completed,
|
|
682
|
+
data: parsed.data,
|
|
683
|
+
});
|
|
684
|
+
return formatResult({ message: "Inbox item updated successfully", item });
|
|
685
|
+
}
|
|
686
|
+
default:
|
|
687
|
+
return {
|
|
688
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
689
|
+
isError: true,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
catch (error) {
|
|
694
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
695
|
+
return {
|
|
696
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
697
|
+
isError: true,
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
function formatResult(data) {
|
|
702
|
+
return {
|
|
703
|
+
content: [
|
|
704
|
+
{
|
|
705
|
+
type: "text",
|
|
706
|
+
text: JSON.stringify(data, null, 2),
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
//# sourceMappingURL=index.js.map
|