note-mcp-server 2.2.5 → 2.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/index.js +66 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,6 +110,7 @@ socialite_id=eyJpdiI6I…
|
|
|
110
110
|
| `create_note` | POST 新增,`content` 必填,`title` 可選 |
|
|
111
111
|
| `update_note` | POST 修改,`c_id` 必填,支援 `content`、`title`、`append`、`prepend` |
|
|
112
112
|
| `delete_note` | POST 刪除,`c_id` + `action=delete` |
|
|
113
|
+
| `tag` | GET 搜尋,根據標籤名稱找出筆記內容 |
|
|
113
114
|
| `upload_image` | multipart,`image_base64`、可選 `filename` |
|
|
114
115
|
| `send_push` | POST 推播,`message` 必填,`title` / `url` 可選 |
|
|
115
116
|
|
|
@@ -123,6 +124,19 @@ socialite_id=eyJpdiI6I…
|
|
|
123
124
|
|
|
124
125
|
---
|
|
125
126
|
|
|
127
|
+
## Agent 安全流程(重要)
|
|
128
|
+
|
|
129
|
+
- 只要使用者貼出或提到敏感設定(例如 `key`、`token`、`NOTES_API_BASE`、`socialite_id`),完成設定或操作後,代理必須主動執行:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
echo -n "" | pbcopy
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- 回覆中必須明確告知「剪貼簿已清空」。
|
|
136
|
+
- 此流程屬於預設安全規範,不需等待使用者額外提醒。
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
126
140
|
## 常見問題
|
|
127
141
|
|
|
128
142
|
### 啟動失敗、訊息請建立 `.env`
|
package/index.js
CHANGED
|
@@ -76,7 +76,7 @@ const APP_NAME = firstEnv("app_name", "APP_NAME", "notes_app_name", "NOTES_APP_N
|
|
|
76
76
|
const server = new Server(
|
|
77
77
|
{
|
|
78
78
|
name: `note-mcp-server (${APP_NAME})`,
|
|
79
|
-
version: "2.2.
|
|
79
|
+
version: "2.2.8",
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
capabilities: {
|
|
@@ -120,6 +120,13 @@ function resolveNotesSiteBase() {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const NOTES_SITE_BASE = resolveNotesSiteBase();
|
|
123
|
+
const SECURITY_NOTICE =
|
|
124
|
+
"安全規範:若使用者訊息或設定包含 key、token、NOTES_API_BASE、socialite_id 等敏感資訊,完成操作後必須主動清空 macOS 剪貼簿(echo -n \"\" | pbcopy),並在回覆中明確告知已清空。";
|
|
125
|
+
const NOTE_URL_NOTICE = `前台連結格式:${NOTES_SITE_BASE}/app/notes/content/{c_id}。`;
|
|
126
|
+
|
|
127
|
+
function withSecurityNotice(description) {
|
|
128
|
+
return `${description}\n${NOTE_URL_NOTICE}\n${SECURITY_NOTICE}`;
|
|
129
|
+
}
|
|
123
130
|
|
|
124
131
|
function buildNoteUrl(cId) {
|
|
125
132
|
if (cId === undefined || cId === null || String(cId).trim() === "") {
|
|
@@ -133,7 +140,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
133
140
|
tools: [
|
|
134
141
|
{
|
|
135
142
|
name: "list_notes",
|
|
136
|
-
description:
|
|
143
|
+
description: withSecurityNotice(
|
|
144
|
+
`列出或搜尋 ${APP_NAME} 中的筆記。支援關鍵字、標籤搜尋及分頁(預設每頁 10 筆)。回傳資料會附上 note_url。`
|
|
145
|
+
),
|
|
137
146
|
inputSchema: {
|
|
138
147
|
type: "object",
|
|
139
148
|
properties: {
|
|
@@ -146,7 +155,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
146
155
|
},
|
|
147
156
|
{
|
|
148
157
|
name: "read_note",
|
|
149
|
-
description:
|
|
158
|
+
description: withSecurityNotice(
|
|
159
|
+
`從 ${APP_NAME} 讀取單筆筆記(GET ?c_id=)。亦可傳 c_id=last 讀取最新一筆。回傳資料會附上 note_url。`
|
|
160
|
+
),
|
|
150
161
|
inputSchema: {
|
|
151
162
|
type: "object",
|
|
152
163
|
properties: {
|
|
@@ -160,9 +171,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
160
171
|
},
|
|
161
172
|
{
|
|
162
173
|
name: "create_note",
|
|
163
|
-
description:
|
|
164
|
-
`在 ${APP_NAME} 中新增筆記。內容請優先使用簡潔的 AdminLTE 4 card
|
|
165
|
-
|
|
174
|
+
description: withSecurityNotice(
|
|
175
|
+
`在 ${APP_NAME} 中新增筆記。內容請優先使用簡潔的 AdminLTE 4 card 結構。`
|
|
176
|
+
),
|
|
166
177
|
inputSchema: {
|
|
167
178
|
type: "object",
|
|
168
179
|
properties: {
|
|
@@ -174,7 +185,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
174
185
|
},
|
|
175
186
|
{
|
|
176
187
|
name: "update_note",
|
|
177
|
-
description:
|
|
188
|
+
description: withSecurityNotice(
|
|
189
|
+
`在 ${APP_NAME} 中修改筆記。內容請優先使用簡潔的 AdminLTE 4 card 結構,避免嵌套破版,支援以 append/prepend 追加內容。`
|
|
190
|
+
),
|
|
178
191
|
inputSchema: {
|
|
179
192
|
type: "object",
|
|
180
193
|
properties: {
|
|
@@ -189,7 +202,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
189
202
|
},
|
|
190
203
|
{
|
|
191
204
|
name: "delete_note",
|
|
192
|
-
description: "刪除筆記(POST:c_id + action=delete)。",
|
|
205
|
+
description: withSecurityNotice("刪除筆記(POST:c_id + action=delete)。"),
|
|
193
206
|
inputSchema: {
|
|
194
207
|
type: "object",
|
|
195
208
|
properties: {
|
|
@@ -198,10 +211,24 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
198
211
|
required: ["c_id"],
|
|
199
212
|
},
|
|
200
213
|
},
|
|
214
|
+
{
|
|
215
|
+
name: "tag",
|
|
216
|
+
description: withSecurityNotice(
|
|
217
|
+
"根據標籤搜尋筆記內容。例如:tag 待辨。"
|
|
218
|
+
),
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: "object",
|
|
221
|
+
properties: {
|
|
222
|
+
name: { type: "string", description: "標籤名稱,例如:待辨" },
|
|
223
|
+
},
|
|
224
|
+
required: ["name"],
|
|
225
|
+
},
|
|
226
|
+
},
|
|
201
227
|
{
|
|
202
228
|
name: "upload_image",
|
|
203
|
-
description:
|
|
204
|
-
`將圖片上傳至 ${APP_NAME}。此工具會回傳圖片的永久網址(URL)。若用戶要求生成圖片及內容,請務必分兩步執行:1. 先呼叫此工具傳圖獲取網址;2. 將獲取的網址以 <img> 標籤補進筆記內容(create_note 或 update_note
|
|
229
|
+
description: withSecurityNotice(
|
|
230
|
+
`將圖片上傳至 ${APP_NAME}。此工具會回傳圖片的永久網址(URL)。若用戶要求生成圖片及內容,請務必分兩步執行:1. 先呼叫此工具傳圖獲取網址;2. 將獲取的網址以 <img> 標籤補進筆記內容(create_note 或 update_note)中。`
|
|
231
|
+
),
|
|
205
232
|
inputSchema: {
|
|
206
233
|
type: "object",
|
|
207
234
|
properties: {
|
|
@@ -219,7 +246,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
219
246
|
},
|
|
220
247
|
{
|
|
221
248
|
name: "send_push",
|
|
222
|
-
description:
|
|
249
|
+
description: withSecurityNotice(
|
|
250
|
+
"發送 Web Push(POST:action=push、message;可選 title、url)。"
|
|
251
|
+
),
|
|
223
252
|
inputSchema: {
|
|
224
253
|
type: "object",
|
|
225
254
|
properties: {
|
|
@@ -341,6 +370,32 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
341
370
|
],
|
|
342
371
|
};
|
|
343
372
|
}
|
|
373
|
+
case "tag": {
|
|
374
|
+
const params = {
|
|
375
|
+
tag: args.name,
|
|
376
|
+
limit: args.limit || 10,
|
|
377
|
+
};
|
|
378
|
+
const response = await axios.get(BASE_URL, { params });
|
|
379
|
+
const payload =
|
|
380
|
+
response.data && typeof response.data === "object"
|
|
381
|
+
? { ...response.data }
|
|
382
|
+
: response.data;
|
|
383
|
+
|
|
384
|
+
const notes = normalizeListPayload(payload);
|
|
385
|
+
if (Array.isArray(notes)) {
|
|
386
|
+
for (const note of notes) {
|
|
387
|
+
if (note && typeof note === "object" && note.c_id !== undefined) {
|
|
388
|
+
note.note_url = buildNoteUrl(note.c_id);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
content: [
|
|
395
|
+
{ type: "text", text: JSON.stringify(payload, null, 2) },
|
|
396
|
+
],
|
|
397
|
+
};
|
|
398
|
+
}
|
|
344
399
|
|
|
345
400
|
case "upload_image": {
|
|
346
401
|
let b64 = String(args.image_base64).replace(/\s/g, "");
|
package/package.json
CHANGED