note-mcp 1.1.2 → 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.
Files changed (3) hide show
  1. package/README.md +34 -2
  2. package/dist/index.js +59 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -40,6 +40,16 @@ Then configure your MCP client without putting cookies in the config:
40
40
  }
41
41
  ```
42
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
+
43
53
  ### Servers, containers, and CI
44
54
 
45
55
  Do not rely on browser login in headless/container environments. Provide a cookie through env or a mounted config file instead:
@@ -102,6 +112,26 @@ Advanced env-based setup:
102
112
  }
103
113
  ```
104
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
+
105
135
  ## Authentication
106
136
 
107
137
  `note-mcp` supports two authentication paths.
@@ -198,7 +228,7 @@ Authentication/setup tools:
198
228
  note.com tools:
199
229
 
200
230
  - `note_auth_check` — verify configured cookie-based access to note.com internal APIs
201
- - `note_list_my_notes` — list notes for the authenticated account
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`.
202
232
  - `note_list_drafts` — list drafts for the authenticated account
203
233
  - `note_get_note` — fetch a note by note key, e.g. `n1a0b26f944f4`
204
234
  - `note_create_draft` — create a draft
@@ -216,10 +246,12 @@ Known endpoint basis:
216
246
 
217
247
  - Base URL: `https://note.com/api`
218
248
  - Note detail: `GET /v3/notes/{noteKey}`
219
- - Own contents: `GET /v2/creators/info/contents?kind=note&page=1`
249
+ - Authenticated creator contents: `GET /v2/creators/info/contents?kind=note&page=1`
220
250
  - Draft save: `POST /v1/text_notes/draft_save?id={draftId}`
221
251
  - Auth smoke test: `GET /v3/notice_counts`
222
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
+
223
255
  ## Release
224
256
 
225
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
- return this.request(`/v2/creators/info/contents?kind=note&page=${page}`);
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;
@@ -397,12 +449,14 @@ async function runMcpServer() {
397
449
  "note_list_my_notes",
398
450
  {
399
451
  title: "List my note.com notes",
400
- description: "Lists notes for the authenticated note.com account.",
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.',
401
453
  inputSchema: {
402
- 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()
403
457
  }
404
458
  },
405
- async ({ page }) => withClient((client) => client.listMyNotes(page))
459
+ async ({ page, fields, includeBody }) => withClient((client) => client.listMyNotes(page, { fields, includeBody }))
406
460
  );
407
461
  server.registerTool(
408
462
  "note_list_drafts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "note-mcp",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Unofficial stdio MCP server for note.com using cookie-based internal APIs.",
5
5
  "type": "module",
6
6
  "bin": {