@seekrit/mcp 0.8.0 → 0.8.1

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.
Files changed (2) hide show
  1. package/dist/index.js +248 -31
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -1136,6 +1136,16 @@ z.object({
1136
1136
  */
1137
1137
  encryptedPrivateKey: z.string().min(1)
1138
1138
  });
1139
+ z.object({
1140
+ /** Base64url WebAuthn credential id — what `allowCredentials` is built from. */
1141
+ credentialId: z.string().min(1).max(512),
1142
+ /** Human label for the device, e.g. "MacBook Touch ID". Display only. */
1143
+ label: z.string().min(1).max(64),
1144
+ /** Base64url PRF evaluation input for this credential; not a secret. */
1145
+ prfInput: z.string().min(1).max(256),
1146
+ /** The private key wrapped to this passkey's PRF output. */
1147
+ encryptedPrivateKey: z.string().min(1).max(8192).refine((v) => v.startsWith("pk2."), { message: "expected a pk2. passkey wrap" })
1148
+ });
1139
1149
  const grantEnvironmentKeySchema = z.object({
1140
1150
  principalType: principalTypeSchema,
1141
1151
  principalId: z.string().min(1),
@@ -1438,7 +1448,9 @@ z.enum([
1438
1448
  "bunnyshell",
1439
1449
  "github-actions",
1440
1450
  "gcp-secret-manager",
1441
- "langgraph-platform"
1451
+ "langgraph-platform",
1452
+ "azure-key-vault",
1453
+ "huggingface-spaces"
1442
1454
  ]);
1443
1455
  /**
1444
1456
  * Vercel account scope. The API token itself is never here — it is wrapped to
@@ -1753,6 +1765,69 @@ const langgraphPlatformConnectionConfigSchema = z.object({
1753
1765
  message: "set region for a LangChain-hosted account or baseUrl for a self-hosted one, not both",
1754
1766
  path: ["baseUrl"]
1755
1767
  });
1768
+ /**
1769
+ * The Azure clouds a vault can live in.
1770
+ *
1771
+ * Unlike AWS, where the China partition can be read off the region string
1772
+ * (`cn-…`), nothing about a tenant id or a vault name says which cloud it
1773
+ * belongs to — and two hosts have to agree with the answer: the Entra authority
1774
+ * that issues the token and the DNS suffix the vault answers on. Getting either
1775
+ * wrong is a failure inside an alarm with nobody watching, so it is stated.
1776
+ */
1777
+ const AZURE_CLOUDS = [
1778
+ "public",
1779
+ "usgov",
1780
+ "china"
1781
+ ];
1782
+ /**
1783
+ * A Microsoft Entra directory (tenant) or application (client) id.
1784
+ *
1785
+ * Both are GUIDs. Entra accepts a verified domain name in place of a tenant id
1786
+ * in the token URL, but not a client id, and taking only the GUID for both
1787
+ * keeps one rule — a tenant's GUID is on the same admin-center page as the
1788
+ * client id it pairs with, so nothing is harder to find.
1789
+ */
1790
+ const azureGuidSchema = z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a GUID, as the Entra admin center shows it");
1791
+ /**
1792
+ * Azure account scope: which directory to authenticate against, as which app.
1793
+ *
1794
+ * The split follows AWS's, and for the same reason. A service principal's
1795
+ * **client secret** is the credential and is wrapped to the connection's key;
1796
+ * the tenant and client ids are *identifiers* — they appear in the token
1797
+ * request URL, in sign-in logs, and on the app registration blade. Keeping them
1798
+ * here lets the dashboard say which principal a connection authenticates as,
1799
+ * which is the first thing worth knowing when a connection starts failing after
1800
+ * a secret expires.
1801
+ *
1802
+ * Client secrets are the only credential kind here: a certificate or federated
1803
+ * credential would need a private key or a trust relationship the sync engine
1804
+ * has nowhere to keep, and Entra caps a client secret at 24 months, which is a
1805
+ * rotation the connection's `lastError` will make loud.
1806
+ */
1807
+ const azureKeyVaultConnectionConfigSchema = z.object({
1808
+ provider: z.literal("azure-key-vault"),
1809
+ /** Entra directory (tenant) ID. */
1810
+ tenantId: azureGuidSchema,
1811
+ /** Application (client) ID of the service principal seekrit signs in as. */
1812
+ clientId: azureGuidSchema,
1813
+ /** Which Azure cloud the tenant and its vaults live in. */
1814
+ cloud: z.enum(AZURE_CLOUDS).default("public")
1815
+ });
1816
+ /**
1817
+ * Hugging Face account scope — empty, as Render's and Fly's are.
1818
+ *
1819
+ * Neither half of "which account, which thing" needs stating. A Hub user access
1820
+ * token belongs to one user and carries their write access to every Space they
1821
+ * or their organizations own; a Space is addressed by `owner/name`, which is
1822
+ * globally unique. So the token plus the destination is the whole address.
1823
+ *
1824
+ * There is deliberately no `baseUrl` twin of the GitHub Enterprise Server
1825
+ * field. `HF_ENDPOINT` exists in the Python client for Hub *mirrors*, which
1826
+ * serve repository content — not the settings API this connector writes, and
1827
+ * not something a mirror is expected to accept a write on. Adding the field
1828
+ * would invite pointing a connection at a host that silently swallows secrets.
1829
+ */
1830
+ const huggingfaceSpacesConnectionConfigSchema = z.object({ provider: z.literal("huggingface-spaces") });
1756
1831
  const syncConnectionConfigSchema = z.discriminatedUnion("provider", [
1757
1832
  vercelConnectionConfigSchema,
1758
1833
  cloudflareWorkersConnectionConfigSchema,
@@ -1770,7 +1845,9 @@ const syncConnectionConfigSchema = z.discriminatedUnion("provider", [
1770
1845
  bunnyshellConnectionConfigSchema,
1771
1846
  githubActionsConnectionConfigSchema,
1772
1847
  gcpSecretManagerConnectionConfigSchema,
1773
- langgraphPlatformConnectionConfigSchema
1848
+ langgraphPlatformConnectionConfigSchema,
1849
+ azureKeyVaultConnectionConfigSchema,
1850
+ huggingfaceSpacesConnectionConfigSchema
1774
1851
  ]);
1775
1852
  const vercelDestinationSchema = z.object({
1776
1853
  provider: z.literal("vercel"),
@@ -2478,6 +2555,77 @@ const langgraphPlatformDestinationSchema = z.object({
2478
2555
  /** Deployment UUID, from the dashboard URL or `GET /v2/deployments`. */
2479
2556
  deploymentId: z.string().trim().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "must be a LangGraph Platform deployment UUID")
2480
2557
  });
2558
+ /**
2559
+ * A Key Vault's name — the leftmost label of its DNS name, so the vault
2560
+ * `acme-prod` answers at `acme-prod.vault.azure.net`.
2561
+ *
2562
+ * Azure's own rule, stated here because the failure it prevents is confusing:
2563
+ * 3–24 characters, alphanumerics and hyphens, starting with a letter, ending
2564
+ * with a letter or digit, and no run of two hyphens. A name that breaks it
2565
+ * cannot exist, so a typo is a DNS failure rather than a 404 — an error that
2566
+ * says nothing about what was wrong.
2567
+ *
2568
+ * The *base URL* is not taken instead. It would let a connection be pointed at
2569
+ * any host, and the whole address seekrit needs is this label plus the cloud
2570
+ * already named on the connection.
2571
+ */
2572
+ const azureVaultNameSchema = z.string().trim().regex(/^[A-Za-z](?!.*--)[A-Za-z0-9-]{1,22}[A-Za-z0-9]$/, "must be a Key Vault name: 3–24 letters, digits, and single hyphens, starting with a letter");
2573
+ /**
2574
+ * Which vault a binding writes to, and under what names.
2575
+ *
2576
+ * There is no layout choice as Secrets Manager has: the reason a `json-bundle`
2577
+ * exists there is billing — AWS charges per secret per month — and Key Vault
2578
+ * charges per *operation*, so fifty names cost the same stored fifty ways. One
2579
+ * secret per name is simply correct here.
2580
+ */
2581
+ const azureKeyVaultDestinationSchema = z.object({
2582
+ provider: z.literal("azure-key-vault"),
2583
+ /** Vault name, e.g. `acme-prod` for `acme-prod.vault.azure.net`. */
2584
+ vault: azureVaultNameSchema,
2585
+ /**
2586
+ * Prepended to every secret name, e.g. `storefront-`. Key Vault has no
2587
+ * hierarchy — its names are flat, and `/` is not among the characters it
2588
+ * accepts — so unlike Parameter Store's `path` this is a naming convention
2589
+ * and nothing more. Worth setting in a vault that holds anything else.
2590
+ */
2591
+ prefix: z.string().trim().max(64).regex(/^[A-Za-z0-9-]*$/, "may contain letters, digits, and hyphens").optional(),
2592
+ /** What to do with a name Key Vault cannot store — see {@link AZURE_KEY_VAULT_NAME_MODES}. */
2593
+ nameMode: z.enum(["dash", "reject"]).default("dash")
2594
+ });
2595
+ /**
2596
+ * The Space whose secrets a binding owns, addressed the way the Hub addresses
2597
+ * every repository: `owner/name`, where `owner` is a user or an organization.
2598
+ *
2599
+ * A Space has **one** secret set, shared by every replica — there is no
2600
+ * per-target split to state, the way Vercel and Pages have one. The Hub's
2601
+ * convention is that staging and production are separate Spaces
2602
+ * (`acme/demo`, `acme/demo-staging`), so pointing at an environment means
2603
+ * naming that Space, exactly as a Fly environment means naming its own app.
2604
+ *
2605
+ * Validated by shape because the two habitual slips both fail *late*: pasting
2606
+ * the browser URL (`https://huggingface.co/spaces/acme/demo`) or the bare name
2607
+ * without its owner. Either one is a 404 from the Hub inside an alarm with
2608
+ * nobody watching, and a 404 says nothing about which half was wrong. The
2609
+ * leading character is held to alphanumeric, which is also what rejects the
2610
+ * `.` and `..` that no repository may be called.
2611
+ */
2612
+ const huggingfaceRepoIdSchema = z.string().trim().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,95}\/[A-Za-z0-9][A-Za-z0-9._-]{0,95}$/, "must be a Space ID as owner/name, e.g. acme/support-demo — not a URL");
2613
+ /**
2614
+ * One Hugging Face **Space**, whose secrets arrive in the app's container as
2615
+ * environment variables.
2616
+ *
2617
+ * Only secrets. A Space also has *variables*, and they are not a second lane
2618
+ * seekrit could use: the Hub calls them "non-sensitive configuration values",
2619
+ * they are "publicly accessible and viewable", and they are copied into every
2620
+ * Space duplicated from this one. Writing a seekrit secret there would publish
2621
+ * it, so this connector has no variables mode — a binding that wants one is
2622
+ * asking for the wrong thing.
2623
+ */
2624
+ const huggingfaceSpacesDestinationSchema = z.object({
2625
+ provider: z.literal("huggingface-spaces"),
2626
+ /** Space ID as `owner/name`, e.g. `acme/support-demo`. */
2627
+ repoId: huggingfaceRepoIdSchema
2628
+ });
2481
2629
  const syncDestinationSchema = z.discriminatedUnion("provider", [
2482
2630
  vercelDestinationSchema,
2483
2631
  cloudflareWorkersDestinationSchema,
@@ -2495,7 +2643,9 @@ const syncDestinationSchema = z.discriminatedUnion("provider", [
2495
2643
  bunnyshellDestinationSchema,
2496
2644
  githubActionsDestinationSchema,
2497
2645
  gcpSecretManagerDestinationSchema,
2498
- langgraphPlatformDestinationSchema
2646
+ langgraphPlatformDestinationSchema,
2647
+ azureKeyVaultDestinationSchema,
2648
+ huggingfaceSpacesDestinationSchema
2499
2649
  ]);
2500
2650
  /**
2501
2651
  * How seekrit secret names become destination key names. Applied in order:
@@ -3225,7 +3375,7 @@ function isServiceToken(value) {
3225
3375
  }
3226
3376
  //#endregion
3227
3377
  //#region ../cli/package.json
3228
- var version$1 = "0.46.0";
3378
+ var version$1 = "1.2.2";
3229
3379
  const PROJECT_FILE = "seekrit.json";
3230
3380
  function globalConfigPath() {
3231
3381
  return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "seekrit", "config.json");
@@ -3347,6 +3497,22 @@ var SeekritClient = class {
3347
3497
  revokeCliSession(sessionId) {
3348
3498
  return this.request("DELETE", `/v1/me/cli-sessions/${sessionId}`);
3349
3499
  }
3500
+ /**
3501
+ * The passkeys enrolled to unlock this user's keyring, each with the `pk2.`
3502
+ * blob its PRF output decrypts. One call is everything the unlock ceremony
3503
+ * needs; the blobs are opaque without the authenticator.
3504
+ */
3505
+ listMyPasskeys() {
3506
+ return this.request("GET", "/v1/me/passkeys");
3507
+ }
3508
+ /** File a private key already wrapped, client-side, to a passkey's PRF output. */
3509
+ enrollMyPasskey(input) {
3510
+ return this.request("POST", "/v1/me/passkeys", input);
3511
+ }
3512
+ /** Stop a passkey unlocking the keyring. The key itself is untouched. */
3513
+ deleteMyPasskey(passkeyId) {
3514
+ return this.request("DELETE", `/v1/me/passkeys/${passkeyId}`);
3515
+ }
3350
3516
  /** What a pending login request is asking for — for the approval screen. */
3351
3517
  getCliLoginRequest(code) {
3352
3518
  return this.request("GET", `/v1/cli-login/${encodeURIComponent(code)}`);
@@ -3953,7 +4119,18 @@ function fail(message) {
3953
4119
  console.error(`error: ${message}`);
3954
4120
  process.exit(1);
3955
4121
  }
3956
- /** Prompt without echoing input (for passphrases). */
4122
+ /**
4123
+ * Prompt without echoing input (for passphrases).
4124
+ *
4125
+ * Piping the answer in (`echo … | seekrit secrets get …`) is supported and
4126
+ * common in CI, so this reads stdin rather than insisting on a TTY. But stdin
4127
+ * can also close with nothing on it — `< /dev/null`, a closed pipe, an agent
4128
+ * spawning us with no stdin — and readline signals that by emitting `close`
4129
+ * without ever calling the `question` callback. Left unhandled the promise
4130
+ * never settles, the event loop drains, and Node exits **0** having printed
4131
+ * nothing: `V=$(seekrit secrets get X)` silently yields an empty value and a
4132
+ * success status. So treat EOF-without-an-answer as the error it is.
4133
+ */
3957
4134
  function promptHidden(question) {
3958
4135
  const muted = new Writable({ write(_chunk, _encoding, callback) {
3959
4136
  callback();
@@ -3964,8 +4141,15 @@ function promptHidden(question) {
3964
4141
  output: muted,
3965
4142
  terminal: true
3966
4143
  });
3967
- return new Promise((resolve) => {
4144
+ return new Promise((resolve, reject) => {
4145
+ let answered = false;
4146
+ rl.on("close", () => {
4147
+ if (answered) return;
4148
+ process.stderr.write("\n");
4149
+ reject(/* @__PURE__ */ new Error("no passphrase on stdin — set SEEKRIT_PASSPHRASE, pipe it in, or run this in a terminal"));
4150
+ });
3968
4151
  rl.question("", (answer) => {
4152
+ answered = true;
3969
4153
  rl.close();
3970
4154
  process.stderr.write("\n");
3971
4155
  resolve(answer);
@@ -3987,9 +4171,23 @@ const CLI_CLIENT = `cli/${version$1}`;
3987
4171
  * `flag > env > .env` credential resolution. Empty for every command but
3988
4172
  * `seekrit run`, which loads `.env` before authenticating.
3989
4173
  */
4174
+ /**
4175
+ * A `SEEKRIT_*` value, or undefined if it is absent *or blank*.
4176
+ *
4177
+ * Blank has to mean absent. An unset CI secret, a `${VAR}` that expanded to
4178
+ * nothing, a bare `export SEEKRIT_TOKEN=` — all arrive as `""`, and `??` only
4179
+ * falls back on null/undefined. Left alone, an empty `SEEKRIT_API_URL` makes
4180
+ * every request relative and an empty `SEEKRIT_TOKEN` authenticates as a
4181
+ * bearer of nothing: a 401 where the honest answer is "you have no
4182
+ * credentials", pointing at the API instead of at the missing variable.
4183
+ */
4184
+ function present(value) {
4185
+ const trimmed = value?.trim();
4186
+ return trimmed ? trimmed : void 0;
4187
+ }
3990
4188
  function tryBuildContext(dotenvVars = {}) {
3991
4189
  const config = readGlobalConfig();
3992
- const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
4190
+ const fromEnv = (key) => present(process.env[key]) ?? present(dotenvVars[key]);
3993
4191
  const apiUrl = fromEnv("SEEKRIT_API_URL") ?? config.apiUrl ?? "https://api.seekrit.dev";
3994
4192
  const token = fromEnv("SEEKRIT_TOKEN") ?? config.token ?? config.sessionToken;
3995
4193
  const devUser = fromEnv("SEEKRIT_DEV_USER") ?? config.devUser;
@@ -4056,11 +4254,46 @@ async function resolveOrg(ctx, orgSlug) {
4056
4254
  fail("specify --org (or run `seekrit init`)");
4057
4255
  }
4058
4256
  /**
4257
+ * The environment a service token is bound to.
4258
+ *
4259
+ * The binding lives on the token row, not in the token string — `GET
4260
+ * /v1/resolve` is where the API publishes it, and `seekrit whoami` reads it the
4261
+ * same way. One round trip, and it also resolves `--branch` against the bound
4262
+ * environment, which is the only environment a token may name a branch of.
4263
+ */
4264
+ async function boundEnvTarget(ctx, opts) {
4265
+ let scope;
4266
+ try {
4267
+ ({scope} = await ctx.client.resolve(opts.branch ? { branch: opts.branch } : {}));
4268
+ } catch (err) {
4269
+ fail(`specify --env — this token has no environment of its own to fall back to (${err instanceof Error ? err.message : String(err)})`);
4270
+ }
4271
+ const env = scope.branchOf ?? {
4272
+ envId: scope.envId,
4273
+ envSlug: scope.envSlug
4274
+ };
4275
+ const label = scope.branchOf ? `${scope.appSlug}/${scope.branchOf.envSlug}#${scope.envSlug}` : `${scope.appSlug}/${scope.envSlug}`;
4276
+ if (opts.org && opts.org !== scope.orgSlug && opts.org !== scope.orgId) fail(`this token belongs to ${scope.orgSlug}, not "${opts.org}"`);
4277
+ if (opts.env && opts.env !== env.envSlug && opts.env !== env.envId) fail(`this token is bound to ${scope.appSlug}/${env.envSlug}, not "${opts.env}" — add --app (or --group) to target another environment you hold a key for`);
4278
+ return {
4279
+ orgId: scope.orgId,
4280
+ envId: scope.envId,
4281
+ label
4282
+ };
4283
+ }
4284
+ /**
4059
4285
  * Resolve an environment to operate on — an application env (`--app --env`,
4060
4286
  * or the config's app + `--env`), a branch of one (`--branch`), or a group env
4061
4287
  * (`--group --env`).
4288
+ *
4289
+ * `--env` is optional for a service token that names no `--app`/`--group`: it is
4290
+ * already bound to exactly one environment, so requiring the flag made every
4291
+ * documented one-liner (`seekrit secrets list`) fail for the CI job and the
4292
+ * agent that are the point of a token. The local MCP server has always inferred
4293
+ * it this way; this is the same rule, in one place, for both.
4062
4294
  */
4063
4295
  async function resolveEnvTarget(ctx, opts) {
4296
+ if (!opts.app && !opts.group && isTokenAuth(ctx)) return boundEnvTarget(ctx, opts);
4064
4297
  const org = await resolveOrg(ctx, opts.org);
4065
4298
  if (!opts.env) fail("specify --env");
4066
4299
  if (opts.group) {
@@ -4636,22 +4869,6 @@ const targetShape = {
4636
4869
  group: z.string().optional().describe("target a group environment instead of an app"),
4637
4870
  env: z.string().optional().describe("environment slug or id (a service token infers its own)")
4638
4871
  };
4639
- /**
4640
- * Resolve which environment a secret tool addresses. A service token with no
4641
- * explicit app/group targets its own bound environment (no flags needed);
4642
- * everyone else names app|group + env.
4643
- */
4644
- async function resolveTargetEnv(ctx, o) {
4645
- if (isTokenAuth(ctx) && !o.app && !o.group) {
4646
- const { scope } = await ctx.client.resolve();
4647
- return {
4648
- orgId: scope.orgId,
4649
- envId: scope.envId,
4650
- label: `${scope.appSlug}/${scope.envSlug}`
4651
- };
4652
- }
4653
- return resolveEnvTarget(ctx, o);
4654
- }
4655
4872
  async function runMcpServer(options = {}) {
4656
4873
  setFailThrows(true);
4657
4874
  await ensureM2mAdminToken();
@@ -4932,7 +5149,7 @@ async function runMcpServer(options = {}) {
4932
5149
  });
4933
5150
  tool("list_secrets", "List secret names + versions in an environment (never values).", ro, targetShape, async (o) => {
4934
5151
  const ctx = getCtx();
4935
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5152
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
4936
5153
  const { secrets } = await ctx.client.listSecrets(orgId, envId);
4937
5154
  return secrets.map((s) => ({
4938
5155
  name: s.name,
@@ -5121,7 +5338,7 @@ async function runMcpServer(options = {}) {
5121
5338
  }, async (o) => {
5122
5339
  const ctx = getCtx();
5123
5340
  ensureDecryptable(ctx);
5124
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5341
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
5125
5342
  await encryptAndSetSecret(ctx, orgId, envId, o.name, o.value);
5126
5343
  return {
5127
5344
  ok: true,
@@ -5136,7 +5353,7 @@ async function runMcpServer(options = {}) {
5136
5353
  version: z.number().int().positive().optional().describe("an earlier version from list_secret_versions (default: current)")
5137
5354
  }, async (o) => {
5138
5355
  const ctx = getCtx();
5139
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5356
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
5140
5357
  if (!o.reveal) {
5141
5358
  const { secrets } = await ctx.client.listSecrets(orgId, envId);
5142
5359
  const row = secrets.find((s) => s.name === o.name);
@@ -5171,7 +5388,7 @@ async function runMcpServer(options = {}) {
5171
5388
  limit: z.number().int().min(1).max(200).optional().describe("default 20")
5172
5389
  }, async (o) => {
5173
5390
  const ctx = getCtx();
5174
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5391
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
5175
5392
  const { versions, currentVersion } = await ctx.client.listSecretVersions(orgId, envId, o.name, { limit: o.limit ?? 20 });
5176
5393
  return {
5177
5394
  currentVersion,
@@ -5189,7 +5406,7 @@ async function runMcpServer(options = {}) {
5189
5406
  version: z.number().int().positive()
5190
5407
  }, async (o) => {
5191
5408
  const ctx = getCtx();
5192
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5409
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
5193
5410
  const { secret, restoredFrom } = await ctx.client.restoreSecret(orgId, envId, o.name, o.version);
5194
5411
  return {
5195
5412
  ok: true,
@@ -5203,7 +5420,7 @@ async function runMcpServer(options = {}) {
5203
5420
  name: z.string()
5204
5421
  }, async (o) => {
5205
5422
  const ctx = getCtx();
5206
- const { orgId, envId } = await resolveTargetEnv(ctx, o);
5423
+ const { orgId, envId } = await resolveEnvTarget(ctx, o);
5207
5424
  await ctx.client.deleteSecret(orgId, envId, o.name);
5208
5425
  return {
5209
5426
  ok: true,
@@ -5326,7 +5543,7 @@ async function runMcpServer(options = {}) {
5326
5543
  if (Boolean(o.user) === Boolean(o.token)) throw new Error("pass exactly one of user or token");
5327
5544
  const ctx = getCtx();
5328
5545
  ensureDecryptable(ctx);
5329
- const { orgId, envId, label } = await resolveTargetEnv(ctx, o);
5546
+ const { orgId, envId, label } = await resolveEnvTarget(ctx, o);
5330
5547
  const dek = await getDek(ctx, orgId, envId);
5331
5548
  let principalType;
5332
5549
  let principalId;
@@ -5504,7 +5721,7 @@ async function runMcpServer(options = {}) {
5504
5721
  * `seekrit mcp`. tsdown bundles the shared server source in at build time, so the
5505
5722
  * published package is self-contained and needs no `@seekrit/cli` install.
5506
5723
  */
5507
- runMcpServer({ version: "0.8.0" }).catch((err) => {
5724
+ runMcpServer({ version: "0.8.1" }).catch((err) => {
5508
5725
  const message = err instanceof Error ? err.message : String(err);
5509
5726
  process.stderr.write(`seekrit-mcp: fatal: ${message}\n`);
5510
5727
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seekrit/mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "npx-able MCP server for seekrit — let Claude Code and other MCP clients provision, manage, and inject end-to-end encrypted secrets.",
5
5
  "mcpName": "dev.seekrit/mcp",
6
6
  "type": "module",
@@ -17,14 +17,14 @@
17
17
  "node": ">=20"
18
18
  },
19
19
  "dependencies": {
20
- "@modelcontextprotocol/sdk": "^1.29.0",
21
- "zod": "^4.4.3"
20
+ "@modelcontextprotocol/sdk": "^1.30.0",
21
+ "zod": "^4.5.4"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^26.1.0",
25
25
  "tsdown": "^0.22.3",
26
- "vitest": "^4.1.9",
27
- "@seekrit/cli": "0.46.0"
26
+ "vitest": "^4.1.11",
27
+ "@seekrit/cli": "1.2.2"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsdown",