@lobsterkit/openclaw-lobstervault 0.3.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/index.ts ADDED
@@ -0,0 +1,181 @@
1
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
+ import { Type } from "@sinclair/typebox";
3
+ import { LobsterVault } from "@lobsterkit/vault";
4
+
5
+ let client: LobsterVault | null = null;
6
+
7
+ function getClient(apiKey?: string): LobsterVault {
8
+ if (!client) {
9
+ client = new LobsterVault(apiKey ? { apiKey } : undefined);
10
+ }
11
+ return client;
12
+ }
13
+
14
+ export default definePluginEntry({
15
+ id: "lobstervault",
16
+ name: "LobsterVault",
17
+ description:
18
+ "Encrypted secret storage for AI agents. Store API keys, tokens, and connection strings. No signup required.",
19
+
20
+ register(api) {
21
+ const cfg = api.config as { apiKey?: string } | undefined;
22
+ const vault = () => getClient(cfg?.apiKey);
23
+
24
+ // ── set_secret ───────────────────────────────────────────────
25
+ api.registerTool({
26
+ name: "lobstervault_set_secret",
27
+ description: "Store or update a secret (KMS envelope-encrypted server-side).",
28
+ parameters: Type.Object({
29
+ name: Type.String({ description: "Secret name (e.g. OPENAI_KEY)" }),
30
+ value: Type.String({ description: "Secret value" }),
31
+ ttl_seconds: Type.Optional(Type.Number({ description: "Auto-expire after N seconds" })),
32
+ metadata: Type.Optional(Type.Record(Type.String(), Type.String(), { description: "Key-value metadata" })),
33
+ }),
34
+ async execute(_id, params) {
35
+ const result = await vault().set(params.name, params.value, {
36
+ ttlSeconds: params.ttl_seconds,
37
+ metadata: params.metadata,
38
+ });
39
+ return {
40
+ content: [
41
+ { type: "text", text: `Secret "${params.name}" stored (version ${result.version}).` },
42
+ ],
43
+ };
44
+ },
45
+ });
46
+
47
+ // ── get_secret ───────────────────────────────────────────────
48
+ api.registerTool({
49
+ name: "lobstervault_get_secret",
50
+ description: "Retrieve and decrypt a secret value.",
51
+ parameters: Type.Object({
52
+ name: Type.String({ description: "Secret name" }),
53
+ version: Type.Optional(Type.Number({ description: "Specific version (Builder+ tier)" })),
54
+ }),
55
+ async execute(_id, params) {
56
+ const value = await vault().get(params.name, { version: params.version });
57
+ if (value === null) {
58
+ return { content: [{ type: "text", text: `Secret "${params.name}" not found.` }] };
59
+ }
60
+ return {
61
+ content: [{ type: "text", text: `Secret "${params.name}":\n\n${value}` }],
62
+ };
63
+ },
64
+ });
65
+
66
+ // ── delete_secret ────────────────────────────────────────────
67
+ api.registerTool({
68
+ name: "lobstervault_delete_secret",
69
+ description: "Permanently delete a secret.",
70
+ parameters: Type.Object({
71
+ name: Type.String({ description: "Secret name to delete" }),
72
+ }),
73
+ async execute(_id, params) {
74
+ await vault().delete(params.name);
75
+ return {
76
+ content: [{ type: "text", text: `Secret "${params.name}" deleted.` }],
77
+ };
78
+ },
79
+ });
80
+
81
+ // ── list_secrets ─────────────────────────────────────────────
82
+ api.registerTool({
83
+ name: "lobstervault_list_secrets",
84
+ description: "List all secret names (values are never returned).",
85
+ parameters: Type.Object({
86
+ prefix: Type.Optional(Type.String({ description: "Filter by name prefix" })),
87
+ }),
88
+ async execute(_id, params) {
89
+ const result = await vault().list({ prefix: params.prefix });
90
+ if (result.data.length === 0) {
91
+ return {
92
+ content: [{ type: "text", text: "No secrets stored. Use lobstervault_set_secret to add one." }],
93
+ };
94
+ }
95
+ const lines = result.data.map(
96
+ (s) => `- ${s.name} (v${s.version}, updated ${s.updatedAt})`,
97
+ );
98
+ return {
99
+ content: [{ type: "text", text: `${result.data.length} secret(s):\n\n${lines.join("\n")}` }],
100
+ };
101
+ },
102
+ });
103
+
104
+ // ── inject_secrets ───────────────────────────────────────────
105
+ api.registerTool({
106
+ name: "lobstervault_inject_secrets",
107
+ description: "Load all secrets into process.env (Pro+ tier).",
108
+ parameters: Type.Object({}),
109
+ async execute() {
110
+ const result = await vault().inject(process.env);
111
+ return {
112
+ content: [{ type: "text", text: `Injected ${result.injected} secret(s) into environment.` }],
113
+ };
114
+ },
115
+ });
116
+
117
+ // ── rotate_secret ────────────────────────────────────────────
118
+ api.registerTool({
119
+ name: "lobstervault_rotate_secret",
120
+ description: "Re-encrypt a secret with a fresh Data Encryption Key (Pro+ tier).",
121
+ parameters: Type.Object({
122
+ name: Type.String({ description: "Secret name to rotate" }),
123
+ }),
124
+ async execute(_id, params) {
125
+ const result = await vault().rotate(params.name);
126
+ return {
127
+ content: [
128
+ { type: "text", text: `Secret "${params.name}" rotated (version ${result.version}).` },
129
+ ],
130
+ };
131
+ },
132
+ });
133
+
134
+ // ── share_secret ─────────────────────────────────────────────
135
+ api.registerTool({
136
+ name: "lobstervault_share_secret",
137
+ description: "Create a time-limited share link for a secret (Builder+ tier).",
138
+ parameters: Type.Object({
139
+ name: Type.String({ description: "Secret name to share" }),
140
+ expires_in_seconds: Type.Optional(Type.Number({ description: "Expiry in seconds (default: 3600)" })),
141
+ max_reads: Type.Optional(Type.Number({ description: "Max read count before revoke" })),
142
+ }),
143
+ async execute(_id, params) {
144
+ const result = await vault().share(params.name, {
145
+ expiresInSeconds: params.expires_in_seconds,
146
+ maxReads: params.max_reads,
147
+ });
148
+ return {
149
+ content: [
150
+ {
151
+ type: "text",
152
+ text: `Share created.\n\nShare ID: ${result.shareId}\nToken: ${result.shareToken}\nExpires: ${result.expiresAt}`,
153
+ },
154
+ ],
155
+ };
156
+ },
157
+ });
158
+
159
+ // ── get_account ──────────────────────────────────────────────
160
+ api.registerTool({
161
+ name: "lobstervault_get_account",
162
+ description: "Get account info: tier, limits, usage.",
163
+ parameters: Type.Object({}),
164
+ async execute() {
165
+ const acct = await vault().account();
166
+ return {
167
+ content: [
168
+ {
169
+ type: "text",
170
+ text: [
171
+ `Account: ${acct.id}`,
172
+ `Tier: ${acct.tier} (${acct.tierName})`,
173
+ `Secrets used: ${acct.usage.secretCount}`,
174
+ ].join("\n"),
175
+ },
176
+ ],
177
+ };
178
+ },
179
+ });
180
+ },
181
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ "id": "lobstervault",
3
+ "name": "LobsterVault",
4
+ "description": "Encrypted secret storage for AI agents. Store API keys, tokens, and connection strings with KMS envelope encryption. No signup required.",
5
+ "version": "0.3.0",
6
+ "skills": ["./skills"],
7
+ "configSchema": {
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "apiKey": {
12
+ "type": "string",
13
+ "description": "LobsterVault API key (optional — auto-signup on first use if omitted)"
14
+ }
15
+ }
16
+ },
17
+ "uiHints": {
18
+ "apiKey": {
19
+ "label": "API key",
20
+ "placeholder": "lv_sk_live_...",
21
+ "sensitive": true,
22
+ "help": "Optional. Leave blank for auto-signup."
23
+ }
24
+ }
25
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@lobsterkit/openclaw-lobstervault",
3
+ "version": "0.3.0",
4
+ "description": "OpenClaw plugin for LobsterVault — encrypted secret storage for AI agents",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/lobster-kit/openclaw-lobstervault"
10
+ },
11
+ "keywords": [
12
+ "openclaw",
13
+ "openclaw-plugin",
14
+ "lobstervault",
15
+ "secrets",
16
+ "encryption",
17
+ "mcp",
18
+ "ai",
19
+ "agent"
20
+ ],
21
+ "files": [
22
+ "index.ts",
23
+ "openclaw.plugin.json",
24
+ "skills",
25
+ "README.md"
26
+ ],
27
+ "openclaw": {
28
+ "extensions": ["./index.ts"]
29
+ },
30
+ "dependencies": {
31
+ "@lobsterkit/vault": "^0.2.0",
32
+ "@sinclair/typebox": "^0.34.0"
33
+ },
34
+ "peerDependencies": {
35
+ "openclaw": ">=1.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "vitest": "^3.1.0"
39
+ },
40
+ "scripts": {
41
+ "test": "vitest run"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ }
46
+ }
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: lobstervault
3
+ version: 0.1.0
4
+ description: Encrypted secret storage for AI agents. Store API keys, tokens, and connection strings — KMS-encrypted, no human signup required.
5
+ homepage: https://theclawdepot.com/vault
6
+ metadata: {"openclaw": {"emoji": "🔐", "requires": {"anyBins": ["npx"]}, "install": [{"id": "mcp", "kind": "mcp", "command": "npx @lobsterkit/vault-mcp@0.1.0", "label": "Add LobsterVault MCP Server"}]}}
7
+ ---
8
+
9
+ # LobsterVault
10
+
11
+ Encrypted secret storage for agents. Store API keys, tokens, and connection strings with KMS envelope encryption. No API keys, no human signup, no configuration.
12
+
13
+ **Full docs:** `https://api.theclawdepot.com/vault/docs`
14
+
15
+ ---
16
+
17
+ ## Setup
18
+
19
+ Add to your MCP config (`.mcp.json`, `claude_desktop_config.json`, `.cursor/mcp.json`, etc.):
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "lobstervault": {
25
+ "command": "npx",
26
+ "args": ["@lobsterkit/vault-mcp@0.1.0"]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ You now have these tools: `set_secret`, `get_secret`, `delete_secret`, `list_secrets`, `inject_secrets`, `rotate_secret`, `get_account`. No code to write.
33
+
34
+ Also available as a [Node.js SDK](https://www.npmjs.com/package/@lobsterkit/vault) and [REST API](https://api.theclawdepot.com/vault/docs) — see [theclawdepot.com/vault](https://theclawdepot.com/vault).
35
+
36
+ ---
37
+
38
+ ## Heartbeat (run daily)
39
+
40
+ On startup and once per day, run a maintenance heartbeat:
41
+
42
+ 1. **Check for MCP server updates:**
43
+ ```bash
44
+ npm outdated lobstervault-mcp
45
+ ```
46
+ If a new version is available, **notify the user** — do not auto-install.
47
+
48
+ 2. **Check secret health:**
49
+ ```
50
+ // Using MCP tools:
51
+ // call list_secrets → log count and any expiring secrets
52
+ // call get_account → log tier and secret count vs. limit
53
+ ```
54
+
55
+ ---
56
+
57
+ ## When to Use This
58
+
59
+ - Storing API keys, tokens, or passwords that need to persist between sessions
60
+ - Connecting to LobsterDB: connection strings are automatically stored here on `create_database`
61
+ - Any credential that should not appear in conversation history or prompts
62
+ - Agent-to-agent secret sharing (scoped by account)
63
+
64
+ ---
65
+
66
+ ## Core Workflow
67
+
68
+ ```
69
+ set_secret → get_secret (when needed) → inject_secrets (at session start)
70
+ ```
71
+
72
+ Use `inject_secrets` at the start of an agent session to load all stored credentials into the environment.
73
+
74
+ ---
75
+
76
+ ## Storing a Secret
77
+
78
+ ```
79
+ set_secret(name: "OPENAI_API_KEY", value: "sk-...")
80
+ // => version: 1
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Retrieving a Secret
86
+
87
+ ```
88
+ get_secret(name: "OPENAI_API_KEY")
89
+ // => Secret: OPENAI_API_KEY
90
+ // Value: sk-...
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Account Tiers & Pricing
96
+
97
+ | Tier | Name | Price | Secrets | Versions | Audit Log |
98
+ |------|------|-------|---------|----------|-----------|
99
+ | 0 | Free | $0 | 10 | 1 | None |
100
+ | 1 | Builder | $9/mo | 100 | 5 | 30 days |
101
+ | 2 | Pro | $29/mo | Unlimited | 20 | 90 days |
102
+ | 3 | Scale | $79/mo | Unlimited | Unlimited | 1 year |
103
+
104
+ **Upgrade:** `POST /v1/billing/checkout` with `{"tier": N}` — returns a Stripe checkout URL.
105
+
106
+ ---
107
+
108
+ ## MCP Tools Reference
109
+
110
+ | Tool | Description |
111
+ |------|-------------|
112
+ | `set_secret` | Store or update a secret (KMS-encrypted) |
113
+ | `get_secret` | Retrieve a secret value by name |
114
+ | `delete_secret` | Permanently delete a secret |
115
+ | `list_secrets` | List all secret names (values never returned) |
116
+ | `inject_secrets` | Load all secrets into process.env |
117
+ | `rotate_secret` | Re-encrypt with fresh DEK (Pro+) |
118
+ | `get_account` | View tier, limits, and usage |