note-mcp 1.1.1 → 1.2.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 +103 -13
- package/dist/index.js +72 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,16 +5,72 @@ Unofficial stdio MCP server for note.com. It uses cookie-based access to note.co
|
|
|
5
5
|
> [!WARNING]
|
|
6
6
|
> This project is unofficial and not affiliated with note.com. Internal APIs can change without notice. Keep cookies local and never commit them to GitHub, npm, logs, or issue reports.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Quick start
|
|
9
|
+
|
|
10
|
+
### Local/desktop agents
|
|
11
|
+
|
|
12
|
+
Use browser login first:
|
|
9
13
|
|
|
10
14
|
```bash
|
|
11
|
-
npx note-mcp
|
|
15
|
+
npx note-mcp auth
|
|
12
16
|
```
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
After you log in to note.com in the opened browser, `note-mcp` saves the cookie locally and prints the saved file path:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"authenticated": true,
|
|
23
|
+
"saved": true,
|
|
24
|
+
"configPath": "/Users/you/.config/note-mcp/config.json",
|
|
25
|
+
"cookiePreview": "fp=b…5948",
|
|
26
|
+
"message": "note.com authentication configured from browser login. Cookie saved to /Users/you/.config/note-mcp/config.json."
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then configure your MCP client without putting cookies in the config:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"note": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["-y", "note-mcp"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Some MCP clients only load newly added tools when a process or conversation starts. After authentication or config changes, restart the client or open a new thread/session if `note_*` tools do not appear immediately.
|
|
44
|
+
|
|
45
|
+
Quick setup check:
|
|
46
|
+
|
|
47
|
+
1. `npx note-mcp auth`
|
|
48
|
+
2. `npx note-mcp auth --status`
|
|
49
|
+
3. Add `npx -y note-mcp` to your MCP client config
|
|
50
|
+
4. Restart the client or open a new thread/session
|
|
51
|
+
5. Run `note_auth_status` from the MCP client
|
|
52
|
+
|
|
53
|
+
### Servers, containers, and CI
|
|
54
|
+
|
|
55
|
+
Do not rely on browser login in headless/container environments. Provide a cookie through env or a mounted config file instead:
|
|
15
56
|
|
|
16
57
|
```bash
|
|
17
|
-
NOTE_COOKIE='your note.com
|
|
58
|
+
NOTE_COOKIE='your note.com Cookie header' npx note-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or mount a config file and point `NOTE_MCP_CONFIG` at it:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
docker run \
|
|
65
|
+
-v ~/.config/note-mcp/config.json:/run/secrets/note-mcp-config.json:ro \
|
|
66
|
+
-e NOTE_MCP_CONFIG=/run/secrets/note-mcp-config.json \
|
|
67
|
+
your-agent-image
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Install / run
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx note-mcp
|
|
18
74
|
```
|
|
19
75
|
|
|
20
76
|
For local development:
|
|
@@ -27,7 +83,7 @@ node dist/index.js
|
|
|
27
83
|
|
|
28
84
|
## MCP client configuration
|
|
29
85
|
|
|
30
|
-
|
|
86
|
+
Recommended desktop setup after `npx note-mcp auth`:
|
|
31
87
|
|
|
32
88
|
```json
|
|
33
89
|
{
|
|
@@ -49,13 +105,33 @@ Advanced env-based setup:
|
|
|
49
105
|
"command": "npx",
|
|
50
106
|
"args": ["-y", "note-mcp"],
|
|
51
107
|
"env": {
|
|
52
|
-
"NOTE_COOKIE": "your note.com
|
|
108
|
+
"NOTE_COOKIE": "your note.com Cookie header"
|
|
53
109
|
}
|
|
54
110
|
}
|
|
55
111
|
}
|
|
56
112
|
}
|
|
57
113
|
```
|
|
58
114
|
|
|
115
|
+
### Codex CLI
|
|
116
|
+
|
|
117
|
+
For Codex, add `note-mcp` as a stdio MCP server with `npx`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
codex mcp add note -- npx -y note-mcp
|
|
121
|
+
codex mcp list
|
|
122
|
+
npx -y note-mcp auth --status
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Recommended verification flow:
|
|
126
|
+
|
|
127
|
+
1. `npx note-mcp auth`
|
|
128
|
+
2. `npx note-mcp auth --status`
|
|
129
|
+
3. `codex mcp add note -- npx -y note-mcp`
|
|
130
|
+
4. Restart Codex or create a new thread
|
|
131
|
+
5. Run `note_auth_status`
|
|
132
|
+
|
|
133
|
+
If the server is listed but `note_*` tools are not available in the current thread, restart Codex or start a new thread so the MCP tools are loaded from the new configuration.
|
|
134
|
+
|
|
59
135
|
## Authentication
|
|
60
136
|
|
|
61
137
|
`note-mcp` supports two authentication paths.
|
|
@@ -78,6 +154,8 @@ This opens a browser, lets you log in to note.com normally, then stores note.com
|
|
|
78
154
|
~/.config/note-mcp/config.json
|
|
79
155
|
```
|
|
80
156
|
|
|
157
|
+
The CLI and MCP tool response include the actual `configPath` used.
|
|
158
|
+
|
|
81
159
|
If the browser executable is not installed yet, install Playwright's Chromium once on the same machine/user account, then retry:
|
|
82
160
|
|
|
83
161
|
```bash
|
|
@@ -92,8 +170,6 @@ npx -p playwright playwright install chromium
|
|
|
92
170
|
|
|
93
171
|
For remote servers, containers, or CI, prefer the secret/env/config-file path below instead of browser login.
|
|
94
172
|
|
|
95
|
-
The config file is written with `0600` permissions where supported.
|
|
96
|
-
|
|
97
173
|
Useful CLI commands:
|
|
98
174
|
|
|
99
175
|
```bash
|
|
@@ -105,7 +181,7 @@ npx note-mcp auth --headed
|
|
|
105
181
|
|
|
106
182
|
### 2. Advanced/server/CI: secret, env, or config file
|
|
107
183
|
|
|
108
|
-
For remote agents, servers, CI, and secret managers, provide a Cookie header via:
|
|
184
|
+
For remote agents, servers, containers, CI, and secret managers, provide a Cookie header via:
|
|
109
185
|
|
|
110
186
|
- `NOTE_COOKIE`
|
|
111
187
|
- `NOTE_SESSION_COOKIE`
|
|
@@ -127,12 +203,24 @@ Cookie lookup priority:
|
|
|
127
203
|
2. `NOTE_SESSION_COOKIE`
|
|
128
204
|
3. config file cookie
|
|
129
205
|
|
|
206
|
+
Default config path:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
~/.config/note-mcp/config.json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Override config path:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
NOTE_MCP_CONFIG=/path/to/config.json npx note-mcp
|
|
216
|
+
```
|
|
217
|
+
|
|
130
218
|
## Tools
|
|
131
219
|
|
|
132
220
|
Authentication/setup tools:
|
|
133
221
|
|
|
134
|
-
- `note_auth_status` — inspect whether auth is configured
|
|
135
|
-
- `note_auth_login` — open a browser login flow and save cookies locally
|
|
222
|
+
- `note_auth_status` — inspect whether auth is configured and which config path is used
|
|
223
|
+
- `note_auth_login` — open a browser login flow and save cookies locally; response includes `configPath`
|
|
136
224
|
- `note_set_cookie` — save a Cookie header to the local config file, optionally verifying it first
|
|
137
225
|
- `note_clear_cookie` — delete the stored config-file cookie
|
|
138
226
|
- `note_login_help` — explain supported setup paths
|
|
@@ -140,7 +228,7 @@ Authentication/setup tools:
|
|
|
140
228
|
note.com tools:
|
|
141
229
|
|
|
142
230
|
- `note_auth_check` — verify configured cookie-based access to note.com internal APIs
|
|
143
|
-
- `note_list_my_notes` — list
|
|
231
|
+
- `note_list_my_notes` — list creator contents for the authenticated account via `GET /v2/creators/info/contents?kind=note&page={page}`. By default returns the full internal API payload. For LLM-friendly list views, pass `fields: "summary"` or `includeBody: false` to return summary fields such as `title`, `key`, `url`, `publishAt`, `status`, and `likeCount`.
|
|
144
232
|
- `note_list_drafts` — list drafts for the authenticated account
|
|
145
233
|
- `note_get_note` — fetch a note by note key, e.g. `n1a0b26f944f4`
|
|
146
234
|
- `note_create_draft` — create a draft
|
|
@@ -158,10 +246,12 @@ Known endpoint basis:
|
|
|
158
246
|
|
|
159
247
|
- Base URL: `https://note.com/api`
|
|
160
248
|
- Note detail: `GET /v3/notes/{noteKey}`
|
|
161
|
-
-
|
|
249
|
+
- Authenticated creator contents: `GET /v2/creators/info/contents?kind=note&page=1`
|
|
162
250
|
- Draft save: `POST /v1/text_notes/draft_save?id={draftId}`
|
|
163
251
|
- Auth smoke test: `GET /v3/notice_counts`
|
|
164
252
|
|
|
253
|
+
`note_list_my_notes` intentionally exposes the authenticated creator contents endpoint above. The exact visibility and shape are determined by note.com's internal API response for the configured cookie; use the default full response when debugging endpoint behavior, and use summary mode when a compact list is enough.
|
|
254
|
+
|
|
165
255
|
## Release
|
|
166
256
|
|
|
167
257
|
Releases are handled by GitHub Actions + semantic-release.
|
package/dist/index.js
CHANGED
|
@@ -131,8 +131,12 @@ var NoteClient = class {
|
|
|
131
131
|
async authCheck() {
|
|
132
132
|
return this.request("/v3/notice_counts");
|
|
133
133
|
}
|
|
134
|
-
async listMyNotes(page = 1) {
|
|
135
|
-
|
|
134
|
+
async listMyNotes(page = 1, options = {}) {
|
|
135
|
+
const payload = await this.request(`/v2/creators/info/contents?kind=note&page=${page}`);
|
|
136
|
+
if (options.fields === "summary" || options.includeBody === false) {
|
|
137
|
+
return summarizeListPayload(payload);
|
|
138
|
+
}
|
|
139
|
+
return payload;
|
|
136
140
|
}
|
|
137
141
|
async listDrafts(page = 1) {
|
|
138
142
|
return this.request(`/v2/creators/info/contents?kind=draft&page=${page}`);
|
|
@@ -181,6 +185,54 @@ var NoteClient = class {
|
|
|
181
185
|
return body;
|
|
182
186
|
}
|
|
183
187
|
};
|
|
188
|
+
function summarizeListPayload(payload) {
|
|
189
|
+
if (!isJsonObject(payload)) return payload;
|
|
190
|
+
if (isJsonObject(payload.data) && Array.isArray(payload.data.contents)) {
|
|
191
|
+
return {
|
|
192
|
+
...payload,
|
|
193
|
+
data: {
|
|
194
|
+
...payload.data,
|
|
195
|
+
contents: payload.data.contents.map(summarizeNoteItem)
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (Array.isArray(payload.contents)) {
|
|
200
|
+
return {
|
|
201
|
+
...payload,
|
|
202
|
+
contents: payload.contents.map(summarizeNoteItem)
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return payload;
|
|
206
|
+
}
|
|
207
|
+
function summarizeNoteItem(item) {
|
|
208
|
+
if (!isJsonObject(item)) return item;
|
|
209
|
+
const key = firstString(item.key, item.noteKey, item.id);
|
|
210
|
+
return omitUndefined({
|
|
211
|
+
key,
|
|
212
|
+
title: firstString(item.title, item.name),
|
|
213
|
+
url: firstString(item.url, item.noteUrl, item.note_url, item.path) ?? noteUrl(key),
|
|
214
|
+
publishAt: firstDefined(item.publishAt, item.publish_at, item.publishedAt, item.published_at),
|
|
215
|
+
status: item.status,
|
|
216
|
+
likeCount: firstDefined(item.likeCount, item.like_count)
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
function firstDefined(...values) {
|
|
220
|
+
return values.find((value) => value !== void 0);
|
|
221
|
+
}
|
|
222
|
+
function firstString(...values) {
|
|
223
|
+
return values.find((value) => typeof value === "string" && value.length > 0);
|
|
224
|
+
}
|
|
225
|
+
function noteUrl(key) {
|
|
226
|
+
return key ? `https://note.com/notes/${key}` : void 0;
|
|
227
|
+
}
|
|
228
|
+
function omitUndefined(record) {
|
|
229
|
+
return Object.fromEntries(
|
|
230
|
+
Object.entries(record).filter((entry) => entry[1] !== void 0)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
function isJsonObject(value) {
|
|
234
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
235
|
+
}
|
|
184
236
|
async function parseBody(response) {
|
|
185
237
|
const text = await response.text();
|
|
186
238
|
if (!text) return null;
|
|
@@ -222,15 +274,9 @@ async function runBrowserLogin(options = {}) {
|
|
|
222
274
|
const client = new NoteClient({ cookie });
|
|
223
275
|
try {
|
|
224
276
|
await client.authCheck();
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return {
|
|
229
|
-
authenticated: true,
|
|
230
|
-
saved: options.save ?? true,
|
|
231
|
-
cookiePreview: previewCookie2(cookie),
|
|
232
|
-
message: "note.com authentication configured from browser login."
|
|
233
|
-
};
|
|
277
|
+
const shouldSave = options.save ?? true;
|
|
278
|
+
const saveStatus = shouldSave ? await saveCookie(cookie) : void 0;
|
|
279
|
+
return buildBrowserLoginResult(cookie, shouldSave, saveStatus);
|
|
234
280
|
} catch {
|
|
235
281
|
}
|
|
236
282
|
}
|
|
@@ -250,6 +296,16 @@ async function importPlaywright() {
|
|
|
250
296
|
);
|
|
251
297
|
}
|
|
252
298
|
}
|
|
299
|
+
function buildBrowserLoginResult(cookie, saved, saveStatus) {
|
|
300
|
+
const configPath = saveStatus?.configPath;
|
|
301
|
+
return {
|
|
302
|
+
authenticated: true,
|
|
303
|
+
saved,
|
|
304
|
+
...configPath ? { configPath } : {},
|
|
305
|
+
cookiePreview: saveStatus?.cookiePreview ?? previewCookie2(cookie),
|
|
306
|
+
message: configPath ? `note.com authentication configured from browser login. Cookie saved to ${configPath}.` : "note.com authentication configured from browser login."
|
|
307
|
+
};
|
|
308
|
+
}
|
|
253
309
|
function toBrowserLoginError(error) {
|
|
254
310
|
const message = error instanceof Error ? error.message : String(error);
|
|
255
311
|
if (message.includes("Executable doesn't exist") || message.includes("Please run the following command to download new browsers") || message.includes("playwright install")) {
|
|
@@ -393,12 +449,14 @@ async function runMcpServer() {
|
|
|
393
449
|
"note_list_my_notes",
|
|
394
450
|
{
|
|
395
451
|
title: "List my note.com notes",
|
|
396
|
-
description:
|
|
452
|
+
description: 'Lists creator contents for the authenticated note.com account via GET /v2/creators/info/contents?kind=note. By default returns the full internal API payload; pass fields: "summary" or includeBody: false for a lightweight list with title/key/url/publishAt/status/likeCount.',
|
|
397
453
|
inputSchema: {
|
|
398
|
-
page: z.number().int().positive().default(1)
|
|
454
|
+
page: z.number().int().positive().default(1),
|
|
455
|
+
fields: z.enum(["full", "summary"]).default("full"),
|
|
456
|
+
includeBody: z.boolean().optional()
|
|
399
457
|
}
|
|
400
458
|
},
|
|
401
|
-
async ({ page }) => withClient((client) => client.listMyNotes(page))
|
|
459
|
+
async ({ page, fields, includeBody }) => withClient((client) => client.listMyNotes(page, { fields, includeBody }))
|
|
402
460
|
);
|
|
403
461
|
server.registerTool(
|
|
404
462
|
"note_list_drafts",
|