feat(pulumi): @mcpctl/pulumi — generic Pulumi provider for mcpctl #79
Reference in New Issue
Block a user
Delete Branch "feat/pulumi-provider"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds a new workspace package
@mcpctl/pulumi: a Pulumi dynamic provider that manages mcpctl resources declaratively from any TypeScript Pulumi program.Why
Model drift: when the deployed vLLM/LiteLLM model changes (source of truth in the kubernetes-deployment Pulumi repo), mcpctl's
llmtarget must follow or it 400s. A Pulumi resource makes the update automatic onpulumi up. Built generic so it's useful to any mcpctl user, not just one homelab.Design
McpctlResource({ kind, name, spec, mcpd })round-trips ANY resource kind; typedLlmwrapper for ergonomics.cli/api-client.ts) hitting the same REST endpoints the CLI uses, mirroringapply's name-keyed upsert (PUT strips immutablename/type) andget -o json's read field-stripping. Nomcpctlbinary needed → CI-friendly.name/type/kind/mcpd.url→ delete-before-replace), 429 retry, token secret in state.Auth
Long-lived PAT (
mcpctl_pat_) with resource-wideview:llms+edit:llmsbindings, passed as a Pulumi secret. (mcpd currently requiresprojectIdon mint — flagged in the README as a future cleanup.)Tests / gates
pnpm --filter @mcpctl/pulumi build+ roottsc --buildclean; eslint clean.Follow-up (not in this PR): publish the package + wire it into kubernetes-deployment; typed wrappers for more kinds.
🤖 Generated with Claude Code
New workspace package: a Pulumi dynamic provider (TypeScript, in-process) that manages mcpctl resources declaratively from any Pulumi program. Motivated by model drift: when the deployed vLLM/LiteLLM model changes, mcpctl's llm target must follow, and a Pulumi resource makes that automatic on `pulumi up`. - Generic core `McpctlResource({ kind, name, spec, mcpd })` round-trips ANY mcpctl resource kind; typed `Llm` wrapper for ergonomics. - Engine talks direct HTTP to mcpd's REST API (ported from cli/api-client.ts), mirroring apply's name-keyed upsert (PUT strips immutable name/type) and get -o json's read field-stripping. No mcpctl binary needed → CI-friendly. - CRUD/diff/check with correct replace semantics (name/type/kind/mcpd.url force delete-before-replace), 429 retry, secret token in state. - Validation deferred to mcpd's Zod schemas, so new resource kinds work with no provider release. - CommonJS build so the serialized dynamic provider's module refs are captured. - 18 Vitest tests (mocked mcpd + Pulumi mocks); build + lint clean; README with auth (PAT) setup and consumer example for kubernetes-deployment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>