@nonz250/notepm-mcp-server 0.3.0 → 0.5.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.
- package/README.md +2 -9
- package/dist/folders/__tests__/client.test.d.ts +2 -0
- package/dist/folders/__tests__/client.test.d.ts.map +1 -0
- package/dist/folders/__tests__/client.test.js +30 -0
- package/dist/folders/__tests__/client.test.js.map +1 -0
- package/dist/folders/__tests__/schemas.test.d.ts +2 -0
- package/dist/folders/__tests__/schemas.test.d.ts.map +1 -0
- package/dist/folders/__tests__/schemas.test.js +27 -0
- package/dist/folders/__tests__/schemas.test.js.map +1 -0
- package/dist/folders/client.d.ts +15 -0
- package/dist/folders/client.d.ts.map +1 -0
- package/dist/folders/client.js +14 -0
- package/dist/folders/client.js.map +1 -0
- package/dist/folders/handlers.d.ts +15 -0
- package/dist/folders/handlers.d.ts.map +1 -0
- package/dist/folders/handlers.js +47 -0
- package/dist/folders/handlers.js.map +1 -0
- package/dist/folders/index.d.ts +9 -0
- package/dist/folders/index.d.ts.map +1 -0
- package/dist/folders/index.js +9 -0
- package/dist/folders/index.js.map +1 -0
- package/dist/folders/schemas.d.ts +10 -0
- package/dist/folders/schemas.d.ts.map +1 -0
- package/dist/folders/schemas.js +11 -0
- package/dist/folders/schemas.js.map +1 -0
- package/dist/folders/tools.d.ts +6 -0
- package/dist/folders/tools.d.ts.map +1 -0
- package/dist/folders/tools.js +11 -0
- package/dist/folders/tools.js.map +1 -0
- package/dist/folders/types.d.ts +24 -0
- package/dist/folders/types.d.ts.map +1 -0
- package/dist/folders/types.js +8 -0
- package/dist/folders/types.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/__tests__/handler.test.js +32 -120
- package/dist/mcp/__tests__/handler.test.js.map +1 -1
- package/dist/mcp/__tests__/tools.test.js +5 -10
- package/dist/mcp/__tests__/tools.test.js.map +1 -1
- package/dist/mcp/handler.d.ts +2 -0
- package/dist/mcp/handler.d.ts.map +1 -1
- package/dist/mcp/handler.js +5 -1
- package/dist/mcp/handler.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +2 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/notes/__tests__/client.test.js +0 -50
- package/dist/notes/__tests__/client.test.js.map +1 -1
- package/dist/notes/__tests__/schemas.test.js +1 -194
- package/dist/notes/__tests__/schemas.test.js.map +1 -1
- package/dist/notes/client.d.ts +1 -31
- package/dist/notes/client.d.ts.map +1 -1
- package/dist/notes/client.js +0 -45
- package/dist/notes/client.js.map +1 -1
- package/dist/notes/handlers.d.ts +1 -1
- package/dist/notes/handlers.d.ts.map +1 -1
- package/dist/notes/handlers.js +9 -57
- package/dist/notes/handlers.js.map +1 -1
- package/dist/notes/schemas.d.ts +0 -45
- package/dist/notes/schemas.d.ts.map +1 -1
- package/dist/notes/schemas.js +0 -32
- package/dist/notes/schemas.js.map +1 -1
- package/dist/notes/tools.d.ts.map +1 -1
- package/dist/notes/tools.js +1 -31
- package/dist/notes/tools.js.map +1 -1
- package/dist/notes/types.d.ts +0 -22
- package/dist/notes/types.d.ts.map +1 -1
- package/dist/notes/types.js +0 -6
- package/dist/notes/types.js.map +1 -1
- package/dist/pages/__tests__/client.test.js +0 -7
- package/dist/pages/__tests__/client.test.js.map +1 -1
- package/dist/pages/__tests__/schemas.test.js +1 -23
- package/dist/pages/__tests__/schemas.test.js.map +1 -1
- package/dist/pages/client.d.ts +0 -5
- package/dist/pages/client.d.ts.map +1 -1
- package/dist/pages/client.js +0 -7
- package/dist/pages/client.js.map +1 -1
- package/dist/pages/handlers.d.ts.map +1 -1
- package/dist/pages/handlers.js +10 -7
- package/dist/pages/handlers.js.map +1 -1
- package/dist/pages/schemas.d.ts +0 -5
- package/dist/pages/schemas.d.ts.map +1 -1
- package/dist/pages/schemas.js +0 -3
- package/dist/pages/schemas.js.map +1 -1
- package/dist/pages/tools.d.ts.map +1 -1
- package/dist/pages/tools.js +1 -6
- package/dist/pages/tools.js.map +1 -1
- package/dist/pages/types.d.ts +0 -1
- package/dist/pages/types.d.ts.map +1 -1
- package/dist/pages/types.js +0 -1
- package/dist/pages/types.js.map +1 -1
- package/dist/shared/__tests__/fixtures.d.ts +9 -0
- package/dist/shared/__tests__/fixtures.d.ts.map +1 -1
- package/dist/shared/__tests__/fixtures.js +15 -0
- package/dist/shared/__tests__/fixtures.js.map +1 -1
- package/dist/shared/__tests__/http-client.test.js +1 -1
- package/dist/shared/__tests__/http-client.test.js.map +1 -1
- package/dist/tags/__tests__/client.test.js +0 -8
- package/dist/tags/__tests__/client.test.js.map +1 -1
- package/dist/tags/__tests__/schemas.test.js +1 -31
- package/dist/tags/__tests__/schemas.test.js.map +1 -1
- package/dist/tags/client.d.ts +1 -6
- package/dist/tags/client.d.ts.map +1 -1
- package/dist/tags/client.js +0 -7
- package/dist/tags/client.js.map +1 -1
- package/dist/tags/handlers.d.ts.map +1 -1
- package/dist/tags/handlers.js +1 -6
- package/dist/tags/handlers.js.map +1 -1
- package/dist/tags/schemas.d.ts +0 -5
- package/dist/tags/schemas.d.ts.map +1 -1
- package/dist/tags/schemas.js +0 -3
- package/dist/tags/schemas.js.map +1 -1
- package/dist/tags/tools.d.ts.map +1 -1
- package/dist/tags/tools.js +1 -6
- package/dist/tags/tools.js.map +1 -1
- package/dist/tags/types.d.ts +0 -5
- package/dist/tags/types.d.ts.map +1 -1
- package/dist/tags/types.js +0 -1
- package/dist/tags/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
An unofficial [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for [NotePM](https://notepm.jp/) - a knowledge management and documentation platform.
|
|
22
22
|
|
|
23
|
-
This server enables AI assistants like Claude to search, read, create,
|
|
23
|
+
This server enables AI assistants like Claude to search, read, create, and update pages in your NotePM workspace.
|
|
24
24
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
@@ -115,21 +115,14 @@ If you installed globally, replace `npx` with the direct command:
|
|
|
115
115
|
|
|
116
116
|
| Tool | Description |
|
|
117
117
|
|------|-------------|
|
|
118
|
+
| `list_folders` | List folders in a note with hierarchy |
|
|
118
119
|
| `list_notes` | List all notes in your workspace |
|
|
119
|
-
| `get_note` | Get a note's details including name, description, and scope |
|
|
120
|
-
| `create_note` | Create a new note with name, description, and access settings |
|
|
121
|
-
| `update_note` | Update an existing note's name, description, or access settings |
|
|
122
|
-
| `delete_note` | Delete a note and all its pages (irreversible) |
|
|
123
|
-
| `archive_note` | Archive a note (hidden from default list but can be restored) |
|
|
124
|
-
| `unarchive_note` | Restore an archived note back to the active list |
|
|
125
120
|
| `search_pages` | Search pages by keyword, note, or tag |
|
|
126
121
|
| `get_page` | Get a page's full content including title, body, and tags |
|
|
127
122
|
| `create_page` | Create a new page in a specified note |
|
|
128
123
|
| `update_page` | Update an existing page's content |
|
|
129
|
-
| `delete_page` | Delete a page (irreversible) |
|
|
130
124
|
| `list_tags` | List all tags in your workspace |
|
|
131
125
|
| `create_tag` | Create a new tag |
|
|
132
|
-
| `delete_tag` | Delete a tag (irreversible) |
|
|
133
126
|
|
|
134
127
|
## Environment Variables
|
|
135
128
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../src/folders/__tests__/client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FolderClient Tests
|
|
3
|
+
*/
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { FolderClient } from "../client.js";
|
|
6
|
+
describe("FolderClient", () => {
|
|
7
|
+
let client;
|
|
8
|
+
let mockHttp;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockHttp = { request: vi.fn() };
|
|
11
|
+
client = new FolderClient(mockHttp);
|
|
12
|
+
});
|
|
13
|
+
describe("list", () => {
|
|
14
|
+
it("should call GET /notes/:note_code/folders", async () => {
|
|
15
|
+
mockHttp.request.mockResolvedValue({ folders: [] });
|
|
16
|
+
await client.list({ note_code: "abc123" });
|
|
17
|
+
expect(mockHttp.request).toHaveBeenCalledWith("GET", "/notes/abc123/folders");
|
|
18
|
+
});
|
|
19
|
+
it("should return folders response", async () => {
|
|
20
|
+
const mockFolders = [
|
|
21
|
+
{ folder_id: 1, name: "Folder 1", parent_folder_id: null },
|
|
22
|
+
{ folder_id: 2, name: "Folder 2", parent_folder_id: 1 },
|
|
23
|
+
];
|
|
24
|
+
mockHttp.request.mockResolvedValue({ folders: mockFolders });
|
|
25
|
+
const result = await client.list({ note_code: "abc123" });
|
|
26
|
+
expect(result.folders).toEqual(mockFolders);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../../src/folders/__tests__/client.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAI,MAAoB,CAAC;IACzB,IAAI,QAA+C,CAAC;IAEpD,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAChC,MAAM,GAAG,IAAI,YAAY,CAAC,QAAiC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAEpD,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE3C,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,WAAW,GAAG;gBAClB,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE;gBAC1D,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,EAAE;aACxD,CAAC;YACF,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YAE7D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE1D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.test.d.ts","sourceRoot":"","sources":["../../../src/folders/__tests__/schemas.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder Schema Validation Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { ListFoldersInputSchema } from "../schemas.js";
|
|
6
|
+
describe("ListFoldersInputSchema", () => {
|
|
7
|
+
it("should require note_code", () => {
|
|
8
|
+
const result = ListFoldersInputSchema.safeParse({});
|
|
9
|
+
expect(result.success).toBe(false);
|
|
10
|
+
});
|
|
11
|
+
it("should accept valid note_code", () => {
|
|
12
|
+
const result = ListFoldersInputSchema.safeParse({ note_code: "abc123" });
|
|
13
|
+
expect(result.success).toBe(true);
|
|
14
|
+
if (result.success) {
|
|
15
|
+
expect(result.data.note_code).toBe("abc123");
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
it("should reject empty note_code", () => {
|
|
19
|
+
const result = ListFoldersInputSchema.safeParse({ note_code: "" });
|
|
20
|
+
expect(result.success).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
it("should reject non-string note_code", () => {
|
|
23
|
+
const result = ListFoldersInputSchema.safeParse({ note_code: 123 });
|
|
24
|
+
expect(result.success).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=schemas.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.test.js","sourceRoot":"","sources":["../../../src/folders/__tests__/schemas.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder domain API client
|
|
3
|
+
*/
|
|
4
|
+
import { HttpClient } from "../shared/http-client.js";
|
|
5
|
+
import type { FoldersResponse, ListFoldersParams } from "./types.js";
|
|
6
|
+
export declare class FolderClient {
|
|
7
|
+
private http;
|
|
8
|
+
constructor(http: HttpClient);
|
|
9
|
+
/**
|
|
10
|
+
* List folders in a note
|
|
11
|
+
* GET /api/v1/notes/:note_code/folders
|
|
12
|
+
*/
|
|
13
|
+
list(params: ListFoldersParams): Promise<FoldersResponse>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/folders/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErE,qBAAa,YAAY;IACX,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEpC;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;CAGhE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export class FolderClient {
|
|
2
|
+
http;
|
|
3
|
+
constructor(http) {
|
|
4
|
+
this.http = http;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* List folders in a note
|
|
8
|
+
* GET /api/v1/notes/:note_code/folders
|
|
9
|
+
*/
|
|
10
|
+
async list(params) {
|
|
11
|
+
return this.http.request("GET", `/notes/${params.note_code}/folders`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/folders/client.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,YAAY;IACH;IAApB,YAAoB,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAExC;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,MAAyB;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAkB,KAAK,EAAE,UAAU,MAAM,CAAC,SAAS,UAAU,CAAC,CAAC;IACzF,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder domain handlers
|
|
3
|
+
*/
|
|
4
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { FolderClient } from "./client.js";
|
|
6
|
+
import type { FolderToolName } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Check if the tool name is a folder tool
|
|
9
|
+
*/
|
|
10
|
+
export declare function isFolderToolName(name: string): name is FolderToolName;
|
|
11
|
+
/**
|
|
12
|
+
* Handle folder tool calls
|
|
13
|
+
*/
|
|
14
|
+
export declare function handleFolderToolCall(client: FolderClient, _name: FolderToolName, args: unknown): Promise<CallToolResult>;
|
|
15
|
+
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/folders/handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAU,cAAc,EAAE,MAAM,YAAY,CAAC;AAiCzD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,cAAc,CAErE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,cAAc,CAAC,CAWzB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { parseInput, success } from "../shared/result.js";
|
|
2
|
+
import { ListFoldersInputSchema } from "./schemas.js";
|
|
3
|
+
import { FOLDER_TOOL_NAMES } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Build folder tree structure for display
|
|
6
|
+
*/
|
|
7
|
+
function buildFolderTree(folders) {
|
|
8
|
+
// Get root folders (no parent)
|
|
9
|
+
const rootFolders = folders.filter((f) => f.parent_folder_id === null);
|
|
10
|
+
// Get child folders for a given parent
|
|
11
|
+
const getChildren = (parentId) => folders.filter((f) => f.parent_folder_id === parentId);
|
|
12
|
+
// Recursively format folder with children
|
|
13
|
+
const formatWithChildren = (folder, indent) => {
|
|
14
|
+
const prefix = " ".repeat(indent);
|
|
15
|
+
const lines = [`${prefix}- **${folder.name}** (id: ${String(folder.folder_id)})`];
|
|
16
|
+
const children = getChildren(folder.folder_id);
|
|
17
|
+
for (const child of children) {
|
|
18
|
+
lines.push(...formatWithChildren(child, indent + 1));
|
|
19
|
+
}
|
|
20
|
+
return lines;
|
|
21
|
+
};
|
|
22
|
+
const lines = [];
|
|
23
|
+
for (const root of rootFolders) {
|
|
24
|
+
lines.push(...formatWithChildren(root, 0));
|
|
25
|
+
}
|
|
26
|
+
return lines.join("\n");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if the tool name is a folder tool
|
|
30
|
+
*/
|
|
31
|
+
export function isFolderToolName(name) {
|
|
32
|
+
return Object.values(FOLDER_TOOL_NAMES).includes(name);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Handle folder tool calls
|
|
36
|
+
*/
|
|
37
|
+
export async function handleFolderToolCall(client, _name, args) {
|
|
38
|
+
// Currently only list_folders is supported
|
|
39
|
+
const { note_code } = parseInput(ListFoldersInputSchema, args);
|
|
40
|
+
const result = await client.list({ note_code });
|
|
41
|
+
if (result.folders.length === 0) {
|
|
42
|
+
return success("No folders found in this note.");
|
|
43
|
+
}
|
|
44
|
+
const folderTree = buildFolderTree(result.folders);
|
|
45
|
+
return success(`Folders in note "${note_code}":\n\n${folderTree}`);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/folders/handlers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,SAAS,eAAe,CAAC,OAAiB;IACxC,+BAA+B;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,IAAI,CAAC,CAAC;IAEvE,uCAAuC;IACvC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAY,EAAE,CACjD,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC;IAEzD,0CAA0C;IAC1C,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAE,MAAc,EAAY,EAAE;QACtE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,OAAO,MAAM,CAAC,IAAI,WAAW,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,IAAsB,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAoB,EACpB,KAAqB,EACrB,IAAa;IAEb,2CAA2C;IAC3C,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAEhD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,gCAAgC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,OAAO,CAAC,oBAAoB,SAAS,SAAS,UAAU,EAAE,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/folders/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/folders/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder domain schemas (Zod)
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
export declare const ListFoldersInputSchema: z.ZodObject<{
|
|
6
|
+
note_code: z.ZodString;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
/** Inferred type for list folders input */
|
|
9
|
+
export type ListFoldersInput = z.infer<typeof ListFoldersInputSchema>;
|
|
10
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/folders/schemas.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,sBAAsB;;iBAEjC,CAAC;AAMH,2CAA2C;AAC3C,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder domain schemas (Zod)
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
// ============================================================
|
|
6
|
+
// Zod Schemas
|
|
7
|
+
// ============================================================
|
|
8
|
+
export const ListFoldersInputSchema = z.object({
|
|
9
|
+
note_code: z.string().min(1).describe("Note code to list folders from"),
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/folders/schemas.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+DAA+D;AAC/D,cAAc;AACd,+DAA+D;AAE/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;CACxE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/folders/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAM/D,eAAO,MAAM,YAAY,EAAE,IAAI,EAM9B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { toInputSchema } from "../shared/index.js";
|
|
2
|
+
import { ListFoldersInputSchema } from "./schemas.js";
|
|
3
|
+
import { FOLDER_TOOL_NAMES } from "./types.js";
|
|
4
|
+
export const FOLDER_TOOLS = [
|
|
5
|
+
{
|
|
6
|
+
name: FOLDER_TOOL_NAMES.LIST_FOLDERS,
|
|
7
|
+
description: "List folders in a NotePM note. Returns folder hierarchy with IDs and names.",
|
|
8
|
+
inputSchema: toInputSchema(ListFoldersInputSchema),
|
|
9
|
+
},
|
|
10
|
+
];
|
|
11
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/folders/tools.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC;QACE,IAAI,EAAE,iBAAiB,CAAC,YAAY;QACpC,WAAW,EAAE,6EAA6E;QAC1F,WAAW,EAAE,aAAa,CAAC,sBAAsB,CAAC;KACnD;CACF,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folder domain types
|
|
3
|
+
*/
|
|
4
|
+
/** Folder information */
|
|
5
|
+
export interface Folder {
|
|
6
|
+
folder_id: number;
|
|
7
|
+
name: string;
|
|
8
|
+
parent_folder_id: number | null;
|
|
9
|
+
}
|
|
10
|
+
/** Folders list response */
|
|
11
|
+
export interface FoldersResponse {
|
|
12
|
+
folders: Folder[];
|
|
13
|
+
}
|
|
14
|
+
/** List folders parameters */
|
|
15
|
+
export interface ListFoldersParams {
|
|
16
|
+
note_code: string;
|
|
17
|
+
}
|
|
18
|
+
/** Tool name constants for folders */
|
|
19
|
+
export declare const FOLDER_TOOL_NAMES: {
|
|
20
|
+
readonly LIST_FOLDERS: "list_folders";
|
|
21
|
+
};
|
|
22
|
+
/** Type representing valid folder tool names */
|
|
23
|
+
export type FolderToolName = (typeof FOLDER_TOOL_NAMES)[keyof typeof FOLDER_TOOL_NAMES];
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/folders/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,yBAAyB;AACzB,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,8BAA8B;AAC9B,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,sCAAsC;AACtC,eAAO,MAAM,iBAAiB;;CAEpB,CAAC;AAEX,gDAAgD;AAChD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/folders/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,sCAAsC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,YAAY,EAAE,cAAc;CACpB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,8 @@ import { createRequire } from "node:module";
|
|
|
13
13
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
16
|
-
import {
|
|
16
|
+
import { FolderClient } from "./folders/index.js";
|
|
17
|
+
import { TOOLS, handleToolCall } from "./mcp/index.js";
|
|
17
18
|
import { NoteClient } from "./notes/index.js";
|
|
18
19
|
import { PageClient } from "./pages/index.js";
|
|
19
20
|
import { HttpClient, loadConfig } from "./shared/index.js";
|
|
@@ -29,6 +30,7 @@ const packageJson = require("../package.json");
|
|
|
29
30
|
const config = loadConfig();
|
|
30
31
|
const httpClient = new HttpClient(config);
|
|
31
32
|
const clients = {
|
|
33
|
+
folders: new FolderClient(httpClient),
|
|
32
34
|
notes: new NoteClient(httpClient),
|
|
33
35
|
pages: new PageClient(httpClient),
|
|
34
36
|
tags: new TagClient(httpClient),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,+DAA+D;AAC/D,oBAAoB;AACpB,+DAA+D;AAE/D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAsC,CAAC;AAEpF,+DAA+D;AAC/D,4CAA4C;AAC5C,+DAA+D;AAE/D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAC5B,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAC1C,MAAM,OAAO,GAAG;IACd,OAAO,EAAE,IAAI,YAAY,CAAC,UAAU,CAAC;IACrC,KAAK,EAAE,IAAI,UAAU,CAAC,UAAU,CAAC;IACjC,KAAK,EAAE,IAAI,UAAU,CAAC,UAAU,CAAC;IACjC,IAAI,EAAE,IAAI,SAAS,CAAC,UAAU,CAAC;CAChC,CAAC;AAEF,+DAA+D;AAC/D,yBAAyB;AACzB,+DAA+D;AAE/D,uDAAuD;AACvD,4EAA4E;AAC5E,4DAA4D;AAC5D,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,WAAW,CAAC,IAAI;IACtB,OAAO,EAAE,WAAW,CAAC,OAAO;CAC7B,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,+DAA+D;AAC/D,0BAA0B;AAC1B,+DAA+D;AAE/D;;GAEG;AACH,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IACjD,OAAO,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,+DAA+D;AAC/D,eAAe;AACf,+DAA+D;AAE/D,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,8BAA8B,MAAM,CAAC,UAAU,aAAa,CAAC,CAAC;AAC9E,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createMockFolder, createMockFoldersResponse, createMockNote, createMockNotesResponse, createMockPage, createMockPagesResponse, createMockTag, createMockTagsResponse, } from "../../shared/__tests__/fixtures.js";
|
|
2
3
|
import { NotePMAPIError } from "../../shared/errors.js";
|
|
3
|
-
import { createMockNote, createMockNotesResponse, createMockPage, createMockPagesResponse, createMockTag, createMockTagsResponse, } from "../../shared/__tests__/fixtures.js";
|
|
4
4
|
import { handleToolCall } from "../index.js";
|
|
5
5
|
// ============================================================
|
|
6
6
|
// Helper Functions
|
|
@@ -18,37 +18,35 @@ function getTextContent(result) {
|
|
|
18
18
|
// ============================================================
|
|
19
19
|
// Mock Setup
|
|
20
20
|
// ============================================================
|
|
21
|
+
const createMockFolderClient = () => ({
|
|
22
|
+
list: vi.fn(),
|
|
23
|
+
});
|
|
21
24
|
const createMockNoteClient = () => ({
|
|
22
25
|
list: vi.fn(),
|
|
23
|
-
get: vi.fn(),
|
|
24
|
-
create: vi.fn(),
|
|
25
|
-
update: vi.fn(),
|
|
26
|
-
delete: vi.fn(),
|
|
27
|
-
archive: vi.fn(),
|
|
28
|
-
unarchive: vi.fn(),
|
|
29
26
|
});
|
|
30
27
|
const createMockPageClient = () => ({
|
|
31
28
|
search: vi.fn(),
|
|
32
29
|
get: vi.fn(),
|
|
33
30
|
create: vi.fn(),
|
|
34
31
|
update: vi.fn(),
|
|
35
|
-
delete: vi.fn(),
|
|
36
32
|
});
|
|
37
33
|
const createMockTagClient = () => ({
|
|
38
34
|
list: vi.fn(),
|
|
39
35
|
create: vi.fn(),
|
|
40
|
-
delete: vi.fn(),
|
|
41
36
|
});
|
|
42
37
|
describe("handleToolCall", () => {
|
|
38
|
+
let mockFolderClient;
|
|
43
39
|
let mockNoteClient;
|
|
44
40
|
let mockPageClient;
|
|
45
41
|
let mockTagClient;
|
|
46
42
|
let clients;
|
|
47
43
|
beforeEach(() => {
|
|
44
|
+
mockFolderClient = createMockFolderClient();
|
|
48
45
|
mockNoteClient = createMockNoteClient();
|
|
49
46
|
mockPageClient = createMockPageClient();
|
|
50
47
|
mockTagClient = createMockTagClient();
|
|
51
48
|
clients = {
|
|
49
|
+
folders: mockFolderClient,
|
|
52
50
|
notes: mockNoteClient,
|
|
53
51
|
pages: mockPageClient,
|
|
54
52
|
tags: mockTagClient,
|
|
@@ -157,14 +155,6 @@ describe("handleToolCall", () => {
|
|
|
157
155
|
expect(getTextContent(result)).toContain("## Updated Page");
|
|
158
156
|
});
|
|
159
157
|
});
|
|
160
|
-
describe("delete_page", () => {
|
|
161
|
-
it("should return success message", async () => {
|
|
162
|
-
mockPageClient.delete.mockResolvedValue(undefined);
|
|
163
|
-
const result = await handleToolCall(clients, "delete_page", { page_code: "page123" });
|
|
164
|
-
expect(result.isError).toBeUndefined();
|
|
165
|
-
expect(getTextContent(result)).toBe("Page deleted: page123");
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
158
|
// ============================================================
|
|
169
159
|
// Note Tools Tests
|
|
170
160
|
// ============================================================
|
|
@@ -208,104 +198,6 @@ describe("handleToolCall", () => {
|
|
|
208
198
|
expect(getTextContent(result)).toContain("(No description)");
|
|
209
199
|
});
|
|
210
200
|
});
|
|
211
|
-
describe("get_note", () => {
|
|
212
|
-
it("should format note with all fields", async () => {
|
|
213
|
-
const note = createMockNote();
|
|
214
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
215
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
216
|
-
expect(result.isError).toBeUndefined();
|
|
217
|
-
expect(getTextContent(result)).toContain("## Test Note");
|
|
218
|
-
expect(getTextContent(result)).toContain("Note code: note123");
|
|
219
|
-
expect(getTextContent(result)).toContain("Scope: All members");
|
|
220
|
-
expect(getTextContent(result)).toContain("Archived: No");
|
|
221
|
-
});
|
|
222
|
-
it("should handle scope as number 0 (open)", async () => {
|
|
223
|
-
const note = createMockNote({ scope: 0 });
|
|
224
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
225
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
226
|
-
expect(result.isError).toBeUndefined();
|
|
227
|
-
expect(getTextContent(result)).toContain("Scope: All members");
|
|
228
|
-
});
|
|
229
|
-
it("should handle private scope", async () => {
|
|
230
|
-
const note = createMockNote({ scope: "private" });
|
|
231
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
232
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
233
|
-
expect(result.isError).toBeUndefined();
|
|
234
|
-
expect(getTextContent(result)).toContain("Scope: Participating members only");
|
|
235
|
-
});
|
|
236
|
-
it("should handle archived note", async () => {
|
|
237
|
-
const note = createMockNote({ archived: true });
|
|
238
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
239
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
240
|
-
expect(result.isError).toBeUndefined();
|
|
241
|
-
expect(getTextContent(result)).toContain("Archived: Yes");
|
|
242
|
-
});
|
|
243
|
-
it("should handle note with no description", async () => {
|
|
244
|
-
const note = createMockNote({ description: "" });
|
|
245
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
246
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
247
|
-
expect(result.isError).toBeUndefined();
|
|
248
|
-
expect(getTextContent(result)).toContain("(No description)");
|
|
249
|
-
});
|
|
250
|
-
it("should handle note with missing dates", async () => {
|
|
251
|
-
const note = createMockNote({ created_at: undefined, updated_at: undefined });
|
|
252
|
-
mockNoteClient.get.mockResolvedValue(note);
|
|
253
|
-
const result = await handleToolCall(clients, "get_note", { note_code: "note123" });
|
|
254
|
-
expect(result.isError).toBeUndefined();
|
|
255
|
-
expect(getTextContent(result)).toContain("Created at: N/A");
|
|
256
|
-
expect(getTextContent(result)).toContain("Updated at: N/A");
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
describe("create_note", () => {
|
|
260
|
-
it("should return success message with note details", async () => {
|
|
261
|
-
const note = createMockNote({ note_code: "new123", name: "New Note" });
|
|
262
|
-
mockNoteClient.create.mockResolvedValue(note);
|
|
263
|
-
const result = await handleToolCall(clients, "create_note", {
|
|
264
|
-
name: "New Note",
|
|
265
|
-
scope: "open",
|
|
266
|
-
});
|
|
267
|
-
expect(result.isError).toBeUndefined();
|
|
268
|
-
expect(getTextContent(result)).toContain("Note created.");
|
|
269
|
-
expect(getTextContent(result)).toContain("## New Note");
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
describe("update_note", () => {
|
|
273
|
-
it("should return success message with updated note details", async () => {
|
|
274
|
-
const note = createMockNote({ note_code: "note123", name: "Updated Note" });
|
|
275
|
-
mockNoteClient.update.mockResolvedValue(note);
|
|
276
|
-
const result = await handleToolCall(clients, "update_note", {
|
|
277
|
-
note_code: "note123",
|
|
278
|
-
name: "Updated Note",
|
|
279
|
-
});
|
|
280
|
-
expect(result.isError).toBeUndefined();
|
|
281
|
-
expect(getTextContent(result)).toContain("Note updated.");
|
|
282
|
-
expect(getTextContent(result)).toContain("## Updated Note");
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
describe("delete_note", () => {
|
|
286
|
-
it("should return success message", async () => {
|
|
287
|
-
mockNoteClient.delete.mockResolvedValue(undefined);
|
|
288
|
-
const result = await handleToolCall(clients, "delete_note", { note_code: "note123" });
|
|
289
|
-
expect(result.isError).toBeUndefined();
|
|
290
|
-
expect(getTextContent(result)).toBe("Note deleted: note123");
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
describe("archive_note", () => {
|
|
294
|
-
it("should return success message", async () => {
|
|
295
|
-
mockNoteClient.archive.mockResolvedValue(undefined);
|
|
296
|
-
const result = await handleToolCall(clients, "archive_note", { note_code: "note123" });
|
|
297
|
-
expect(result.isError).toBeUndefined();
|
|
298
|
-
expect(getTextContent(result)).toBe("Note archived: note123");
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
describe("unarchive_note", () => {
|
|
302
|
-
it("should return success message", async () => {
|
|
303
|
-
mockNoteClient.unarchive.mockResolvedValue(undefined);
|
|
304
|
-
const result = await handleToolCall(clients, "unarchive_note", { note_code: "note123" });
|
|
305
|
-
expect(result.isError).toBeUndefined();
|
|
306
|
-
expect(getTextContent(result)).toBe("Note unarchived: note123");
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
201
|
// ============================================================
|
|
310
202
|
// Tag Tools Tests
|
|
311
203
|
// ============================================================
|
|
@@ -333,12 +225,32 @@ describe("handleToolCall", () => {
|
|
|
333
225
|
expect(getTextContent(result)).toBe("Tag created: new-tag");
|
|
334
226
|
});
|
|
335
227
|
});
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
228
|
+
// ============================================================
|
|
229
|
+
// Folder Tools Tests
|
|
230
|
+
// ============================================================
|
|
231
|
+
describe("list_folders", () => {
|
|
232
|
+
it("should return 'No folders found.' for empty results", async () => {
|
|
233
|
+
mockFolderClient.list.mockResolvedValue(createMockFoldersResponse([]));
|
|
234
|
+
const result = await handleToolCall(clients, "list_folders", { note_code: "note123" });
|
|
340
235
|
expect(result.isError).toBeUndefined();
|
|
341
|
-
expect(getTextContent(result)).toBe("
|
|
236
|
+
expect(getTextContent(result)).toBe("No folders found in this note.");
|
|
237
|
+
});
|
|
238
|
+
it("should format folder list with hierarchy", async () => {
|
|
239
|
+
const folders = [
|
|
240
|
+
createMockFolder({ folder_id: 1, name: "Parent Folder", parent_folder_id: null }),
|
|
241
|
+
createMockFolder({ folder_id: 2, name: "Child Folder", parent_folder_id: 1 }),
|
|
242
|
+
];
|
|
243
|
+
mockFolderClient.list.mockResolvedValue(createMockFoldersResponse(folders));
|
|
244
|
+
const result = await handleToolCall(clients, "list_folders", { note_code: "note123" });
|
|
245
|
+
expect(result.isError).toBeUndefined();
|
|
246
|
+
expect(getTextContent(result)).toContain('Folders in note "note123"');
|
|
247
|
+
expect(getTextContent(result)).toContain("**Parent Folder**");
|
|
248
|
+
expect(getTextContent(result)).toContain("**Child Folder**");
|
|
249
|
+
});
|
|
250
|
+
it("should require note_code parameter", async () => {
|
|
251
|
+
const result = await handleToolCall(clients, "list_folders", {});
|
|
252
|
+
expect(result.isError).toBe(true);
|
|
253
|
+
expect(getTextContent(result)).toContain("Input error:");
|
|
342
254
|
});
|
|
343
255
|
});
|
|
344
256
|
});
|