feat: mcpctl v0.0.1 — first public release
Some checks are pending
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / test (push) Waiting to run
CI / build (push) Blocked by required conditions
CI / package (push) Blocked by required conditions

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:
Michal
2026-02-27 17:05:05 +00:00
parent 414a8d3774
commit 69867bd47a
65 changed files with 5710 additions and 695 deletions

View File

@@ -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', () => {