whiteboard-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +76 -0
  2. package/dist/api-client.d.ts +80 -0
  3. package/dist/api-client.d.ts.map +1 -0
  4. package/dist/api-client.js +72 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/config.d.ts +6 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +10 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +253 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/tools/create-note.d.ts +21 -0
  15. package/dist/tools/create-note.d.ts.map +1 -0
  16. package/dist/tools/create-note.js +28 -0
  17. package/dist/tools/create-note.js.map +1 -0
  18. package/dist/tools/delete-note.d.ts +12 -0
  19. package/dist/tools/delete-note.d.ts.map +1 -0
  20. package/dist/tools/delete-note.js +14 -0
  21. package/dist/tools/delete-note.js.map +1 -0
  22. package/dist/tools/get-comments.d.ts +15 -0
  23. package/dist/tools/get-comments.d.ts.map +1 -0
  24. package/dist/tools/get-comments.js +44 -0
  25. package/dist/tools/get-comments.js.map +1 -0
  26. package/dist/tools/list-notes.d.ts +18 -0
  27. package/dist/tools/list-notes.d.ts.map +1 -0
  28. package/dist/tools/list-notes.js +21 -0
  29. package/dist/tools/list-notes.js.map +1 -0
  30. package/dist/tools/read-note.d.ts +12 -0
  31. package/dist/tools/read-note.d.ts.map +1 -0
  32. package/dist/tools/read-note.js +21 -0
  33. package/dist/tools/read-note.js.map +1 -0
  34. package/dist/tools/resolve-thread.d.ts +18 -0
  35. package/dist/tools/resolve-thread.d.ts.map +1 -0
  36. package/dist/tools/resolve-thread.js +18 -0
  37. package/dist/tools/resolve-thread.js.map +1 -0
  38. package/dist/tools/update-note.d.ts +15 -0
  39. package/dist/tools/update-note.d.ts.map +1 -0
  40. package/dist/tools/update-note.js +17 -0
  41. package/dist/tools/update-note.js.map +1 -0
  42. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Whiteboard MCP Server
