niffler-app-mcp 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 +160 -0
  2. package/dist/bin/niffler-mcp.d.ts +3 -0
  3. package/dist/bin/niffler-mcp.d.ts.map +1 -0
  4. package/dist/bin/niffler-mcp.js +4 -0
  5. package/dist/bin/niffler-mcp.js.map +1 -0
  6. package/dist/src/client.d.ts +90 -0
  7. package/dist/src/client.d.ts.map +1 -0
  8. package/dist/src/client.js +85 -0
  9. package/dist/src/client.js.map +1 -0
  10. package/dist/src/index.d.ts +2 -0
  11. package/dist/src/index.d.ts.map +1 -0
  12. package/dist/src/index.js +24 -0
  13. package/dist/src/index.js.map +1 -0
  14. package/dist/src/resources/data-model.d.ts +3 -0
  15. package/dist/src/resources/data-model.d.ts.map +1 -0
  16. package/dist/src/resources/data-model.js +104 -0
  17. package/dist/src/resources/data-model.js.map +1 -0
  18. package/dist/src/server.d.ts +3 -0
  19. package/dist/src/server.d.ts.map +1 -0
  20. package/dist/src/server.js +23 -0
  21. package/dist/src/server.js.map +1 -0
  22. package/dist/src/tools/categories.d.ts +4 -0
  23. package/dist/src/tools/categories.d.ts.map +1 -0
  24. package/dist/src/tools/categories.js +55 -0
  25. package/dist/src/tools/categories.js.map +1 -0
  26. package/dist/src/tools/items.d.ts +4 -0
  27. package/dist/src/tools/items.d.ts.map +1 -0
  28. package/dist/src/tools/items.js +169 -0
  29. package/dist/src/tools/items.js.map +1 -0
  30. package/dist/src/tools/manage.d.ts +4 -0
  31. package/dist/src/tools/manage.d.ts.map +1 -0
  32. package/dist/src/tools/manage.js +82 -0
  33. package/dist/src/tools/manage.js.map +1 -0
  34. package/dist/src/tools/read.d.ts +4 -0
  35. package/dist/src/tools/read.d.ts.map +1 -0
  36. package/dist/src/tools/read.js +130 -0
  37. package/dist/src/tools/read.js.map +1 -0
  38. package/dist/src/types.d.ts +90 -0
  39. package/dist/src/types.d.ts.map +1 -0
  40. package/dist/src/types.js +2 -0
  41. package/dist/src/types.js.map +1 -0
  42. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # Niffler MCP Server
