@seekrit/mcp 0.3.0 → 0.5.0
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.
- package/README.md +31 -6
- package/dist/index.js +188 -7
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -18,15 +18,38 @@ it just publishes it as its own binary so no CLI install is required first.
|
|
|
18
18
|
## Setup
|
|
19
19
|
|
|
20
20
|
Add it to any MCP client with a stdio server whose command runs this package via
|
|
21
|
-
`npx`, passing a credential in its environment.
|
|
21
|
+
`npx`, passing a credential in its environment.
|
|
22
|
+
|
|
23
|
+
**Fully autonomous agent (recommended).** An agent with no account can
|
|
24
|
+
[sign up](https://seekrit.dev/docs/guides/ai-agents) for **machine credentials**
|
|
25
|
+
(`POST https://mcp.seekrit.dev/signup`) and use the *same* client id + secret for
|
|
26
|
+
everything — the hosted metadata plane and this local crypto plane. Point this
|
|
27
|
+
server at them and it mints its own admin token automatically on first use
|
|
28
|
+
(keyless — the keypair is generated locally), so there is no token to copy:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"seekrit": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["-y", "@seekrit/mcp"],
|
|
36
|
+
"env": {
|
|
37
|
+
"SEEKRIT_CLIENT_ID": "<your client id>",
|
|
38
|
+
"SEEKRIT_CLIENT_SECRET": "<your client secret>"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**With an existing token.** If you already hold a service token, pass it directly.
|
|
46
|
+
For Claude Code:
|
|
22
47
|
|
|
23
48
|
```sh
|
|
24
49
|
# An admin token lets the agent provision structure (apps/envs/tokens) too:
|
|
25
50
|
claude mcp add seekrit --env SEEKRIT_TOKEN=skt_… -- npx -y @seekrit/mcp
|
|
26
51
|
```
|
|
27
52
|
|
|
28
|
-
Or drop a `.mcp.json` in your project — the whole setup is this snippet:
|
|
29
|
-
|
|
30
53
|
```json
|
|
31
54
|
{
|
|
32
55
|
"mcpServers": {
|
|
@@ -73,12 +96,14 @@ The container still decrypts locally — nothing plaintext leaves it.
|
|
|
73
96
|
|
|
74
97
|
## Choosing the credential
|
|
75
98
|
|
|
76
|
-
The server authenticates exactly like the CLI — `
|
|
77
|
-
config at
|
|
99
|
+
The server authenticates exactly like the CLI — `SEEKRIT_CLIENT_ID` +
|
|
100
|
+
`SEEKRIT_CLIENT_SECRET`, `SEEKRIT_TOKEN`, or saved config at
|
|
101
|
+
`~/.config/seekrit/config.json`.
|
|
78
102
|
|
|
79
103
|
| Credential | Good for | Notes |
|
|
80
104
|
| --- | --- | --- |
|
|
81
|
-
| **
|
|
105
|
+
| **Machine credentials** (`SEEKRIT_CLIENT_ID` + `SEEKRIT_CLIENT_SECRET`) | Fully autonomous agents: one credential for both planes | Auto-mints + caches an admin token on first use. Get them from `POST /signup`. |
|
|
106
|
+
| **Admin token** (`seekrit token create --admin`) | Provisioning: create apps/groups/envs, compose, grant, mint tokens | Org-scoped; a fixed headless credential for structure. |
|
|
82
107
|
| **Runtime token** (bound to an env) | Reading/writing/injecting one environment's secrets | Self-decrypts — no passphrase. Cannot provision. |
|
|
83
108
|
|
|
84
109
|
Under user auth (no token), tools that decrypt need `SEEKRIT_PASSPHRASE` in the
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { dirname, join, parse } from "node:path";
|
|
9
9
|
import { createInterface } from "node:readline";
|
|
@@ -664,7 +664,7 @@ function isServiceToken(value) {
|
|
|
664
664
|
}
|
|
665
665
|
//#endregion
|
|
666
666
|
//#region ../cli/package.json
|
|
667
|
-
var version$1 = "0.
|
|
667
|
+
var version$1 = "0.23.0";
|
|
668
668
|
const PROJECT_FILE = "seekrit.json";
|
|
669
669
|
function globalConfigPath() {
|
|
670
670
|
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "seekrit", "config.json");
|
|
@@ -674,6 +674,26 @@ function readGlobalConfig() {
|
|
|
674
674
|
if (!existsSync(path)) return {};
|
|
675
675
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
676
676
|
}
|
|
677
|
+
function writeGlobalConfig(update) {
|
|
678
|
+
const path = globalConfigPath();
|
|
679
|
+
const merged = {
|
|
680
|
+
...readGlobalConfig(),
|
|
681
|
+
...update
|
|
682
|
+
};
|
|
683
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
684
|
+
writeFileSync(path, `${JSON.stringify(merged, null, 2)}\n`, { mode: 384 });
|
|
685
|
+
}
|
|
686
|
+
/** The admin token previously auto-minted from these M2M credentials, if any. */
|
|
687
|
+
function readCachedM2mToken(clientId) {
|
|
688
|
+
return readGlobalConfig().m2mTokens?.[clientId];
|
|
689
|
+
}
|
|
690
|
+
/** Remember an auto-minted admin token so the next run reuses it. */
|
|
691
|
+
function cacheM2mToken(clientId, token) {
|
|
692
|
+
writeGlobalConfig({ m2mTokens: {
|
|
693
|
+
...readGlobalConfig().m2mTokens,
|
|
694
|
+
[clientId]: token
|
|
695
|
+
} });
|
|
696
|
+
}
|
|
677
697
|
/** Walk up from cwd looking for seekrit.json. */
|
|
678
698
|
function findProjectConfig(startDir = process.cwd()) {
|
|
679
699
|
let dir = startDir;
|
|
@@ -706,19 +726,23 @@ var SeekritClient = class {
|
|
|
706
726
|
baseUrl;
|
|
707
727
|
auth;
|
|
708
728
|
fetchImpl;
|
|
729
|
+
client;
|
|
709
730
|
constructor(options) {
|
|
710
731
|
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
711
732
|
this.auth = options.auth;
|
|
712
733
|
this.fetchImpl = options.fetch ?? ((...args) => fetch(...args));
|
|
734
|
+
this.client = options.client;
|
|
713
735
|
}
|
|
714
736
|
async request(method, path, body) {
|
|
715
737
|
const headers = { accept: "application/json" };
|
|
738
|
+
if (this.client) headers["x-seekrit-client"] = this.client;
|
|
716
739
|
if (this.auth.type === "bearer") headers.authorization = `Bearer ${this.auth.token}`;
|
|
717
740
|
else if (this.auth.type === "dynamic") {
|
|
718
741
|
const token = await this.auth.getToken();
|
|
719
742
|
if (!token) throw new SeekritApiError(401, "unauthorized", "session expired");
|
|
720
743
|
headers.authorization = `Bearer ${token}`;
|
|
721
|
-
} else
|
|
744
|
+
} else if (this.auth.type === "m2m") headers.authorization = `Basic ${btoa(`${this.auth.clientId}:${this.auth.clientSecret}`)}`;
|
|
745
|
+
else headers["x-seekrit-dev-user"] = this.auth.email;
|
|
722
746
|
if (body !== void 0) headers["content-type"] = "application/json";
|
|
723
747
|
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
724
748
|
method,
|
|
@@ -971,6 +995,10 @@ var SeekritClient = class {
|
|
|
971
995
|
disableKmsKey(orgId, keyId) {
|
|
972
996
|
return this.request("POST", `/v1/orgs/${orgId}/kms/keys/${keyId}/disable`);
|
|
973
997
|
}
|
|
998
|
+
/** Soft-delete a key: it drops out of every listing and read path. */
|
|
999
|
+
deleteKmsKey(orgId, keyId) {
|
|
1000
|
+
return this.request("DELETE", `/v1/orgs/${orgId}/kms/keys/${keyId}`);
|
|
1001
|
+
}
|
|
974
1002
|
/** The broker's public key — wrap the admin credential to it before registering a target. */
|
|
975
1003
|
getLeaseBrokerKey(orgId) {
|
|
976
1004
|
return this.request("GET", `/v1/orgs/${orgId}/leases/broker-key`);
|
|
@@ -1087,6 +1115,8 @@ function promptHidden(question) {
|
|
|
1087
1115
|
}
|
|
1088
1116
|
//#endregion
|
|
1089
1117
|
//#region ../cli/src/context.ts
|
|
1118
|
+
/** Sent as `x-seekrit-client` so the API attributes usage to the CLI (analytics). */
|
|
1119
|
+
const CLI_CLIENT = `cli/${version$1}`;
|
|
1090
1120
|
/**
|
|
1091
1121
|
* Build the client context from configured credentials, or return null when
|
|
1092
1122
|
* none are set. `seekrit run` uses this to degrade to a plain launcher instead
|
|
@@ -1117,7 +1147,8 @@ function tryBuildContext(dotenvVars = {}) {
|
|
|
1117
1147
|
return {
|
|
1118
1148
|
client: new SeekritClient({
|
|
1119
1149
|
baseUrl: apiUrl,
|
|
1120
|
-
auth
|
|
1150
|
+
auth,
|
|
1151
|
+
client: CLI_CLIENT
|
|
1121
1152
|
}),
|
|
1122
1153
|
auth
|
|
1123
1154
|
};
|
|
@@ -1296,6 +1327,78 @@ async function kmsRecoverMaterial(ctx, orgId, keyId, version) {
|
|
|
1296
1327
|
};
|
|
1297
1328
|
}
|
|
1298
1329
|
//#endregion
|
|
1330
|
+
//#region ../cli/src/m2m.ts
|
|
1331
|
+
/**
|
|
1332
|
+
* Resolve M2M client credentials from (in order) the process environment, a
|
|
1333
|
+
* `.env` overlay (for `seekrit run`), then saved config. Both halves must come
|
|
1334
|
+
* through for the credential to be usable.
|
|
1335
|
+
*/
|
|
1336
|
+
function readM2mCreds(dotenvVars = {}) {
|
|
1337
|
+
const config = readGlobalConfig();
|
|
1338
|
+
const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
|
|
1339
|
+
const clientId = fromEnv("SEEKRIT_CLIENT_ID") ?? config.clientId;
|
|
1340
|
+
const clientSecret = fromEnv("SEEKRIT_CLIENT_SECRET") ?? config.clientSecret;
|
|
1341
|
+
if (!clientId || !clientSecret) return null;
|
|
1342
|
+
return {
|
|
1343
|
+
clientId,
|
|
1344
|
+
clientSecret
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
/** True when a service/dev credential is already configured explicitly. */
|
|
1348
|
+
function hasExplicitCredential(dotenvVars) {
|
|
1349
|
+
const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
|
|
1350
|
+
if (fromEnv("SEEKRIT_TOKEN") || fromEnv("SEEKRIT_DEV_USER")) return true;
|
|
1351
|
+
const config = readGlobalConfig();
|
|
1352
|
+
return Boolean(config.token || config.devUser);
|
|
1353
|
+
}
|
|
1354
|
+
/** Mint a fresh org-scoped admin token using M2M credentials (keyless). */
|
|
1355
|
+
async function mintAdminToken(apiUrl, creds) {
|
|
1356
|
+
const client = new SeekritClient({
|
|
1357
|
+
baseUrl: apiUrl,
|
|
1358
|
+
auth: {
|
|
1359
|
+
type: "m2m",
|
|
1360
|
+
clientId: creds.clientId,
|
|
1361
|
+
clientSecret: creds.clientSecret
|
|
1362
|
+
},
|
|
1363
|
+
client: `cli/${version$1}`
|
|
1364
|
+
});
|
|
1365
|
+
const { orgs } = await client.listOrgs();
|
|
1366
|
+
const org = orgs[0];
|
|
1367
|
+
if (!org) throw new Error("machine client has no organization — sign up first (POST /signup)");
|
|
1368
|
+
const created = await createServiceToken();
|
|
1369
|
+
await client.createToken(org.id, {
|
|
1370
|
+
name: "agent-admin (auto)",
|
|
1371
|
+
tokenId: created.tokenId,
|
|
1372
|
+
tokenHash: created.tokenHash,
|
|
1373
|
+
publicKeyJwk: created.publicKeyJwk,
|
|
1374
|
+
role: "admin",
|
|
1375
|
+
environmentId: null
|
|
1376
|
+
});
|
|
1377
|
+
return created.token;
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* If M2M credentials are configured (and no explicit token/dev-user is), ensure
|
|
1381
|
+
* an admin token exists for them — minting and caching one on first use — and
|
|
1382
|
+
* expose it as `SEEKRIT_TOKEN` so the normal credential resolution
|
|
1383
|
+
* ({@link tryBuildContext}) picks it up. A no-op (returns null) when there is
|
|
1384
|
+
* nothing to bootstrap. Throws only when credentials ARE present but minting
|
|
1385
|
+
* fails, so the reason surfaces instead of a later opaque "no credentials".
|
|
1386
|
+
*/
|
|
1387
|
+
async function ensureM2mAdminToken(dotenvVars = {}) {
|
|
1388
|
+
if (hasExplicitCredential(dotenvVars)) return null;
|
|
1389
|
+
const creds = readM2mCreds(dotenvVars);
|
|
1390
|
+
if (!creds) return null;
|
|
1391
|
+
const cached = readCachedM2mToken(creds.clientId);
|
|
1392
|
+
if (cached) {
|
|
1393
|
+
process.env.SEEKRIT_TOKEN = cached;
|
|
1394
|
+
return cached;
|
|
1395
|
+
}
|
|
1396
|
+
const token = await mintAdminToken(process.env.SEEKRIT_API_URL ?? dotenvVars.SEEKRIT_API_URL ?? readGlobalConfig().apiUrl ?? "https://api.seekrit.dev", creds);
|
|
1397
|
+
cacheM2mToken(creds.clientId, token);
|
|
1398
|
+
process.env.SEEKRIT_TOKEN = token;
|
|
1399
|
+
return token;
|
|
1400
|
+
}
|
|
1401
|
+
//#endregion
|
|
1299
1402
|
//#region ../cli/src/dotenv.ts
|
|
1300
1403
|
/**
|
|
1301
1404
|
* Minimal `.env` parser: `KEY=VALUE`, `#` comments, an optional `export`
|
|
@@ -1413,10 +1516,78 @@ function errText(err) {
|
|
|
1413
1516
|
isError: true
|
|
1414
1517
|
};
|
|
1415
1518
|
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Short primer surfaced as the MCP server `instructions`. Most clients show
|
|
1521
|
+
* this to the model on connect, so it has to orient an agent that lands here
|
|
1522
|
+
* with zero context in a few lines.
|
|
1523
|
+
*/
|
|
1524
|
+
function serverInstructions() {
|
|
1525
|
+
return [
|
|
1526
|
+
"seekrit is a zero-knowledge secrets manager. This is the LOCAL CRYPTO plane —",
|
|
1527
|
+
"it runs on this machine, next to your key, so it's the one server that can",
|
|
1528
|
+
"actually read or write a secret VALUE (everything else can only see structure).",
|
|
1529
|
+
"",
|
|
1530
|
+
"Auth comes from SEEKRIT_TOKEN (a skt_… token), SEEKRIT_CLIENT_ID +",
|
|
1531
|
+
"SEEKRIT_CLIENT_SECRET (machine credentials — an admin token is minted and",
|
|
1532
|
+
"cached automatically on first use), or the config saved by `seekrit login`.",
|
|
1533
|
+
"Decrypting under a user session (not a token) additionally needs",
|
|
1534
|
+
"SEEKRIT_PASSPHRASE set in this server's env — there's no TTY to prompt on.",
|
|
1535
|
+
"",
|
|
1536
|
+
"Model: org → apps/groups → environments → secrets. Call `whoami` first, then",
|
|
1537
|
+
"`get_started` for the recommended end-to-end recipe. Prefer `run_command` over",
|
|
1538
|
+
"`get_secret reveal:true` — it injects secrets into a subprocess so plaintext",
|
|
1539
|
+
"never enters your context or the transcript."
|
|
1540
|
+
].join("\n");
|
|
1541
|
+
}
|
|
1542
|
+
/** The `get_started` tool body: the recommended first-project flow end to end. */
|
|
1543
|
+
function getStartedText() {
|
|
1544
|
+
return [
|
|
1545
|
+
"# Standing up a project with seekrit (agent, end to end)",
|
|
1546
|
+
"",
|
|
1547
|
+
"This server is the crypto plane — every step below runs locally, next to your",
|
|
1548
|
+
"key, so secret values never leave this machine.",
|
|
1549
|
+
"",
|
|
1550
|
+
"## 1. Confirm identity",
|
|
1551
|
+
"`whoami` — see who you're authenticated as and which orgs you can reach. If it",
|
|
1552
|
+
"fails, check SEEKRIT_TOKEN / SEEKRIT_CLIENT_ID+SEEKRIT_CLIENT_SECRET / saved",
|
|
1553
|
+
"login in this server's env.",
|
|
1554
|
+
"",
|
|
1555
|
+
"## 2. Provision structure",
|
|
1556
|
+
"- `create_org` (user session only — a service token can't own one) if you",
|
|
1557
|
+
" don't have one yet, otherwise skip to the next step.",
|
|
1558
|
+
"- `create_app` — an application to hold environments.",
|
|
1559
|
+
"- `create_env` — generates the data key on this machine and grants it to you.",
|
|
1560
|
+
"- `create_group` + `compose_group` (optional) — a reusable secret bag layered",
|
|
1561
|
+
" under one or more app environments.",
|
|
1562
|
+
"",
|
|
1563
|
+
"## 3. Store secrets",
|
|
1564
|
+
"- `set_secret` — encrypts a value locally and stores the ciphertext.",
|
|
1565
|
+
"- `list_secrets` — confirm names + versions (never returns values).",
|
|
1566
|
+
"",
|
|
1567
|
+
"## 4. Use secrets without exposing them",
|
|
1568
|
+
"- `run_command -- <cmd>` — inject secrets into a subprocess; prefer this.",
|
|
1569
|
+
"- `export_env` — materialize a `.env` file when a tool needs one on disk.",
|
|
1570
|
+
"- `get_secret reveal:true` — only when the value itself is what's needed.",
|
|
1571
|
+
"",
|
|
1572
|
+
"## 5. Propagate access",
|
|
1573
|
+
"- `create_token` bound to an app+env — a runtime credential for CI/another",
|
|
1574
|
+
" agent to decrypt with (pass `admin:true` instead for a provisioning token).",
|
|
1575
|
+
"- `grant_env` — give another member or token access to an env's data key.",
|
|
1576
|
+
"- `configure_project` — link a directory to an org/app (writes seekrit.json)",
|
|
1577
|
+
" so a bound token can infer its target without flags.",
|
|
1578
|
+
"",
|
|
1579
|
+
"## 6. Verify",
|
|
1580
|
+
"`audit` — every write, grant, and revocation is recorded; read it back.",
|
|
1581
|
+
"",
|
|
1582
|
+
"Also available: `kms_*` (client-side managed encrypt/sign keys) and",
|
|
1583
|
+
"`create_pg_lease`/`create_mysql_lease` (short-lived database credentials whose",
|
|
1584
|
+
"password is generated here and never stored anywhere in plaintext)."
|
|
1585
|
+
].join("\n");
|
|
1586
|
+
}
|
|
1416
1587
|
/** Build the client context or throw a friendly, agent-readable error. */
|
|
1417
1588
|
function getCtx() {
|
|
1418
1589
|
const ctx = tryBuildContext();
|
|
1419
|
-
if (!ctx) throw new Error("no credentials — set SEEKRIT_TOKEN (a skt_… token)
|
|
1590
|
+
if (!ctx) throw new Error("no credentials — set SEEKRIT_CLIENT_ID + SEEKRIT_CLIENT_SECRET (machine credentials from POST /signup) or SEEKRIT_TOKEN (a skt_… token) in the MCP server env, or run `seekrit login` first");
|
|
1420
1591
|
return ctx;
|
|
1421
1592
|
}
|
|
1422
1593
|
/**
|
|
@@ -1504,10 +1675,11 @@ async function resolveTargetEnv(ctx, o) {
|
|
|
1504
1675
|
}
|
|
1505
1676
|
async function runMcpServer(options = {}) {
|
|
1506
1677
|
setFailThrows(true);
|
|
1678
|
+
await ensureM2mAdminToken();
|
|
1507
1679
|
const server = new McpServer({
|
|
1508
1680
|
name: "seekrit",
|
|
1509
1681
|
version: options.version ?? version$1
|
|
1510
|
-
});
|
|
1682
|
+
}, { instructions: serverInstructions() });
|
|
1511
1683
|
/** Register a tool whose handler returns data (serialized) or throws (→ isError). */
|
|
1512
1684
|
const tool = (name, description, shape, handler) => {
|
|
1513
1685
|
server.registerTool(name, {
|
|
@@ -1521,6 +1693,15 @@ async function runMcpServer(options = {}) {
|
|
|
1521
1693
|
}
|
|
1522
1694
|
}));
|
|
1523
1695
|
};
|
|
1696
|
+
server.registerTool("get_started", {
|
|
1697
|
+
description: "The recommended first-project recipe: provision structure, store secrets, and use them without exposing values. Call this before doing anything else.",
|
|
1698
|
+
inputSchema: {},
|
|
1699
|
+
annotations: {
|
|
1700
|
+
title: "get_started",
|
|
1701
|
+
readOnlyHint: true,
|
|
1702
|
+
openWorldHint: false
|
|
1703
|
+
}
|
|
1704
|
+
}, async () => jsonText(getStartedText()));
|
|
1524
1705
|
tool("whoami", "Show the authenticated identity, its role, and accessible orgs.", {}, async () => {
|
|
1525
1706
|
const ctx = getCtx();
|
|
1526
1707
|
if (isTokenAuth(ctx) && ctx.auth.type === "bearer") {
|
|
@@ -2221,7 +2402,7 @@ async function runMcpServer(options = {}) {
|
|
|
2221
2402
|
* `seekrit mcp`. tsdown bundles the shared server source in at build time, so the
|
|
2222
2403
|
* published package is self-contained and needs no `@seekrit/cli` install.
|
|
2223
2404
|
*/
|
|
2224
|
-
runMcpServer({ version: "0.
|
|
2405
|
+
runMcpServer({ version: "0.5.0" }).catch((err) => {
|
|
2225
2406
|
const message = err instanceof Error ? err.message : String(err);
|
|
2226
2407
|
process.stderr.write(`seekrit-mcp: fatal: ${message}\n`);
|
|
2227
2408
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seekrit/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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
|
+
"mcpName": "dev.seekrit/mcp",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"publishConfig": {
|
|
7
8
|
"access": "public"
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/node": "^26.1.0",
|
|
24
25
|
"tsdown": "^0.22.3",
|
|
25
|
-
"@seekrit/cli": "0.
|
|
26
|
+
"@seekrit/cli": "0.23.0"
|
|
26
27
|
},
|
|
27
28
|
"scripts": {
|
|
28
29
|
"build": "tsdown",
|