rote-toolkit 0.2.1 → 0.3.1
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 +17 -9
- package/dist/api.js +13 -2
- package/dist/cli.js +33 -3
- package/dist/config.js +2 -2
- package/dist/mcp.js +19 -7
- package/dist/types.d.ts +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,10 +21,11 @@ npm install -g rote-toolkit
|
|
|
21
21
|
运行以下命令进行全局配置:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
rote
|
|
24
|
+
rote config
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
系统会提示你输入:
|
|
28
|
+
|
|
28
29
|
1. **Rote API URL**:例如 `https://your-rote-domain.com`
|
|
29
30
|
2. **OpenKey**:你的 API 密钥
|
|
30
31
|
|
|
@@ -38,18 +39,26 @@ rote login
|
|
|
38
39
|
rote add "今天学到了 MCP 协议,非常有趣!"
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
附带标签、设为公开并置顶:
|
|
42
43
|
|
|
43
44
|
```bash
|
|
44
|
-
rote add "实现了一个新的前端组件" -t "代码,前端,React"
|
|
45
|
+
rote add "实现了一个新的前端组件" -t "代码,前端,React" --public --pin
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
### 2)
|
|
48
|
+
### 2) 搜索和获取笔记
|
|
49
|
+
|
|
50
|
+
搜索包含 "MCP" 的笔记:
|
|
48
51
|
|
|
49
52
|
```bash
|
|
50
53
|
rote search "MCP"
|
|
51
54
|
```
|
|
52
55
|
|
|
56
|
+
获取最近的笔记(支持过滤归档和标签):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
rote list --limit 5 --archived -t "知识管理"
|
|
60
|
+
```
|
|
61
|
+
|
|
53
62
|
## MCP 模式使用指南
|
|
54
63
|
|
|
55
64
|
启动 MCP Server:
|
|
@@ -71,11 +80,7 @@ rote-mcp
|
|
|
71
80
|
"mcpServers": {
|
|
72
81
|
"rote-toolkit": {
|
|
73
82
|
"command": "npx",
|
|
74
|
-
"args": [
|
|
75
|
-
"-y",
|
|
76
|
-
"rote-toolkit",
|
|
77
|
-
"mcp"
|
|
78
|
-
]
|
|
83
|
+
"args": ["-y", "rote-toolkit", "mcp"]
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
}
|
|
@@ -88,7 +93,9 @@ rote-mcp
|
|
|
88
93
|
- `rote_list_notes`
|
|
89
94
|
|
|
90
95
|
## 本地开发
|
|
96
|
+
|
|
91
97
|
[text](../../../Downloads/API-KEY-GUIDE.md)
|
|
98
|
+
|
|
92
99
|
```bash
|
|
93
100
|
npm install
|
|
94
101
|
npm run build
|
|
@@ -117,6 +124,7 @@ npm run release:major
|
|
|
117
124
|
```
|
|
118
125
|
|
|
119
126
|
发布脚本会执行:
|
|
127
|
+
|
|
120
128
|
1. 检查 git 工作区是否干净
|
|
121
129
|
2. 检查 npm 登录状态
|
|
122
130
|
3. `npm run build`
|
package/dist/api.js
CHANGED
|
@@ -16,8 +16,7 @@ export class RoteClient {
|
|
|
16
16
|
content: input.content,
|
|
17
17
|
title: input.title ?? "",
|
|
18
18
|
tags: input.tags ?? [],
|
|
19
|
-
state: input.
|
|
20
|
-
type: input.type ?? "rote",
|
|
19
|
+
state: input.isPublic ? "public" : "private",
|
|
21
20
|
pin: input.pin ?? false,
|
|
22
21
|
...(input.articleId ? { articleId: input.articleId } : {}),
|
|
23
22
|
};
|
|
@@ -37,6 +36,12 @@ export class RoteClient {
|
|
|
37
36
|
limit: String(input.limit ?? 10),
|
|
38
37
|
skip: String(input.skip ?? 0),
|
|
39
38
|
});
|
|
39
|
+
if (input.archived !== undefined) {
|
|
40
|
+
params.set("archived", String(input.archived));
|
|
41
|
+
}
|
|
42
|
+
if (input.tag) {
|
|
43
|
+
input.tag.forEach((t) => params.append("tag", t));
|
|
44
|
+
}
|
|
40
45
|
return this.request(`/v2/api/openkey/notes/search?${params.toString()}`);
|
|
41
46
|
}
|
|
42
47
|
async listNotes(input = {}) {
|
|
@@ -45,6 +50,12 @@ export class RoteClient {
|
|
|
45
50
|
limit: String(input.limit ?? 10),
|
|
46
51
|
skip: String(input.skip ?? 0),
|
|
47
52
|
});
|
|
53
|
+
if (input.archived !== undefined) {
|
|
54
|
+
params.set("archived", String(input.archived));
|
|
55
|
+
}
|
|
56
|
+
if (input.tag) {
|
|
57
|
+
input.tag.forEach((t) => params.append("tag", t));
|
|
58
|
+
}
|
|
48
59
|
return this.request(`/v2/api/openkey/notes?${params.toString()}`);
|
|
49
60
|
}
|
|
50
61
|
async createArticle(input) {
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,8 @@ import { startMcpServer } from "./mcp.js";
|
|
|
9
9
|
const program = new Command();
|
|
10
10
|
program.name("rote").description("Rote Toolkit CLI").version("0.1.0");
|
|
11
11
|
program
|
|
12
|
-
.command("
|
|
12
|
+
.command("config")
|
|
13
|
+
.alias("login")
|
|
13
14
|
.description("Configure Rote API URL and OpenKey")
|
|
14
15
|
.action(async () => {
|
|
15
16
|
const rl = createInterface({ input, output });
|
|
@@ -29,7 +30,8 @@ program
|
|
|
29
30
|
.argument("<content>", "note content")
|
|
30
31
|
.option("-t, --tags <tags>", "comma-separated tags")
|
|
31
32
|
.option("--title <title>", "title")
|
|
32
|
-
.option("--
|
|
33
|
+
.option("--public", "publish as public note")
|
|
34
|
+
.option("--pin", "pin the note")
|
|
33
35
|
.option("--article-id <articleId>", "bind to an existing article")
|
|
34
36
|
.action(async (content, options) => {
|
|
35
37
|
const client = new RoteClient();
|
|
@@ -38,7 +40,8 @@ program
|
|
|
38
40
|
content,
|
|
39
41
|
tags,
|
|
40
42
|
title: options.title,
|
|
41
|
-
|
|
43
|
+
isPublic: options.public,
|
|
44
|
+
pin: options.pin,
|
|
42
45
|
articleId: options.articleId,
|
|
43
46
|
});
|
|
44
47
|
console.log(`Created note: ${note.id}`);
|
|
@@ -84,6 +87,8 @@ program
|
|
|
84
87
|
.argument("<action>", "action to perform (get|update)")
|
|
85
88
|
.option("--nickname <nickname>", "new nickname")
|
|
86
89
|
.option("--description <description>", "new description")
|
|
90
|
+
.option("--avatar <url>", "new avatar URL")
|
|
91
|
+
.option("--cover <url>", "new cover URL")
|
|
87
92
|
.option("--username <username>", "new username")
|
|
88
93
|
.action(async (action, options) => {
|
|
89
94
|
const client = new RoteClient();
|
|
@@ -95,6 +100,8 @@ program
|
|
|
95
100
|
const profile = await client.updateProfile({
|
|
96
101
|
nickname: options.nickname,
|
|
97
102
|
description: options.description,
|
|
103
|
+
avatar: options.avatar,
|
|
104
|
+
cover: options.cover,
|
|
98
105
|
username: options.username,
|
|
99
106
|
});
|
|
100
107
|
console.log(`Updated profile for: ${profile.username}`);
|
|
@@ -117,12 +124,35 @@ program
|
|
|
117
124
|
.argument("<keyword>", "search keyword")
|
|
118
125
|
.option("-l, --limit <limit>", "max results", parseInt, 10)
|
|
119
126
|
.option("-s, --skip <skip>", "offset", parseInt, 0)
|
|
127
|
+
.option("--archived", "include archived notes")
|
|
128
|
+
.option("-t, --tag <tags>", "comma-separated tags to filter by")
|
|
120
129
|
.action(async (keyword, options) => {
|
|
121
130
|
const client = new RoteClient();
|
|
131
|
+
const tag = parseTags(options.tag);
|
|
122
132
|
const notes = await client.searchNotes({
|
|
123
133
|
keyword,
|
|
124
134
|
limit: options.limit,
|
|
125
135
|
skip: options.skip,
|
|
136
|
+
archived: options.archived,
|
|
137
|
+
tag: tag.length > 0 ? tag : undefined,
|
|
138
|
+
});
|
|
139
|
+
printNotes(notes);
|
|
140
|
+
});
|
|
141
|
+
program
|
|
142
|
+
.command("list")
|
|
143
|
+
.description("List recent notes")
|
|
144
|
+
.option("-l, --limit <limit>", "max results", parseInt, 10)
|
|
145
|
+
.option("-s, --skip <skip>", "offset", parseInt, 0)
|
|
146
|
+
.option("--archived", "include archived notes")
|
|
147
|
+
.option("-t, --tag <tags>", "comma-separated tags to filter by")
|
|
148
|
+
.action(async (options) => {
|
|
149
|
+
const client = new RoteClient();
|
|
150
|
+
const tag = parseTags(options.tag);
|
|
151
|
+
const notes = await client.listNotes({
|
|
152
|
+
limit: options.limit,
|
|
153
|
+
skip: options.skip,
|
|
154
|
+
archived: options.archived,
|
|
155
|
+
tag: tag.length > 0 ? tag : undefined,
|
|
126
156
|
});
|
|
127
157
|
printNotes(notes);
|
|
128
158
|
});
|
package/dist/config.js
CHANGED
|
@@ -19,12 +19,12 @@ export function saveConfig(config) {
|
|
|
19
19
|
}
|
|
20
20
|
export function loadConfig() {
|
|
21
21
|
if (!existsSync(CONFIG_PATH)) {
|
|
22
|
-
throw new Error(`Config not found at ${CONFIG_PATH}. Run "rote
|
|
22
|
+
throw new Error(`Config not found at ${CONFIG_PATH}. Run "rote config" first.`);
|
|
23
23
|
}
|
|
24
24
|
const raw = readFileSync(CONFIG_PATH, 'utf8');
|
|
25
25
|
const parsed = JSON.parse(raw);
|
|
26
26
|
if (!parsed.apiUrl || !parsed.openKey) {
|
|
27
|
-
throw new Error(`Invalid config at ${CONFIG_PATH}. Run "rote
|
|
27
|
+
throw new Error(`Invalid config at ${CONFIG_PATH}. Run "rote config" again.`);
|
|
28
28
|
}
|
|
29
29
|
return {
|
|
30
30
|
apiUrl: normalizeApiUrl(parsed.apiUrl),
|
package/dist/mcp.js
CHANGED
|
@@ -15,18 +15,20 @@ export async function startMcpServer() {
|
|
|
15
15
|
content: z.string().min(1).describe("Note content"),
|
|
16
16
|
title: z.string().optional().describe("Optional note title"),
|
|
17
17
|
tags: z.array(z.string()).optional().describe("Optional list of tags"),
|
|
18
|
-
|
|
18
|
+
isPublic: z.boolean().optional().describe("Publish as public note"),
|
|
19
|
+
pin: z.boolean().optional().describe("Whether to pin the note"),
|
|
19
20
|
articleId: z
|
|
20
21
|
.string()
|
|
21
22
|
.optional()
|
|
22
23
|
.describe("Optional article ID to bind to"),
|
|
23
24
|
},
|
|
24
|
-
}, async ({ content, title, tags,
|
|
25
|
+
}, async ({ content, title, tags, isPublic, pin, articleId }) => {
|
|
25
26
|
const note = await client.createNote({
|
|
26
27
|
content,
|
|
27
28
|
title,
|
|
28
29
|
tags,
|
|
29
|
-
|
|
30
|
+
isPublic,
|
|
31
|
+
pin,
|
|
30
32
|
articleId,
|
|
31
33
|
});
|
|
32
34
|
return {
|
|
@@ -163,9 +165,17 @@ export async function startMcpServer() {
|
|
|
163
165
|
.min(0)
|
|
164
166
|
.optional()
|
|
165
167
|
.describe("Pagination offset, default 0"),
|
|
168
|
+
archived: z.boolean().optional().describe("Include archived notes"),
|
|
169
|
+
tag: z.array(z.string()).optional().describe("Tag filter"),
|
|
166
170
|
},
|
|
167
|
-
}, async ({ keyword, limit, skip }) => {
|
|
168
|
-
const notes = await client.searchNotes({
|
|
171
|
+
}, async ({ keyword, limit, skip, archived, tag }) => {
|
|
172
|
+
const notes = await client.searchNotes({
|
|
173
|
+
keyword,
|
|
174
|
+
limit,
|
|
175
|
+
skip,
|
|
176
|
+
archived,
|
|
177
|
+
tag,
|
|
178
|
+
});
|
|
169
179
|
const lines = notes.map((note, i) => `${i + 1}. ${truncateSingleLine(note.content, 100)}`);
|
|
170
180
|
return {
|
|
171
181
|
content: [
|
|
@@ -192,9 +202,11 @@ export async function startMcpServer() {
|
|
|
192
202
|
.min(0)
|
|
193
203
|
.optional()
|
|
194
204
|
.describe("Pagination offset, default 0"),
|
|
205
|
+
archived: z.boolean().optional().describe("Include archived notes"),
|
|
206
|
+
tag: z.array(z.string()).optional().describe("Tag filter"),
|
|
195
207
|
},
|
|
196
|
-
}, async ({ limit, skip }) => {
|
|
197
|
-
const notes = await client.listNotes({ limit, skip });
|
|
208
|
+
}, async ({ limit, skip, archived, tag }) => {
|
|
209
|
+
const notes = await client.listNotes({ limit, skip, archived, tag });
|
|
198
210
|
const lines = notes.map((note, i) => `${i + 1}. ${truncateSingleLine(note.content, 100)}`);
|
|
199
211
|
return {
|
|
200
212
|
content: [
|
package/dist/types.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export interface RoteNote {
|
|
|
8
8
|
title?: string;
|
|
9
9
|
tags?: string[];
|
|
10
10
|
state?: string;
|
|
11
|
-
type?: string;
|
|
12
11
|
createdAt?: string;
|
|
13
12
|
updatedAt?: string;
|
|
14
13
|
}
|
|
@@ -21,8 +20,7 @@ export interface CreateNoteInput {
|
|
|
21
20
|
content: string;
|
|
22
21
|
title?: string;
|
|
23
22
|
tags?: string[];
|
|
24
|
-
|
|
25
|
-
type?: string;
|
|
23
|
+
isPublic?: boolean;
|
|
26
24
|
pin?: boolean;
|
|
27
25
|
articleId?: string;
|
|
28
26
|
}
|
|
@@ -83,8 +81,12 @@ export interface SearchNotesInput {
|
|
|
83
81
|
keyword: string;
|
|
84
82
|
limit?: number;
|
|
85
83
|
skip?: number;
|
|
84
|
+
archived?: boolean;
|
|
85
|
+
tag?: string[];
|
|
86
86
|
}
|
|
87
87
|
export interface ListNotesInput {
|
|
88
88
|
limit?: number;
|
|
89
89
|
skip?: number;
|
|
90
|
+
archived?: boolean;
|
|
91
|
+
tag?: string[];
|
|
90
92
|
}
|