feat: mcpctl v0.0.1 — first public release
Comprehensive MCP server management with kubectl-style CLI. Key features in this release: - Declarative YAML apply/get round-trip with project cloning support - Gated sessions with prompt intelligence for Claude - Interactive MCP console with traffic inspector - Persistent STDIO connections for containerized servers - RBAC with name-scoped bindings - Shell completions (fish + bash) auto-generated - Rate-limit retry with exponential backoff in apply - Project-scoped prompt management - Credential scrubbing from git history Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,22 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { execSync } from 'node:child_process';
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
||||
const fishFile = readFileSync(join(root, 'completions', 'mcpctl.fish'), 'utf-8');
|
||||
const bashFile = readFileSync(join(root, 'completions', 'mcpctl.bash'), 'utf-8');
|
||||
|
||||
describe('freshness', () => {
|
||||
it('committed completions match generator output', () => {
|
||||
const generatorPath = join(root, 'scripts', 'generate-completions.ts');
|
||||
expect(existsSync(generatorPath), 'generator script must exist').toBe(true);
|
||||
// Run the generator in --check mode; exit 0 means files are up to date
|
||||
execSync(`npx tsx ${generatorPath} --check`, { cwd: root, stdio: 'pipe' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('fish completions', () => {
|
||||
it('erases stale completions at the top', () => {
|
||||
const lines = fishFile.split('\n');
|
||||
@@ -52,8 +62,8 @@ describe('fish completions', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('defines --project option', () => {
|
||||
expect(fishFile).toContain("complete -c mcpctl -l project");
|
||||
it('defines --project option with -p shorthand', () => {
|
||||
expect(fishFile).toContain("-s p -l project");
|
||||
});
|
||||
|
||||
it('attach-server command only shows with --project', () => {
|
||||
@@ -139,8 +149,11 @@ describe('bash completions', () => {
|
||||
|
||||
it('fetches resource names dynamically after resource type', () => {
|
||||
expect(bashFile).toContain('_mcpctl_resource_names');
|
||||
// get/describe/delete should use resource_names when resource_type is set
|
||||
expect(bashFile).toMatch(/get\|describe\|delete\)[\s\S]*?_mcpctl_resource_names/);
|
||||
// get, describe, and delete should each use resource_names when resource_type is set
|
||||
for (const cmd of ['get', 'describe', 'delete']) {
|
||||
const block = bashFile.match(new RegExp(`${cmd}\\)[\\s\\S]*?return ;;`))?.[0] ?? '';
|
||||
expect(block, `${cmd} case must use _mcpctl_resource_names`).toContain('_mcpctl_resource_names');
|
||||
}
|
||||
});
|
||||
|
||||
it('attach-server filters out already-attached servers and guards against repeat', () => {
|
||||
|
||||
Reference in New Issue
Block a user