2
+
3
+ Serveur MCP (Model Context Protocol) pour intégrer les notes Whiteboard avec Claude Code.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g whiteboard-mcp-server
9
+ ```
10
+
11
+ ## Configuration Claude Code
12
+
13
+ 1. **Générer une API key** depuis l'interface Whiteboard :
14
+ - Aller sur https://whiteboard.kepochan.com/api-keys
15
+ - Créer une nouvelle clé avec les scopes souhaités
16
+
17
+ 2. **Configurer Claude Code** dans `~/.claude/mcp_servers.json` :
18
+
19
+ ```json
20
+ {
21
+ "whiteboard": {
22
+ "command": "npx",
23
+ "args": ["whiteboard-mcp-server"],
24
+ "env": {
25
+ "WHITEBOARD_API_KEY": "wb_votre_cle_api"
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Outils disponibles
32
+
33
+ | Outil | Description | Scopes requis |
34
+ |-------|-------------|---------------|
35
+ | `list_notes` | Lister les notes accessibles | `notes:read` |
36
+ | `read_note` | Lire le contenu d'une note | `notes:read` |
37
+ | `create_note` | Créer une nouvelle note | `notes:write` |
38
+ | `update_note` | Modifier une note existante | `notes:write` |
39
+ | `delete_note` | Supprimer une note | `notes:write` |
40
+ | `get_note_comments` | Récupérer les commentaires | `comments:read` |
41
+ | `resolve_comment_thread` | Résoudre un thread | `comments:write` |
42
+
43
+ ## Ressources MCP
44
+
45
+ - `note://[slug]` - Contenu d'une note (lecture directe)
46
+
47
+ ## Variables d'environnement
48
+
49
+ | Variable | Description | Défaut |
50
+ |----------|-------------|--------|
51
+ | `WHITEBOARD_API_KEY` | Clé API (requis) | - |
52
+ | `WHITEBOARD_API_URL` | URL de l'API | `https://whiteboard-api.kepochan.com` |
53
+
54
+ ## Exemples d'utilisation
55
+
56
+ Dans Claude Code, vous pouvez maintenant dire :
57
+
58
+ - "Liste mes notes"
59
+ - "Lis la note `ma-note`"
60
+ - "Modifie la note `projet-x` avec ce nouveau contenu : ..."
61
+ - "Crée une note `nouvelle-idee` avec le contenu suivant : ..."
62
+ - "Quels sont les commentaires sur la note `documentation` ?"
63
+ - "Résous le thread de commentaire XYZ sur la note `spec`"
64
+
65
+ ## Développement
66
+
67
+ ```bash
68
+ # Mode développement (avec hot reload)
69
+ npm run dev
70
+
71
+ # Typecheck uniquement
72
+ npm run typecheck
73
+
74
+ # Build
75
+ npm run build
76
+ ```
@@ -0,0 +1,80 @@
1
+ import { Config } from './config.js';
2
+ export interface Note {
3
+ id: string;
4
+ slug: string;
5
+ content: string;
6
+ sharingMode: string;
7
+ workspaceId: string | null;
8
+ ownerId: string;
9
+ publishedContent: string | null;
10
+ publishedAt: string | null;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
14
+ export interface NoteWithPermission extends Note {
15
+ permission: 'read' | 'write' | 'none';
16
+ }
17
+ export interface NotesListResponse {
18
+ notes: Note[];
19
+ total: number;
20
+ page: number;
21
+ limit: number;
22
+ totalPages: number;
23
+ }
24
+ export interface CommentThread {
25
+ id: string;
26
+ noteId: string;
27
+ anchor: {
28
+ type: string;
29
+ start: string;
30
+ end: string;
31
+ originalText?: string;
32
+ };
33
+ resolved: boolean;
34
+ createdBy: {
35
+ id: string;
36
+ name: string | null;
37
+ email: string;
38
+ };
39
+ comments: Comment[];
40
+ createdAt: string;
41
+ }
42
+ export interface Comment {
43
+ id: string;
44
+ threadId: string;
45
+ content: string;
46
+ author: {
47
+ id: string;
48
+ name: string | null;
49
+ email: string;
50
+ };
51
+ createdAt: string;
52
+ updatedAt: string;
53
+ }
54
+ export declare class ApiClient {
55
+ private config;
56
+ constructor(config: Config);
57
+ private request;
58
+ listNotes(options?: {
59
+ workspaceId?: string;
60
+ page?: number;
61
+ limit?: number;
62
+ }): Promise<NotesListResponse>;
63
+ getNoteBySlug(slug: string): Promise<NoteWithPermission>;
64
+ getNoteById(id: string): Promise<Note>;
65
+ createNote(data: {
66
+ slug: string;
67
+ content?: string;
68
+ workspaceId?: string;
69
+ sharingMode?: string;
70
+ }): Promise<Note>;
71
+ updateNote(id: string, data: {
72
+ slug?: string;
73
+ content?: string;
74
+ }): Promise<Note>;
75
+ deleteNote(id: string): Promise<void>;
76
+ listCommentThreads(noteId: string): Promise<CommentThread[]>;
77
+ getCommentThread(noteId: string, threadId: string): Promise<CommentThread>;
78
+ resolveThread(noteId: string, threadId: string, resolved: boolean): Promise<CommentThread>;
79
+ }
80
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ export class ApiClient {
2
+ config;
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ async request(path, options = {}) {
7
+ const url = `${this.config.apiUrl}${path}`;
8
+ const response = await fetch(url, {
9
+ ...options,
10
+ headers: {
11
+ 'Content-Type': 'application/json',
12
+ 'X-API-Key': this.config.apiKey,
13
+ ...options.headers,
14
+ },
15
+ });
16
+ if (!response.ok) {
17
+ const text = await response.text();
18
+ throw new Error(`API error ${response.status}: ${text}`);
19
+ }
20
+ if (response.status === 204) {
21
+ return undefined;
22
+ }
23
+ return response.json();
24
+ }
25
+ async listNotes(options) {
26
+ const params = new URLSearchParams();
27
+ if (options?.workspaceId)
28
+ params.set('workspaceId', options.workspaceId);
29
+ if (options?.page)
30
+ params.set('page', String(options.page));
31
+ if (options?.limit)
32
+ params.set('limit', String(options.limit));
33
+ const query = params.toString();
34
+ return this.request(`/notes${query ? `?${query}` : ''}`);
35
+ }
36
+ async getNoteBySlug(slug) {
37
+ return this.request(`/notes/by-slug/${encodeURIComponent(slug)}`);
38
+ }
39
+ async getNoteById(id) {
40
+ return this.request(`/notes/${id}`);
41
+ }
42
+ async createNote(data) {
43
+ return this.request('/notes', {
44
+ method: 'POST',
45
+ body: JSON.stringify(data),
46
+ });
47
+ }
48
+ async updateNote(id, data) {
49
+ return this.request(`/notes/${id}`, {
50
+ method: 'PUT',
51
+ body: JSON.stringify(data),
52
+ });
53
+ }
54
+ async deleteNote(id) {
55
+ await this.request(`/notes/${id}`, {
56
+ method: 'DELETE',
57
+ });
58
+ }
59
+ async listCommentThreads(noteId) {
60
+ return this.request(`/notes/${noteId}/threads`);
61
+ }
62
+ async getCommentThread(noteId, threadId) {
63
+ return this.request(`/notes/${noteId}/threads/${threadId}`);
64
+ }
65
+ async resolveThread(noteId, threadId, resolved) {
66
+ return this.request(`/notes/${noteId}/threads/${threadId}`, {
67
+ method: 'PUT',
68
+ body: JSON.stringify({ resolved }),
69
+ });
70
+ }
71
+ }
72
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface Config {
2
+ apiUrl: string;
3
+ apiKey: string;
4
+ }
5
+ export declare function getConfig(): Config;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,SAAS,IAAI,MAAM,CAYlC"}
package/dist/config.js ADDED
@@ -0,0 +1,10 @@
1
+ export function getConfig() {
2
+ const apiUrl = process.env.WHITEBOARD_API_URL || 'https://whiteboard-api.kepochan.com';
3
+ const apiKey = process.env.WHITEBOARD_API_KEY;
4
+ if (!apiKey) {
5
+ throw new Error('WHITEBOARD_API_KEY environment variable is required. ' +
6
+ 'Generate one from the Whiteboard settings page.');
7
+ }
8
+ return { apiUrl, apiKey };
9
+ }
10
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,qCAAqC,CAAC;IACvF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,uDAAuD;YACvD,iDAAiD,CAClD,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { getConfig } from './config.js';
6
+ import { ApiClient } from './api-client.js';
7
+ import { listNotes, listNotesSchema } from './tools/list-notes.js';
8
+ import { readNote, readNoteSchema } from './tools/read-note.js';
9
+ import { updateNote, updateNoteSchema } from './tools/update-note.js';
10
+ import { createNote, createNoteSchema } from './tools/create-note.js';
11
+ import { deleteNote, deleteNoteSchema } from './tools/delete-note.js';
12
+ import { getComments, getCommentsSchema } from './tools/get-comments.js';
13
+ import { resolveThread, resolveThreadSchema } from './tools/resolve-thread.js';
14
+ const config = getConfig();
15
+ const apiClient = new ApiClient(config);
16
+ const server = new Server({
17
+ name: 'whiteboard-mcp',
18
+ version: '1.0.0',
19
+ }, {
20
+ capabilities: {
21
+ tools: {},
22
+ resources: {},
23
+ },
24
+ });
25
+ // Tool definitions
26
+ const TOOLS = [
27
+ {
28
+ name: 'list_notes',
29
+ description: 'List all notes accessible to you. Returns note slugs, IDs, and metadata.',
30
+ inputSchema: {
31
+ type: 'object',
32
+ properties: {
33
+ workspaceId: {
34
+ type: 'string',
35
+ description: 'Filter by workspace ID (optional)',
36
+ },
37
+ page: {
38
+ type: 'number',
39
+ description: 'Page number (default: 1)',
40
+ },
41
+ limit: {
42
+ type: 'number',
43
+ description: 'Items per page (default: 15, max: 100)',
44
+ },
45
+ },
46
+ },
47
+ },
48
+ {
49
+ name: 'read_note',
50
+ description: 'Read the full markdown content of a note by its slug.',
51
+ inputSchema: {
52
+ type: 'object',
53
+ properties: {
54
+ slug: {
55
+ type: 'string',
56
+ description: 'The slug (URL-friendly name) of the note to read',
57
+ },
58
+ },
59
+ required: ['slug'],
60
+ },
61
+ },
62
+ {
63
+ name: 'update_note',
64
+ description: 'Update the content of an existing note. Requires write permission.',
65
+ inputSchema: {
66
+ type: 'object',
67
+ properties: {
68
+ slug: {
69
+ type: 'string',
70
+ description: 'The slug of the note to update',
71
+ },
72
+ content: {
73
+ type: 'string',
74
+ description: 'The new markdown content for the note',
75
+ },
76
+ },
77
+ required: ['slug', 'content'],
78
+ },
79
+ },
80
+ {
81
+ name: 'create_note',
82
+ description: 'Create a new note with a unique slug.',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ slug: {
87
+ type: 'string',
88
+ description: 'URL-friendly slug (lowercase, hyphens allowed, e.g., "my-new-note")',
89
+ },
90
+ content: {
91
+ type: 'string',
92
+ description: 'Initial markdown content for the note (optional)',
93
+ },
94
+ workspaceId: {
95
+ type: 'string',
96
+ description: 'Workspace ID to create the note in (optional)',
97
+ },
98
+ sharingMode: {
99
+ type: 'string',
100
+ enum: ['private', 'protected', 'limited', 'editable', 'public', 'open-bar'],
101
+ description: 'Sharing mode for the note (default: private)',
102
+ },
103
+ },
104
+ required: ['slug'],
105
+ },
106
+ },
107
+ {
108
+ name: 'delete_note',
109
+ description: 'Delete a note. Requires write permission. This action is irreversible.',
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ slug: {
114
+ type: 'string',
115
+ description: 'The slug of the note to delete',
116
+ },
117
+ },
118
+ required: ['slug'],
119
+ },
120
+ },
121
+ {
122
+ name: 'get_note_comments',
123
+ description: 'Get all comment threads on a note, with their replies.',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ slug: {
128
+ type: 'string',
129
+ description: 'The slug of the note to get comments from',
130
+ },
131
+ includeResolved: {
132
+ type: 'boolean',
133
+ description: 'Include resolved comment threads (default: true)',
134
+ },
135
+ },
136
+ required: ['slug'],
137
+ },
138
+ },
139
+ {
140
+ name: 'resolve_comment_thread',
141
+ description: 'Mark a comment thread as resolved or reopen it.',
142
+ inputSchema: {
143
+ type: 'object',
144
+ properties: {
145
+ slug: {
146
+ type: 'string',
147
+ description: 'The slug of the note containing the thread',
148
+ },
149
+ threadId: {
150
+ type: 'string',
151
+ description: 'The ID of the comment thread to resolve/unresolve',
152
+ },
153
+ resolved: {
154
+ type: 'boolean',
155
+ description: 'Set to true to resolve, false to unresolve (default: true)',
156
+ },
157
+ },
158
+ required: ['slug', 'threadId'],
159
+ },
160
+ },
161
+ ];
162
+ // Handle tool list requests
163
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
164
+ tools: TOOLS,
165
+ }));
166
+ // Handle tool calls
167
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
168
+ const { name, arguments: args } = request.params;
169
+ try {
170
+ let result;
171
+ switch (name) {
172
+ case 'list_notes':
173
+ result = await listNotes(apiClient, listNotesSchema.parse(args || {}));
174
+ break;
175
+ case 'read_note':
176
+ result = await readNote(apiClient, readNoteSchema.parse(args));
177
+ break;
178
+ case 'update_note':
179
+ result = await updateNote(apiClient, updateNoteSchema.parse(args));
180
+ break;
181
+ case 'create_note':
182
+ result = await createNote(apiClient, createNoteSchema.parse(args));
183
+ break;
184
+ case 'delete_note':
185
+ result = await deleteNote(apiClient, deleteNoteSchema.parse(args));
186
+ break;
187
+ case 'get_note_comments':
188
+ result = await getComments(apiClient, getCommentsSchema.parse(args));
189
+ break;
190
+ case 'resolve_comment_thread':
191
+ result = await resolveThread(apiClient, resolveThreadSchema.parse(args));
192
+ break;
193
+ default:
194
+ throw new Error(`Unknown tool: ${name}`);
195
+ }
196
+ return {
197
+ content: [{ type: 'text', text: result }],
198
+ };
199
+ }
200
+ catch (error) {
201
+ const message = error instanceof Error ? error.message : String(error);
202
+ return {
203
+ content: [{ type: 'text', text: `Error: ${message}` }],
204
+ isError: true,
205
+ };
206
+ }
207
+ });
208
+ // Handle resource list requests (notes as resources)
209
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
210
+ try {
211
+ const response = await apiClient.listNotes({ limit: 100 });
212
+ return {
213
+ resources: response.notes.map((note) => ({
214
+ uri: `note://${note.slug}`,
215
+ name: note.slug,
216
+ description: `Note: ${note.slug} (${note.sharingMode})`,
217
+ mimeType: 'text/markdown',
218
+ })),
219
+ };
220
+ }
221
+ catch (error) {
222
+ return { resources: [] };
223
+ }
224
+ });
225
+ // Handle resource read requests
226
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
227
+ const { uri } = request.params;
228
+ if (!uri.startsWith('note://')) {
229
+ throw new Error(`Unknown resource URI scheme: ${uri}`);
230
+ }
231
+ const slug = uri.replace('note://', '');
232
+ const note = await apiClient.getNoteBySlug(slug);
233
+ return {
234
+ contents: [
235
+ {
236
+ uri,
237
+ mimeType: 'text/markdown',
238
+ text: note.content || '',
239
+ },
240
+ ],
241
+ };
242
+ });
243
+ // Start the server
244
+ async function main() {
245
+ const transport = new StdioServerTransport();
246
+ await server.connect(transport);
247
+ console.error('Whiteboard MCP server running on stdio');
248
+ }
249
+ main().catch((error) => {
250
+ console.error('Failed to start server:', error);
251
+ process.exit(1);
252
+ });
253
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const createNoteSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ content: z.ZodOptional<z.ZodString>;
6
+ workspaceId: z.ZodOptional<z.ZodString>;
7
+ sharingMode: z.ZodOptional<z.ZodEnum<["private", "protected", "limited", "editable", "public", "open-bar"]>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ slug: string;
10
+ workspaceId?: string | undefined;
11
+ content?: string | undefined;
12
+ sharingMode?: "private" | "protected" | "limited" | "editable" | "public" | "open-bar" | undefined;
13
+ }, {
14
+ slug: string;
15
+ workspaceId?: string | undefined;
16
+ content?: string | undefined;
17
+ sharingMode?: "private" | "protected" | "limited" | "editable" | "public" | "open-bar" | undefined;
18
+ }>;
19
+ export type CreateNoteInput = z.infer<typeof createNoteSchema>;
20
+ export declare function createNote(client: ApiClient, input: CreateNoteInput): Promise<string>;
21
+ //# sourceMappingURL=create-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-note.d.ts","sourceRoot":"","sources":["../../src/tools/create-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAW3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ export const createNoteSchema = z.object({
3
+ slug: z
4
+ .string()
5
+ .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
6
+ .describe('URL-friendly slug for the note (lowercase, hyphens allowed, e.g., "my-new-note")'),
7
+ content: z.string().optional().describe('Initial markdown content for the note'),
8
+ workspaceId: z.string().uuid().optional().describe('Workspace ID to create the note in'),
9
+ sharingMode: z
10
+ .enum(['private', 'protected', 'limited', 'editable', 'public', 'open-bar'])
11
+ .optional()
12
+ .describe('Sharing mode for the note (default: private)'),
13
+ });
14
+ export async function createNote(client, input) {
15
+ const note = await client.createNote(input);
16
+ const lines = [
17
+ `Note "${note.slug}" created successfully!`,
18
+ '',
19
+ `- **ID**: ${note.id}`,
20
+ `- **Sharing Mode**: ${note.sharingMode}`,
21
+ `- **Created**: ${new Date(note.createdAt).toLocaleString()}`,
22
+ ];
23
+ if (input.content) {
24
+ lines.push(`- **Content**: ${input.content.length} characters`);
25
+ }
26
+ return lines.join('\n');
27
+ }
28
+ //# sourceMappingURL=create-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-note.js","sourceRoot":"","sources":["../../src/tools/create-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,KAAK,CAAC,4BAA4B,CAAC;SACnC,QAAQ,CAAC,kFAAkF,CAAC;IAC/F,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IAChF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IACxF,WAAW,EAAE,CAAC;SACX,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;SAC3E,QAAQ,EAAE;SACV,QAAQ,CAAC,8CAA8C,CAAC;CAC5D,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAiB,EACjB,KAAsB;IAEtB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG;QACZ,SAAS,IAAI,CAAC,IAAI,yBAAyB;QAC3C,EAAE;QACF,aAAa,IAAI,CAAC,EAAE,EAAE;QACtB,uBAAuB,IAAI,CAAC,WAAW,EAAE;QACzC,kBAAkB,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE;KAC9D,CAAC;IAEF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,kBAAkB,KAAK,CAAC,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const deleteNoteSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ slug: string;
7
+ }, {
8
+ slug: string;
9
+ }>;
10
+ export type DeleteNoteInput = z.infer<typeof deleteNoteSchema>;
11
+ export declare function deleteNote(client: ApiClient, input: DeleteNoteInput): Promise<string>;
12
+ //# sourceMappingURL=delete-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-note.d.ts","sourceRoot":"","sources":["../../src/tools/delete-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,gBAAgB;;;;;;EAE3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,MAAM,CAAC,CAWjB"}
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ export const deleteNoteSchema = z.object({
3
+ slug: z.string().describe('The slug of the note to delete'),
4
+ });
5
+ export async function deleteNote(client, input) {
6
+ // First get the note to find its ID
7
+ const existingNote = await client.getNoteBySlug(input.slug);
8
+ if (existingNote.permission !== 'write') {
9
+ throw new Error(`You don't have write permission on this note (current permission: ${existingNote.permission})`);
10
+ }
11
+ await client.deleteNote(existingNote.id);
12
+ return `Note "${input.slug}" (ID: ${existingNote.id}) has been deleted.`;
13
+ }
14
+ //# sourceMappingURL=delete-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-note.js","sourceRoot":"","sources":["../../src/tools/delete-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;CAC5D,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAiB,EACjB,KAAsB;IAEtB,oCAAoC;IACpC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE5D,IAAI,YAAY,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,qEAAqE,YAAY,CAAC,UAAU,GAAG,CAAC,CAAC;IACnH,CAAC;IAED,MAAM,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAEzC,OAAO,SAAS,KAAK,CAAC,IAAI,UAAU,YAAY,CAAC,EAAE,qBAAqB,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const getCommentsSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ includeResolved: z.ZodOptional<z.ZodBoolean>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ slug: string;
8
+ includeResolved?: boolean | undefined;
9
+ }, {
10
+ slug: string;
11
+ includeResolved?: boolean | undefined;
12
+ }>;
13
+ export type GetCommentsInput = z.infer<typeof getCommentsSchema>;
14
+ export declare function getComments(client: ApiClient, input: GetCommentsInput): Promise<string>;
15
+ //# sourceMappingURL=get-comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-comments.d.ts","sourceRoot":"","sources":["../../src/tools/get-comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,MAAM,CAAC,CA6CjB"}
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ export const getCommentsSchema = z.object({
3
+ slug: z.string().describe('The slug of the note to get comments from'),
4
+ includeResolved: z.boolean().optional().describe('Include resolved comment threads (default: true)'),
5
+ });
6
+ export async function getComments(client, input) {
7
+ // First get the note to find its ID
8
+ const note = await client.getNoteBySlug(input.slug);
9
+ const threads = await client.listCommentThreads(note.id);
10
+ const filteredThreads = input.includeResolved === false
11
+ ? threads.filter(t => !t.resolved)
12
+ : threads;
13
+ if (filteredThreads.length === 0) {
14
+ return `No ${input.includeResolved === false ? 'unresolved ' : ''}comments found on note "${input.slug}".`;
15
+ }
16
+ const lines = [
17
+ `# Comments on "${input.slug}"`,
18
+ '',
19
+ `Found ${filteredThreads.length} comment thread(s):`,
20
+ '',
21
+ ];
22
+ for (const thread of filteredThreads) {
23
+ const status = thread.resolved ? '(Resolved)' : '(Open)';
24
+ const originalText = thread.anchor.originalText
25
+ ? `"${thread.anchor.originalText.substring(0, 50)}${thread.anchor.originalText.length > 50 ? '...' : ''}"`
26
+ : '(no text anchor)';
27
+ lines.push(`## Thread ${status}`);
28
+ lines.push(`**ID**: ${thread.id}`);
29
+ lines.push(`**On text**: ${originalText}`);
30
+ lines.push(`**Started by**: ${thread.createdBy.name || thread.createdBy.email}`);
31
+ lines.push('');
32
+ for (const comment of thread.comments) {
33
+ const author = comment.author.name || comment.author.email;
34
+ const date = new Date(comment.createdAt).toLocaleString();
35
+ lines.push(`> **${author}** (${date}):`);
36
+ lines.push(`> ${comment.content.replace(/\n/g, '\n> ')}`);
37
+ lines.push('');
38
+ }
39
+ lines.push('---');
40
+ lines.push('');
41
+ }
42
+ return lines.join('\n');
43
+ }
44
+ //# sourceMappingURL=get-comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-comments.js","sourceRoot":"","sources":["../../src/tools/get-comments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const listNotesSchema: z.ZodObject<{
4
+ workspaceId: z.ZodOptional<z.ZodString>;
5
+ page: z.ZodOptional<z.ZodNumber>;
6
+ limit: z.ZodOptional<z.ZodNumber>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ workspaceId?: string | undefined;
9
+ page?: number | undefined;
10
+ limit?: number | undefined;
11
+ }, {
12
+ workspaceId?: string | undefined;
13
+ page?: number | undefined;
14
+ limit?: number | undefined;
15
+ }>;
16
+ export type ListNotesInput = z.infer<typeof listNotesSchema>;
17
+ export declare function listNotes(client: ApiClient, input: ListNotesInput): Promise<string>;
18
+ //# sourceMappingURL=list-notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-notes.d.ts","sourceRoot":"","sources":["../../src/tools/list-notes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,eAAe;;;;;;;;;;;;EAI1B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE7D,wBAAsB,SAAS,CAC7B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ export const listNotesSchema = z.object({
3
+ workspaceId: z.string().uuid().optional().describe('Filter by workspace ID'),
4
+ page: z.number().int().positive().optional().describe('Page number (default: 1)'),
5
+ limit: z.number().int().positive().max(100).optional().describe('Items per page (default: 15, max: 100)'),
6
+ });
7
+ export async function listNotes(client, input) {
8
+ const response = await client.listNotes(input);
9
+ const lines = [
10
+ `Found ${response.total} notes (page ${response.page}/${response.totalPages}):`,
11
+ '',
12
+ ];
13
+ for (const note of response.notes) {
14
+ lines.push(`- **${note.slug}** (${note.sharingMode})`);
15
+ lines.push(` ID: ${note.id}`);
16
+ lines.push(` Updated: ${new Date(note.updatedAt).toLocaleString()}`);
17
+ lines.push('');
18
+ }
19
+ return lines.join('\n');
20
+ }
21
+ //# sourceMappingURL=list-notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-notes.js","sourceRoot":"","sources":["../../src/tools/list-notes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAC5E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACjF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;CAC1G,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAiB,EACjB,KAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG;QACZ,SAAS,QAAQ,CAAC,KAAK,gBAAgB,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,UAAU,IAAI;QAC/E,EAAE;KACH,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const readNoteSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ slug: string;
7
+ }, {
8
+ slug: string;
9
+ }>;
10
+ export type ReadNoteInput = z.infer<typeof readNoteSchema>;
11
+ export declare function readNote(client: ApiClient, input: ReadNoteInput): Promise<string>;
12
+ //# sourceMappingURL=read-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-note.d.ts","sourceRoot":"","sources":["../../src/tools/read-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,cAAc;;;;;;EAEzB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE3D,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,MAAM,CAAC,CAiBjB"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ export const readNoteSchema = z.object({
3
+ slug: z.string().describe('The slug (URL-friendly name) of the note to read'),
4
+ });
5
+ export async function readNote(client, input) {
6
+ const note = await client.getNoteBySlug(input.slug);
7
+ const lines = [
8
+ `# Note: ${note.slug}`,
9
+ '',
10
+ `- **ID**: ${note.id}`,
11
+ `- **Permission**: ${note.permission}`,
12
+ `- **Sharing Mode**: ${note.sharingMode}`,
13
+ `- **Updated**: ${new Date(note.updatedAt).toLocaleString()}`,
14
+ '',
15
+ '---',
16
+ '',
17
+ note.content || '(empty note)',
18
+ ];
19
+ return lines.join('\n');
20
+ }
21
+ //# sourceMappingURL=read-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-note.js","sourceRoot":"","sources":["../../src/tools/read-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;CAC9E,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAiB,EACjB,KAAoB;IAEpB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpD,MAAM,KAAK,GAAG;QACZ,WAAW,IAAI,CAAC,IAAI,EAAE;QACtB,EAAE;QACF,aAAa,IAAI,CAAC,EAAE,EAAE;QACtB,qBAAqB,IAAI,CAAC,UAAU,EAAE;QACtC,uBAAuB,IAAI,CAAC,WAAW,EAAE;QACzC,kBAAkB,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,EAAE;QAC7D,EAAE;QACF,KAAK;QACL,EAAE;QACF,IAAI,CAAC,OAAO,IAAI,cAAc;KAC/B,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const resolveThreadSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ threadId: z.ZodString;
6
+ resolved: z.ZodOptional<z.ZodBoolean>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ slug: string;
9
+ threadId: string;
10
+ resolved?: boolean | undefined;
11
+ }, {
12
+ slug: string;
13
+ threadId: string;
14
+ resolved?: boolean | undefined;
15
+ }>;
16
+ export type ResolveThreadInput = z.infer<typeof resolveThreadSchema>;
17
+ export declare function resolveThread(client: ApiClient, input: ResolveThreadInput): Promise<string>;
18
+ //# sourceMappingURL=resolve-thread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-thread.d.ts","sourceRoot":"","sources":["../../src/tools/resolve-thread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAErE,wBAAsB,aAAa,CACjC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export const resolveThreadSchema = z.object({
3
+ slug: z.string().describe('The slug of the note containing the thread'),
4
+ threadId: z.string().uuid().describe('The ID of the comment thread to resolve/unresolve'),
5
+ resolved: z.boolean().optional().describe('Set to true to resolve, false to unresolve (default: true)'),
6
+ });
7
+ export async function resolveThread(client, input) {
8
+ // First get the note to find its ID
9
+ const note = await client.getNoteBySlug(input.slug);
10
+ const resolved = input.resolved !== false;
11
+ const thread = await client.resolveThread(note.id, input.threadId, resolved);
12
+ const action = resolved ? 'resolved' : 'reopened';
13
+ const originalText = thread.anchor.originalText
14
+ ? `on "${thread.anchor.originalText.substring(0, 30)}..."`
15
+ : '';
16
+ return `Comment thread ${originalText} has been ${action}.`;
17
+ }
18
+ //# sourceMappingURL=resolve-thread.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-thread.js","sourceRoot":"","sources":["../../src/tools/resolve-thread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;IACvE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;IACzF,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;CACxG,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAiB,EACjB,KAAyB;IAEzB,oCAAoC;IACpC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC;IAE1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAClD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY;QAC7C,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM;QAC1D,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,kBAAkB,YAAY,aAAa,MAAM,GAAG,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ import { ApiClient } from '../api-client.js';
3
+ export declare const updateNoteSchema: z.ZodObject<{
4
+ slug: z.ZodString;
5
+ content: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ slug: string;
8
+ content: string;
9
+ }, {
10
+ slug: string;
11
+ content: string;
12
+ }>;
13
+ export type UpdateNoteInput = z.infer<typeof updateNoteSchema>;
14
+ export declare function updateNote(client: ApiClient, input: UpdateNoteInput): Promise<string>;
15
+ //# sourceMappingURL=update-note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-note.d.ts","sourceRoot":"","sources":["../../src/tools/update-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,eAAO,MAAM,gBAAgB;;;;;;;;;EAG3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export const updateNoteSchema = z.object({
3
+ slug: z.string().describe('The slug of the note to update'),
4
+ content: z.string().describe('The new markdown content for the note'),
5
+ });
6
+ export async function updateNote(client, input) {
7
+ // First get the note to find its ID
8
+ const existingNote = await client.getNoteBySlug(input.slug);
9
+ if (existingNote.permission !== 'write') {
10
+ throw new Error(`You don't have write permission on this note (current permission: ${existingNote.permission})`);
11
+ }
12
+ const updated = await client.updateNote(existingNote.id, {
13
+ content: input.content,
14
+ });
15
+ return `Note "${updated.slug}" updated successfully.\n\nNew content length: ${input.content.length} characters`;
16
+ }
17
+ //# sourceMappingURL=update-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-note.js","sourceRoot":"","sources":["../../src/tools/update-note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAC3D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;CACtE,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAiB,EACjB,KAAsB;IAEtB,oCAAoC;IACpC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE5D,IAAI,YAAY,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,qEAAqE,YAAY,CAAC,UAAU,GAAG,CAAC,CAAC;IACnH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,EAAE;QACvD,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC,CAAC;IAEH,OAAO,SAAS,OAAO,CAAC,IAAI,kDAAkD,KAAK,CAAC,OAAO,CAAC,MAAM,aAAa,CAAC;AAClH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "whiteboard-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Whiteboard notes integration with Claude Code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "whiteboard-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "start": "node dist/index.js",
17
+ "dev": "tsx src/index.ts",
18
+ "typecheck": "tsc --noEmit",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "claude",
24
+ "anthropic",
25
+ "whiteboard",
26
+ "notes",
27
+ "markdown"
28
+ ],
29
+ "author": "",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": ""
34
+ },
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.0.0",
37
+ "zod": "^3.24.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^22.0.0",
41
+ "tsx": "^4.19.0",
42
+ "typescript": "^5.6.0"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ }
47
+ }