2
+
3
+ Connect AI agents like Claude, Cursor, and Windsurf to your Niffler account. Save bookmarks, notes, tasks, and events — organized into categories — all from your AI assistant.
4
+
5
+ ## Getting Started
6
+
7
+ ### 1. Get your API key
8
+
9
+ Open Niffler > **Settings** > **API Keys** and create a new key. Copy it — it starts with `nif_` and is only shown once.
10
+
11
+ ### 2. Add to your AI client
12
+
13
+ #### Claude Code
14
+
15
+ ```bash
16
+ claude mcp add niffler -- npx -y niffler-app-mcp
17
+ ```
18
+
19
+ Then set the environment variable:
20
+
21
+ ```bash
22
+ export NIFFLER_API_KEY=nif_your_key_here
23
+ ```
24
+
25
+ #### Claude Desktop
26
+
27
+ Add to your `claude_desktop_config.json`:
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "niffler": {
33
+ "command": "npx",
34
+ "args": ["-y", "niffler-app-mcp"],
35
+ "env": {
36
+ "NIFFLER_API_KEY": "nif_your_key_here"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ #### Cursor
44
+
45
+ Open **Settings** > **MCP Servers** > **Add Server**:
46
+
47
+ - **Name:** Niffler
48
+ - **Command:** `npx -y niffler-app-mcp`
49
+ - **Environment:** `NIFFLER_API_KEY=nif_your_key_here`
50
+
51
+ #### Windsurf
52
+
53
+ Add to your MCP config:
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "niffler": {
59
+ "command": "npx",
60
+ "args": ["-y", "niffler-app-mcp"],
61
+ "env": {
62
+ "NIFFLER_API_KEY": "nif_your_key_here"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ #### VS Code / Copilot
70
+
71
+ Add to your `.vscode/mcp.json`:
72
+
73
+ ```json
74
+ {
75
+ "servers": {
76
+ "niffler": {
77
+ "command": "npx",
78
+ "args": ["-y", "niffler-app-mcp"],
79
+ "env": {
80
+ "NIFFLER_API_KEY": "nif_your_key_here"
81
+ }
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ #### Other MCP Clients
88
+
89
+ Any MCP-compatible client can connect using:
90
+
91
+ - **Command:** `npx -y niffler-app-mcp`
92
+ - **Environment variable:** `NIFFLER_API_KEY` (required)
93
+ - **Transport:** stdio
94
+
95
+ ## Available Tools
96
+
97
+ ### Browse & Search
98
+
99
+ | Tool | Description |
100
+ |------|-------------|
101
+ | `list_categories` | List all your spaces with name, emoji, and type (list or planner) |
102
+ | `get_items` | List items in a category — filter by type, date, or completion |
103
+ | `get_dividers` | List sections within a category |
104
+ | `search` | Full-text search across all items |
105
+
106
+ ### Create
107
+
108
+ | Tool | Description |
109
+ |------|-------------|
110
+ | `create_category` | Create a new space (list for collections, planner for scheduling) |
111
+ | `create_bookmark` | Save a URL with title and description |
112
+ | `create_note` | Create a markdown note |
113
+ | `create_task` | Create a task with optional due date |
114
+ | `create_event` | Create an event with start/end dates |
115
+ | `create_divider` | Create a section separator to organize items |
116
+
117
+ ### Manage
118
+
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `update_item` | Update any item's title, description, URL, content, or due date |
122
+ | `complete_task` | Mark a task as completed or incomplete |
123
+ | `delete_item` | Permanently delete an item |
124
+
125
+ ### Utility
126
+
127
+ | Tool | Description |
128
+ |------|-------------|
129
+ | `health_check` | Verify API connectivity and authentication |
130
+
131
+ ## Data Model
132
+
133
+ The MCP server includes a built-in resource (`niffler://data-model`) that teaches your AI agent how Niffler works. The agent reads it automatically to make smart decisions about:
134
+
135
+ - **Category types** — `list` for collections and research, `planner` for scheduling and trips
136
+ - **Item types** — bookmarks (URLs), tasks (to-dos), events (calendar), notes (markdown), dividers (sections)
137
+ - **Organization** — how to use sections, date-based placement, and category structure
138
+
139
+ ## Configuration
140
+
141
+ | Variable | Required | Description |
142
+ |----------|----------|-------------|
143
+ | `NIFFLER_API_KEY` | Yes | Your Niffler API key (starts with `nif_`) |
144
+ | `NIFFLER_API_URL` | No | Custom API endpoint (defaults to Niffler production) |
145
+
146
+ ## Examples
147
+
148
+ Once connected, you can say things like:
149
+
150
+ - *"Save this article to my Reading List"*
151
+ - *"Create a task to review the PR by Friday in my Work space"*
152
+ - *"What bookmarks do I have about React?"*
153
+ - *"Set up a new trip planner for Tokyo with sections for Hotels, Restaurants, and Activities"*
154
+ - *"Show me my overdue tasks"*
155
+ - *"Write a note summarizing our meeting discussion"*
156
+
157
+ ## Requirements
158
+
159
+ - Node.js 18+
160
+ - A Niffler account with an API key (Pro or Early Adopter plan)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=niffler-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"niffler-mcp.d.ts","sourceRoot":"","sources":["../../bin/niffler-mcp.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "../src/index.js";
3
+ main();
4
+ //# sourceMappingURL=niffler-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"niffler-mcp.js","sourceRoot":"","sources":["../../bin/niffler-mcp.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,90 @@
1
+ import type { CategoriesResponse, ItemsResponse, DividersResponse, SearchResponse, CreateItemResponse, HealthResponse } from "./types.js";
2
+ export declare class NifflerClient {
3
+ private baseUrl;
4
+ private apiKey;
5
+ constructor(apiKey: string, baseUrl: string);
6
+ private request;
7
+ listCategories(group?: string): Promise<CategoriesResponse>;
8
+ createCategory(data: {
9
+ name: string;
10
+ emoji?: string;
11
+ view_type?: "list" | "planner";
12
+ color?: string;
13
+ description?: string;
14
+ }): Promise<{
15
+ success: boolean;
16
+ category: {
17
+ id: string;
18
+ };
19
+ message: string;
20
+ }>;
21
+ getItems(category: string, filters?: {
22
+ type?: "all" | "tasks" | "bookmarks" | "notes";
23
+ date?: string;
24
+ completed?: "true" | "false" | "all";
25
+ }): Promise<ItemsResponse>;
26
+ getDividers(category: string): Promise<DividersResponse>;
27
+ createBookmark(data: {
28
+ url: string;
29
+ title?: string;
30
+ description?: string;
31
+ category_name?: string;
32
+ category_id?: string;
33
+ after_divider?: string;
34
+ }): Promise<CreateItemResponse>;
35
+ createNote(data: {
36
+ title: string;
37
+ note_content: string;
38
+ category_name?: string;
39
+ category_id?: string;
40
+ after_divider?: string;
41
+ }): Promise<CreateItemResponse>;
42
+ createTask(data: {
43
+ title: string;
44
+ due_date?: string;
45
+ description?: string;
46
+ category_name?: string;
47
+ category_id?: string;
48
+ after_divider?: string;
49
+ }): Promise<CreateItemResponse>;
50
+ createEvent(data: {
51
+ title: string;
52
+ event_start_date: string;
53
+ event_end_date: string;
54
+ event_is_all_day?: boolean;
55
+ description?: string;
56
+ category_name?: string;
57
+ category_id?: string;
58
+ after_divider?: string;
59
+ }): Promise<CreateItemResponse>;
60
+ createDivider(data: {
61
+ title: string;
62
+ category_name?: string;
63
+ category_id?: string;
64
+ after_divider?: string;
65
+ }): Promise<CreateItemResponse>;
66
+ search(query: string, limit?: number): Promise<SearchResponse>;
67
+ updateItem(itemId: string, updates: {
68
+ title?: string;
69
+ description?: string | null;
70
+ url?: string | null;
71
+ note_content?: string | null;
72
+ due_date?: string | null;
73
+ divider_title?: string;
74
+ }): Promise<{
75
+ success: boolean;
76
+ message: string;
77
+ item_id: string;
78
+ }>;
79
+ completeTask(itemId: string, completed: boolean): Promise<{
80
+ success: boolean;
81
+ message: string;
82
+ item_id: string;
83
+ }>;
84
+ deleteItem(itemId: string): Promise<{
85
+ success: boolean;
86
+ message: string;
87
+ }>;
88
+ healthCheck(): Promise<HealthResponse>;
89
+ }
90
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;YAK7B,OAAO;IA2Bf,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAK3D,cAAc,CAAC,IAAI,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAKtE,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;QAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;KACtC,GACA,OAAO,CAAC,aAAa,CAAC;IAQnB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQxD,cAAc,CAAC,IAAI,EAAE;QACzB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIzB,UAAU,CAAC,IAAI,EAAE;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIzB,UAAU,CAAC,IAAI,EAAE;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIzB,WAAW,CAAC,IAAI,EAAE;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIzB,aAAa,CAAC,IAAI,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAKzB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,CAAC;IAKpB,UAAU,CACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GACA,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAI5D,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAO5D,UAAU,CACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAK3C,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;CAG7C"}
@@ -0,0 +1,85 @@
1
+ export class NifflerClient {
2
+ baseUrl;
3
+ apiKey;
4
+ constructor(apiKey, baseUrl) {
5
+ this.apiKey = apiKey;
6
+ this.baseUrl = baseUrl.replace(/\/$/, "");
7
+ }
8
+ async request(method, path, body) {
9
+ const url = `${this.baseUrl}${path}`;
10
+ const headers = {
11
+ "x-api-key": this.apiKey,
12
+ "Content-Type": "application/json",
13
+ };
14
+ const res = await fetch(url, {
15
+ method,
16
+ headers,
17
+ body: body ? JSON.stringify(body) : undefined,
18
+ });
19
+ const data = await res.json();
20
+ if (!res.ok || data.success === false) {
21
+ throw new Error(data.error || `API error: ${res.status}`);
22
+ }
23
+ return data;
24
+ }
25
+ // Categories
26
+ async listCategories(group) {
27
+ const params = group ? `?group=${encodeURIComponent(group)}` : "";
28
+ return this.request("GET", `/categories${params}`);
29
+ }
30
+ async createCategory(data) {
31
+ return this.request("POST", "/categories", data);
32
+ }
33
+ // Items
34
+ async getItems(category, filters) {
35
+ const params = new URLSearchParams({ category });
36
+ if (filters?.type)
37
+ params.set("type", filters.type);
38
+ if (filters?.date)
39
+ params.set("date", filters.date);
40
+ if (filters?.completed)
41
+ params.set("completed", filters.completed);
42
+ return this.request("GET", `/items?${params}`);
43
+ }
44
+ async getDividers(category) {
45
+ return this.request("GET", `/dividers?category=${encodeURIComponent(category)}`);
46
+ }
47
+ // Create items
48
+ async createBookmark(data) {
49
+ return this.request("POST", "/bookmarks", data);
50
+ }
51
+ async createNote(data) {
52
+ return this.request("POST", "/notes", data);
53
+ }
54
+ async createTask(data) {
55
+ return this.request("POST", "/tasks", data);
56
+ }
57
+ async createEvent(data) {
58
+ return this.request("POST", "/events", data);
59
+ }
60
+ async createDivider(data) {
61
+ return this.request("POST", "/dividers", data);
62
+ }
63
+ // Search
64
+ async search(query, limit) {
65
+ return this.request("POST", "/search", { query, limit });
66
+ }
67
+ // Update items
68
+ async updateItem(itemId, updates) {
69
+ return this.request("PATCH", `/items/${itemId}`, updates);
70
+ }
71
+ async completeTask(itemId, completed) {
72
+ return this.request("PATCH", `/items/${itemId}/complete`, {
73
+ is_completed: completed,
74
+ });
75
+ }
76
+ // Delete
77
+ async deleteItem(itemId) {
78
+ return this.request("DELETE", `/items/${itemId}`);
79
+ }
80
+ // Health
81
+ async healthCheck() {
82
+ return this.request("GET", "/health");
83
+ }
84
+ }
85
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function main(): Promise<void>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,wBAAsB,IAAI,kBAkBzB"}
@@ -0,0 +1,24 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { createServer } from "./server.js";
3
+ const DEFAULT_API_URL = "https://bnmfnuyxpempbsgoimcl.supabase.co/functions/v1/shortcuts-api";
4
+ export async function main() {
5
+ const apiKey = process.env.NIFFLER_API_KEY;
6
+ if (!apiKey) {
7
+ console.error("Error: NIFFLER_API_KEY environment variable is required.");
8
+ console.error("Get your API key from Niffler > Settings > API Keys.");
9
+ process.exit(1);
10
+ }
11
+ if (!apiKey.startsWith("nif_")) {
12
+ console.error('Error: NIFFLER_API_KEY must start with "nif_".');
13
+ process.exit(1);
14
+ }
15
+ const apiUrl = process.env.NIFFLER_API_URL || DEFAULT_API_URL;
16
+ const server = createServer(apiKey, apiUrl);
17
+ const transport = new StdioServerTransport();
18
+ await server.connect(transport);
19
+ }
20
+ main().catch((error) => {
21
+ console.error("Fatal error:", error instanceof Error ? error.message : "Unknown error");
22
+ process.exit(1);
23
+ });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,eAAe,GAAG,qEAAqE,CAAC;AAE9F,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAAC;IAE9D,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerDataModelResource(server: McpServer): void;
3
+ //# sourceMappingURL=data-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-model.d.ts","sourceRoot":"","sources":["../../../src/resources/data-model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4FpE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,QAmB1D"}
@@ -0,0 +1,104 @@
1
+ const DATA_MODEL_GUIDE = `# Niffler Data Model Guide
2
+
3
+ Niffler is an organizational tool for saving bookmarks, notes, tasks, and events into structured categories (called "spaces"). This guide helps you choose the right category type and item type.
4
+
5
+ ## Category Types
6
+
7
+ ### List (view_type: "list")
8
+ A vertical list of items, optionally organized into sections using dividers.
9
+
10
+ **Best for:**
11
+ - Bookmark collections (articles, tools, resources)
12
+ - Research notes
13
+ - Reading lists
14
+ - Shopping lists
15
+ - Reference material
16
+ - Any collection that doesn't need date-based scheduling
17
+
18
+ **Example categories:** "React Resources", "Recipes to Try", "Gift Ideas", "Meeting Notes"
19
+
20
+ ### Planner (view_type: "planner")
21
+ A calendar-based view showing items organized by date, with a 14-day lookahead and a "Someday" section for undated items.
22
+
23
+ **Best for:**
24
+ - Weekly task planning
25
+ - Trip itineraries (flights, hotels, activities by day)
26
+ - Project timelines
27
+ - Event scheduling
28
+ - Habit tracking
29
+ - Any collection where items have dates or deadlines
30
+
31
+ **Example categories:** "This Week", "Japan Trip", "Product Launch", "Workout Plan"
32
+
33
+ ## Item Types
34
+
35
+ ### Bookmark (Link)
36
+ A saved URL with optional title and description.
37
+ - **When to use:** Saving web pages, articles, tools, documentation, videos, any URL
38
+ - **Required:** url
39
+ - **Optional:** title (auto-detected), description
40
+
41
+ ### Task (Reminder)
42
+ An actionable item that can be marked complete.
43
+ - **When to use:** To-dos, action items, follow-ups, things to buy/do
44
+ - **Required:** title
45
+ - **Optional:** due_date (ISO 8601 UTC), description
46
+ - **Note:** In planner categories, tasks with due dates appear on the corresponding day. Tasks without dates go to "Someday".
47
+
48
+ ### Event
49
+ A time-bound occurrence with start and end dates.
50
+ - **When to use:** Meetings, flights, appointments, reservations, deadlines with specific times
51
+ - **Required:** title, event_start_date, event_end_date (both ISO 8601 UTC)
52
+ - **Optional:** event_is_all_day, description
53
+
54
+ ### Note
55
+ A markdown text document stored in Niffler.
56
+ - **When to use:** Summaries, research findings, meeting notes, ideas, any text content
57
+ - **Required:** title, note_content (markdown)
58
+ - **Note:** Supports full markdown: headings, lists, links, code blocks, bold, italic
59
+
60
+ ### Divider (Section)
61
+ A section separator that groups items within a category.
62
+ - **When to use:** Organizing items into named groups (e.g., "Restaurants" / "Hotels" / "Activities" in a travel category)
63
+ - **Required:** title (the section name)
64
+ - **Note:** When creating items, use the after_divider parameter to place them under a specific section
65
+
66
+ ## Organization Patterns
67
+
68
+ ### Flat list
69
+ Just add items to a category. Good for simple collections.
70
+
71
+ ### Sectioned list
72
+ Create dividers first, then add items under each section:
73
+ 1. create_divider("Restaurants", category: "Tokyo Trip")
74
+ 2. create_divider("Hotels", category: "Tokyo Trip")
75
+ 3. create_bookmark(url, after_divider: "Restaurants", category: "Tokyo Trip")
76
+
77
+ ### Planner with dates
78
+ Create items with due dates in a planner category:
79
+ 1. create_task("Pack bags", due_date: "2025-03-14T12:00:00Z", category: "Japan Trip")
80
+ 2. create_event("Flight to Tokyo", start: "2025-03-15T08:00:00Z", end: "2025-03-15T20:00:00Z", category: "Japan Trip")
81
+
82
+ ## API Conventions
83
+ - Category names are matched case-insensitively
84
+ - If a category doesn't exist and you use category_name, some endpoints auto-create it
85
+ - Dates must be ISO 8601 UTC (ending in Z)
86
+ - Use list_categories first to see existing spaces
87
+ - Use get_dividers to see a category's structure before adding items
88
+ - Item IDs are UUIDs — get them from get_items or search results
89
+ `;
90
+ export function registerDataModelResource(server) {
91
+ server.resource("data-model", "niffler://data-model", {
92
+ description: "Guide to Niffler's data model: category types (list vs planner), item types (bookmark, task, event, note, divider), and organization patterns. Read this first to understand how to structure content in Niffler.",
93
+ mimeType: "text/markdown",
94
+ }, async () => ({
95
+ contents: [
96
+ {
97
+ uri: "niffler://data-model",
98
+ mimeType: "text/markdown",
99
+ text: DATA_MODEL_GUIDE,
100
+ },
101
+ ],
102
+ }));
103
+ }
104
+ //# sourceMappingURL=data-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-model.js","sourceRoot":"","sources":["../../../src/resources/data-model.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwFxB,CAAC;AAEF,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,sBAAsB,EACtB;QACE,WAAW,EACT,mNAAmN;QACrN,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,sBAAsB;gBAC3B,QAAQ,EAAE,eAAe;gBACzB,IAAI,EAAE,gBAAgB;aACvB;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(apiKey: string, apiUrl: string): McpServer;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAkBtE"}
@@ -0,0 +1,23 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { NifflerClient } from "./client.js";
3
+ import { registerCategoryTools } from "./tools/categories.js";
4
+ import { registerItemCreationTools } from "./tools/items.js";
5
+ import { registerReadTools } from "./tools/read.js";
6
+ import { registerManageTools } from "./tools/manage.js";
7
+ import { registerDataModelResource } from "./resources/data-model.js";
8
+ export function createServer(apiKey, apiUrl) {
9
+ const server = new McpServer({
10
+ name: "Niffler",
11
+ version: "1.0.0",
12
+ });
13
+ const client = new NifflerClient(apiKey, apiUrl);
14
+ // Register all tools
15
+ registerCategoryTools(server, client);
16
+ registerItemCreationTools(server, client);
17
+ registerReadTools(server, client);
18
+ registerManageTools(server, client);
19
+ // Register resources
20
+ registerDataModelResource(server);
21
+ return server;
22
+ }
23
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,MAAc;IACzD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjD,qBAAqB;IACrB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpC,qBAAqB;IACrB,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { NifflerClient } from "../client.js";
3
+ export declare function registerCategoryTools(server: McpServer, client: NifflerClient): void;
4
+ //# sourceMappingURL=categories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../../src/tools/categories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,QA0E7E"}
@@ -0,0 +1,55 @@
1
+ import { z } from "zod";
2
+ export function registerCategoryTools(server, client) {
3
+ server.tool("list_categories", "List all Niffler spaces/categories. Returns name, emoji, view type (list or planner), and group. Use this first to see what exists before creating items.", {
4
+ group: z
5
+ .string()
6
+ .optional()
7
+ .describe('Filter by group name. Use "All" for all categories, or a specific group name.'),
8
+ }, async ({ group }) => {
9
+ const data = await client.listCategories(group);
10
+ const lines = data.categories.map((c) => `${c.emoji} ${c.name} (${c.view_type})${c.group_name ? ` [${c.group_name}]` : ""}`);
11
+ return {
12
+ content: [
13
+ {
14
+ type: "text",
15
+ text: `Found ${data.categories.length} categories:\n\n${lines.join("\n")}\n\n${data.has_groups
16
+ ? `Groups: ${data.groups.join(", ")}`
17
+ : "No groups configured."}`,
18
+ },
19
+ ],
20
+ };
21
+ });
22
+ server.tool("create_category", "Create a new Niffler space/category. Use 'list' for collections, bookmarks, research notes. Use 'planner' for scheduling, tasks with dates, events, trip planning.", {
23
+ name: z.string().describe("Category name (e.g. 'Travel Research', 'Weekly Tasks')"),
24
+ emoji: z
25
+ .string()
26
+ .optional()
27
+ .describe("Emoji icon for the category (e.g. '✈️', '📋'). Defaults to '📁'."),
28
+ view_type: z
29
+ .enum(["list", "planner"])
30
+ .optional()
31
+ .describe("Category type. 'list' for collections/bookmarks/notes. 'planner' for calendar-based tasks/events. Defaults to 'list'."),
32
+ color: z
33
+ .string()
34
+ .optional()
35
+ .describe("Hex color for the category (e.g. '#6366f1'). Optional."),
36
+ description: z.string().optional().describe("Short description of the category. Optional."),
37
+ }, async ({ name, emoji, view_type, color, description }) => {
38
+ const data = await client.createCategory({
39
+ name,
40
+ emoji,
41
+ view_type,
42
+ color,
43
+ description,
44
+ });
45
+ return {
46
+ content: [
47
+ {
48
+ type: "text",
49
+ text: `Created category "${name}" (${view_type || "list"}) with ID: ${data.category.id}`,
50
+ },
51
+ ],
52
+ };
53
+ });
54
+ }
55
+ //# sourceMappingURL=categories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories.js","sourceRoot":"","sources":["../../../src/tools/categories.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAqB;IAC5E,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,2JAA2J,EAC3J;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,+EAA+E,CAChF;KACJ,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAC/B,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrF,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,SAAS,IAAI,CAAC,UAAU,CAAC,MAAM,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OACtE,IAAI,CAAC,UAAU;wBACb,CAAC,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;wBACrC,CAAC,CAAC,uBACN,EAAE;iBACH;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,oKAAoK,EACpK;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;QACnF,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kEAAkE,CAAC;QAC/E,SAAS,EAAE,CAAC;aACT,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;aACzB,QAAQ,EAAE;aACV,QAAQ,CACP,uHAAuH,CACxH;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KAC5F,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;YACvC,IAAI;YACJ,KAAK;YACL,SAAS;YACT,KAAK;YACL,WAAW;SACZ,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,qBAAqB,IAAI,MAAM,SAAS,IAAI,MAAM,cAAc,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;iBACzF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { NifflerClient } from "../client.js";
3
+ export declare function registerItemCreationTools(server: McpServer, client: NifflerClient): void;
4
+ //# sourceMappingURL=items.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../../src/tools/items.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,QAqNjF"}
@@ -0,0 +1,169 @@
1
+ import { z } from "zod";
2
+ export function registerItemCreationTools(server, client) {
3
+ server.tool("create_bookmark", "Save a URL/link to Niffler. Best for web pages, articles, tools, resources. The bookmark is saved to the specified category (or default if none given).", {
4
+ url: z.string().describe("The URL to bookmark"),
5
+ title: z.string().optional().describe("Title for the bookmark. Auto-detected if omitted."),
6
+ description: z.string().optional().describe("Short description or note about this link"),
7
+ category_name: z
8
+ .string()
9
+ .optional()
10
+ .describe("Category name to save into. Creates the category if it doesn't exist."),
11
+ category_id: z.string().optional().describe("Category ID (alternative to category_name)"),
12
+ after_divider: z
13
+ .string()
14
+ .optional()
15
+ .describe("Place the bookmark after this section/divider name. Use 'Top of category' for the top."),
16
+ }, async ({ url, title, description, category_name, category_id, after_divider }) => {
17
+ const data = await client.createBookmark({
18
+ url,
19
+ title,
20
+ description,
21
+ category_name,
22
+ category_id,
23
+ after_divider,
24
+ });
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: `Bookmark saved: ${title || url} (ID: ${data.bookmark?.id})`,
30
+ },
31
+ ],
32
+ };
33
+ });
34
+ server.tool("create_note", "Create a markdown note in Niffler. Best for text content, summaries, research notes, meeting notes, ideas. Supports full markdown.", {
35
+ title: z.string().describe("Note title"),
36
+ note_content: z
37
+ .string()
38
+ .describe("Markdown content for the note. Supports headings, lists, links, code blocks, etc."),
39
+ category_name: z
40
+ .string()
41
+ .optional()
42
+ .describe("Category name to save into. Creates the category if it doesn't exist."),
43
+ category_id: z.string().optional().describe("Category ID (alternative to category_name)"),
44
+ after_divider: z
45
+ .string()
46
+ .optional()
47
+ .describe("Place the note after this section/divider name."),
48
+ }, async ({ title, note_content, category_name, category_id, after_divider }) => {
49
+ const data = await client.createNote({
50
+ title,
51
+ note_content,
52
+ category_name,
53
+ category_id,
54
+ after_divider,
55
+ });
56
+ return {
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: `Note created: "${title}" (ID: ${data.note?.id})`,
61
+ },
62
+ ],
63
+ };
64
+ });
65
+ server.tool("create_task", "Create a task/reminder in Niffler. Best for action items, to-dos, things to follow up on. Optionally set a due date. Works great in planner categories.", {
66
+ title: z.string().describe("Task description (e.g. 'Review PR #42', 'Buy groceries')"),
67
+ due_date: z
68
+ .string()
69
+ .optional()
70
+ .describe("Due date in ISO 8601 format (e.g. '2025-03-15T12:00:00Z'). For planner categories, this determines which day it appears on."),
71
+ description: z.string().optional().describe("Additional details about the task"),
72
+ category_name: z
73
+ .string()
74
+ .optional()
75
+ .describe("Category name to save into. Creates the category if it doesn't exist."),
76
+ category_id: z.string().optional().describe("Category ID (alternative to category_name)"),
77
+ after_divider: z
78
+ .string()
79
+ .optional()
80
+ .describe("Place the task after this section/divider name."),
81
+ }, async ({ title, due_date, description, category_name, category_id, after_divider }) => {
82
+ const data = await client.createTask({
83
+ title,
84
+ due_date,
85
+ description,
86
+ category_name,
87
+ category_id,
88
+ after_divider,
89
+ });
90
+ return {
91
+ content: [
92
+ {
93
+ type: "text",
94
+ text: `Task created: "${title}"${due_date ? ` (due: ${due_date})` : ""} (ID: ${data.task?.id})`,
95
+ },
96
+ ],
97
+ };
98
+ });
99
+ server.tool("create_event", "Create a calendar event in Niffler. Best for meetings, appointments, scheduled activities. Requires start and end dates. Works great in planner categories.", {
100
+ title: z.string().describe("Event title (e.g. 'Team standup', 'Flight to NYC')"),
101
+ event_start_date: z
102
+ .string()
103
+ .describe("Event start date/time in ISO 8601 UTC (e.g. '2025-03-15T09:00:00Z')"),
104
+ event_end_date: z
105
+ .string()
106
+ .describe("Event end date/time in ISO 8601 UTC (e.g. '2025-03-15T10:00:00Z')"),
107
+ event_is_all_day: z
108
+ .boolean()
109
+ .optional()
110
+ .describe("Whether this is an all-day event. Defaults to false."),
111
+ description: z.string().optional().describe("Additional details about the event"),
112
+ category_name: z
113
+ .string()
114
+ .optional()
115
+ .describe("Category name to save into. Creates the category if it doesn't exist."),
116
+ category_id: z.string().optional().describe("Category ID (alternative to category_name)"),
117
+ after_divider: z
118
+ .string()
119
+ .optional()
120
+ .describe("Place the event after this section/divider name."),
121
+ }, async ({ title, event_start_date, event_end_date, event_is_all_day, description, category_name, category_id, after_divider, }) => {
122
+ const data = await client.createEvent({
123
+ title,
124
+ event_start_date,
125
+ event_end_date,
126
+ event_is_all_day,
127
+ description,
128
+ category_name,
129
+ category_id,
130
+ after_divider,
131
+ });
132
+ return {
133
+ content: [
134
+ {
135
+ type: "text",
136
+ text: `Event created: "${title}" (${event_start_date} → ${event_end_date}) (ID: ${data.event?.id})`,
137
+ },
138
+ ],
139
+ };
140
+ });
141
+ server.tool("create_divider", "Create a section divider in a Niffler category. Dividers organize items into named groups within a category. For example: 'Restaurants', 'Hotels', 'Activities' in a travel category.", {
142
+ title: z.string().describe("Section name (e.g. 'Restaurants', 'Day 1', 'High Priority')"),
143
+ category_name: z
144
+ .string()
145
+ .optional()
146
+ .describe("Category name to create the divider in."),
147
+ category_id: z.string().optional().describe("Category ID (alternative to category_name)"),
148
+ after_divider: z
149
+ .string()
150
+ .optional()
151
+ .describe("Place this divider after an existing divider."),
152
+ }, async ({ title, category_name, category_id, after_divider }) => {
153
+ const data = await client.createDivider({
154
+ title,
155
+ category_name,
156
+ category_id,
157
+ after_divider,
158
+ });
159
+ return {
160
+ content: [
161
+ {
162
+ type: "text",
163
+ text: `Divider created: "${title}" (ID: ${data.divider?.id})`,
164
+ },
165
+ ],
166
+ };
167
+ });
168
+ }
169
+ //# sourceMappingURL=items.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"items.js","sourceRoot":"","sources":["../../../src/tools/items.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,yBAAyB,CAAC,MAAiB,EAAE,MAAqB;IAChF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,yJAAyJ,EACzJ;QACE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QAC1F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QACxF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uEAAuE,CAAC;QACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,wFAAwF,CACzF;KACJ,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,EAAE;QAC/E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;YACvC,GAAG;YACH,KAAK;YACL,WAAW;YACX,aAAa;YACb,WAAW;YACX,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,mBAAmB,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG;iBACnE;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,oIAAoI,EACpI;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QACxC,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,CAAC,mFAAmF,CAAC;QAChG,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uEAAuE,CAAC;QACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,iDAAiD,CAAC;KAC/D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,EAAE;QAC3E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACnC,KAAK;YACL,YAAY;YACZ,aAAa;YACb,WAAW;YACX,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,kBAAkB,KAAK,UAAU,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG;iBACxD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,yJAAyJ,EACzJ;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0DAA0D,CAAC;QACtF,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,6HAA6H,CAC9H;QACH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAChF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uEAAuE,CAAC;QACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,iDAAiD,CAAC;KAC/D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,EAAE;QACpF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACnC,KAAK;YACL,QAAQ;YACR,WAAW;YACX,aAAa;YACb,WAAW;YACX,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,kBAAkB,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,UAAU,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG;iBAChG;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,6JAA6J,EAC7J;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QAChF,gBAAgB,EAAE,CAAC;aAChB,MAAM,EAAE;aACR,QAAQ,CAAC,qEAAqE,CAAC;QAClF,cAAc,EAAE,CAAC;aACd,MAAM,EAAE;aACR,QAAQ,CAAC,mEAAmE,CAAC;QAChF,gBAAgB,EAAE,CAAC;aAChB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,sDAAsD,CAAC;QACnE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACjF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uEAAuE,CAAC;QACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;KAChE,EACD,KAAK,EAAE,EACL,KAAK,EACL,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,WAAW,EACX,aAAa,GACd,EAAE,EAAE;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;YACpC,KAAK;YACL,gBAAgB;YAChB,cAAc;YACd,gBAAgB;YAChB,WAAW;YACX,aAAa;YACb,WAAW;YACX,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,mBAAmB,KAAK,MAAM,gBAAgB,MAAM,cAAc,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG;iBACpG;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,uLAAuL,EACvL;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yCAAyC,CAAC;QACtD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACzF,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,+CAA+C,CAAC;KAC7D,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,EAAE;QAC7D,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;YACtC,KAAK;YACL,aAAa;YACb,WAAW;YACX,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,qBAAqB,KAAK,UAAU,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG;iBAC9D;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { NifflerClient } from "../client.js";
3
+ export declare function registerManageTools(server: McpServer, client: NifflerClient): void;
4
+ //# sourceMappingURL=manage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../../src/tools/manage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,QA8F3E"}
@@ -0,0 +1,82 @@
1
+ import { z } from "zod";
2
+ export function registerManageTools(server, client) {
3
+ server.tool("update_item", "Update an existing Niffler item. Can change title, description, URL, note content, due date, or divider title. Get the item ID from list_items or search first.", {
4
+ item_id: z.string().uuid().describe("The item's UUID (get this from get_items or search)"),
5
+ title: z.string().optional().describe("New title"),
6
+ description: z
7
+ .string()
8
+ .nullable()
9
+ .optional()
10
+ .describe("New description (or null to clear)"),
11
+ url: z
12
+ .string()
13
+ .nullable()
14
+ .optional()
15
+ .describe("New URL (or null to clear). Only for bookmark items."),
16
+ note_content: z
17
+ .string()
18
+ .nullable()
19
+ .optional()
20
+ .describe("New markdown content (or null to clear). Only for note items."),
21
+ due_date: z
22
+ .string()
23
+ .nullable()
24
+ .optional()
25
+ .describe("New due date in ISO 8601 (or null to clear). Only for task items."),
26
+ divider_title: z
27
+ .string()
28
+ .optional()
29
+ .describe("New section/divider title. Only for divider items."),
30
+ }, async ({ item_id, title, description, url, note_content, due_date, divider_title }) => {
31
+ const updates = {};
32
+ if (title !== undefined)
33
+ updates.title = title;
34
+ if (description !== undefined)
35
+ updates.description = description;
36
+ if (url !== undefined)
37
+ updates.url = url;
38
+ if (note_content !== undefined)
39
+ updates.note_content = note_content;
40
+ if (due_date !== undefined)
41
+ updates.due_date = due_date;
42
+ if (divider_title !== undefined)
43
+ updates.divider_title = divider_title;
44
+ const data = await client.updateItem(item_id, updates);
45
+ return {
46
+ content: [
47
+ {
48
+ type: "text",
49
+ text: `Item updated: ${data.item_id} — ${Object.keys(updates).join(", ")} changed.`,
50
+ },
51
+ ],
52
+ };
53
+ });
54
+ server.tool("complete_task", "Mark a task as completed or uncompleted in Niffler. Get the task ID from get_items or search first.", {
55
+ item_id: z.string().uuid().describe("The task's UUID"),
56
+ completed: z.boolean().describe("true to mark complete, false to mark incomplete"),
57
+ }, async ({ item_id, completed }) => {
58
+ await client.completeTask(item_id, completed);
59
+ return {
60
+ content: [
61
+ {
62
+ type: "text",
63
+ text: `Task ${item_id} marked as ${completed ? "completed ✅" : "incomplete ☐"}.`,
64
+ },
65
+ ],
66
+ };
67
+ });
68
+ server.tool("delete_item", "Permanently delete an item from Niffler. This cannot be undone. Get the item ID from get_items or search first.", {
69
+ item_id: z.string().uuid().describe("The item's UUID to delete"),
70
+ }, async ({ item_id }) => {
71
+ await client.deleteItem(item_id);
72
+ return {
73
+ content: [
74
+ {
75
+ type: "text",
76
+ text: `Item ${item_id} deleted permanently.`,
77
+ },
78
+ ],
79
+ };
80
+ });
81
+ }
82
+ //# sourceMappingURL=manage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.js","sourceRoot":"","sources":["../../../src/tools/manage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { NifflerClient } from "../client.js";
3
+ export declare function registerReadTools(server: McpServer, client: NifflerClient): void;
4
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,QAuJzE"}
@@ -0,0 +1,130 @@
1
+ import { z } from "zod";
2
+ export function registerReadTools(server, client) {
3
+ server.tool("get_items", "List items in a Niffler category. Returns bookmarks, tasks, notes, and events. Filter by type, date, or completion status.", {
4
+ category: z.string().describe("Category name (case-insensitive match)"),
5
+ type: z
6
+ .enum(["all", "tasks", "bookmarks", "notes"])
7
+ .optional()
8
+ .describe("Filter by item type. Defaults to 'all'."),
9
+ date: z
10
+ .string()
11
+ .optional()
12
+ .describe("Filter by date: 'today', 'tomorrow', 'someday' (no date), or a specific date 'YYYY-MM-DD'. Useful for planner categories."),
13
+ completed: z
14
+ .enum(["true", "false", "all"])
15
+ .optional()
16
+ .describe("Filter tasks by completion: 'true', 'false', or 'all'. Defaults to 'all'."),
17
+ }, async ({ category, type, date, completed }) => {
18
+ const data = await client.getItems(category, { type, date, completed });
19
+ if (data.items.length === 0) {
20
+ return {
21
+ content: [
22
+ {
23
+ type: "text",
24
+ text: `No items found in "${data.category_name}"${type ? ` (type: ${type})` : ""}${date ? ` (date: ${date})` : ""}.`,
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ const lines = data.items.map((item) => {
30
+ const prefix = item.type === "task"
31
+ ? item.is_completed
32
+ ? "✅"
33
+ : "☐"
34
+ : item.type === "event"
35
+ ? "📅"
36
+ : item.type === "note"
37
+ ? "📝"
38
+ : "🔗";
39
+ let line = `${prefix} ${item.title}`;
40
+ if (item.url)
41
+ line += ` — ${item.url}`;
42
+ if (item.due_date)
43
+ line += ` (due: ${item.due_date})`;
44
+ if (item.description)
45
+ line += `\n ${item.description}`;
46
+ line += ` [id: ${item.id}]`;
47
+ return line;
48
+ });
49
+ return {
50
+ content: [
51
+ {
52
+ type: "text",
53
+ text: `${data.category_name} — ${data.count} items:\n\n${lines.join("\n")}`,
54
+ },
55
+ ],
56
+ };
57
+ });
58
+ server.tool("get_dividers", "List sections/dividers in a Niffler category. For list categories, returns section names. For planner categories, returns the next 14 days. Use this to understand category structure before adding items.", {
59
+ category: z.string().describe("Category name (case-insensitive match)"),
60
+ }, async ({ category }) => {
61
+ const data = await client.getDividers(category);
62
+ if (data.is_calendar) {
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: `"${data.category_name}" is a planner category.\nAvailable date slots:\n${data.names.join("\n")}`,
68
+ },
69
+ ],
70
+ };
71
+ }
72
+ if (!data.has_dividers) {
73
+ return {
74
+ content: [
75
+ {
76
+ type: "text",
77
+ text: `"${data.category_name}" has no sections/dividers. Items are in a flat list.`,
78
+ },
79
+ ],
80
+ };
81
+ }
82
+ return {
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: `"${data.category_name}" sections:\n${data.names.join("\n")}`,
87
+ },
88
+ ],
89
+ };
90
+ });
91
+ server.tool("search", "Full-text search across all Niffler items (bookmarks, notes, tasks, events). Searches titles, descriptions, URLs, and note content.", {
92
+ query: z.string().describe("Search query text"),
93
+ limit: z
94
+ .number()
95
+ .optional()
96
+ .describe("Max results to return (1-50, default 10)"),
97
+ }, async ({ query, limit }) => {
98
+ const data = await client.search(query, limit);
99
+ if (data.results.length === 0) {
100
+ return {
101
+ content: [
102
+ {
103
+ type: "text",
104
+ text: `No results found for "${query}".`,
105
+ },
106
+ ],
107
+ };
108
+ }
109
+ const lines = data.results.map((r) => {
110
+ let line = `${r.category_emoji || "📁"} [${r.category_name}] ${r.title}`;
111
+ if (r.url)
112
+ line += ` — ${r.url}`;
113
+ if (r.type === "task")
114
+ line += r.is_completed ? " ✅" : " ☐";
115
+ if (r.due_date)
116
+ line += ` (due: ${r.due_date})`;
117
+ line += ` [id: ${r.id}]`;
118
+ return line;
119
+ });
120
+ return {
121
+ content: [
122
+ {
123
+ type: "text",
124
+ text: `Found ${data.results.length} results for "${query}":\n\n${lines.join("\n")}`,
125
+ },
126
+ ],
127
+ };
128
+ });
129
+ }
130
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/tools/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ export interface Category {
2
+ id: string;
3
+ name: string;
4
+ emoji: string;
5
+ color: string;
6
+ description: string | null;
7
+ group_name: string | null;
8
+ view_type: "list" | "planner";
9
+ }
10
+ export interface Item {
11
+ id: string;
12
+ title: string;
13
+ url?: string;
14
+ description?: string;
15
+ note_content?: string;
16
+ due_date?: string;
17
+ is_completed: boolean;
18
+ type: "bookmark" | "task" | "note" | "event";
19
+ event_start_date?: string;
20
+ event_end_date?: string;
21
+ event_is_all_day?: boolean;
22
+ created_at: string;
23
+ }
24
+ export interface Divider {
25
+ id: string;
26
+ name: string;
27
+ sort_order: number;
28
+ }
29
+ export interface SearchResult extends Item {
30
+ category_name: string;
31
+ category_emoji: string;
32
+ score: number;
33
+ }
34
+ export interface ApiResponse<T = unknown> {
35
+ success: boolean;
36
+ error?: string;
37
+ [key: string]: T | boolean | string | undefined;
38
+ }
39
+ export interface CategoriesResponse {
40
+ success: boolean;
41
+ categories: Category[];
42
+ names: string[];
43
+ groups: string[];
44
+ has_groups: boolean;
45
+ }
46
+ export interface ItemsResponse {
47
+ success: boolean;
48
+ category_name: string;
49
+ count: number;
50
+ items: Item[];
51
+ }
52
+ export interface DividersResponse {
53
+ success: boolean;
54
+ category_id: string;
55
+ category_name: string;
56
+ is_calendar: boolean;
57
+ dividers?: Divider[];
58
+ names: string[];
59
+ has_dividers: boolean;
60
+ }
61
+ export interface SearchResponse {
62
+ success: boolean;
63
+ query: string;
64
+ results: SearchResult[];
65
+ }
66
+ export interface CreateItemResponse {
67
+ success: boolean;
68
+ bookmark?: {
69
+ id: string;
70
+ };
71
+ note?: {
72
+ id: string;
73
+ };
74
+ task?: {
75
+ id: string;
76
+ };
77
+ event?: {
78
+ id: string;
79
+ };
80
+ divider?: {
81
+ id: string;
82
+ };
83
+ message?: string;
84
+ }
85
+ export interface HealthResponse {
86
+ success: boolean;
87
+ message: string;
88
+ user_id: string;
89
+ }
90
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "niffler-app-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Niffler – save, organize, and retrieve bookmarks, notes, tasks, and events via AI agents",
5
+ "type": "module",
6
+ "main": "./dist/src/index.js",
7
+ "bin": {
8
+ "niffler-mcp": "dist/bin/niffler-mcp.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/bin/niffler-mcp.js"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.12.1",
17
+ "zod": "^3.23.0"
18
+ },
19
+ "devDependencies": {
20
+ "typescript": "^5.5.0",
21
+ "@types/node": "^20.0.0"
22
+ },
23
+ "engines": {
24
+ "node": ">=18.0.0"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "keywords": [
30
+ "mcp",
31
+ "niffler",
32
+ "bookmarks",
33
+ "ai-agent",
34
+ "claude"
35
+ ],
36
+ "license": "MIT"
37
+ }