@taotao7/bypass-mcp 1.0.0 → 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 +44 -30
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/services/api.d.ts +5 -0
- package/dist/services/api.js +37 -0
- package/dist/services/api.js.map +1 -0
- package/dist/tools/articles.js +17 -44
- package/dist/tools/articles.js.map +1 -1
- package/dist/tools/courses.js +80 -50
- package/dist/tools/courses.js.map +1 -1
- package/dist/tools/orders.js +8 -17
- package/dist/tools/orders.js.map +1 -1
- package/dist/tools/stats.js +5 -12
- package/dist/tools/stats.js.map +1 -1
- package/dist/tools/students.js +15 -29
- package/dist/tools/students.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
|
-
# @bypass
|
|
1
|
+
# @taotao7/bypass-mcp
|
|
2
2
|
|
|
3
|
-
bypass-saas
|
|
3
|
+
bypass-saas 课程平台的 MCP Server,提供课程、文章、学员、订单等管理能力,供 Claude Desktop / Claude Code 等 MCP 客户端调用。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 快速开始
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### 1. 获取 API Token
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
2. 创建 Token,权限选择 **D1 Edit**
|
|
11
|
-
3. 记录生成的 Token
|
|
9
|
+
在你部署的 bypass-saas **Admin 后台**中生成 Token:
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
1. 登录 Admin 后台
|
|
12
|
+
2. 进入 **设置 → API Token 管理**
|
|
13
|
+
3. 点击"生成 Token",复制生成的 `bp_xxx` 格式 token
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
# 在 monorepo 根目录
|
|
17
|
-
pnpm install
|
|
18
|
-
cd packages/mcp && pnpm build
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## 配置
|
|
15
|
+
### 2. 配置 MCP 客户端
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
#### Claude Desktop
|
|
24
18
|
|
|
25
19
|
编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
26
20
|
|
|
@@ -28,35 +22,43 @@ cd packages/mcp && pnpm build
|
|
|
28
22
|
{
|
|
29
23
|
"mcpServers": {
|
|
30
24
|
"bypass": {
|
|
31
|
-
"command": "
|
|
32
|
-
"args": ["/
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@taotao7/bypass-mcp"],
|
|
33
27
|
"env": {
|
|
34
|
-
"
|
|
28
|
+
"BYPASS_API_URL": "https://admin.airbypass.com/api",
|
|
29
|
+
"BYPASS_API_TOKEN": "bp_your-token-here"
|
|
35
30
|
}
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
33
|
}
|
|
39
34
|
```
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
#### Claude Code
|
|
42
37
|
|
|
43
|
-
|
|
38
|
+
编辑 `.claude/settings.json` 或全局配置:
|
|
44
39
|
|
|
45
40
|
```json
|
|
46
41
|
{
|
|
47
42
|
"mcpServers": {
|
|
48
43
|
"bypass": {
|
|
49
|
-
"command": "
|
|
50
|
-
"args": ["
|
|
51
|
-
"cwd": "/path/to/bypass-saas",
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["-y", "@taotao7/bypass-mcp"],
|
|
52
46
|
"env": {
|
|
53
|
-
"
|
|
47
|
+
"BYPASS_API_URL": "https://admin.airbypass.com/api",
|
|
48
|
+
"BYPASS_API_TOKEN": "bp_your-token-here"
|
|
54
49
|
}
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
}
|
|
58
53
|
```
|
|
59
54
|
|
|
55
|
+
### 环境变量
|
|
56
|
+
|
|
57
|
+
| 变量 | 必填 | 说明 |
|
|
58
|
+
|------|------|------|
|
|
59
|
+
| `BYPASS_API_URL` | 是 | Admin 后台 API 地址(如 `https://admin.airbypass.com/api`) |
|
|
60
|
+
| `BYPASS_API_TOKEN` | 是 | 在 Admin 后台 **设置 → API Token 管理** 中生成的 Token(`bp_xxx` 格式) |
|
|
61
|
+
|
|
60
62
|
## 可用工具
|
|
61
63
|
|
|
62
64
|
### 课程管理
|
|
@@ -64,11 +66,20 @@ cd packages/mcp && pnpm build
|
|
|
64
66
|
| 工具 | 说明 |
|
|
65
67
|
|------|------|
|
|
66
68
|
| `bypass_list_courses` | 列出课程,支持 status/category_id/search 筛选 + 分页 |
|
|
67
|
-
| `bypass_get_course` | 按 ID
|
|
68
|
-
| `bypass_create_course` |
|
|
69
|
+
| `bypass_get_course` | 按 ID 获取单个课程详情(含购买项列表) |
|
|
70
|
+
| `bypass_create_course` | 创建课程(价格通过购买项管理,非课程级别) |
|
|
69
71
|
| `bypass_update_course` | 更新课程,仅更新传入的字段 |
|
|
70
72
|
| `bypass_delete_course` | 删除课程 |
|
|
71
73
|
|
|
74
|
+
### 课程购买项管理
|
|
75
|
+
|
|
76
|
+
| 工具 | 说明 |
|
|
77
|
+
|------|------|
|
|
78
|
+
| `bypass_list_course_items` | 列出课程下所有购买项 |
|
|
79
|
+
| `bypass_create_course_item` | 创建购买项(价格单位:分,content_url 为交付链接,用户购买后通过 iframe 查看) |
|
|
80
|
+
| `bypass_update_course_item` | 更新购买项,仅更新传入的字段 |
|
|
81
|
+
| `bypass_delete_course_item` | 删除购买项 |
|
|
82
|
+
|
|
72
83
|
### 文章管理
|
|
73
84
|
|
|
74
85
|
| 工具 | 说明 |
|
|
@@ -101,7 +112,10 @@ cd packages/mcp && pnpm build
|
|
|
101
112
|
|
|
102
113
|
## 技术细节
|
|
103
114
|
|
|
104
|
-
- 传输方式:stdio
|
|
105
|
-
- 数据访问:通过
|
|
106
|
-
- 数据库:`bypass-saas-db`(与 web/admin 共享同一个 D1)
|
|
115
|
+
- 传输方式:stdio
|
|
116
|
+
- 数据访问:通过 Admin REST API (`/api/v1/*`),使用 API Token 认证
|
|
107
117
|
- 所有列表接口支持 `limit` + `offset` 分页,返回 `total` / `has_more` 元数据
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import {
|
|
4
|
+
import { initApi } from "./services/api.js";
|
|
5
5
|
import { registerCourseTools } from "./tools/courses.js";
|
|
6
6
|
import { registerArticleTools } from "./tools/articles.js";
|
|
7
7
|
import { registerStudentTools } from "./tools/students.js";
|
|
8
8
|
import { registerOrderTools } from "./tools/orders.js";
|
|
9
9
|
import { registerStatsTools } from "./tools/stats.js";
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
console.error("
|
|
14
|
-
console.error("
|
|
10
|
+
const apiUrl = process.env.BYPASS_API_URL;
|
|
11
|
+
const apiToken = process.env.BYPASS_API_TOKEN;
|
|
12
|
+
if (!apiUrl || !apiToken) {
|
|
13
|
+
console.error("ERROR: BYPASS_API_URL and BYPASS_API_TOKEN environment variables are required.");
|
|
14
|
+
console.error("1. Generate a token in Admin → Settings → API Token Management");
|
|
15
|
+
console.error("2. Set BYPASS_API_URL to your admin API base (e.g. http://localhost:3001/api)");
|
|
16
|
+
console.error("3. Set BYPASS_API_TOKEN to the generated bp_xxx token");
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
initApi(apiUrl, apiToken);
|
|
18
20
|
const server = new McpServer({
|
|
19
21
|
name: "bypass-mcp-server",
|
|
20
|
-
version: "1.
|
|
22
|
+
version: "1.1.0",
|
|
21
23
|
});
|
|
22
24
|
registerCourseTools(server);
|
|
23
25
|
registerArticleTools(server);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE9C,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,OAAO,CAAC,KAAK,CACX,gFAAgF,CACjF,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;IAChF,OAAO,CAAC,KAAK,CAAC,+EAA+E,CAAC,CAAC;IAC/F,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAE3B,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;AACvD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function initApi(url: string, token: string): void;
|
|
2
|
+
export declare function apiGet<T = unknown>(path: string): Promise<T>;
|
|
3
|
+
export declare function apiPost<T = unknown>(path: string, body: unknown): Promise<T>;
|
|
4
|
+
export declare function apiPatch<T = unknown>(path: string, body: unknown): Promise<T>;
|
|
5
|
+
export declare function apiDelete<T = unknown>(path: string): Promise<T>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
let baseUrl;
|
|
2
|
+
let apiToken;
|
|
3
|
+
export function initApi(url, token) {
|
|
4
|
+
baseUrl = url.replace(/\/+$/, "");
|
|
5
|
+
apiToken = token;
|
|
6
|
+
}
|
|
7
|
+
async function request(method, path, body) {
|
|
8
|
+
const url = `${baseUrl}/v1${path}`;
|
|
9
|
+
const headers = {
|
|
10
|
+
Authorization: `Bearer ${apiToken}`,
|
|
11
|
+
};
|
|
12
|
+
if (body)
|
|
13
|
+
headers["Content-Type"] = "application/json";
|
|
14
|
+
const res = await fetch(url, {
|
|
15
|
+
method,
|
|
16
|
+
headers,
|
|
17
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
18
|
+
});
|
|
19
|
+
if (!res.ok) {
|
|
20
|
+
const text = await res.text();
|
|
21
|
+
throw new Error(`API error ${res.status}: ${text}`);
|
|
22
|
+
}
|
|
23
|
+
return res.json();
|
|
24
|
+
}
|
|
25
|
+
export function apiGet(path) {
|
|
26
|
+
return request("GET", path);
|
|
27
|
+
}
|
|
28
|
+
export function apiPost(path, body) {
|
|
29
|
+
return request("POST", path, body);
|
|
30
|
+
}
|
|
31
|
+
export function apiPatch(path, body) {
|
|
32
|
+
return request("PATCH", path, body);
|
|
33
|
+
}
|
|
34
|
+
export function apiDelete(path) {
|
|
35
|
+
return request("DELETE", path);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":"AAAA,IAAI,OAAe,CAAC;AACpB,IAAI,QAAgB,CAAC;AAErB,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,KAAa;IAChD,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI,EAAE,CAAC;IACnC,MAAM,OAAO,GAA2B;QACtC,aAAa,EAAE,UAAU,QAAQ,EAAE;KACpC,CAAC;IACF,IAAI,IAAI;QAAE,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;IAEvD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,MAAM,CAAc,IAAY;IAC9C,OAAO,OAAO,CAAI,KAAK,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,OAAO,CAAc,IAAY,EAAE,IAAa;IAC9D,OAAO,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAc,IAAY,EAAE,IAAa;IAC/D,OAAO,OAAO,CAAI,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS,CAAc,IAAY;IACjD,OAAO,OAAO,CAAI,QAAQ,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/tools/articles.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { apiGet, apiPost, apiPatch, apiDelete } from "../services/api.js";
|
|
3
3
|
export function registerArticleTools(server) {
|
|
4
4
|
server.registerTool("bypass_list_articles", {
|
|
5
5
|
title: "List Articles",
|
|
@@ -13,26 +13,17 @@ export function registerArticleTools(server) {
|
|
|
13
13
|
},
|
|
14
14
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
15
15
|
}, async (params) => {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
conditions.push("title LIKE ?");
|
|
28
|
-
binds.push(`%${params.search}%`);
|
|
29
|
-
}
|
|
30
|
-
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
31
|
-
const countResult = await queryFirst(`SELECT COUNT(*) as total FROM blog_articles ${where}`, binds);
|
|
32
|
-
const total = countResult?.total ?? 0;
|
|
33
|
-
const rows = await query(`SELECT * FROM blog_articles ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`, [...binds, params.limit, params.offset]);
|
|
34
|
-
const output = { total, count: rows.results.length, offset: params.offset, articles: rows.results, has_more: total > params.offset + rows.results.length };
|
|
35
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
16
|
+
const qs = new URLSearchParams();
|
|
17
|
+
if (params.status)
|
|
18
|
+
qs.set("status", params.status);
|
|
19
|
+
if (params.category)
|
|
20
|
+
qs.set("category", params.category);
|
|
21
|
+
if (params.search)
|
|
22
|
+
qs.set("search", params.search);
|
|
23
|
+
qs.set("limit", String(params.limit));
|
|
24
|
+
qs.set("offset", String(params.offset));
|
|
25
|
+
const data = await apiGet(`/articles?${qs}`);
|
|
26
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
36
27
|
});
|
|
37
28
|
server.registerTool("bypass_get_article", {
|
|
38
29
|
title: "Get Article",
|
|
@@ -40,10 +31,8 @@ export function registerArticleTools(server) {
|
|
|
40
31
|
inputSchema: { id: z.number().int().describe("Article ID") },
|
|
41
32
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
42
33
|
}, async (params) => {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return { content: [{ type: "text", text: `Article ${params.id} not found` }], isError: true };
|
|
46
|
-
return { content: [{ type: "text", text: JSON.stringify(article, null, 2) }] };
|
|
34
|
+
const data = await apiGet(`/articles/${params.id}`);
|
|
35
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
47
36
|
});
|
|
48
37
|
server.registerTool("bypass_create_article", {
|
|
49
38
|
title: "Create Article",
|
|
@@ -60,8 +49,7 @@ export function registerArticleTools(server) {
|
|
|
60
49
|
},
|
|
61
50
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
62
51
|
}, async (params) => {
|
|
63
|
-
|
|
64
|
-
await query(`INSERT INTO blog_articles (slug, title, excerpt, content, category, cover_url, author_name, status, published_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [params.slug, params.title, params.excerpt ?? null, params.content ?? null, params.category, params.cover_url ?? null, params.author_name, params.status, publishedAt]);
|
|
52
|
+
await apiPost("/articles", params);
|
|
65
53
|
return { content: [{ type: "text", text: `Article "${params.title}" created.` }] };
|
|
66
54
|
});
|
|
67
55
|
server.registerTool("bypass_update_article", {
|
|
@@ -78,22 +66,7 @@ export function registerArticleTools(server) {
|
|
|
78
66
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
79
67
|
}, async (params) => {
|
|
80
68
|
const { id, ...fields } = params;
|
|
81
|
-
|
|
82
|
-
const binds = [];
|
|
83
|
-
for (const [key, val] of Object.entries(fields)) {
|
|
84
|
-
if (val !== undefined) {
|
|
85
|
-
sets.push(`${key} = ?`);
|
|
86
|
-
binds.push(val);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (fields.status === "published") {
|
|
90
|
-
sets.push("published_at = COALESCE(published_at, CURRENT_TIMESTAMP)");
|
|
91
|
-
}
|
|
92
|
-
if (!sets.length)
|
|
93
|
-
return { content: [{ type: "text", text: "No fields to update." }] };
|
|
94
|
-
sets.push("updated_at = CURRENT_TIMESTAMP");
|
|
95
|
-
binds.push(id);
|
|
96
|
-
await query(`UPDATE blog_articles SET ${sets.join(", ")} WHERE id = ?`, binds);
|
|
69
|
+
await apiPatch(`/articles/${id}`, fields);
|
|
97
70
|
return { content: [{ type: "text", text: `Article ${id} updated.` }] };
|
|
98
71
|
});
|
|
99
72
|
server.registerTool("bypass_delete_article", {
|
|
@@ -102,7 +75,7 @@ export function registerArticleTools(server) {
|
|
|
102
75
|
inputSchema: { id: z.number().int().describe("Article ID") },
|
|
103
76
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
104
77
|
}, async (params) => {
|
|
105
|
-
await
|
|
78
|
+
await apiDelete(`/articles/${params.id}`);
|
|
106
79
|
return { content: [{ type: "text", text: `Article ${params.id} deleted.` }] };
|
|
107
80
|
});
|
|
108
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/tools/articles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/tools/articles.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/courses.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { apiGet, apiPost, apiPatch, apiDelete } from "../services/api.js";
|
|
3
3
|
export function registerCourseTools(server) {
|
|
4
4
|
server.registerTool("bypass_list_courses", {
|
|
5
5
|
title: "List Courses",
|
|
@@ -13,87 +13,62 @@ export function registerCourseTools(server) {
|
|
|
13
13
|
},
|
|
14
14
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
15
15
|
}, async (params) => {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
conditions.push("c.title LIKE ?");
|
|
28
|
-
binds.push(`%${params.search}%`);
|
|
29
|
-
}
|
|
30
|
-
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
31
|
-
const countResult = await queryFirst(`SELECT COUNT(*) as total FROM courses c ${where}`, binds);
|
|
32
|
-
const total = countResult?.total ?? 0;
|
|
33
|
-
const rows = await query(`SELECT c.*, cat.name AS category_name FROM courses c LEFT JOIN categories cat ON c.category_id = cat.id ${where} ORDER BY c.created_at DESC LIMIT ? OFFSET ?`, [...binds, params.limit, params.offset]);
|
|
34
|
-
const output = { total, count: rows.results.length, offset: params.offset, courses: rows.results, has_more: total > params.offset + rows.results.length };
|
|
35
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
16
|
+
const qs = new URLSearchParams();
|
|
17
|
+
if (params.status)
|
|
18
|
+
qs.set("status", params.status);
|
|
19
|
+
if (params.category_id)
|
|
20
|
+
qs.set("category_id", String(params.category_id));
|
|
21
|
+
if (params.search)
|
|
22
|
+
qs.set("search", params.search);
|
|
23
|
+
qs.set("limit", String(params.limit));
|
|
24
|
+
qs.set("offset", String(params.offset));
|
|
25
|
+
const data = await apiGet(`/courses?${qs}`);
|
|
26
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
36
27
|
});
|
|
37
28
|
server.registerTool("bypass_get_course", {
|
|
38
29
|
title: "Get Course",
|
|
39
|
-
description: "Get a single course by ID with category info.",
|
|
30
|
+
description: "Get a single course by ID with category info and purchase items.",
|
|
40
31
|
inputSchema: { id: z.number().int().describe("Course ID") },
|
|
41
32
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
42
33
|
}, async (params) => {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return { content: [{ type: "text", text: `Course ${params.id} not found` }], isError: true };
|
|
46
|
-
return { content: [{ type: "text", text: JSON.stringify(course, null, 2) }] };
|
|
34
|
+
const data = await apiGet(`/courses/${params.id}`);
|
|
35
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
47
36
|
});
|
|
48
37
|
server.registerTool("bypass_create_course", {
|
|
49
38
|
title: "Create Course",
|
|
50
|
-
description: "Create a new course.
|
|
39
|
+
description: "Create a new course. Pricing is managed through course items (purchase items), not at the course level.",
|
|
51
40
|
inputSchema: {
|
|
52
41
|
title: z.string().min(1).describe("Course title"),
|
|
53
42
|
slug: z.string().min(1).describe("URL slug"),
|
|
54
|
-
price: z.number().int().min(0).describe("Price in cents"),
|
|
55
43
|
instructor: z.string().default("包帕斯").describe("Instructor name"),
|
|
56
|
-
|
|
44
|
+
images: z.string().optional().describe("JSON array of course introduction image URLs"),
|
|
57
45
|
category_id: z.number().int().optional().describe("Category ID"),
|
|
58
|
-
original_price: z.number().int().optional().describe("Original price in cents"),
|
|
59
46
|
instructor_title: z.string().optional().describe("Instructor title"),
|
|
60
47
|
cover_url: z.string().optional().describe("Cover image URL"),
|
|
61
|
-
|
|
48
|
+
outline_image: z.string().optional().describe("Course outline/syllabus image URL"),
|
|
62
49
|
status: z.enum(["draft", "published"]).default("draft").describe("Status"),
|
|
63
50
|
},
|
|
64
51
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
65
52
|
}, async (params) => {
|
|
66
|
-
await
|
|
53
|
+
await apiPost("/courses", { ...params, price: 0 });
|
|
67
54
|
return { content: [{ type: "text", text: `Course "${params.title}" created successfully.` }] };
|
|
68
55
|
});
|
|
69
56
|
server.registerTool("bypass_update_course", {
|
|
70
57
|
title: "Update Course",
|
|
71
|
-
description: "Update an existing course by ID. Only provided fields are updated.",
|
|
58
|
+
description: "Update an existing course by ID. Only provided fields are updated. Pricing is managed through course items.",
|
|
72
59
|
inputSchema: {
|
|
73
60
|
id: z.number().int().describe("Course ID"),
|
|
74
61
|
title: z.string().optional(), slug: z.string().optional(),
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
images: z.string().optional().describe("JSON array of course introduction image URLs"),
|
|
63
|
+
category_id: z.number().int().optional(),
|
|
77
64
|
instructor: z.string().optional(), instructor_title: z.string().optional(),
|
|
78
|
-
cover_url: z.string().optional(),
|
|
65
|
+
cover_url: z.string().optional(), outline_image: z.string().optional(),
|
|
79
66
|
status: z.enum(["draft", "published"]).optional(),
|
|
80
67
|
},
|
|
81
68
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
82
69
|
}, async (params) => {
|
|
83
70
|
const { id, ...fields } = params;
|
|
84
|
-
|
|
85
|
-
const binds = [];
|
|
86
|
-
for (const [key, val] of Object.entries(fields)) {
|
|
87
|
-
if (val !== undefined) {
|
|
88
|
-
sets.push(`${key} = ?`);
|
|
89
|
-
binds.push(val);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (!sets.length)
|
|
93
|
-
return { content: [{ type: "text", text: "No fields to update." }] };
|
|
94
|
-
sets.push("updated_at = CURRENT_TIMESTAMP");
|
|
95
|
-
binds.push(id);
|
|
96
|
-
await query(`UPDATE courses SET ${sets.join(", ")} WHERE id = ?`, binds);
|
|
71
|
+
await apiPatch(`/courses/${id}`, fields);
|
|
97
72
|
return { content: [{ type: "text", text: `Course ${id} updated.` }] };
|
|
98
73
|
});
|
|
99
74
|
server.registerTool("bypass_delete_course", {
|
|
@@ -102,8 +77,63 @@ export function registerCourseTools(server) {
|
|
|
102
77
|
inputSchema: { id: z.number().int().describe("Course ID") },
|
|
103
78
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
104
79
|
}, async (params) => {
|
|
105
|
-
await
|
|
80
|
+
await apiDelete(`/courses/${params.id}`);
|
|
106
81
|
return { content: [{ type: "text", text: `Course ${params.id} deleted.` }] };
|
|
107
82
|
});
|
|
83
|
+
// Course Items (Purchase Items)
|
|
84
|
+
server.registerTool("bypass_list_course_items", {
|
|
85
|
+
title: "List Course Items",
|
|
86
|
+
description: "List all purchase items for a course.",
|
|
87
|
+
inputSchema: { course_id: z.number().int().describe("Course ID") },
|
|
88
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
89
|
+
}, async (params) => {
|
|
90
|
+
const data = await apiGet(`/courses/${params.course_id}/items`);
|
|
91
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
92
|
+
});
|
|
93
|
+
server.registerTool("bypass_create_course_item", {
|
|
94
|
+
title: "Create Course Item",
|
|
95
|
+
description: "Create a new purchase item for a course. Price in cents (e.g. 9900 = ¥99). Content URL is the actual content rendered via iframe.",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
course_id: z.number().int().describe("Course ID"),
|
|
98
|
+
title: z.string().min(1).describe("Item title"),
|
|
99
|
+
price: z.number().int().min(0).describe("Price in cents"),
|
|
100
|
+
content_url: z.string().optional().describe("Content delivery URL (rendered via iframe after purchase)"),
|
|
101
|
+
sort_order: z.number().int().optional().describe("Sort order (lower first)"),
|
|
102
|
+
},
|
|
103
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
104
|
+
}, async (params) => {
|
|
105
|
+
const { course_id, ...body } = params;
|
|
106
|
+
await apiPost(`/courses/${course_id}/items`, body);
|
|
107
|
+
return { content: [{ type: "text", text: `Course item "${params.title}" created.` }] };
|
|
108
|
+
});
|
|
109
|
+
server.registerTool("bypass_update_course_item", {
|
|
110
|
+
title: "Update Course Item",
|
|
111
|
+
description: "Update an existing course item. Only provided fields are updated.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
course_id: z.number().int().describe("Course ID"),
|
|
114
|
+
item_id: z.number().int().describe("Item ID"),
|
|
115
|
+
title: z.string().optional(),
|
|
116
|
+
content_url: z.string().optional().describe("Content delivery URL (rendered via iframe after purchase)"),
|
|
117
|
+
price: z.number().int().optional(),
|
|
118
|
+
sort_order: z.number().int().optional(),
|
|
119
|
+
},
|
|
120
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
121
|
+
}, async (params) => {
|
|
122
|
+
const { course_id, item_id, ...fields } = params;
|
|
123
|
+
await apiPatch(`/courses/${course_id}/items/${item_id}`, fields);
|
|
124
|
+
return { content: [{ type: "text", text: `Course item ${item_id} updated.` }] };
|
|
125
|
+
});
|
|
126
|
+
server.registerTool("bypass_delete_course_item", {
|
|
127
|
+
title: "Delete Course Item",
|
|
128
|
+
description: "Permanently delete a course item by ID.",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
course_id: z.number().int().describe("Course ID"),
|
|
131
|
+
item_id: z.number().int().describe("Item ID"),
|
|
132
|
+
},
|
|
133
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
134
|
+
}, async (params) => {
|
|
135
|
+
await apiDelete(`/courses/${params.course_id}/items/${params.item_id}`);
|
|
136
|
+
return { content: [{ type: "text", text: `Course item ${params.item_id} deleted.` }] };
|
|
137
|
+
});
|
|
108
138
|
}
|
|
109
139
|
//# sourceMappingURL=courses.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"courses.js","sourceRoot":"","sources":["../../src/tools/courses.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"courses.js","sourceRoot":"","sources":["../../src/tools/courses.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CAAC,qBAAqB,EAAE;QACzC,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,2FAA2F;QACxG,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAC9E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC1E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YACzD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC3E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;SACzE;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,MAAM;YAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,MAAM,CAAC,WAAW;YAAE,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1E,IAAI,MAAM,CAAC,MAAM;YAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAExC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,mBAAmB,EAAE;QACvC,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,kEAAkE;QAC/E,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QAC3D,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,sBAAsB,EAAE;QAC1C,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,yGAAyG;QACtH,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;YACjD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC5C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YACjE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;YACtF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;YAChE,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YACpE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC5D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YAClF,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;SAC3E;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1G,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,WAAW,MAAM,CAAC,KAAK,yBAAyB,EAAE,CAAC,EAAE,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,sBAAsB,EAAE;QAC1C,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,6GAA6G;QAC1H,WAAW,EAAE;YACX,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACzD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;YACtF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACtE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE;SAClD;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACzG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;QACjC,MAAM,QAAQ,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,sBAAsB,EAAE;QAC1C,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,oCAAoC;QACjD,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QAC3D,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,SAAS,CAAC,YAAY,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,gCAAgC;IAChC,MAAM,CAAC,YAAY,CAAC,0BAA0B,EAAE;QAC9C,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,uCAAuC;QACpD,WAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QAClE,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,MAAM,CAAC,SAAS,QAAQ,CAAC,CAAC;QAChE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,2BAA2B,EAAE;QAC/C,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,mIAAmI;QAChJ,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YACjD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACzD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;YACxG,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;SAC7E;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE;KAC1G,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;QACtC,MAAM,OAAO,CAAC,YAAY,SAAS,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gBAAgB,MAAM,CAAC,KAAK,YAAY,EAAE,CAAC,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,2BAA2B,EAAE;QAC/C,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,mEAAmE;QAChF,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC7C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;YACxG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACxC;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACzG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC;QACjD,MAAM,QAAQ,CAAC,YAAY,SAAS,UAAU,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;QACjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,OAAO,WAAW,EAAE,CAAC,EAAE,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,2BAA2B,EAAE;QAC/C,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,yCAAyC;QACtD,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;YACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;SAC9C;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,SAAS,CAAC,YAAY,MAAM,CAAC,SAAS,UAAU,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,MAAM,CAAC,OAAO,WAAW,EAAE,CAAC,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/tools/orders.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { apiGet } from "../services/api.js";
|
|
3
3
|
export function registerOrderTools(server) {
|
|
4
4
|
server.registerTool("bypass_list_orders", {
|
|
5
5
|
title: "List Orders",
|
|
@@ -11,22 +11,13 @@ export function registerOrderTools(server) {
|
|
|
11
11
|
},
|
|
12
12
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
13
13
|
}, async (params) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const countResult = await queryFirst(`SELECT COUNT(*) as total FROM orders o ${where}`, binds);
|
|
22
|
-
const total = countResult?.total ?? 0;
|
|
23
|
-
const rows = await query(`SELECT o.*, u.name AS user_name, u.email AS user_email, c.title AS course_title
|
|
24
|
-
FROM orders o
|
|
25
|
-
LEFT JOIN users u ON o.user_id = u.id
|
|
26
|
-
LEFT JOIN courses c ON o.course_id = c.id
|
|
27
|
-
${where} ORDER BY o.created_at DESC LIMIT ? OFFSET ?`, [...binds, params.limit, params.offset]);
|
|
28
|
-
const output = { total, count: rows.results.length, offset: params.offset, orders: rows.results, has_more: total > params.offset + rows.results.length };
|
|
29
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
14
|
+
const qs = new URLSearchParams();
|
|
15
|
+
if (params.status)
|
|
16
|
+
qs.set("status", params.status);
|
|
17
|
+
qs.set("limit", String(params.limit));
|
|
18
|
+
qs.set("offset", String(params.offset));
|
|
19
|
+
const data = await apiGet(`/orders?${qs}`);
|
|
20
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
30
21
|
});
|
|
31
22
|
}
|
|
32
23
|
//# sourceMappingURL=orders.js.map
|
package/dist/tools/orders.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orders.js","sourceRoot":"","sources":["../../src/tools/orders.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"orders.js","sourceRoot":"","sources":["../../src/tools/orders.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,YAAY,CAAC,oBAAoB,EAAE;QACxC,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,yEAAyE;QACtF,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;YAC3F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC3E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;SACzE;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAClB,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,MAAM;YAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAExC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/tools/stats.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { apiGet } from "../services/api.js";
|
|
2
2
|
export function registerStatsTools(server) {
|
|
3
3
|
server.registerTool("bypass_get_stats", {
|
|
4
4
|
title: "Get Dashboard Stats",
|
|
@@ -6,15 +6,8 @@ export function registerStatsTools(server) {
|
|
|
6
6
|
inputSchema: {},
|
|
7
7
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
8
8
|
}, async () => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
queryFirst(`SELECT COUNT(*) as total, SUM(CASE WHEN status='published' THEN 1 ELSE 0 END) as published, SUM(CASE WHEN status='draft' THEN 1 ELSE 0 END) as draft FROM courses`),
|
|
12
|
-
queryFirst(`SELECT COUNT(*) as total_orders, SUM(CASE WHEN status='paid' THEN 1 ELSE 0 END) as paid_orders, COALESCE(SUM(CASE WHEN status='paid' THEN amount ELSE 0 END),0) as total_revenue FROM orders`),
|
|
13
|
-
queryFirst(`SELECT COUNT(*) as total, SUM(CASE WHEN status='published' THEN 1 ELSE 0 END) as published FROM blog_articles`),
|
|
14
|
-
queryFirst(`SELECT COUNT(*) as total_enrollments, COUNT(DISTINCT user_id) as total_students, COALESCE(AVG(progress),0) as avg_progress, SUM(CASE WHEN progress>=100 THEN 1 ELSE 0 END) as completed FROM user_courses`),
|
|
15
|
-
]);
|
|
16
|
-
const output = { users, courses, orders, articles, enrollments };
|
|
17
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
9
|
+
const data = await apiGet("/stats");
|
|
10
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
18
11
|
});
|
|
19
12
|
server.registerTool("bypass_list_categories", {
|
|
20
13
|
title: "List Categories",
|
|
@@ -22,8 +15,8 @@ export function registerStatsTools(server) {
|
|
|
22
15
|
inputSchema: {},
|
|
23
16
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
24
17
|
}, async () => {
|
|
25
|
-
const
|
|
26
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
18
|
+
const data = await apiGet("/categories");
|
|
19
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
27
20
|
});
|
|
28
21
|
}
|
|
29
22
|
//# sourceMappingURL=stats.js.map
|
package/dist/tools/stats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/tools/stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/tools/stats.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,YAAY,CAAC,kBAAkB,EAAE;QACtC,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,qFAAqF;QAClG,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,IAAI,EAAE;QACZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAAC,wBAAwB,EAAE;QAC5C,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,6BAA6B;QAC1C,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACxG,EAAE,KAAK,IAAI,EAAE;QACZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/tools/students.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { apiGet } from "../services/api.js";
|
|
3
3
|
export function registerStudentTools(server) {
|
|
4
4
|
server.registerTool("bypass_list_students", {
|
|
5
5
|
title: "List Student Enrollments",
|
|
@@ -11,21 +11,13 @@ export function registerStudentTools(server) {
|
|
|
11
11
|
},
|
|
12
12
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
13
13
|
}, async (params) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
22
|
-
const countResult = await queryFirst(`SELECT COUNT(*) as total FROM user_courses uc JOIN users u ON uc.user_id = u.id JOIN courses c ON uc.course_id = c.id ${where}`, binds);
|
|
23
|
-
const total = countResult?.total ?? 0;
|
|
24
|
-
const rows = await query(`SELECT uc.*, u.name AS user_name, u.email AS user_email, c.title AS course_title, c.price AS course_price
|
|
25
|
-
FROM user_courses uc JOIN users u ON uc.user_id = u.id JOIN courses c ON uc.course_id = c.id
|
|
26
|
-
${where} ORDER BY uc.purchased_at DESC LIMIT ? OFFSET ?`, [...binds, params.limit, params.offset]);
|
|
27
|
-
const output = { total, count: rows.results.length, offset: params.offset, enrollments: rows.results, has_more: total > params.offset + rows.results.length };
|
|
28
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
14
|
+
const qs = new URLSearchParams();
|
|
15
|
+
if (params.search)
|
|
16
|
+
qs.set("search", params.search);
|
|
17
|
+
qs.set("limit", String(params.limit));
|
|
18
|
+
qs.set("offset", String(params.offset));
|
|
19
|
+
const data = await apiGet(`/students?${qs}`);
|
|
20
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
29
21
|
});
|
|
30
22
|
server.registerTool("bypass_list_users", {
|
|
31
23
|
title: "List Users",
|
|
@@ -37,19 +29,13 @@ export function registerStudentTools(server) {
|
|
|
37
29
|
},
|
|
38
30
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
39
31
|
}, async (params) => {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
48
|
-
const countResult = await queryFirst(`SELECT COUNT(*) as total FROM users ${where}`, binds);
|
|
49
|
-
const total = countResult?.total ?? 0;
|
|
50
|
-
const rows = await query(`SELECT * FROM users ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`, [...binds, params.limit, params.offset]);
|
|
51
|
-
const output = { total, count: rows.results.length, offset: params.offset, users: rows.results, has_more: total > params.offset + rows.results.length };
|
|
52
|
-
return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }] };
|
|
32
|
+
const qs = new URLSearchParams();
|
|
33
|
+
if (params.search)
|
|
34
|
+
qs.set("search", params.search);
|
|
35
|
+
qs.set("limit", String(params.limit));
|
|
36
|
+
qs.set("offset", String(params.offset));
|
|
37
|
+
const data = await apiGet(`/users?${qs}`);
|
|
38
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
53
39
|
});
|
|
54
40
|
}
|
|
55
41
|
//# sourceMappingURL=students.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"students.js","sourceRoot":"","sources":["../../src/tools/students.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"students.js","sourceRoot":"","sources":["../../src/tools/students.ts"],"names":[],"mappings":"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"}
|