nubase_cli 0.1.7 → 0.1.8
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 +12 -5
- package/dist/src/index.js +1 -1
- package/dist/src/install-skills.d.ts +3 -0
- package/dist/src/install-skills.js +31 -3
- package/dist/src/mcp-stdio.js +10 -17
- package/package.json +1 -1
- package/skills/nubase/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -70,8 +70,8 @@ node packages/mcp-bridge/dist/src/index.js
|
|
|
70
70
|
"mcpServers": {
|
|
71
71
|
"nubase": {
|
|
72
72
|
"type": "stdio",
|
|
73
|
-
"command": "
|
|
74
|
-
"args": ["
|
|
73
|
+
"command": "npx",
|
|
74
|
+
"args": ["-y", "nubase_cli@latest"],
|
|
75
75
|
"env": {
|
|
76
76
|
"NUBASE_AGENT_ID": "claude-code",
|
|
77
77
|
"NUBASE_CONFIG": "/absolute/project/path/.nubase/config.json"
|
|
@@ -81,6 +81,9 @@ node packages/mcp-bridge/dist/src/index.js
|
|
|
81
81
|
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
The bridge code is shared across projects via the npm cache; only `.nubase/config.json`
|
|
85
|
+
(holding this project's `projectKey`) is project-specific, pointed to by `NUBASE_CONFIG`.
|
|
86
|
+
|
|
84
87
|
You may still set `NUBASE_URL` and `NUBASE_PROJECT_KEY` explicitly. Environment variables take precedence over the saved authorization config.
|
|
85
88
|
|
|
86
89
|
## Install Agent Skills
|
|
@@ -99,15 +102,15 @@ Targets:
|
|
|
99
102
|
|
|
100
103
|
Use `--skills-scope project` to write `.claude/skills/nubase/**` and `.codex/skills/nubase/**` in the current project instead.
|
|
101
104
|
|
|
102
|
-
By default, when the target includes `claude`, the command
|
|
105
|
+
By default, when the target includes `claude`, the command creates or merges a project `.mcp.json` that runs the bridge via `npx` (shared across projects through the npm cache):
|
|
103
106
|
|
|
104
107
|
```json
|
|
105
108
|
{
|
|
106
109
|
"mcpServers": {
|
|
107
110
|
"nubase": {
|
|
108
111
|
"type": "stdio",
|
|
109
|
-
"command": "
|
|
110
|
-
"args": ["
|
|
112
|
+
"command": "npx",
|
|
113
|
+
"args": ["-y", "nubase_cli@<version>"],
|
|
111
114
|
"env": {
|
|
112
115
|
"NUBASE_AGENT_ID": "claude-code",
|
|
113
116
|
"NUBASE_CONFIG": "/absolute/project/path/.nubase/config.json"
|
|
@@ -117,6 +120,10 @@ By default, when the target includes `claude`, the command also copies the local
|
|
|
117
120
|
}
|
|
118
121
|
```
|
|
119
122
|
|
|
123
|
+
The `npx` spec is pinned to the installed CLI version for reproducibility. Pass
|
|
124
|
+
`--mcp-delivery local` instead to copy a hermetic, version-pinned bridge into
|
|
125
|
+
`.nubase/mcp-bridge` and reference it with `command: "node"` (no npm dependency at runtime).
|
|
126
|
+
|
|
120
127
|
Use `--mcp both` to also write project `.codex/config.toml` for Codex. Use `--no-mcp` to skip MCP config.
|
|
121
128
|
|
|
122
129
|
Installed structure:
|
package/dist/src/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { installSkills, parseInstallArgs } from './install-skills.js';
|
|
|
6
6
|
import { McpStdioServer } from './mcp-stdio.js';
|
|
7
7
|
import { NubaseClient } from './nubase-client.js';
|
|
8
8
|
import { callTool, TOOLS } from './tools.js';
|
|
9
|
-
const CLI_VERSION = '0.1.
|
|
9
|
+
const CLI_VERSION = '0.1.8';
|
|
10
10
|
if (process.argv[2] === 'install-skills') {
|
|
11
11
|
const options = parseInstallArgs(process.argv.slice(3));
|
|
12
12
|
const installed = await installSkills(options);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type SkillTarget = 'claude' | 'codex' | 'both';
|
|
2
2
|
export type SkillInstallScope = 'user' | 'project';
|
|
3
3
|
export type McpInstallTarget = 'none' | 'claude' | 'codex' | 'both';
|
|
4
|
+
export type McpDelivery = 'npx' | 'local';
|
|
4
5
|
export interface InstallSkillsOptions {
|
|
5
6
|
target: SkillTarget;
|
|
6
7
|
projectDir: string;
|
|
@@ -9,6 +10,7 @@ export interface InstallSkillsOptions {
|
|
|
9
10
|
skills?: boolean;
|
|
10
11
|
skillsScope?: SkillInstallScope;
|
|
11
12
|
mcp?: McpInstallTarget;
|
|
13
|
+
mcpDelivery?: McpDelivery;
|
|
12
14
|
configPath?: string;
|
|
13
15
|
homeDir?: string;
|
|
14
16
|
}
|
|
@@ -21,5 +23,6 @@ export declare function parseInstallArgs(argv: string[]): {
|
|
|
21
23
|
skills: boolean;
|
|
22
24
|
skillsScope: SkillInstallScope;
|
|
23
25
|
mcp: McpInstallTarget;
|
|
26
|
+
mcpDelivery: McpDelivery;
|
|
24
27
|
configPath: string;
|
|
25
28
|
};
|
|
@@ -19,10 +19,16 @@ export async function installSkills(options) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
const mcpTargets = resolveMcpTargets(options.mcp ?? 'claude', targets);
|
|
22
|
+
const mcpDelivery = options.mcpDelivery ?? 'npx';
|
|
22
23
|
let mcpCommand = null;
|
|
23
24
|
if (mcpTargets.length > 0) {
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
if (mcpDelivery === 'local') {
|
|
26
|
+
mcpCommand = await installProjectMcpBridge(options.projectDir);
|
|
27
|
+
installed.push(mcpCommand.entrypoint);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
mcpCommand = await npxMcpCommand();
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
if (mcpTargets.includes('claude')) {
|
|
28
34
|
installed.push(await installClaudeMcpConfig(options.projectDir, configPath, mcpCommand));
|
|
@@ -40,6 +46,7 @@ export function parseInstallArgs(argv) {
|
|
|
40
46
|
let skills = true;
|
|
41
47
|
let skillsScope = 'user';
|
|
42
48
|
let mcp = 'claude';
|
|
49
|
+
let mcpDelivery = 'npx';
|
|
43
50
|
let configPath;
|
|
44
51
|
const authArgs = ['--prompt-only'];
|
|
45
52
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -83,6 +90,13 @@ export function parseInstallArgs(argv) {
|
|
|
83
90
|
}
|
|
84
91
|
skillsScope = value;
|
|
85
92
|
}
|
|
93
|
+
else if (arg === '--mcp-delivery') {
|
|
94
|
+
const value = argv[++i];
|
|
95
|
+
if (value !== 'npx' && value !== 'local') {
|
|
96
|
+
throw new Error('--mcp-delivery must be npx or local');
|
|
97
|
+
}
|
|
98
|
+
mcpDelivery = value;
|
|
99
|
+
}
|
|
86
100
|
else if (arg === '--config') {
|
|
87
101
|
const value = argv[++i];
|
|
88
102
|
if (!value)
|
|
@@ -101,7 +115,7 @@ export function parseInstallArgs(argv) {
|
|
|
101
115
|
}
|
|
102
116
|
configPath = configPath ?? projectConfigPath(projectDir);
|
|
103
117
|
authArgs.push('--config', configPath);
|
|
104
|
-
return { target, projectDir, authorize, authArgs, skills, skillsScope, mcp, configPath };
|
|
118
|
+
return { target, projectDir, authorize, authArgs, skills, skillsScope, mcp, mcpDelivery, configPath };
|
|
105
119
|
}
|
|
106
120
|
function bundledSkillDir() {
|
|
107
121
|
return path.join(bundledPackageRoot(), 'skills', 'nubase');
|
|
@@ -126,6 +140,20 @@ function resolveMcpTargets(mcp, skillTargets) {
|
|
|
126
140
|
const requested = mcp === 'both' ? ['claude', 'codex'] : [mcp];
|
|
127
141
|
return requested.filter((target) => skillTargets.includes(target));
|
|
128
142
|
}
|
|
143
|
+
async function npxMcpCommand() {
|
|
144
|
+
const spec = `nubase_cli@${await bundledPackageVersion()}`;
|
|
145
|
+
return { command: 'npx', args: ['-y', spec], entrypoint: spec };
|
|
146
|
+
}
|
|
147
|
+
async function bundledPackageVersion() {
|
|
148
|
+
try {
|
|
149
|
+
const raw = await readFile(path.join(bundledPackageRoot(), 'package.json'), 'utf8');
|
|
150
|
+
const version = JSON.parse(raw).version;
|
|
151
|
+
return typeof version === 'string' && version.trim() ? version.trim() : 'latest';
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return 'latest';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
129
157
|
async function installProjectMcpBridge(projectDir) {
|
|
130
158
|
const packageRoot = bundledPackageRoot();
|
|
131
159
|
const destRoot = path.join(projectDir, '.nubase', 'mcp-bridge');
|
package/dist/src/mcp-stdio.js
CHANGED
|
@@ -47,25 +47,18 @@ export class McpStdioServer {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
readMessage() {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
// MCP stdio transport frames messages as newline-delimited JSON
|
|
51
|
+
// (one JSON-RPC object per line, no embedded newlines).
|
|
52
|
+
const newlineIndex = this.buffer.indexOf('\n');
|
|
53
|
+
if (newlineIndex === -1)
|
|
52
54
|
return null;
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
if (!
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const length = Number(match[1]);
|
|
59
|
-
const bodyStart = headerEnd + 4;
|
|
60
|
-
const bodyEnd = bodyStart + length;
|
|
61
|
-
if (this.buffer.length < bodyEnd)
|
|
62
|
-
return null;
|
|
63
|
-
const body = this.buffer.subarray(bodyStart, bodyEnd).toString('utf8');
|
|
64
|
-
this.buffer = this.buffer.subarray(bodyEnd);
|
|
65
|
-
return JSON.parse(body);
|
|
55
|
+
const line = this.buffer.subarray(0, newlineIndex).toString('utf8').trim();
|
|
56
|
+
this.buffer = this.buffer.subarray(newlineIndex + 1);
|
|
57
|
+
if (!line)
|
|
58
|
+
return this.readMessage();
|
|
59
|
+
return JSON.parse(line);
|
|
66
60
|
}
|
|
67
61
|
write(message) {
|
|
68
|
-
|
|
69
|
-
stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
|
|
62
|
+
stdout.write(`${JSON.stringify(message)}\n`);
|
|
70
63
|
}
|
|
71
64
|
}
|
package/package.json
CHANGED
package/skills/nubase/SKILL.md
CHANGED
|
@@ -79,8 +79,8 @@ Expected `.mcp.json` shape:
|
|
|
79
79
|
"mcpServers": {
|
|
80
80
|
"nubase": {
|
|
81
81
|
"type": "stdio",
|
|
82
|
-
"command": "
|
|
83
|
-
"args": ["
|
|
82
|
+
"command": "npx",
|
|
83
|
+
"args": ["-y", "nubase_cli@latest"],
|
|
84
84
|
"env": {
|
|
85
85
|
"NUBASE_AGENT_ID": "claude-code",
|
|
86
86
|
"NUBASE_CONFIG": "/absolute/project/path/.nubase/config.json"
|