rote-toolkit 0.3.3 → 0.4.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 CHANGED
@@ -1,79 +1,103 @@
1
+ <p align="right">English | <a href="./README.zh-CN.md">中文</a></p>
2
+
1
3
  # Rote Toolkit
2
4
 
3
- Rote Toolkit 是一个基于 TypeScript 的增强工具包,主要用于在终端或 AI Agents 侧连接和增强你的 [Rote](https://rote.ink) 笔记系统。基于 Rote OpenKey API 授权,即插即用,无需繁复的登录流程。
5
+ Rote Toolkit is a TypeScript toolkit for connecting to and extending your [Rote](https://rote.ink) note system from terminal workflows and AI agents. It uses the Rote OpenKey API for simple, reusable authentication.
6
+
7
+ Main project repository: [`Rabithua/rote`](https://github.com/Rabithua/rote).
4
8
 
5
- ## 特性
9
+ ## Features
6
10
 
7
- - **CLI 模式**:通过终端快速记笔记、搜索笔记。
8
- - **MCP 模式**:作为 Model Context Protocol 服务端,让 AI (Claude/Cursor) 能够安全、规范地读写 Rote 笔记。
9
- - **无感鉴权**:只需一次配置 OpenKey 即可长期使用。
11
+ - **CLI mode**: quickly create and search notes from terminal.
12
+ - **MCP mode**: run as a Model Context Protocol server so AI tools (Claude/Cursor/VS Code) can safely read and write Rote notes.
13
+ - **Simple auth**: configure OpenKey once and reuse it.
10
14
 
11
- ## 安装
15
+ ## Install
12
16
 
13
- > 要求 Node.js v18 或更高版本。
17
+ > Node.js v18 or higher is required.
14
18
 
15
19
  ```bash
16
20
  npm install -g rote-toolkit
17
21
  ```
18
22
 
19
- ## 配置鉴权
23
+ ## Configure Auth
20
24
 
21
- 运行以下命令进行全局配置:
25
+ Run this command once:
22
26
 
23
27
  ```bash
24
28
  rote config
25
29
  ```
26
30
 
27
- 系统会提示你输入:
31
+ You will be prompted for:
28
32
 
29
- 1. **Rote API URL**:例如 `https://your-rote-domain.com`
30
- 2. **OpenKey**:你的 API 密钥
33
+ 1. **Rote API URL**: for example `https://your-rote-domain.com`
34
+ 2. **OpenKey**: your API key
31
35
 
32
- 凭证会保存在本地:`~/.rote-toolkit/config.json`。
36
+ Credentials are stored at: `~/.rote-toolkit/config.json`.
33
37
 
34
- ## CLI 模式使用指南
38
+ ## CLI Usage
35
39
 
36
- ### 1) 快速记录笔记
40
+ ### 1) Create a note
37
41
 
38
42
  ```bash
39
- rote add "今天学到了 MCP 协议,非常有趣!"
43
+ rote add "Today I learned MCP and it is great"
40
44
  ```
41
45
 
42
- 附带标签、设为公开并置顶:
46
+ Add tags, publish as public, and pin:
43
47
 
44
48
  ```bash
45
- rote add "实现了一个新的前端组件" -t "代码,前端,React" --public --pin
49
+ rote add "Built a new frontend component" -t "code,frontend,React" --public --pin
46
50
  ```
47
51
 
48
- ### 2) 搜索和获取笔记
52
+ ### 2) Search and list notes
49
53
 
50
- 搜索包含 "MCP" 的笔记:
54
+ Search notes containing `MCP`:
51
55
 
52
56
  ```bash
53
57
  rote search "MCP"
54
58
  ```
55
59
 
56
- 获取最近的笔记(支持过滤归档和标签):
60
+ List recent notes (with archive/tag filters):
61
+
62
+ ```bash
63
+ rote list --limit 5 --archived -t "knowledge"
64
+ ```
65
+
66
+ List explore notes (no auth required):
57
67
 
58
68
  ```bash
59
- rote list --limit 5 --archived -t "知识管理"
69
+ rote explore --limit 5
60
70
  ```
61
71
 
62
- ## MCP 模式使用指南
72
+ ## MCP Usage
63
73
 
64
- 启动 MCP Server:
74
+ ### Do I need pre-installation?
75
+
76
+ No.
77
+ If you configure MCP with `npx` or `bunx`, the package is downloaded and run automatically when the MCP server starts.
78
+
79
+ Global install is only needed when you want to run commands directly on your machine:
65
80
 
66
81
  ```bash
67
- rote mcp
82
+ npm install -g rote-toolkit
83
+ ```
84
+
85
+ ### 1) Configure credentials first (one time)
86
+
87
+ ```bash
88
+ rote config
68
89
  ```
69
90
 
70
- 或独立命令:
91
+ ### 2) Manual local start (optional, for debugging)
92
+
93
+ These two commands are equivalent:
71
94
 
72
95
  ```bash
96
+ rote mcp
73
97
  rote-mcp
74
98
  ```
75
99
 
76
- ### Claude Desktop / VS Code 配置示例(推荐)
100
+ ### 3) Claude Desktop example
77
101
 
78
102
  ```json
79
103
  {
@@ -86,28 +110,42 @@ rote-mcp
86
110
  }
87
111
  ```
88
112
 
89
- 使用 Bun 也可以:
113
+ ### 4) VS Code example
90
114
 
91
115
  ```json
92
116
  {
93
- "mcpServers": {
117
+ "servers": {
94
118
  "rote-toolkit": {
119
+ "type": "stdio",
95
120
  "command": "bunx",
96
- "args": ["-y", "rote-toolkit@latest", "rote-mcp"]
121
+ "args": ["-y", "--package", "rote-toolkit@latest", "rote-mcp"]
97
122
  }
98
123
  }
99
124
  }
100
125
  ```
101
126
 
102
- ### AI 可使用的能力 (Tools)
127
+ ### Version strategy
128
+
129
+ - Track latest: `rote-toolkit@latest`
130
+ - Reproducible setup: pin a version, for example `rote-toolkit@0.3.3`
131
+
132
+ ### Common errors
133
+
134
+ - `could not determine executable to run`: usually incorrect `npx` args, use `-p rote-toolkit@... rote-mcp`.
135
+ - `unknown command 'rote-mcp'` (bunx): include `--package`, for example `bunx -y --package rote-toolkit@latest rote-mcp`.
136
+
137
+ ### Available AI Tools
103
138
 
104
139
  - `rote_create_note`
140
+ - `rote_update_note`
141
+ - `rote_delete_note`
105
142
  - `rote_search_notes`
106
143
  - `rote_list_notes`
144
+ - `rote_explore_notes`
107
145
 
108
- ## 本地开发
146
+ ## Local Development
109
147
 
110
- [text](../../../Downloads/API-KEY-GUIDE.md)
148
+ [API Key Usage Guide](./API-KEY-GUIDE.md)
111
149
 
112
150
  ```bash
113
151
  npm install
@@ -115,31 +153,31 @@ npm run build
115
153
  npm run dev -- --help
116
154
  ```
117
155
 
118
- ## 发布到 npm
156
+ ## Publish to npm
119
157
 
120
- 首次发布前先登录:
158
+ Login first:
121
159
 
122
160
  ```bash
123
161
  npm login
124
162
  ```
125
163
 
126
- 自动构建 + 自动升级版本 + 发布:
164
+ Build + bump version + publish:
127
165
 
128
166
  ```bash
129
167
  npm run release:patch
130
168
  ```
131
169
 
132
- 也支持:
170
+ Also available:
133
171
 
134
172
  ```bash
135
173
  npm run release:minor
136
174
  npm run release:major
137
175
  ```
138
176
 
139
- 发布脚本会执行:
177
+ Release script steps:
140
178
 
141
- 1. 检查 git 工作区是否干净
142
- 2. 检查 npm 登录状态
179
+ 1. Ensure git workspace is clean
180
+ 2. Check npm login state
143
181
  3. `npm run build`
144
182
  4. `npm pack --dry-run`
145
183
  5. `npm version <patch|minor|major>`
@@ -0,0 +1,184 @@
1
+ <p align="right"><a href="./README.md">English</a> | 中文</p>
2
+
3
+ # Rote Toolkit
4
+
5
+ Rote Toolkit 是一个基于 TypeScript 的增强工具包,主要用于在终端或 AI Agents 侧连接和增强你的 [Rote](https://rote.ink) 笔记系统。基于 Rote OpenKey API 授权,即插即用,无需繁复的登录流程。
6
+
7
+ 主项目仓库:[`Rabithua/rote`](https://github.com/Rabithua/rote)。
8
+
9
+ ## 特性
10
+
11
+ - **CLI 模式**:通过终端快速记笔记、搜索笔记。
12
+ - **MCP 模式**:作为 Model Context Protocol 服务端,让 AI (Claude/Cursor) 能够安全、规范地读写 Rote 笔记。
13
+ - **无感鉴权**:只需一次配置 OpenKey 即可长期使用。
14
+
15
+ ## 安装
16
+
17
+ > 要求 Node.js v18 或更高版本。
18
+
19
+ ```bash
20
+ npm install -g rote-toolkit
21
+ ```
22
+
23
+ ## 配置鉴权
24
+
25
+ 运行以下命令进行全局配置:
26
+
27
+ ```bash
28
+ rote config
29
+ ```
30
+
31
+ 系统会提示你输入:
32
+
33
+ 1. **Rote API URL**:例如 `https://your-rote-domain.com`
34
+ 2. **OpenKey**:你的 API 密钥
35
+
36
+ 凭证会保存在本地:`~/.rote-toolkit/config.json`。
37
+
38
+ ## CLI 模式使用指南
39
+
40
+ ### 1) 快速记录笔记
41
+
42
+ ```bash
43
+ rote add "今天学到了 MCP 协议,非常有趣!"
44
+ ```
45
+
46
+ 附带标签、设为公开并置顶:
47
+
48
+ ```bash
49
+ rote add "实现了一个新的前端组件" -t "代码,前端,React" --public --pin
50
+ ```
51
+
52
+ ### 2) 搜索和获取笔记
53
+
54
+ 搜索包含 "MCP" 的笔记:
55
+
56
+ ```bash
57
+ rote search "MCP"
58
+ ```
59
+
60
+ 获取最近的笔记(支持过滤归档和标签):
61
+
62
+ ```bash
63
+ rote list --limit 5 --archived -t "知识管理"
64
+ ```
65
+
66
+ 获取探索页面的笔记(无需配置 OpenKey):
67
+
68
+ ```bash
69
+ rote explore --limit 5
70
+ ```
71
+
72
+ ## MCP 模式使用指南
73
+
74
+ ### 是否需要提前安装?
75
+
76
+ 不需要。
77
+ 在 VS Code / Claude Desktop 里使用 `npx` 或 `bunx` 配置时,会在启动 MCP Server 时自动下载并运行 `rote-toolkit`。
78
+
79
+ 仅当你希望本机直接运行命令时,才需要全局安装:
80
+
81
+ ```bash
82
+ npm install -g rote-toolkit
83
+ ```
84
+
85
+ ### 1) 先完成凭证配置(一次即可)
86
+
87
+ ```bash
88
+ rote config
89
+ ```
90
+
91
+ ### 2) 本机手动启动(可选,用于调试)
92
+
93
+ 以下两条命令等价:
94
+
95
+ ```bash
96
+ rote mcp
97
+ rote-mcp
98
+ ```
99
+
100
+ ### 3) Claude Desktop 配置示例
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "rote-toolkit": {
106
+ "command": "npx",
107
+ "args": ["-y", "-p", "rote-toolkit@latest", "rote-mcp"]
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### 4) VS Code 配置示例
114
+
115
+ ```json
116
+ {
117
+ "servers": {
118
+ "rote-toolkit": {
119
+ "type": "stdio",
120
+ "command": "bunx",
121
+ "args": ["-y", "--package", "rote-toolkit@latest", "rote-mcp"]
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### 版本建议
128
+
129
+ - 追踪最新版:`rote-toolkit@latest`
130
+ - 需要稳定可复现:固定版本号,例如 `rote-toolkit@0.3.3`
131
+
132
+ ### 常见问题
133
+
134
+ - 报错 `could not determine executable to run`:通常是 `npx` 参数写法不对,确认使用 `-p rote-toolkit@... rote-mcp`。
135
+ - 报错 `unknown command 'rote-mcp'`(bunx):需要 `--package`,例如 `bunx -y --package rote-toolkit@latest rote-mcp`。
136
+
137
+ ### AI 可使用的能力 (Tools)
138
+
139
+ - `rote_create_note`
140
+ - `rote_update_note`
141
+ - `rote_delete_note`
142
+ - `rote_search_notes`
143
+ - `rote_list_notes`
144
+ - `rote_explore_notes`
145
+
146
+ ## 本地开发
147
+
148
+ [API Key Usage Guide](./API-KEY-GUIDE.md)
149
+
150
+ ```bash
151
+ npm install
152
+ npm run build
153
+ npm run dev -- --help
154
+ ```
155
+
156
+ ## 发布到 npm
157
+
158
+ 首次发布前先登录:
159
+
160
+ ```bash
161
+ npm login
162
+ ```
163
+
164
+ 自动构建 + 自动升级版本 + 发布:
165
+
166
+ ```bash
167
+ npm run release:patch
168
+ ```
169
+
170
+ 也支持:
171
+
172
+ ```bash
173
+ npm run release:minor
174
+ npm run release:major
175
+ ```
176
+
177
+ 发布脚本会执行:
178
+
179
+ 1. 检查 git 工作区是否干净
180
+ 2. 检查 npm 登录状态
181
+ 3. `npm run build`
182
+ 4. `npm pack --dry-run`
183
+ 5. `npm version <patch|minor|major>`
184
+ 6. `npm publish`
package/dist/api.d.ts CHANGED
@@ -1,11 +1,14 @@
1
- import type { AddReactionInput, CreateArticleInput, CreateNoteInput, ListNotesInput, RemoveReactionInput, RemoveReactionResponse, RoteArticle, RoteNote, RotePermissions, RoteProfile, RoteReaction, SearchNotesInput, ToolkitConfig, UpdateProfileInput } from "./types.js";
1
+ import type { AddReactionInput, CreateArticleInput, CreateNoteInput, ExploreNotesInput, ListNotesInput, RemoveReactionInput, RemoveReactionResponse, RoteArticle, RoteNote, RotePermissions, RoteProfile, RoteReaction, SearchNotesInput, ToolkitConfig, UpdateNoteInput, UpdateProfileInput } from "./types.js";
2
2
  export declare class RoteClient {
3
3
  private readonly apiUrl;
4
4
  private readonly openKey;
5
5
  constructor(config?: ToolkitConfig);
6
6
  createNote(input: CreateNoteInput): Promise<RoteNote>;
7
+ updateNote(input: UpdateNoteInput): Promise<RoteNote>;
8
+ deleteNote(noteId: string): Promise<unknown>;
7
9
  searchNotes(input: SearchNotesInput): Promise<RoteNote[]>;
8
10
  listNotes(input?: ListNotesInput): Promise<RoteNote[]>;
11
+ exploreNotes(input?: ExploreNotesInput): Promise<RoteNote[]>;
9
12
  createArticle(input: CreateArticleInput): Promise<RoteArticle>;
10
13
  addReaction(input: AddReactionInput): Promise<RoteReaction>;
11
14
  removeReaction(input: RemoveReactionInput): Promise<RemoveReactionResponse>;
package/dist/api.js CHANGED
@@ -26,6 +26,59 @@ export class RoteClient {
26
26
  body: JSON.stringify(body),
27
27
  });
28
28
  }
29
+ async updateNote(input) {
30
+ const noteId = input.noteId?.trim();
31
+ if (!noteId) {
32
+ throw new Error("noteId is required");
33
+ }
34
+ const hasUpdates = input.content !== undefined ||
35
+ input.title !== undefined ||
36
+ input.tags !== undefined ||
37
+ input.isPublic !== undefined ||
38
+ input.pin !== undefined ||
39
+ input.archived !== undefined ||
40
+ input.articleId !== undefined;
41
+ if (!hasUpdates) {
42
+ throw new Error("at least one field to update is required");
43
+ }
44
+ const body = {
45
+ openkey: this.openKey,
46
+ };
47
+ if (input.content !== undefined) {
48
+ body.content = input.content;
49
+ }
50
+ if (input.title !== undefined) {
51
+ body.title = input.title;
52
+ }
53
+ if (input.tags !== undefined) {
54
+ body.tags = input.tags;
55
+ }
56
+ if (input.isPublic !== undefined) {
57
+ body.state = input.isPublic ? "public" : "private";
58
+ }
59
+ if (input.pin !== undefined) {
60
+ body.pin = input.pin;
61
+ }
62
+ if (input.archived !== undefined) {
63
+ body.archived = input.archived;
64
+ }
65
+ if (input.articleId !== undefined) {
66
+ body.articleId = input.articleId;
67
+ }
68
+ return this.request(`/v2/api/openkey/notes/${encodeURIComponent(noteId)}`, {
69
+ method: "PUT",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify(body),
72
+ });
73
+ }
74
+ async deleteNote(noteId) {
75
+ const resolved = noteId?.trim();
76
+ if (!resolved) {
77
+ throw new Error("noteId is required");
78
+ }
79
+ const params = new URLSearchParams({ openkey: this.openKey });
80
+ return this.request(`/v2/api/openkey/notes/${encodeURIComponent(resolved)}?${params.toString()}`, { method: "DELETE" });
81
+ }
29
82
  async searchNotes(input) {
30
83
  if (!input.keyword?.trim()) {
31
84
  throw new Error("keyword is required");
@@ -58,6 +111,13 @@ export class RoteClient {
58
111
  }
59
112
  return this.request(`/v2/api/openkey/notes?${params.toString()}`);
60
113
  }
114
+ async exploreNotes(input = {}) {
115
+ const params = new URLSearchParams({
116
+ limit: String(input.limit ?? 20),
117
+ skip: String(input.skip ?? 0),
118
+ });
119
+ return this.request(`/v2/api/notes/public?${params.toString()}`);
120
+ }
61
121
  async createArticle(input) {
62
122
  if (!input.content?.trim()) {
63
123
  throw new Error("content is required");
package/dist/cli.js CHANGED
@@ -159,6 +159,19 @@ program
159
159
  });
160
160
  printNotes(notes);
161
161
  });
162
+ program
163
+ .command("explore")
164
+ .description("List explore notes (no authentication required)")
165
+ .option("-l, --limit <limit>", "max results", parseInt, 20)
166
+ .option("-s, --skip <skip>", "offset", parseInt, 0)
167
+ .action(async (options) => {
168
+ const client = new RoteClient();
169
+ const notes = await client.exploreNotes({
170
+ limit: options.limit,
171
+ skip: options.skip,
172
+ });
173
+ printNotes(notes);
174
+ });
162
175
  program
163
176
  .command("mcp")
164
177
  .description("Start MCP server over stdio")
package/dist/mcp.js CHANGED
@@ -40,6 +40,60 @@ export async function startMcpServer() {
40
40
  ],
41
41
  };
42
42
  });
43
+ server.registerTool("rote_update_note", {
44
+ description: "Update an existing note in Rote via OpenKey API.",
45
+ inputSchema: {
46
+ noteId: z.string().min(1).describe("Note ID"),
47
+ content: z.string().optional().describe("Updated note content"),
48
+ title: z.string().optional().describe("Updated note title"),
49
+ tags: z.array(z.string()).optional().describe("Updated list of tags"),
50
+ isPublic: z
51
+ .boolean()
52
+ .optional()
53
+ .describe("Set note visibility (public/private)"),
54
+ pin: z.boolean().optional().describe("Whether to pin the note"),
55
+ archived: z.boolean().optional().describe("Whether to archive the note"),
56
+ articleId: z
57
+ .string()
58
+ .optional()
59
+ .describe("Optional article ID to bind to"),
60
+ },
61
+ }, async ({ noteId, content, title, tags, isPublic, pin, archived, articleId }) => {
62
+ const note = await client.updateNote({
63
+ noteId,
64
+ content,
65
+ title,
66
+ tags,
67
+ isPublic,
68
+ pin,
69
+ archived,
70
+ articleId,
71
+ });
72
+ return {
73
+ content: [
74
+ {
75
+ type: "text",
76
+ text: `Updated note ${note.id}: ${truncateSingleLine(note.content, 100)}`,
77
+ },
78
+ ],
79
+ };
80
+ });
81
+ server.registerTool("rote_delete_note", {
82
+ description: "Delete a note in Rote via OpenKey API.",
83
+ inputSchema: {
84
+ noteId: z.string().min(1).describe("Note ID"),
85
+ },
86
+ }, async ({ noteId }) => {
87
+ await client.deleteNote(noteId);
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `Deleted note ${noteId}`,
93
+ },
94
+ ],
95
+ };
96
+ });
43
97
  server.registerTool("rote_create_article", {
44
98
  description: "Create an article in Rote via OpenKey API.",
45
99
  inputSchema: {
@@ -217,6 +271,35 @@ export async function startMcpServer() {
217
271
  ],
218
272
  };
219
273
  });
274
+ server.registerTool("rote_explore_notes", {
275
+ description: "Get explore notes in Rote (no authentication required).",
276
+ inputSchema: {
277
+ limit: z
278
+ .number()
279
+ .int()
280
+ .min(1)
281
+ .max(50)
282
+ .optional()
283
+ .describe("Max results, default 20"),
284
+ skip: z
285
+ .number()
286
+ .int()
287
+ .min(0)
288
+ .optional()
289
+ .describe("Pagination offset, default 0"),
290
+ },
291
+ }, async ({ limit, skip }) => {
292
+ const notes = await client.exploreNotes({ limit, skip });
293
+ const lines = notes.map((note, i) => `${i + 1}. ${truncateSingleLine(note.content, 100)}`);
294
+ return {
295
+ content: [
296
+ {
297
+ type: "text",
298
+ text: lines.length > 0 ? lines.join("\n") : "No explore notes found.",
299
+ },
300
+ ],
301
+ };
302
+ });
220
303
  const transport = new StdioServerTransport();
221
304
  await server.connect(transport);
222
305
  }
package/dist/types.d.ts CHANGED
@@ -24,6 +24,16 @@ export interface CreateNoteInput {
24
24
  pin?: boolean;
25
25
  articleId?: string;
26
26
  }
27
+ export interface UpdateNoteInput {
28
+ noteId: string;
29
+ content?: string;
30
+ title?: string;
31
+ tags?: string[];
32
+ isPublic?: boolean;
33
+ pin?: boolean;
34
+ archived?: boolean;
35
+ articleId?: string;
36
+ }
27
37
  export interface RoteArticle {
28
38
  id: string;
29
39
  content: string;
@@ -90,3 +100,7 @@ export interface ListNotesInput {
90
100
  archived?: boolean;
91
101
  tag?: string[];
92
102
  }
103
+ export interface ExploreNotesInput {
104
+ limit?: number;
105
+ skip?: number;
106
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rote-toolkit",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "CLI and MCP toolkit for Rote OpenKey API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",