@happycastle/oh-my-openclaw 0.13.2 → 0.13.3
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/cli/mcporter-setup.d.ts +41 -0
- package/dist/cli/mcporter-setup.js +102 -0
- package/dist/cli/setup.d.ts +5 -0
- package/dist/cli/setup.js +31 -5
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
type McpServerEntry = {
|
|
2
|
+
url: string;
|
|
3
|
+
description: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const OMOC_MCP_SERVERS: Record<string, McpServerEntry>;
|
|
6
|
+
type McporterConfig = {
|
|
7
|
+
mcpServers: Record<string, {
|
|
8
|
+
url?: string;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolve mcporter config path.
|
|
17
|
+
* Priority: ~/.openclaw/workspace/config/mcporter.json > ~/.config/mcporter/mcporter.json
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveMcporterConfigPath(): string;
|
|
20
|
+
export declare function readMcporterConfig(configPath: string): McporterConfig;
|
|
21
|
+
export declare function writeMcporterConfig(configPath: string, config: McporterConfig): void;
|
|
22
|
+
export interface McporterMergeResult {
|
|
23
|
+
added: string[];
|
|
24
|
+
skipped: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare function mergeMcpServers(existing: McporterConfig, servers: Record<string, McpServerEntry>): {
|
|
27
|
+
config: McporterConfig;
|
|
28
|
+
result: McporterMergeResult;
|
|
29
|
+
};
|
|
30
|
+
type Logger = {
|
|
31
|
+
info: (msg: string) => void;
|
|
32
|
+
warn: (msg: string) => void;
|
|
33
|
+
error: (msg: string) => void;
|
|
34
|
+
};
|
|
35
|
+
export interface McporterSetupOptions {
|
|
36
|
+
configPath?: string;
|
|
37
|
+
dryRun?: boolean;
|
|
38
|
+
logger: Logger;
|
|
39
|
+
}
|
|
40
|
+
export declare function runMcporterSetup(options: McporterSetupOptions): McporterMergeResult;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export const OMOC_MCP_SERVERS = {
|
|
4
|
+
'web-search-prime': {
|
|
5
|
+
url: 'https://api.z.ai/api/mcp/web_search_prime/mcp',
|
|
6
|
+
description: 'Keyword-based web search (news, blogs, general)',
|
|
7
|
+
},
|
|
8
|
+
'web-reader': {
|
|
9
|
+
url: 'https://api.z.ai/api/mcp/web_reader/mcp',
|
|
10
|
+
description: 'Clean full-page content extraction',
|
|
11
|
+
},
|
|
12
|
+
exa: {
|
|
13
|
+
url: 'https://mcp.exa.ai/mcp?tools=web_search_exa',
|
|
14
|
+
description: 'Semantic web search (Exa)',
|
|
15
|
+
},
|
|
16
|
+
context7: {
|
|
17
|
+
url: 'https://mcp.context7.com/mcp',
|
|
18
|
+
description: 'Library/framework documentation search',
|
|
19
|
+
},
|
|
20
|
+
grep_app: {
|
|
21
|
+
url: 'https://mcp.grep.app',
|
|
22
|
+
description: 'Open-source code search on GitHub',
|
|
23
|
+
},
|
|
24
|
+
zread: {
|
|
25
|
+
url: 'https://api.z.ai/api/mcp/zread/mcp',
|
|
26
|
+
description: 'Direct GitHub repository exploration',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolve mcporter config path.
|
|
31
|
+
* Priority: ~/.openclaw/workspace/config/mcporter.json > ~/.config/mcporter/mcporter.json
|
|
32
|
+
*/
|
|
33
|
+
export function resolveMcporterConfigPath() {
|
|
34
|
+
const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '';
|
|
35
|
+
const openclawPath = path.join(homeDir, '.openclaw', 'workspace', 'config', 'mcporter.json');
|
|
36
|
+
if (fs.existsSync(openclawPath)) {
|
|
37
|
+
return openclawPath;
|
|
38
|
+
}
|
|
39
|
+
const mcporterHomePath = path.join(homeDir, '.config', 'mcporter', 'mcporter.json');
|
|
40
|
+
if (fs.existsSync(mcporterHomePath)) {
|
|
41
|
+
return mcporterHomePath;
|
|
42
|
+
}
|
|
43
|
+
return openclawPath;
|
|
44
|
+
}
|
|
45
|
+
export function readMcporterConfig(configPath) {
|
|
46
|
+
if (!fs.existsSync(configPath)) {
|
|
47
|
+
return { mcpServers: {} };
|
|
48
|
+
}
|
|
49
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
50
|
+
const parsed = JSON.parse(raw);
|
|
51
|
+
if (!parsed.mcpServers || typeof parsed.mcpServers !== 'object') {
|
|
52
|
+
parsed.mcpServers = {};
|
|
53
|
+
}
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
export function writeMcporterConfig(configPath, config) {
|
|
57
|
+
const dir = path.dirname(configPath);
|
|
58
|
+
if (!fs.existsSync(dir)) {
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
62
|
+
}
|
|
63
|
+
export function mergeMcpServers(existing, servers) {
|
|
64
|
+
const result = { added: [], skipped: [] };
|
|
65
|
+
const merged = { ...existing, mcpServers: { ...existing.mcpServers } };
|
|
66
|
+
for (const [name, entry] of Object.entries(servers)) {
|
|
67
|
+
if (merged.mcpServers[name]) {
|
|
68
|
+
result.skipped.push(name);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
merged.mcpServers[name] = { url: entry.url };
|
|
72
|
+
result.added.push(name);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { config: merged, result };
|
|
76
|
+
}
|
|
77
|
+
export function runMcporterSetup(options) {
|
|
78
|
+
const { logger, dryRun = false } = options;
|
|
79
|
+
const configPath = options.configPath ?? resolveMcporterConfigPath();
|
|
80
|
+
logger.info(`mcporter config: ${configPath}`);
|
|
81
|
+
const existing = readMcporterConfig(configPath);
|
|
82
|
+
const { config: merged, result } = mergeMcpServers(existing, OMOC_MCP_SERVERS);
|
|
83
|
+
if (result.added.length === 0) {
|
|
84
|
+
logger.info('No changes needed — all MCP servers already configured.');
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
if (dryRun) {
|
|
88
|
+
logger.info(`[dry-run] Would add ${result.added.length} MCP server(s): ${result.added.join(', ')}`);
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
if (fs.existsSync(configPath)) {
|
|
92
|
+
const backupPath = configPath + '.bak';
|
|
93
|
+
fs.copyFileSync(configPath, backupPath);
|
|
94
|
+
logger.info(`Backup created: ${backupPath}`);
|
|
95
|
+
}
|
|
96
|
+
writeMcporterConfig(configPath, merged);
|
|
97
|
+
logger.info(`Added ${result.added.length} MCP server(s): ${result.added.join(', ')}`);
|
|
98
|
+
if (result.skipped.length > 0) {
|
|
99
|
+
logger.info(`Skipped ${result.skipped.length} existing server(s): ${result.skipped.join(', ')}`);
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
package/dist/cli/setup.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface MergeResult {
|
|
|
27
27
|
added: string[];
|
|
28
28
|
skipped: string[];
|
|
29
29
|
updated: string[];
|
|
30
|
+
mcporterAdded?: string[];
|
|
31
|
+
mcporterSkipped?: string[];
|
|
30
32
|
}
|
|
31
33
|
export declare function mergeAgentConfigs(existing: Array<{
|
|
32
34
|
id: string;
|
|
@@ -41,6 +43,7 @@ export declare function mergeAgentConfigs(existing: Array<{
|
|
|
41
43
|
export declare function applyProviderToConfigs(configs: OmocAgentConfig[], provider: string): OmocAgentConfig[];
|
|
42
44
|
export declare function runInteractiveSetup(logger: Logger): Promise<{
|
|
43
45
|
provider: string;
|
|
46
|
+
setupMcporter: boolean;
|
|
44
47
|
}>;
|
|
45
48
|
export interface SetupOptions {
|
|
46
49
|
configPath?: string;
|
|
@@ -48,6 +51,8 @@ export interface SetupOptions {
|
|
|
48
51
|
force?: boolean;
|
|
49
52
|
dryRun?: boolean;
|
|
50
53
|
provider?: string;
|
|
54
|
+
setupMcporter?: boolean;
|
|
55
|
+
mcporterConfigPath?: string;
|
|
51
56
|
interactive?: boolean;
|
|
52
57
|
logger: Logger;
|
|
53
58
|
}
|
package/dist/cli/setup.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as readline from 'node:readline';
|
|
|
4
4
|
import JSON5 from 'json5';
|
|
5
5
|
import { OMOC_AGENT_CONFIGS } from '../agents/agent-configs.js';
|
|
6
6
|
import { PROVIDER_PRESETS, PROVIDER_LABELS, AGENT_TIER_MAP, MODEL_TIERS, applyProviderPreset, getProviderNames, buildCustomPreset, registerCustomPreset, } from './model-presets.js';
|
|
7
|
+
import { OMOC_MCP_SERVERS, runMcporterSetup } from './mcporter-setup.js';
|
|
7
8
|
const CONFIG_FILENAMES = [
|
|
8
9
|
'openclaw.json5',
|
|
9
10
|
'openclaw.json',
|
|
@@ -148,8 +149,7 @@ function printPreview(logger, provider) {
|
|
|
148
149
|
}
|
|
149
150
|
async function runCustomProviderFlow(rl, logger) {
|
|
150
151
|
logger.info('');
|
|
151
|
-
logger.info('
|
|
152
|
-
logger.info(' Format: provider/model (e.g., cliproxy/claude-opus-4-6, z.ai/gpt-5.3-codex)');
|
|
152
|
+
logger.info('Step 1/3: Select your AI provider');
|
|
153
153
|
logger.info('');
|
|
154
154
|
const tierModels = {};
|
|
155
155
|
for (const tier of MODEL_TIERS) {
|
|
@@ -211,17 +211,29 @@ export async function runInteractiveSetup(logger) {
|
|
|
211
211
|
logger.info('');
|
|
212
212
|
logger.info(` ✓ Selected: ${PROVIDER_LABELS[provider] ?? 'Custom'}`);
|
|
213
213
|
logger.info('');
|
|
214
|
-
logger.info('Step 2/
|
|
214
|
+
logger.info('Step 2/3: Model configuration preview');
|
|
215
215
|
logger.info('');
|
|
216
216
|
printPreview(logger, provider);
|
|
217
217
|
logger.info('');
|
|
218
218
|
const confirm = await askQuestion(rl, ' Apply this configuration? (Y/n): ');
|
|
219
219
|
if (confirm.toLowerCase() === 'n' || confirm.toLowerCase() === 'no') {
|
|
220
220
|
logger.info(' Setup cancelled.');
|
|
221
|
-
return { provider: '' };
|
|
221
|
+
return { provider: '', setupMcporter: false };
|
|
222
222
|
}
|
|
223
223
|
logger.info('');
|
|
224
|
-
|
|
224
|
+
logger.info('Step 3/3: Web search MCP servers');
|
|
225
|
+
logger.info('');
|
|
226
|
+
logger.info(' OmOC agents use mcporter MCP servers for web search,');
|
|
227
|
+
logger.info(' documentation lookup, and code search:');
|
|
228
|
+
logger.info('');
|
|
229
|
+
for (const [name, entry] of Object.entries(OMOC_MCP_SERVERS)) {
|
|
230
|
+
logger.info(` ${name}: ${entry.description}`);
|
|
231
|
+
}
|
|
232
|
+
logger.info('');
|
|
233
|
+
const mcpConfirm = await askQuestion(rl, ' Set up these MCP servers? (Y/n): ');
|
|
234
|
+
const setupMcporter = mcpConfirm.toLowerCase() !== 'n' && mcpConfirm.toLowerCase() !== 'no';
|
|
235
|
+
logger.info('');
|
|
236
|
+
return { provider, setupMcporter };
|
|
225
237
|
}
|
|
226
238
|
finally {
|
|
227
239
|
rl.close();
|
|
@@ -281,6 +293,17 @@ export function runSetup(options) {
|
|
|
281
293
|
if (result.added.length === 0 && result.updated.length === 0) {
|
|
282
294
|
logger.info('No changes needed — all OmOC agents already present.');
|
|
283
295
|
}
|
|
296
|
+
if (options.setupMcporter) {
|
|
297
|
+
logger.info('');
|
|
298
|
+
logger.info('Setting up mcporter MCP servers...');
|
|
299
|
+
const mcpResult = runMcporterSetup({
|
|
300
|
+
configPath: options.mcporterConfigPath,
|
|
301
|
+
dryRun,
|
|
302
|
+
logger,
|
|
303
|
+
});
|
|
304
|
+
result.mcporterAdded = mcpResult.added;
|
|
305
|
+
result.mcporterSkipped = mcpResult.skipped;
|
|
306
|
+
}
|
|
284
307
|
return result;
|
|
285
308
|
}
|
|
286
309
|
export function registerSetupCli(ctx) {
|
|
@@ -299,11 +322,13 @@ export function registerSetupCli(ctx) {
|
|
|
299
322
|
const valid = getProviderNames().join(', ');
|
|
300
323
|
throw new Error(`Unknown provider "${provider}". Valid: ${valid}`);
|
|
301
324
|
}
|
|
325
|
+
let setupMcporter = false;
|
|
302
326
|
if (!provider && process.stdin.isTTY) {
|
|
303
327
|
const result = await runInteractiveSetup(ctx.logger);
|
|
304
328
|
if (!result.provider)
|
|
305
329
|
return;
|
|
306
330
|
provider = result.provider;
|
|
331
|
+
setupMcporter = result.setupMcporter;
|
|
307
332
|
}
|
|
308
333
|
runSetup({
|
|
309
334
|
configPath: opts.config,
|
|
@@ -311,6 +336,7 @@ export function registerSetupCli(ctx) {
|
|
|
311
336
|
force: provider ? true : opts.force,
|
|
312
337
|
dryRun: opts.dryRun,
|
|
313
338
|
provider,
|
|
339
|
+
setupMcporter,
|
|
314
340
|
logger: ctx.logger,
|
|
315
341
|
});
|
|
316
342
|
ctx.logger.info('');
|
package/package.json
CHANGED