@redonvn/cli 0.1.6 → 0.1.9
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/dist/auth/permissions.d.ts +20 -0
- package/dist/auth/permissions.js +73 -0
- package/dist/auth/permissions.js.map +1 -0
- package/dist/auth/store.d.ts +1 -0
- package/dist/auth/store.js.map +1 -1
- package/dist/build-info.d.ts +2 -2
- package/dist/build-info.js +2 -2
- package/dist/cli/commands/ask.d.ts +1 -0
- package/dist/cli/commands/ask.js +451 -0
- package/dist/cli/commands/ask.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +20 -0
- package/dist/cli/commands/mcp.js +175 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/permission.d.ts +1 -0
- package/dist/cli/commands/permission.js +176 -0
- package/dist/cli/commands/permission.js.map +1 -0
- package/dist/cli/index.js +67 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli-router/detect.js +6 -0
- package/dist/cli-router/detect.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/daemon/tunnel.js +2 -0
- package/dist/daemon/tunnel.js.map +1 -1
- package/dist/mcp/client.d.ts +14 -0
- package/dist/mcp/client.js +51 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config.d.ts +65 -0
- package/dist/mcp/config.js +132 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/tools/mcp-call.d.ts +1 -0
- package/dist/tools/mcp-call.js +20 -0
- package/dist/tools/mcp-call.js.map +1 -0
- package/dist/tools/mcp-list.d.ts +13 -0
- package/dist/tools/mcp-list.js +43 -0
- package/dist/tools/mcp-list.js.map +1 -0
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.js +9 -0
- package/dist/tools/registry.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mcpClientPool = void 0;
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
/**
|
|
8
|
+
* Singleton pool giữ kết nối MCP client cho từng server.
|
|
9
|
+
* Lazy spawn — chỉ connect khi có tool call đầu tiên đến server đó.
|
|
10
|
+
* Auto-reconnect: nếu transport bị đóng, xóa khỏi pool → lần sau sẽ spawn lại.
|
|
11
|
+
*/
|
|
12
|
+
class McpClientPool {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.pool = new Map();
|
|
15
|
+
}
|
|
16
|
+
async getClient(serverName) {
|
|
17
|
+
const existing = this.pool.get(serverName);
|
|
18
|
+
if (existing)
|
|
19
|
+
return existing.client;
|
|
20
|
+
const servers = (0, config_1.loadMcpConfig)();
|
|
21
|
+
const cfg = servers[serverName];
|
|
22
|
+
if (!cfg) {
|
|
23
|
+
throw new Error(`MCP server "${serverName}" not found in ~/.redai/mcp.json`);
|
|
24
|
+
}
|
|
25
|
+
const transport = new stdio_js_1.StdioClientTransport({
|
|
26
|
+
command: cfg.command,
|
|
27
|
+
args: cfg.args ?? [],
|
|
28
|
+
env: cfg.env
|
|
29
|
+
? Object.fromEntries(Object.entries({ ...process.env, ...cfg.env }).filter(([, v]) => v !== undefined))
|
|
30
|
+
: undefined,
|
|
31
|
+
});
|
|
32
|
+
const client = new index_js_1.Client({ name: 'redai-cli', version: '1.0.0' }, { capabilities: {} });
|
|
33
|
+
await client.connect(transport);
|
|
34
|
+
// Khi transport đóng bất ngờ → xóa khỏi pool để lần sau spawn lại
|
|
35
|
+
transport.onclose = () => {
|
|
36
|
+
this.pool.delete(serverName);
|
|
37
|
+
};
|
|
38
|
+
this.pool.set(serverName, { client, transport });
|
|
39
|
+
return client;
|
|
40
|
+
}
|
|
41
|
+
async shutdown() {
|
|
42
|
+
const entries = [...this.pool.values()];
|
|
43
|
+
this.pool.clear();
|
|
44
|
+
await Promise.allSettled(entries.map((e) => e.client.close()));
|
|
45
|
+
}
|
|
46
|
+
listConnected() {
|
|
47
|
+
return [...this.pool.keys()];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.mcpClientPool = new McpClientPool();
|
|
51
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":";;;AAAA,wEAAmE;AACnE,wEAAiF;AACjF,qCAA+D;AAO/D;;;;GAIG;AACH,MAAM,aAAa;IAAnB;QACU,SAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IA+C9C,CAAC;IA7CC,KAAK,CAAC,SAAS,CAAC,UAAkB;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,MAAM,CAAC;QAErC,MAAM,OAAO,GAAG,IAAA,sBAAa,GAAE,CAAC;QAChC,MAAM,GAAG,GAAgC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,kCAAkC,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,+BAAoB,CAAC;YACzC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;YACpB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACV,CAAC,CAAE,MAAM,CAAC,WAAW,CACjB,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CACvD;gBAC9B,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,iBAAM,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,EACvC,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;QAEF,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,kEAAkE;QAClE,SAAS,CAAC,OAAO,GAAG,GAAG,EAAE;YACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,aAAa;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;CACF;AAEY,QAAA,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const McpServerConfigSchema: z.ZodObject<{
|
|
3
|
+
command: z.ZodString;
|
|
4
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
5
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
6
|
+
transport: z.ZodLiteral<"stdio">;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
command: string;
|
|
9
|
+
transport: "stdio";
|
|
10
|
+
args?: string[] | undefined;
|
|
11
|
+
env?: Record<string, string> | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
command: string;
|
|
14
|
+
transport: "stdio";
|
|
15
|
+
args?: string[] | undefined;
|
|
16
|
+
env?: Record<string, string> | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
declare const McpConfigFileSchema: z.ZodObject<{
|
|
19
|
+
servers: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
20
|
+
command: z.ZodString;
|
|
21
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
22
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
23
|
+
transport: z.ZodLiteral<"stdio">;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
command: string;
|
|
26
|
+
transport: "stdio";
|
|
27
|
+
args?: string[] | undefined;
|
|
28
|
+
env?: Record<string, string> | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
command: string;
|
|
31
|
+
transport: "stdio";
|
|
32
|
+
args?: string[] | undefined;
|
|
33
|
+
env?: Record<string, string> | undefined;
|
|
34
|
+
}>>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
servers: Record<string, {
|
|
37
|
+
command: string;
|
|
38
|
+
transport: "stdio";
|
|
39
|
+
args?: string[] | undefined;
|
|
40
|
+
env?: Record<string, string> | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
}, {
|
|
43
|
+
servers: Record<string, {
|
|
44
|
+
command: string;
|
|
45
|
+
transport: "stdio";
|
|
46
|
+
args?: string[] | undefined;
|
|
47
|
+
env?: Record<string, string> | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
}>;
|
|
50
|
+
export type McpServerConfig = z.infer<typeof McpServerConfigSchema>;
|
|
51
|
+
export type McpConfigFile = z.infer<typeof McpConfigFileSchema>;
|
|
52
|
+
export declare function loadMcpConfig(): Record<string, McpServerConfig>;
|
|
53
|
+
export declare function getMcpConfigPath(): string;
|
|
54
|
+
export declare function saveMcpConfig(servers: Record<string, McpServerConfig>): void;
|
|
55
|
+
export interface McpCatalogEntry {
|
|
56
|
+
/** Key sẽ dùng trong mcp.json */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Mô tả ngắn cho user */
|
|
59
|
+
description: string;
|
|
60
|
+
/** Các tool nổi bật */
|
|
61
|
+
tools: string;
|
|
62
|
+
config: McpServerConfig;
|
|
63
|
+
}
|
|
64
|
+
export declare const MCP_CATALOG: McpCatalogEntry[];
|
|
65
|
+
export {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MCP_CATALOG = void 0;
|
|
7
|
+
exports.loadMcpConfig = loadMcpConfig;
|
|
8
|
+
exports.getMcpConfigPath = getMcpConfigPath;
|
|
9
|
+
exports.saveMcpConfig = saveMcpConfig;
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const os_1 = __importDefault(require("os"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
const McpServerConfigSchema = zod_1.z.object({
|
|
15
|
+
command: zod_1.z.string(),
|
|
16
|
+
args: zod_1.z.array(zod_1.z.string()).optional(),
|
|
17
|
+
env: zod_1.z.record(zod_1.z.string()).optional(),
|
|
18
|
+
transport: zod_1.z.literal('stdio'),
|
|
19
|
+
});
|
|
20
|
+
const McpConfigFileSchema = zod_1.z.object({
|
|
21
|
+
servers: zod_1.z.record(McpServerConfigSchema),
|
|
22
|
+
});
|
|
23
|
+
const MCP_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), '.redai', 'mcp.json');
|
|
24
|
+
function loadMcpConfig() {
|
|
25
|
+
try {
|
|
26
|
+
if (!fs_1.default.existsSync(MCP_CONFIG_PATH))
|
|
27
|
+
return {};
|
|
28
|
+
const raw = fs_1.default.readFileSync(MCP_CONFIG_PATH, 'utf-8');
|
|
29
|
+
const parsed = McpConfigFileSchema.safeParse(JSON.parse(raw));
|
|
30
|
+
if (!parsed.success)
|
|
31
|
+
return {};
|
|
32
|
+
return parsed.data.servers;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function getMcpConfigPath() {
|
|
39
|
+
return MCP_CONFIG_PATH;
|
|
40
|
+
}
|
|
41
|
+
function saveMcpConfig(servers) {
|
|
42
|
+
const dir = path_1.default.dirname(MCP_CONFIG_PATH);
|
|
43
|
+
if (!fs_1.default.existsSync(dir))
|
|
44
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
45
|
+
fs_1.default.writeFileSync(MCP_CONFIG_PATH, JSON.stringify({ servers }, null, 2), 'utf-8');
|
|
46
|
+
}
|
|
47
|
+
exports.MCP_CATALOG = [
|
|
48
|
+
{
|
|
49
|
+
name: 'chrome',
|
|
50
|
+
description: 'Chrome / Puppeteer — điều khiển trình duyệt, chụp screenshot, scrape web',
|
|
51
|
+
tools: 'puppeteer_navigate, puppeteer_screenshot, puppeteer_click, puppeteer_fill, ...',
|
|
52
|
+
config: {
|
|
53
|
+
command: 'npx',
|
|
54
|
+
args: ['-y', '@modelcontextprotocol/server-puppeteer'],
|
|
55
|
+
transport: 'stdio',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'filesystem',
|
|
60
|
+
description: 'Filesystem — đọc/ghi file với sandbox trong thư mục cho phép',
|
|
61
|
+
tools: 'read_file, write_file, list_directory, search_files, ...',
|
|
62
|
+
config: {
|
|
63
|
+
command: 'npx',
|
|
64
|
+
args: ['-y', '@modelcontextprotocol/server-filesystem', process.env['HOME'] ?? '.'],
|
|
65
|
+
transport: 'stdio',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'postgres',
|
|
70
|
+
description: 'PostgreSQL — query database, describe schema',
|
|
71
|
+
tools: 'query, list_tables, describe_table',
|
|
72
|
+
config: {
|
|
73
|
+
command: 'npx',
|
|
74
|
+
args: ['-y', '@modelcontextprotocol/server-postgres', 'postgresql://localhost/mydb'],
|
|
75
|
+
transport: 'stdio',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'github',
|
|
80
|
+
description: 'GitHub — quản lý repo, PR, issues, search code',
|
|
81
|
+
tools: 'create_issue, list_pull_requests, search_repositories, get_file_contents, ...',
|
|
82
|
+
config: {
|
|
83
|
+
command: 'npx',
|
|
84
|
+
args: ['-y', '@modelcontextprotocol/server-github'],
|
|
85
|
+
env: { GITHUB_PERSONAL_ACCESS_TOKEN: '<your-token>' },
|
|
86
|
+
transport: 'stdio',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'slack',
|
|
91
|
+
description: 'Slack — đọc/gửi message, list channels',
|
|
92
|
+
tools: 'post_message, list_channels, get_channel_history, ...',
|
|
93
|
+
config: {
|
|
94
|
+
command: 'npx',
|
|
95
|
+
args: ['-y', '@modelcontextprotocol/server-slack'],
|
|
96
|
+
env: { SLACK_BOT_TOKEN: '<your-token>', SLACK_TEAM_ID: '<team-id>' },
|
|
97
|
+
transport: 'stdio',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'brave-search',
|
|
102
|
+
description: 'Brave Search — web search + local search qua Brave API',
|
|
103
|
+
tools: 'brave_web_search, brave_local_search',
|
|
104
|
+
config: {
|
|
105
|
+
command: 'npx',
|
|
106
|
+
args: ['-y', '@modelcontextprotocol/server-brave-search'],
|
|
107
|
+
env: { BRAVE_API_KEY: '<your-key>' },
|
|
108
|
+
transport: 'stdio',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: 'memory',
|
|
113
|
+
description: 'Memory — lưu trữ knowledge graph persistent cho AI agent',
|
|
114
|
+
tools: 'create_entities, create_relations, search_nodes, read_graph, ...',
|
|
115
|
+
config: {
|
|
116
|
+
command: 'npx',
|
|
117
|
+
args: ['-y', '@modelcontextprotocol/server-memory'],
|
|
118
|
+
transport: 'stdio',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'fetch',
|
|
123
|
+
description: 'Fetch — HTTP client: fetch URL, convert HTML sang markdown',
|
|
124
|
+
tools: 'fetch (GET/POST any URL)',
|
|
125
|
+
config: {
|
|
126
|
+
command: 'npx',
|
|
127
|
+
args: ['-y', '@modelcontextprotocol/server-fetch'],
|
|
128
|
+
transport: 'stdio',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/mcp/config.ts"],"names":[],"mappings":";;;;;;AAqBA,sCAUC;AAED,4CAEC;AAED,sCAIC;AAzCD,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,6BAAwB;AAExB,MAAM,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IACrC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,GAAG,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,SAAS,EAAE,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC;CACzC,CAAC,CAAC;AAKH,MAAM,eAAe,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AAEtE,SAAgB,aAAa;IAC3B,IAAI,CAAC;QACH,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,eAAe,CAAC;YAAE,OAAO,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,SAAgB,aAAa,CAAC,OAAwC;IACpE,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC1C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,YAAE,CAAC,aAAa,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACnF,CAAC;AAcY,QAAA,WAAW,GAAsB;IAC5C;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,0EAA0E;QACvF,KAAK,EAAE,gFAAgF;QACvF,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,wCAAwC,CAAC;YACtD,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,8DAA8D;QAC3E,KAAK,EAAE,0DAA0D;QACjE,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,yCAAyC,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;YACnF,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,8CAA8C;QAC3D,KAAK,EAAE,oCAAoC;QAC3C,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,uCAAuC,EAAE,6BAA6B,CAAC;YACpF,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,gDAAgD;QAC7D,KAAK,EAAE,+EAA+E;QACtF,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,qCAAqC,CAAC;YACnD,GAAG,EAAE,EAAE,4BAA4B,EAAE,cAAc,EAAE;YACrD,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,wCAAwC;QACrD,KAAK,EAAE,uDAAuD;QAC9D,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,oCAAoC,CAAC;YAClD,GAAG,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE;YACpE,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,wDAAwD;QACrE,KAAK,EAAE,sCAAsC;QAC7C,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,2CAA2C,CAAC;YACzD,GAAG,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE;YACpC,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,0DAA0D;QACvE,KAAK,EAAE,kEAAkE;QACzE,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,qCAAqC,CAAC;YACnD,SAAS,EAAE,OAAO;SACnB;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,4DAA4D;QACzE,KAAK,EAAE,0BAA0B;QACjC,MAAM,EAAE;YACN,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,oCAAoC,CAAC;YAClD,SAAS,EAAE,OAAO;SACnB;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function mcpCallTool(input: unknown): Promise<unknown>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mcpCallTool = mcpCallTool;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const client_1 = require("../mcp/client");
|
|
6
|
+
const McpCallParamsSchema = zod_1.z.object({
|
|
7
|
+
server: zod_1.z.string().min(1),
|
|
8
|
+
tool: zod_1.z.string().min(1),
|
|
9
|
+
arguments: zod_1.z.record(zod_1.z.unknown()).optional().default({}),
|
|
10
|
+
});
|
|
11
|
+
async function mcpCallTool(input) {
|
|
12
|
+
const params = McpCallParamsSchema.parse(input);
|
|
13
|
+
const client = await client_1.mcpClientPool.getClient(params.server);
|
|
14
|
+
const response = await client.callTool({
|
|
15
|
+
name: params.tool,
|
|
16
|
+
arguments: params.arguments,
|
|
17
|
+
});
|
|
18
|
+
return response;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=mcp-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-call.js","sourceRoot":"","sources":["../../src/tools/mcp-call.ts"],"names":[],"mappings":";;AASA,kCAUC;AAnBD,6BAAwB;AACxB,0CAA8C;AAE9C,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,SAAS,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACxD,CAAC,CAAC;AAEI,KAAK,UAAU,WAAW,CAAC,KAAc;IAC9C,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,MAAM,sBAAa,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;QACrC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface McpToolInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
inputSchema?: unknown;
|
|
5
|
+
}
|
|
6
|
+
interface McpListResult {
|
|
7
|
+
servers: Record<string, {
|
|
8
|
+
tools: McpToolInfo[];
|
|
9
|
+
error?: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export declare function mcpListTool(input: unknown): Promise<McpListResult>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mcpListTool = mcpListTool;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const config_1 = require("../mcp/config");
|
|
6
|
+
const client_1 = require("../mcp/client");
|
|
7
|
+
const McpListParamsSchema = zod_1.z.object({
|
|
8
|
+
server: zod_1.z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
async function mcpListTool(input) {
|
|
11
|
+
const params = McpListParamsSchema.parse(input);
|
|
12
|
+
const servers = (0, config_1.loadMcpConfig)();
|
|
13
|
+
const result = { servers: {} };
|
|
14
|
+
const targetServers = params.server
|
|
15
|
+
? params.server in servers
|
|
16
|
+
? [params.server]
|
|
17
|
+
: []
|
|
18
|
+
: Object.keys(servers);
|
|
19
|
+
if (params.server && !(params.server in servers)) {
|
|
20
|
+
throw new Error(`MCP server "${params.server}" not found in ~/.redai/mcp.json`);
|
|
21
|
+
}
|
|
22
|
+
await Promise.all(targetServers.map(async (name) => {
|
|
23
|
+
try {
|
|
24
|
+
const client = await client_1.mcpClientPool.getClient(name);
|
|
25
|
+
const { tools } = await client.listTools();
|
|
26
|
+
result.servers[name] = {
|
|
27
|
+
tools: tools.map((t) => ({
|
|
28
|
+
name: t.name,
|
|
29
|
+
description: t.description,
|
|
30
|
+
inputSchema: t.inputSchema,
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
result.servers[name] = {
|
|
36
|
+
tools: [],
|
|
37
|
+
error: err instanceof Error ? err.message : String(err),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}));
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=mcp-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-list.js","sourceRoot":"","sources":["../../src/tools/mcp-list.ts"],"names":[],"mappings":";;AAkBA,kCAqCC;AAvDD,6BAAwB;AACxB,0CAA8C;AAC9C,0CAA8C;AAE9C,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAYI,KAAK,UAAU,WAAW,CAAC,KAAc;IAC9C,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAA,sBAAa,GAAE,CAAC;IAChC,MAAM,MAAM,GAAkB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAE9C,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM;QACjC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO;YACxB,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;YACjB,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEzB,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,CAAC,MAAM,kCAAkC,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,OAAO,CAAC,GAAG,CACf,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,sBAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG;gBACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACvB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;iBAC3B,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG;gBACrB,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ToolName = 'Read' | 'Write' | 'Edit' | 'Bash' | 'Grep' | 'Glob' | 'WebFetch' | 'RunClaude' | 'RunCodex' | 'RunGemini' | 'LLMRequest';
|
|
1
|
+
export type ToolName = 'Read' | 'Write' | 'Edit' | 'Bash' | 'Grep' | 'Glob' | 'WebFetch' | 'RunClaude' | 'RunCodex' | 'RunGemini' | 'LLMRequest' | 'McpCall' | 'McpList';
|
|
2
2
|
export interface ToolContext {
|
|
3
3
|
timeoutMs?: number;
|
|
4
4
|
cwd?: string;
|
package/dist/tools/registry.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runTool = runTool;
|
|
4
|
+
const permissions_1 = require("../auth/permissions");
|
|
4
5
|
const llm_request_1 = require("../llm/llm-request");
|
|
5
6
|
const bash_1 = require("./bash");
|
|
6
7
|
const edit_1 = require("./edit");
|
|
7
8
|
const glob_1 = require("./glob");
|
|
8
9
|
const grep_1 = require("./grep");
|
|
10
|
+
const mcp_call_1 = require("./mcp-call");
|
|
11
|
+
const mcp_list_1 = require("./mcp-list");
|
|
9
12
|
const read_1 = require("./read");
|
|
10
13
|
const run_cli_1 = require("./run-cli");
|
|
11
14
|
const webfetch_1 = require("./webfetch");
|
|
@@ -22,6 +25,8 @@ const HANDLERS = {
|
|
|
22
25
|
RunCodex: (p, ctx) => (0, run_cli_1.runCliTool)('codex', injectCwd(p, ctx.cwd)),
|
|
23
26
|
RunGemini: (p, ctx) => (0, run_cli_1.runCliTool)('gemini', injectCwd(p, ctx.cwd)),
|
|
24
27
|
LLMRequest: (p, ctx) => (0, llm_request_1.llmRequestTool)(p, { onStream: ctx.onStream }),
|
|
28
|
+
McpCall: (p) => (0, mcp_call_1.mcpCallTool)(p),
|
|
29
|
+
McpList: (p) => (0, mcp_list_1.mcpListTool)(p),
|
|
25
30
|
};
|
|
26
31
|
function injectCwd(params, cwd) {
|
|
27
32
|
if (!cwd)
|
|
@@ -38,6 +43,10 @@ async function runTool(name, params, ctx = {}) {
|
|
|
38
43
|
if (!handler) {
|
|
39
44
|
throw new Error(`Tool not supported on this CLI: ${name}`);
|
|
40
45
|
}
|
|
46
|
+
const perms = (0, permissions_1.loadPermissions)();
|
|
47
|
+
if (!(0, permissions_1.isToolAllowed)(name, perms)) {
|
|
48
|
+
throw new Error(`Tool '${name}' is disabled on this machine. Run \`redai permission enable ${name}\` to allow it.`);
|
|
49
|
+
}
|
|
41
50
|
return handler(params, ctx);
|
|
42
51
|
}
|
|
43
52
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redonvn/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "RedAI CLI — kết nối máy bạn với RedAI agent runtime. AI cloud agent có thể run tools (Read/Write/Edit/Bash/Grep/Glob/WebFetch), spawn code-CLI (Claude/Codex/Gemini), và proxy LLM request qua OAuth của bạn (Claude Code / ChatGPT / Gemini / Antigravity / Qwen / Kimi / iFlow / xAI).",
|
|
5
5
|
"bin": {
|
|
6
6
|
"redai": "./bin/redai.js"
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"homepage": "https://github.com/redonvn/redai-cli#readme",
|
|
58
58
|
"dependencies": {
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
59
60
|
"@redonvn/cli-protocol": "^0.1.2",
|
|
60
61
|
"@vscode/ripgrep": "^1.15.9",
|
|
61
62
|
"axios": "^1.7.7",
|