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.
- package/README.md +160 -0
- package/dist/bin/niffler-mcp.d.ts +3 -0
- package/dist/bin/niffler-mcp.d.ts.map +1 -0
- package/dist/bin/niffler-mcp.js +4 -0
- package/dist/bin/niffler-mcp.js.map +1 -0
- package/dist/src/client.d.ts +90 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/client.js +85 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +24 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/resources/data-model.d.ts +3 -0
- package/dist/src/resources/data-model.d.ts.map +1 -0
- package/dist/src/resources/data-model.js +104 -0
- package/dist/src/resources/data-model.js.map +1 -0
- package/dist/src/server.d.ts +3 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +23 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tools/categories.d.ts +4 -0
- package/dist/src/tools/categories.d.ts.map +1 -0
- package/dist/src/tools/categories.js +55 -0
- package/dist/src/tools/categories.js.map +1 -0
- package/dist/src/tools/items.d.ts +4 -0
- package/dist/src/tools/items.d.ts.map +1 -0
- package/dist/src/tools/items.js +169 -0
- package/dist/src/tools/items.js.map +1 -0
- package/dist/src/tools/manage.d.ts +4 -0
- package/dist/src/tools/manage.d.ts.map +1 -0
- package/dist/src/tools/manage.js +82 -0
- package/dist/src/tools/manage.js.map +1 -0
- package/dist/src/tools/read.d.ts +4 -0
- package/dist/src/tools/read.d.ts.map +1 -0
- package/dist/src/tools/read.js +130 -0
- package/dist/src/tools/read.js.map +1 -0
- package/dist/src/types.d.ts +90 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"niffler-mcp.d.ts","sourceRoot":"","sources":["../../bin/niffler-mcp.ts"],"names":[],"mappings":""}
|
|
@@ -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":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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 @@
|
|
|
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":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CACjD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,KAAK,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -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
|
+
}
|