agentlock-shared 0.2.0 → 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/dist/__tests__/billing.test.d.ts +2 -0
- package/dist/__tests__/billing.test.d.ts.map +1 -0
- package/dist/__tests__/billing.test.js +31 -0
- package/dist/__tests__/billing.test.js.map +1 -0
- package/dist/__tests__/dns-pinning.test.d.ts +2 -0
- package/dist/__tests__/dns-pinning.test.d.ts.map +1 -0
- package/dist/__tests__/dns-pinning.test.js +33 -0
- package/dist/__tests__/dns-pinning.test.js.map +1 -0
- package/dist/__tests__/llm-classifier-cache-store.test.d.ts +2 -0
- package/dist/__tests__/llm-classifier-cache-store.test.d.ts.map +1 -0
- package/dist/__tests__/llm-classifier-cache-store.test.js +65 -0
- package/dist/__tests__/llm-classifier-cache-store.test.js.map +1 -0
- package/dist/__tests__/llm-classifier-cache.test.d.ts +2 -0
- package/dist/__tests__/llm-classifier-cache.test.d.ts.map +1 -0
- package/dist/__tests__/llm-classifier-cache.test.js +44 -0
- package/dist/__tests__/llm-classifier-cache.test.js.map +1 -0
- package/dist/__tests__/llm-classifier.test.d.ts +2 -0
- package/dist/__tests__/llm-classifier.test.d.ts.map +1 -0
- package/dist/__tests__/llm-classifier.test.js +167 -0
- package/dist/__tests__/llm-classifier.test.js.map +1 -0
- package/dist/__tests__/plans-classifier-limits.test.d.ts +2 -0
- package/dist/__tests__/plans-classifier-limits.test.d.ts.map +1 -0
- package/dist/__tests__/plans-classifier-limits.test.js +22 -0
- package/dist/__tests__/plans-classifier-limits.test.js.map +1 -0
- package/dist/__tests__/policy-category-floor.test.d.ts +2 -0
- package/dist/__tests__/policy-category-floor.test.d.ts.map +1 -0
- package/dist/__tests__/policy-category-floor.test.js +46 -0
- package/dist/__tests__/policy-category-floor.test.js.map +1 -0
- package/dist/__tests__/policy-claude-bash.test.d.ts +2 -0
- package/dist/__tests__/policy-claude-bash.test.d.ts.map +1 -0
- package/dist/__tests__/policy-claude-bash.test.js +401 -0
- package/dist/__tests__/policy-claude-bash.test.js.map +1 -0
- package/dist/__tests__/policy-llm-floor.test.d.ts +2 -0
- package/dist/__tests__/policy-llm-floor.test.d.ts.map +1 -0
- package/dist/__tests__/policy-llm-floor.test.js +107 -0
- package/dist/__tests__/policy-llm-floor.test.js.map +1 -0
- package/dist/__tests__/policy-ssh-e2e.test.d.ts +2 -0
- package/dist/__tests__/policy-ssh-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/policy-ssh-e2e.test.js +89 -0
- package/dist/__tests__/policy-ssh-e2e.test.js.map +1 -0
- package/dist/__tests__/policy-ssh-sessions.test.d.ts +2 -0
- package/dist/__tests__/policy-ssh-sessions.test.d.ts.map +1 -0
- package/dist/__tests__/policy-ssh-sessions.test.js +139 -0
- package/dist/__tests__/policy-ssh-sessions.test.js.map +1 -0
- package/dist/__tests__/policy-ssh.test.d.ts +2 -0
- package/dist/__tests__/policy-ssh.test.d.ts.map +1 -0
- package/dist/__tests__/policy-ssh.test.js +180 -0
- package/dist/__tests__/policy-ssh.test.js.map +1 -0
- package/dist/__tests__/policy.test.js +400 -2
- package/dist/__tests__/policy.test.js.map +1 -1
- package/dist/__tests__/redact.test.js +76 -0
- package/dist/__tests__/redact.test.js.map +1 -1
- package/dist/__tests__/signing.test.js +89 -0
- package/dist/__tests__/signing.test.js.map +1 -1
- package/dist/__tests__/ssh-fingerprint.test.d.ts +2 -0
- package/dist/__tests__/ssh-fingerprint.test.d.ts.map +1 -0
- package/dist/__tests__/ssh-fingerprint.test.js +19 -0
- package/dist/__tests__/ssh-fingerprint.test.js.map +1 -0
- package/dist/__tests__/vpn-route.test.d.ts +2 -0
- package/dist/__tests__/vpn-route.test.d.ts.map +1 -0
- package/dist/__tests__/vpn-route.test.js +72 -0
- package/dist/__tests__/vpn-route.test.js.map +1 -0
- package/dist/__tests__/wireguard.test.d.ts +2 -0
- package/dist/__tests__/wireguard.test.d.ts.map +1 -0
- package/dist/__tests__/wireguard.test.js +114 -0
- package/dist/__tests__/wireguard.test.js.map +1 -0
- package/dist/billing.d.ts +12 -0
- package/dist/billing.d.ts.map +1 -0
- package/dist/billing.js +41 -0
- package/dist/billing.js.map +1 -0
- package/dist/crypto.d.ts +5 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +80 -23
- package/dist/crypto.js.map +1 -1
- package/dist/dns-pinning.d.ts +28 -0
- package/dist/dns-pinning.d.ts.map +1 -0
- package/dist/dns-pinning.js +113 -0
- package/dist/dns-pinning.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/llm-classifier-cache-store.d.ts +49 -0
- package/dist/llm-classifier-cache-store.d.ts.map +1 -0
- package/dist/llm-classifier-cache-store.js +63 -0
- package/dist/llm-classifier-cache-store.js.map +1 -0
- package/dist/llm-classifier-cache.d.ts +6 -0
- package/dist/llm-classifier-cache.d.ts.map +1 -0
- package/dist/llm-classifier-cache.js +52 -0
- package/dist/llm-classifier-cache.js.map +1 -0
- package/dist/llm-classifier.d.ts +29 -0
- package/dist/llm-classifier.d.ts.map +1 -0
- package/dist/llm-classifier.js +191 -0
- package/dist/llm-classifier.js.map +1 -0
- package/dist/observability.d.ts +36 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +75 -0
- package/dist/observability.js.map +1 -0
- package/dist/plans.d.ts +17 -0
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +36 -14
- package/dist/plans.js.map +1 -1
- package/dist/policy.d.ts +173 -3
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +910 -42
- package/dist/policy.js.map +1 -1
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +83 -3
- package/dist/redact.js.map +1 -1
- package/dist/regex-safety.d.ts +21 -0
- package/dist/regex-safety.d.ts.map +1 -0
- package/dist/regex-safety.js +49 -0
- package/dist/regex-safety.js.map +1 -0
- package/dist/sanitize.d.ts +31 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +54 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/schemas.d.ts +202 -10
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +91 -1
- package/dist/schemas.js.map +1 -1
- package/dist/signing.d.ts +15 -0
- package/dist/signing.d.ts.map +1 -1
- package/dist/signing.js +53 -4
- package/dist/signing.js.map +1 -1
- package/dist/ssh-fingerprint.d.ts +10 -0
- package/dist/ssh-fingerprint.d.ts.map +1 -0
- package/dist/ssh-fingerprint.js +52 -0
- package/dist/ssh-fingerprint.js.map +1 -0
- package/dist/ssrf.d.ts +36 -0
- package/dist/ssrf.d.ts.map +1 -0
- package/dist/ssrf.js +140 -0
- package/dist/ssrf.js.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wireguard.d.ts +63 -0
- package/dist/wireguard.d.ts.map +1 -0
- package/dist/wireguard.js +226 -0
- package/dist/wireguard.js.map +1 -0
- package/package.json +42 -29
- package/.turbo/turbo-build.log +0 -4
- package/.turbo/turbo-test.log +0 -76
- package/dist/__tests__/content-crypto.test.d.ts +0 -2
- package/dist/__tests__/content-crypto.test.d.ts.map +0 -1
- package/dist/__tests__/content-crypto.test.js +0 -117
- package/dist/__tests__/content-crypto.test.js.map +0 -1
- package/dist/__tests__/signing.test (# Edit conflict 2026-04-01 z3etfmC #).js +0 -51
- package/dist/__tests__/signing.test.js (# Edit conflict 2026-04-01 4rndy9C #).map +0 -1
- package/dist/content-crypto.d.ts +0 -24
- package/dist/content-crypto.d.ts.map +0 -1
- package/dist/content-crypto.js +0 -58
- package/dist/content-crypto.js.map +0 -1
- package/src/__tests__/crypto.test.ts +0 -169
- package/src/__tests__/messaging.test.ts +0 -83
- package/src/__tests__/policy.test.ts +0 -222
- package/src/__tests__/redact.test.ts +0 -41
- package/src/__tests__/signing.test.ts +0 -55
- package/src/crypto.ts +0 -235
- package/src/index.ts +0 -8
- package/src/mcp-catalog.ts +0 -181
- package/src/plans.ts +0 -116
- package/src/policy.ts +0 -216
- package/src/redact.ts +0 -131
- package/src/schemas.ts +0 -121
- package/src/signing.ts +0 -120
- package/src/types.ts +0 -213
- package/test-gateway.mjs +0 -47
- package/tsconfig.json +0 -10
- package/vitest.config.ts +0 -8
package/src/crypto.ts
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import nacl from 'tweetnacl';
|
|
2
|
-
import { encodeBase64, decodeBase64 } from 'tweetnacl-util';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Envelope encryption prefix. Data encrypted with envelopeEncrypt() is
|
|
6
|
-
* stored as a single string: "env1:<base64-wrappedDEK>:<base64-payload>".
|
|
7
|
-
* The decrypt() function detects this prefix and automatically unwraps
|
|
8
|
-
* using the DEK, maintaining backward compatibility with legacy data
|
|
9
|
-
* encrypted directly with MASTER_KEY.
|
|
10
|
-
*/
|
|
11
|
-
const ENVELOPE_PREFIX = 'env1:';
|
|
12
|
-
|
|
13
|
-
export function generateKey(): Uint8Array {
|
|
14
|
-
return nacl.randomBytes(32);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Low-level symmetric encryption using a provided key.
|
|
19
|
-
* Callers that need envelope encryption (per-data DEK) should use
|
|
20
|
-
* envelopeEncrypt() instead.
|
|
21
|
-
*/
|
|
22
|
-
export function encrypt(data: string, key: Uint8Array): string {
|
|
23
|
-
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
|
|
24
|
-
const message = new TextEncoder().encode(data);
|
|
25
|
-
const box = nacl.secretbox(message, nonce, key);
|
|
26
|
-
|
|
27
|
-
const combined = new Uint8Array(nonce.length + box.length);
|
|
28
|
-
combined.set(nonce);
|
|
29
|
-
combined.set(box, nonce.length);
|
|
30
|
-
|
|
31
|
-
return encodeBase64(combined);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Low-level symmetric decryption. Handles both envelope-encrypted data
|
|
36
|
-
* (prefixed with "env1:") and legacy direct-key encrypted data.
|
|
37
|
-
*
|
|
38
|
-
* For envelope data: unwraps the per-data DEK using the master key,
|
|
39
|
-
* then decrypts the payload with the DEK.
|
|
40
|
-
*
|
|
41
|
-
* For legacy data: decrypts directly with the provided key, falling
|
|
42
|
-
* back to MASTER_KEY_PREVIOUS for key rotation support.
|
|
43
|
-
*/
|
|
44
|
-
export function decrypt(encryptedData: string, key: Uint8Array): string {
|
|
45
|
-
// Detect envelope-encrypted format and handle transparently
|
|
46
|
-
if (encryptedData.startsWith(ENVELOPE_PREFIX)) {
|
|
47
|
-
return envelopeDecryptInternal(encryptedData, key);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Legacy format: data encrypted directly with MASTER_KEY
|
|
51
|
-
const combined = decodeBase64(encryptedData);
|
|
52
|
-
const nonce = combined.slice(0, nacl.secretbox.nonceLength);
|
|
53
|
-
const box = combined.slice(nacl.secretbox.nonceLength);
|
|
54
|
-
|
|
55
|
-
const message = nacl.secretbox.open(box, nonce, key);
|
|
56
|
-
if (message) {
|
|
57
|
-
return new TextDecoder().decode(message);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Try previous master key for rotation support
|
|
61
|
-
const prevKey = getPreviousMasterKey();
|
|
62
|
-
if (prevKey) {
|
|
63
|
-
const message2 = nacl.secretbox.open(box, nonce, prevKey);
|
|
64
|
-
if (message2) {
|
|
65
|
-
return new TextDecoder().decode(message2);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
throw new Error('Decryption failed: invalid key or corrupted data');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Encrypt arbitrary data using a per-data DEK (envelope encryption).
|
|
74
|
-
* Generates a fresh 256-bit DEK, encrypts the data with it, then wraps
|
|
75
|
-
* the DEK with the provided master key. Returns a single string in the
|
|
76
|
-
* format "env1:<wrappedDEK>:<encryptedPayload>" so it fits in a single
|
|
77
|
-
* database column and is backward-compatible with decrypt().
|
|
78
|
-
*
|
|
79
|
-
* Use this instead of encrypt() for all data at rest. Each encrypted
|
|
80
|
-
* value gets its own DEK, so compromising one ciphertext does not
|
|
81
|
-
* expose other data -- the attacker still needs the master key to
|
|
82
|
-
* unwrap any individual DEK.
|
|
83
|
-
*/
|
|
84
|
-
export function envelopeEncrypt(data: string, masterKey: Uint8Array): string {
|
|
85
|
-
const dek = generateKey();
|
|
86
|
-
try {
|
|
87
|
-
const wrappedDEK = encrypt(encodeBase64(dek), masterKey);
|
|
88
|
-
const encryptedPayload = encrypt(data, dek);
|
|
89
|
-
return `${ENVELOPE_PREFIX}${wrappedDEK}:${encryptedPayload}`;
|
|
90
|
-
} finally {
|
|
91
|
-
// Zero DEK from memory after use (defense-in-depth against heap dumps)
|
|
92
|
-
dek.fill(0);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Decrypt data produced by envelopeEncrypt(). Expects the "env1:" prefixed
|
|
98
|
-
* format. For general use, call decrypt() which auto-detects the format.
|
|
99
|
-
*/
|
|
100
|
-
export function envelopeDecrypt(encryptedData: string, masterKey: Uint8Array): string {
|
|
101
|
-
if (!encryptedData.startsWith(ENVELOPE_PREFIX)) {
|
|
102
|
-
throw new Error('Not an envelope-encrypted value (missing env1: prefix)');
|
|
103
|
-
}
|
|
104
|
-
return envelopeDecryptInternal(encryptedData, masterKey);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Internal envelope decryption. Parses the "env1:wrappedDEK:payload" format,
|
|
109
|
-
* unwraps the DEK, and decrypts the payload.
|
|
110
|
-
*/
|
|
111
|
-
function envelopeDecryptInternal(encryptedData: string, masterKey: Uint8Array): string {
|
|
112
|
-
// Format: "env1:<base64-wrappedDEK>:<base64-encryptedPayload>"
|
|
113
|
-
// The wrapped DEK itself is a base64 string produced by encrypt(), which
|
|
114
|
-
// can contain '+', '/', '=' but never ':'. So we split on ':' after the prefix.
|
|
115
|
-
const withoutPrefix = encryptedData.slice(ENVELOPE_PREFIX.length);
|
|
116
|
-
const separatorIndex = withoutPrefix.lastIndexOf(':');
|
|
117
|
-
if (separatorIndex <= 0) {
|
|
118
|
-
throw new Error('Invalid envelope format: missing DEK/payload separator');
|
|
119
|
-
}
|
|
120
|
-
const wrappedDEK = withoutPrefix.slice(0, separatorIndex);
|
|
121
|
-
const encryptedPayload = withoutPrefix.slice(separatorIndex + 1);
|
|
122
|
-
|
|
123
|
-
if (!wrappedDEK || !encryptedPayload) {
|
|
124
|
-
throw new Error('Invalid envelope format: empty DEK or payload');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Unwrap the DEK using the master key (with key-rotation fallback)
|
|
128
|
-
let dekBase64: string;
|
|
129
|
-
try {
|
|
130
|
-
dekBase64 = decrypt(wrappedDEK, masterKey);
|
|
131
|
-
} catch {
|
|
132
|
-
throw new Error('Envelope decryption failed: could not unwrap DEK');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const dek = decodeBase64(dekBase64);
|
|
136
|
-
try {
|
|
137
|
-
// Decrypt the payload using the per-data DEK
|
|
138
|
-
// Use low-level decryption here (not decrypt()) to avoid infinite
|
|
139
|
-
// recursion on the envelope prefix check -- the inner payload is
|
|
140
|
-
// always in legacy format.
|
|
141
|
-
const combined = decodeBase64(encryptedPayload);
|
|
142
|
-
const nonce = combined.slice(0, nacl.secretbox.nonceLength);
|
|
143
|
-
const box = combined.slice(nacl.secretbox.nonceLength);
|
|
144
|
-
const message = nacl.secretbox.open(box, nonce, dek);
|
|
145
|
-
if (!message) {
|
|
146
|
-
throw new Error('Envelope decryption failed: payload decryption failed');
|
|
147
|
-
}
|
|
148
|
-
return new TextDecoder().decode(message);
|
|
149
|
-
} finally {
|
|
150
|
-
// Zero DEK from memory after use
|
|
151
|
-
dek.fill(0);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function encryptDEK(dek: Uint8Array, masterKey: Uint8Array): string {
|
|
156
|
-
return encrypt(encodeBase64(dek), masterKey);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export function decryptDEK(encryptedDEK: string, masterKey: Uint8Array): Uint8Array {
|
|
160
|
-
const dekBase64 = decrypt(encryptedDEK, masterKey);
|
|
161
|
-
return decodeBase64(dekBase64);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Cache the decoded master key to avoid creating multiple copies in memory.
|
|
165
|
-
// A single copy is preferable to many short-lived copies scattered on the heap.
|
|
166
|
-
let _cachedMasterKey: Uint8Array | null = null;
|
|
167
|
-
|
|
168
|
-
export function getMasterKey(): Uint8Array {
|
|
169
|
-
if (_cachedMasterKey) return _cachedMasterKey.slice();
|
|
170
|
-
const key = process.env.MASTER_KEY;
|
|
171
|
-
if (!key) throw new Error('MASTER_KEY environment variable not set');
|
|
172
|
-
_cachedMasterKey = decodeBase64(key);
|
|
173
|
-
return _cachedMasterKey.slice();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Support MASTER_KEY rotation: try previous key when current key fails
|
|
177
|
-
let _cachedPrevKey: Uint8Array | null = null;
|
|
178
|
-
let _prevKeyChecked = false;
|
|
179
|
-
|
|
180
|
-
export function getPreviousMasterKey(): Uint8Array | null {
|
|
181
|
-
if (_prevKeyChecked) return _cachedPrevKey ? _cachedPrevKey.slice() : null;
|
|
182
|
-
_prevKeyChecked = true;
|
|
183
|
-
const key = process.env.MASTER_KEY_PREVIOUS;
|
|
184
|
-
if (!key) return null;
|
|
185
|
-
_cachedPrevKey = decodeBase64(key);
|
|
186
|
-
return _cachedPrevKey.slice();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/** Zero and release cached master keys. Call on graceful shutdown. */
|
|
190
|
-
export function clearCachedKeys(): void {
|
|
191
|
-
if (_cachedMasterKey) {
|
|
192
|
-
_cachedMasterKey.fill(0);
|
|
193
|
-
_cachedMasterKey = null;
|
|
194
|
-
}
|
|
195
|
-
if (_cachedPrevKey) {
|
|
196
|
-
_cachedPrevKey.fill(0);
|
|
197
|
-
_cachedPrevKey = null;
|
|
198
|
-
}
|
|
199
|
-
_prevKeyChecked = false;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export function generateMasterKey(): string {
|
|
203
|
-
return encodeBase64(generateKey());
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function encryptCredential(
|
|
207
|
-
payload: Record<string, unknown>,
|
|
208
|
-
masterKey: Uint8Array
|
|
209
|
-
): { encryptedDEK: string; encryptedPayload: string } {
|
|
210
|
-
const dek = generateKey();
|
|
211
|
-
try {
|
|
212
|
-
const encryptedDEK = encryptDEK(dek, masterKey);
|
|
213
|
-
const encryptedPayload = encrypt(JSON.stringify(payload), dek);
|
|
214
|
-
return { encryptedDEK, encryptedPayload };
|
|
215
|
-
} finally {
|
|
216
|
-
// Zero DEK from memory after use (defense-in-depth against heap dumps)
|
|
217
|
-
dek.fill(0);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export function decryptCredential(
|
|
222
|
-
encryptedDEK: string,
|
|
223
|
-
encryptedPayload: string,
|
|
224
|
-
masterKey: Uint8Array
|
|
225
|
-
): Record<string, unknown> {
|
|
226
|
-
const dek = decryptDEK(encryptedDEK, masterKey);
|
|
227
|
-
try {
|
|
228
|
-
const json = decrypt(encryptedPayload, dek);
|
|
229
|
-
return JSON.parse(json);
|
|
230
|
-
} finally {
|
|
231
|
-
// Best-effort: zero DEK from memory to minimize exposure window.
|
|
232
|
-
// Not guaranteed by JS runtime, but reduces risk of heap-dump leaks.
|
|
233
|
-
dek.fill(0);
|
|
234
|
-
}
|
|
235
|
-
}
|
package/src/index.ts
DELETED
package/src/mcp-catalog.ts
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
export interface McpServerTemplate {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
serverUrl: string;
|
|
6
|
-
authType: 'bearer' | 'none';
|
|
7
|
-
authLabel?: string;
|
|
8
|
-
authPlaceholder?: string;
|
|
9
|
-
authHelpUrl?: string;
|
|
10
|
-
category: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const MCP_CATALOG: McpServerTemplate[] = [
|
|
14
|
-
// --- Developer Tools ---
|
|
15
|
-
{
|
|
16
|
-
id: 'github',
|
|
17
|
-
name: 'GitHub',
|
|
18
|
-
description: 'Manage repos, issues, PRs, and code search',
|
|
19
|
-
|
|
20
|
-
serverUrl: 'https://api.githubcopilot.com/mcp/',
|
|
21
|
-
authType: 'bearer',
|
|
22
|
-
authLabel: 'Personal Access Token',
|
|
23
|
-
authPlaceholder: 'ghp_...',
|
|
24
|
-
authHelpUrl: 'https://github.com/settings/tokens',
|
|
25
|
-
category: 'Developer Tools',
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
id: 'gitlab',
|
|
29
|
-
name: 'GitLab',
|
|
30
|
-
description: 'Projects, merge requests, pipelines, and issues',
|
|
31
|
-
|
|
32
|
-
serverUrl: 'https://gitlab.com/-/mcp',
|
|
33
|
-
authType: 'bearer',
|
|
34
|
-
authLabel: 'Personal Access Token',
|
|
35
|
-
authPlaceholder: 'glpat-...',
|
|
36
|
-
authHelpUrl: 'https://gitlab.com/-/user_settings/personal_access_tokens',
|
|
37
|
-
category: 'Developer Tools',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: 'linear',
|
|
41
|
-
name: 'Linear',
|
|
42
|
-
description: 'Issue tracking, projects, and team workflows',
|
|
43
|
-
|
|
44
|
-
serverUrl: 'https://mcp.linear.app/sse',
|
|
45
|
-
authType: 'bearer',
|
|
46
|
-
authLabel: 'API Key',
|
|
47
|
-
authPlaceholder: 'lin_api_...',
|
|
48
|
-
authHelpUrl: 'https://linear.app/settings/api',
|
|
49
|
-
category: 'Developer Tools',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: 'sentry',
|
|
53
|
-
name: 'Sentry',
|
|
54
|
-
description: 'Error tracking, performance monitoring, and alerts',
|
|
55
|
-
|
|
56
|
-
serverUrl: 'https://mcp.sentry.dev/sse',
|
|
57
|
-
authType: 'bearer',
|
|
58
|
-
authLabel: 'Auth Token',
|
|
59
|
-
authPlaceholder: 'sntrys_...',
|
|
60
|
-
authHelpUrl: 'https://sentry.io/settings/account/api/auth-tokens/',
|
|
61
|
-
category: 'Developer Tools',
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
// --- Cloud & Infrastructure ---
|
|
65
|
-
{
|
|
66
|
-
id: 'cloudflare',
|
|
67
|
-
name: 'Cloudflare',
|
|
68
|
-
description: 'Workers, KV, D1, R2, and DNS management',
|
|
69
|
-
serverUrl: 'https://workers-mcp.cloudflare.com/mcp',
|
|
70
|
-
authType: 'bearer',
|
|
71
|
-
authLabel: 'API Token',
|
|
72
|
-
authPlaceholder: '',
|
|
73
|
-
authHelpUrl: 'https://dash.cloudflare.com/profile/api-tokens',
|
|
74
|
-
category: 'Cloud & Infrastructure',
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
// --- Communication ---
|
|
78
|
-
{
|
|
79
|
-
id: 'slack',
|
|
80
|
-
name: 'Slack',
|
|
81
|
-
description: 'Send messages, manage channels, and search conversations',
|
|
82
|
-
serverUrl: 'https://slack.com/api/mcp',
|
|
83
|
-
authType: 'bearer',
|
|
84
|
-
authLabel: 'Bot Token',
|
|
85
|
-
authPlaceholder: 'xoxb-...',
|
|
86
|
-
authHelpUrl: 'https://api.slack.com/apps',
|
|
87
|
-
category: 'Communication',
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
// --- Search & Data ---
|
|
91
|
-
{
|
|
92
|
-
id: 'brave-search',
|
|
93
|
-
name: 'Brave Search',
|
|
94
|
-
description: 'Web search, news, and local results',
|
|
95
|
-
serverUrl: 'https://mcp.brave.com/sse',
|
|
96
|
-
authType: 'bearer',
|
|
97
|
-
authLabel: 'API Key',
|
|
98
|
-
authPlaceholder: 'BSA...',
|
|
99
|
-
authHelpUrl: 'https://brave.com/search/api/',
|
|
100
|
-
category: 'Search & Data',
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
// --- Productivity ---
|
|
104
|
-
{
|
|
105
|
-
id: 'notion',
|
|
106
|
-
name: 'Notion',
|
|
107
|
-
description: 'Pages, databases, and workspace content',
|
|
108
|
-
serverUrl: 'https://mcp.notion.so/sse',
|
|
109
|
-
authType: 'bearer',
|
|
110
|
-
authLabel: 'Integration Token',
|
|
111
|
-
authPlaceholder: 'ntn_...',
|
|
112
|
-
authHelpUrl: 'https://www.notion.so/my-integrations',
|
|
113
|
-
category: 'Productivity',
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
// --- AI & LLMs ---
|
|
117
|
-
{
|
|
118
|
-
id: 'context7',
|
|
119
|
-
name: 'Context7',
|
|
120
|
-
description: 'Up-to-date documentation and code examples for any library',
|
|
121
|
-
serverUrl: 'https://mcp.context7.com/sse',
|
|
122
|
-
authType: 'none',
|
|
123
|
-
category: 'AI & LLMs',
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
// --- Databases ---
|
|
127
|
-
{
|
|
128
|
-
id: 'supabase',
|
|
129
|
-
name: 'Supabase',
|
|
130
|
-
description: 'Database queries, auth, storage, and edge functions',
|
|
131
|
-
serverUrl: 'https://mcp.supabase.com/sse',
|
|
132
|
-
authType: 'bearer',
|
|
133
|
-
authLabel: 'Access Token',
|
|
134
|
-
authPlaceholder: 'sbp_...',
|
|
135
|
-
authHelpUrl: 'https://supabase.com/dashboard/account/tokens',
|
|
136
|
-
category: 'Databases',
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
id: 'neon',
|
|
140
|
-
name: 'Neon',
|
|
141
|
-
description: 'Serverless Postgres — branches, queries, and management',
|
|
142
|
-
serverUrl: 'https://mcp.neon.tech/sse',
|
|
143
|
-
authType: 'bearer',
|
|
144
|
-
authLabel: 'API Key',
|
|
145
|
-
authPlaceholder: '',
|
|
146
|
-
authHelpUrl: 'https://console.neon.tech/app/settings/api-keys',
|
|
147
|
-
category: 'Databases',
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
// --- Payments ---
|
|
151
|
-
{
|
|
152
|
-
id: 'stripe',
|
|
153
|
-
name: 'Stripe',
|
|
154
|
-
description: 'Payments, subscriptions, customers, and invoices',
|
|
155
|
-
serverUrl: 'https://mcp.stripe.com/sse',
|
|
156
|
-
authType: 'bearer',
|
|
157
|
-
authLabel: 'Secret Key',
|
|
158
|
-
authPlaceholder: 'sk_...',
|
|
159
|
-
authHelpUrl: 'https://dashboard.stripe.com/apikeys',
|
|
160
|
-
category: 'Payments',
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
// --- Monitoring ---
|
|
164
|
-
{
|
|
165
|
-
id: 'grafana',
|
|
166
|
-
name: 'Grafana',
|
|
167
|
-
description: 'Dashboards, alerts, and observability data',
|
|
168
|
-
serverUrl: 'https://mcp.grafana.com/sse',
|
|
169
|
-
authType: 'bearer',
|
|
170
|
-
authLabel: 'Service Account Token',
|
|
171
|
-
authPlaceholder: 'glsa_...',
|
|
172
|
-
authHelpUrl: 'https://grafana.com/docs/grafana/latest/administration/service-accounts/',
|
|
173
|
-
category: 'Monitoring',
|
|
174
|
-
},
|
|
175
|
-
];
|
|
176
|
-
|
|
177
|
-
export const MCP_CATEGORIES = [...new Set(MCP_CATALOG.map((s) => s.category))];
|
|
178
|
-
|
|
179
|
-
export function getMcpTemplate(id: string): McpServerTemplate | undefined {
|
|
180
|
-
return MCP_CATALOG.find((s) => s.id === id);
|
|
181
|
-
}
|
package/src/plans.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
export type PlanId = 'free' | 'pro' | 'team';
|
|
2
|
-
|
|
3
|
-
export interface PlanLimits {
|
|
4
|
-
actionsPerMonth: number;
|
|
5
|
-
agents: number;
|
|
6
|
-
credentials: number;
|
|
7
|
-
members: number;
|
|
8
|
-
policies: number;
|
|
9
|
-
timelineHistoryDays: number;
|
|
10
|
-
undoEnabled: boolean;
|
|
11
|
-
browserSessions: number;
|
|
12
|
-
messagesPerMonth: number;
|
|
13
|
-
messageHistoryDays: number;
|
|
14
|
-
threadsPerAgent: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface PlanDefinition extends PlanLimits {
|
|
18
|
-
id: PlanId;
|
|
19
|
-
name: string;
|
|
20
|
-
monthlyPrice: number; // USD cents
|
|
21
|
-
yearlyPrice: number; // USD cents (total per year)
|
|
22
|
-
stripePriceMonthly: string;
|
|
23
|
-
stripePriceYearly: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const PLANS: Record<PlanId, PlanDefinition> = {
|
|
27
|
-
free: {
|
|
28
|
-
id: 'free',
|
|
29
|
-
name: 'Free',
|
|
30
|
-
monthlyPrice: 0,
|
|
31
|
-
yearlyPrice: 0,
|
|
32
|
-
stripePriceMonthly: '',
|
|
33
|
-
stripePriceYearly: '',
|
|
34
|
-
actionsPerMonth: 1000,
|
|
35
|
-
agents: 3,
|
|
36
|
-
credentials: 2,
|
|
37
|
-
members: 1,
|
|
38
|
-
policies: 3,
|
|
39
|
-
timelineHistoryDays: 14,
|
|
40
|
-
undoEnabled: false,
|
|
41
|
-
browserSessions: 0,
|
|
42
|
-
messagesPerMonth: 100,
|
|
43
|
-
messageHistoryDays: 7,
|
|
44
|
-
threadsPerAgent: 5,
|
|
45
|
-
},
|
|
46
|
-
pro: {
|
|
47
|
-
id: 'pro',
|
|
48
|
-
name: 'Pro',
|
|
49
|
-
monthlyPrice: 900,
|
|
50
|
-
yearlyPrice: 7900,
|
|
51
|
-
stripePriceMonthly: 'price_1T6b3m2NRlIkxMrBZ9bmEDYE',
|
|
52
|
-
stripePriceYearly: 'price_1T6b3m2NRlIkxMrBo2yx01sJ',
|
|
53
|
-
actionsPerMonth: Infinity,
|
|
54
|
-
agents: 10,
|
|
55
|
-
credentials: 25,
|
|
56
|
-
members: 5,
|
|
57
|
-
policies: 10,
|
|
58
|
-
timelineHistoryDays: 90,
|
|
59
|
-
undoEnabled: true,
|
|
60
|
-
browserSessions: 2,
|
|
61
|
-
messagesPerMonth: 5000,
|
|
62
|
-
messageHistoryDays: 30,
|
|
63
|
-
threadsPerAgent: 50,
|
|
64
|
-
},
|
|
65
|
-
team: {
|
|
66
|
-
id: 'team',
|
|
67
|
-
name: 'Team',
|
|
68
|
-
monthlyPrice: 4900,
|
|
69
|
-
yearlyPrice: 41000,
|
|
70
|
-
stripePriceMonthly: 'price_1T6b3n2NRlIkxMrBstkfVECC',
|
|
71
|
-
stripePriceYearly: 'price_1T6b3o2NRlIkxMrBzHoQKPjz',
|
|
72
|
-
actionsPerMonth: Infinity,
|
|
73
|
-
agents: 50,
|
|
74
|
-
credentials: Infinity,
|
|
75
|
-
members: 25,
|
|
76
|
-
policies: 50,
|
|
77
|
-
timelineHistoryDays: 365,
|
|
78
|
-
undoEnabled: true,
|
|
79
|
-
browserSessions: 5,
|
|
80
|
-
messagesPerMonth: Infinity,
|
|
81
|
-
messageHistoryDays: 90,
|
|
82
|
-
threadsPerAgent: Infinity,
|
|
83
|
-
},
|
|
84
|
-
} as const;
|
|
85
|
-
|
|
86
|
-
export function getPlanLimits(plan: string): PlanLimits {
|
|
87
|
-
const def = PLANS[plan as PlanId];
|
|
88
|
-
if (!def) return PLANS.free;
|
|
89
|
-
return {
|
|
90
|
-
actionsPerMonth: def.actionsPerMonth,
|
|
91
|
-
agents: def.agents,
|
|
92
|
-
credentials: def.credentials,
|
|
93
|
-
members: def.members,
|
|
94
|
-
policies: def.policies,
|
|
95
|
-
timelineHistoryDays: def.timelineHistoryDays,
|
|
96
|
-
undoEnabled: def.undoEnabled,
|
|
97
|
-
browserSessions: def.browserSessions,
|
|
98
|
-
messagesPerMonth: def.messagesPerMonth,
|
|
99
|
-
messageHistoryDays: def.messageHistoryDays,
|
|
100
|
-
threadsPerAgent: def.threadsPerAgent,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function canUndo(plan: string): boolean {
|
|
105
|
-
return getPlanLimits(plan).undoEnabled;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Map a Stripe price ID back to a plan ID */
|
|
109
|
-
export function planFromPriceId(priceId: string): PlanId | null {
|
|
110
|
-
for (const plan of Object.values(PLANS)) {
|
|
111
|
-
if (plan.stripePriceMonthly === priceId || plan.stripePriceYearly === priceId) {
|
|
112
|
-
return plan.id;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return null;
|
|
116
|
-
}
|