chore: release 0.7.2
This commit is contained in:
parent
cd36e8fe61
commit
d1cf5572f9
12
CHANGELOG.md
12
CHANGELOG.md
@ -4,6 +4,18 @@
|
||||
|
||||
No unreleased changes yet.
|
||||
|
||||
## [0.7.2] - 2025-12-29
|
||||
### CLI
|
||||
- Fixed generated CLIs to read Commander.js option values via camelCased properties so snake_case tool schemas map correctly.
|
||||
|
||||
### Tests
|
||||
- Added regression coverage for snake_case, camelCase, and numeric option names in generated CLIs.
|
||||
- Increased the Bun bundler integration-test timeout to reduce flakes on slower runners.
|
||||
|
||||
### Tooling / Dependencies
|
||||
- Updated dependency set (SDK, Rolldown, Zod, Biome, Oxlint, Bun types).
|
||||
- Synced the Biome schema URL to the current CLI version.
|
||||
|
||||
## [0.7.1] - 2025-12-08
|
||||
### Daemon
|
||||
- Track config file mtimes for every loaded layer (home + project or explicit) in daemon metadata and auto-restart when any layer changes, so newly added keep-alive servers are picked up without manual restarts. Includes regression tests for stale-daemon detection.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
|
||||
24
package.json
24
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mcporter",
|
||||
"version": "0.7.1",
|
||||
"version": "0.7.2",
|
||||
"description": "TypeScript runtime and CLI for connecting to configured Model Context Protocol servers.",
|
||||
"packageManager": "pnpm@10.22.0",
|
||||
"pnpm": {
|
||||
@ -48,30 +48,30 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@modelcontextprotocol/sdk": "^1.24.3",
|
||||
"@modelcontextprotocol/sdk": "^1.25.1",
|
||||
"acorn": "^8.15.0",
|
||||
"commander": "^14.0.2",
|
||||
"es-toolkit": "^1.42.0",
|
||||
"es-toolkit": "^1.43.0",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"ora": "^9.0.0",
|
||||
"rolldown": "1.0.0-beta.53",
|
||||
"zod": "^4.1.13"
|
||||
"rolldown": "1.0.0-beta.57",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.3.8",
|
||||
"@biomejs/biome": "^2.3.10",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/node": "^24.10.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251205.1",
|
||||
"bun-types": "^1.3.3",
|
||||
"@types/node": "^25.0.3",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251229.1",
|
||||
"bun-types": "^1.3.5",
|
||||
"cross-env": "^10.1.0",
|
||||
"express": "^5.2.1",
|
||||
"oxlint": "^1.31.0",
|
||||
"oxlint-tsgolint": "^0.8.3",
|
||||
"oxlint": "^1.36.0",
|
||||
"oxlint-tsgolint": "^0.10.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.15"
|
||||
"vitest": "^4.0.16"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11.0"
|
||||
|
||||
1322
pnpm-lock.yaml
generated
1322
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -434,8 +434,12 @@ export function renderToolCommand(
|
||||
});
|
||||
const buildArgs = tool.options
|
||||
.map((option) => {
|
||||
// Commander.js converts kebab-case flags to camelCase property names
|
||||
const camelCaseProp = option.cliName.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
||||
// Commander.js camelcases flag names (e.g. --relative-path => relativePath).
|
||||
const camelCaseProp = option.cliName
|
||||
.split('-')
|
||||
.filter(Boolean)
|
||||
.map((segment, index) => (index === 0 ? segment : `${segment.charAt(0).toUpperCase()}${segment.slice(1)}`))
|
||||
.join('');
|
||||
const source = `cmdOpts.${camelCaseProp}`;
|
||||
return `if (${source} !== undefined) args.${option.property} = ${source};`;
|
||||
})
|
||||
|
||||
@ -200,7 +200,57 @@ describe('mcporter CLI integration', () => {
|
||||
expect(helpOutput.stdout).toContain('ping - Simple health check');
|
||||
expect(helpOutput.stdout).toContain('--echo <echo>');
|
||||
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
||||
});
|
||||
}, 20000);
|
||||
|
||||
it('generates a Bun CLI that can call a tool', async () => {
|
||||
if (!(await ensureBunSupport('Bun CLI execution test'))) {
|
||||
return;
|
||||
}
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'mcporter-bun-cli-'));
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, 'package.json'),
|
||||
JSON.stringify({ name: 'mcporter-bun-cli', version: '0.0.0' }, null, 2),
|
||||
'utf8'
|
||||
);
|
||||
const bundlePath = path.join(tempDir, 'context7-bun-cli.js');
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
execFile(
|
||||
process.execPath,
|
||||
[CLI_ENTRY, 'generate-cli', '--command', baseUrl.toString(), '--runtime', 'bun', '--bundle', bundlePath],
|
||||
{
|
||||
cwd: tempDir,
|
||||
env: { ...process.env, MCPORTER_NO_FORCE_EXIT: '1' },
|
||||
},
|
||||
(error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const result = await new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {
|
||||
execFile(
|
||||
bundlePath,
|
||||
['ping', '--echo', 'ban', '--output', 'json'],
|
||||
{ env: process.env },
|
||||
(error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve({ stdout, stderr });
|
||||
}
|
||||
);
|
||||
});
|
||||
const parsed = JSON.parse(result.stdout.trim()) as { ok: boolean; echo?: string };
|
||||
expect(parsed.ok).toBe(true);
|
||||
expect(parsed.echo).toBe('ban');
|
||||
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
||||
}, 20000);
|
||||
|
||||
it('runs "node dist/cli.js generate-cli --compile" when bun is available', async () => {
|
||||
if (!(await ensureBunSupport('compile integration test'))) {
|
||||
|
||||
@ -54,6 +54,24 @@ if (process.platform !== 'win32') {
|
||||
};
|
||||
}
|
||||
);
|
||||
server.registerTool(
|
||||
'option_case_test',
|
||||
{
|
||||
title: 'Option Case Test',
|
||||
description: 'Tool with snake_case, camelCase, and numeric option names',
|
||||
inputSchema: {
|
||||
relative_path: z.string(),
|
||||
api_key: z.string(),
|
||||
tls_1_3: z.boolean(),
|
||||
issueId: z.string(),
|
||||
},
|
||||
outputSchema: { ok: z.boolean() },
|
||||
},
|
||||
async () => ({
|
||||
content: [{ type: 'text', text: JSON.stringify({ ok: true }) }],
|
||||
structuredContent: { ok: true },
|
||||
})
|
||||
);
|
||||
server.registerResource(
|
||||
'greeting',
|
||||
new ResourceTemplate('greeting://{name}', { list: undefined }),
|
||||
@ -317,6 +335,36 @@ describeGenerateCli('generateCli', () => {
|
||||
expect(stdout).not.toContain('<tool> key=value');
|
||||
});
|
||||
|
||||
it('maps CLI options to Commander camelCase properties', async () => {
|
||||
const inline = JSON.stringify({
|
||||
name: 'case-options',
|
||||
description: 'Case options test',
|
||||
command: baseUrl.toString(),
|
||||
});
|
||||
const outputPath = path.join(tmpDir, 'case-options.ts');
|
||||
await fs.rm(outputPath, { force: true });
|
||||
|
||||
const { outputPath: renderedPath } = await generateCli({
|
||||
serverRef: inline,
|
||||
outputPath,
|
||||
runtime: 'node',
|
||||
timeoutMs: 5_000,
|
||||
});
|
||||
const content = await fs.readFile(renderedPath, 'utf8');
|
||||
|
||||
expect(content).toContain('args.relative_path');
|
||||
expect(content).toContain('args.api_key');
|
||||
expect(content).toContain('args.tls_1_3');
|
||||
expect(content).toContain('args.issueId');
|
||||
expect(content).toContain('cmdOpts.relativePath');
|
||||
expect(content).toContain('cmdOpts.apiKey');
|
||||
expect(content).toContain('cmdOpts.tls13');
|
||||
expect(content).toContain('cmdOpts.issueId');
|
||||
expect(content).not.toContain('cmdOpts.relative_path');
|
||||
expect(content).not.toContain('cmdOpts.api_key');
|
||||
expect(content).not.toContain('cmdOpts.tls_1_3');
|
||||
});
|
||||
|
||||
it('accepts both kebab-case and underscore tool names for generated CLIs', async () => {
|
||||
const deepwikiRef = JSON.stringify({
|
||||
name: 'deepwiki',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user