@brainmcp/brainmcp 0.1.11 → 0.1.13
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 +72 -5
- package/dist/agent-config.js +229 -32
- package/dist/commands/auth.d.ts +47 -0
- package/dist/commands/auth.js +390 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/capture.d.ts +34 -0
- package/dist/commands/capture.js +349 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/dispatch.d.ts +43 -0
- package/dist/commands/dispatch.js +287 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +180 -36
- package/dist/commands/index.js.map +1 -1
- package/dist/hooks/adapters.d.ts +14 -0
- package/dist/hooks/adapters.js +41 -0
- package/dist/hooks/adapters.js.map +1 -0
- package/dist/hooks/claude.d.ts +24 -0
- package/dist/hooks/claude.js +36 -0
- package/dist/hooks/claude.js.map +1 -0
- package/dist/hooks/codex.d.ts +18 -0
- package/dist/hooks/codex.js +36 -0
- package/dist/hooks/codex.js.map +1 -0
- package/dist/hooks/cursor.d.ts +22 -0
- package/dist/hooks/cursor.js +26 -0
- package/dist/hooks/cursor.js.map +1 -0
- package/dist/hooks/managed-hooks.d.ts +30 -0
- package/dist/hooks/managed-hooks.js +189 -0
- package/dist/hooks/managed-hooks.js.map +1 -0
- package/dist/hooks/vscode.d.ts +22 -0
- package/dist/hooks/vscode.js +27 -0
- package/dist/hooks/vscode.js.map +1 -0
- package/dist/index.js +7 -102
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +32 -0
- package/dist/lib/api-client.js +203 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/callback-server.d.ts +17 -0
- package/dist/lib/callback-server.js +145 -0
- package/dist/lib/callback-server.js.map +1 -0
- package/dist/lib/cli-contracts.d.ts +193 -0
- package/dist/lib/cli-contracts.js +242 -0
- package/dist/lib/cli-contracts.js.map +1 -0
- package/dist/lib/config.d.ts +4 -2
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/credentials.d.ts +89 -0
- package/dist/lib/credentials.js +304 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/http.d.ts +3 -0
- package/dist/lib/http.js +50 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/managed.d.ts +8 -0
- package/dist/lib/managed.js +72 -6
- package/dist/lib/managed.js.map +1 -1
- package/dist/lib/oauth-client.d.ts +55 -0
- package/dist/lib/oauth-client.js +154 -0
- package/dist/lib/oauth-client.js.map +1 -0
- package/dist/lib/pkce.d.ts +14 -0
- package/dist/lib/pkce.js +33 -0
- package/dist/lib/pkce.js.map +1 -0
- package/dist/lib/vault.d.ts +26 -0
- package/dist/lib/vault.js +221 -0
- package/dist/lib/vault.js.map +1 -0
- package/dist/runtime/brainmcp-hook-runtime.mjs +3211 -0
- package/dist/runtime/capture.d.ts +83 -0
- package/dist/runtime/capture.js +332 -0
- package/dist/runtime/capture.js.map +1 -0
- package/dist/runtime/diagnostics.d.ts +7 -0
- package/dist/runtime/diagnostics.js +75 -0
- package/dist/runtime/diagnostics.js.map +1 -0
- package/dist/runtime/doctor-checks.d.ts +14 -0
- package/dist/runtime/doctor-checks.js +205 -0
- package/dist/runtime/doctor-checks.js.map +1 -0
- package/dist/runtime/flush.d.ts +30 -0
- package/dist/runtime/flush.js +193 -0
- package/dist/runtime/flush.js.map +1 -0
- package/dist/runtime/hook-dispatcher.d.ts +31 -0
- package/dist/runtime/hook-dispatcher.js +381 -0
- package/dist/runtime/hook-dispatcher.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.js +69 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/installer.d.ts +26 -0
- package/dist/runtime/installer.js +134 -0
- package/dist/runtime/installer.js.map +1 -0
- package/dist/runtime/lock.d.ts +19 -0
- package/dist/runtime/lock.js +116 -0
- package/dist/runtime/lock.js.map +1 -0
- package/dist/runtime/orient.d.ts +55 -0
- package/dist/runtime/orient.js +255 -0
- package/dist/runtime/orient.js.map +1 -0
- package/dist/runtime/queue.d.ts +7 -0
- package/dist/runtime/queue.js +80 -0
- package/dist/runtime/queue.js.map +1 -0
- package/dist/runtime/retention.d.ts +26 -0
- package/dist/runtime/retention.js +175 -0
- package/dist/runtime/retention.js.map +1 -0
- package/dist/runtime/session.d.ts +68 -0
- package/dist/runtime/session.js +283 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/runtime/storage.d.ts +32 -0
- package/dist/runtime/storage.js +236 -0
- package/dist/runtime/storage.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { PkcePair } from './pkce.js';
|
|
2
|
+
export declare function grantedCliScopes(requested: string[], tokenScope?: string): string[];
|
|
3
|
+
export interface OAuthEndpoints {
|
|
4
|
+
issuer: string;
|
|
5
|
+
authorizationEndpoint: string;
|
|
6
|
+
tokenEndpoint: string;
|
|
7
|
+
revocationEndpoint: string;
|
|
8
|
+
}
|
|
9
|
+
export interface TokenResponse {
|
|
10
|
+
access_token: string;
|
|
11
|
+
token_type: string;
|
|
12
|
+
expires_in?: number;
|
|
13
|
+
refresh_token?: string;
|
|
14
|
+
scope?: string;
|
|
15
|
+
id_token?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface OAuthClientOptions {
|
|
19
|
+
issuerUrl?: string;
|
|
20
|
+
clientId?: string;
|
|
21
|
+
fetchFn?: typeof fetch;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const DEFAULT_ISSUER = "https://mcp.brainmcp.ai";
|
|
25
|
+
export declare class OAuthClient {
|
|
26
|
+
readonly issuer: string;
|
|
27
|
+
readonly clientId: string;
|
|
28
|
+
private fetchFn;
|
|
29
|
+
private timeoutMs;
|
|
30
|
+
constructor(options?: OAuthClientOptions);
|
|
31
|
+
discoverEndpoints(signal?: AbortSignal): Promise<OAuthEndpoints>;
|
|
32
|
+
buildAuthorizationUrl(input: {
|
|
33
|
+
authorizationEndpoint: string;
|
|
34
|
+
redirectUri: string;
|
|
35
|
+
pkce: PkcePair;
|
|
36
|
+
scopes?: string[];
|
|
37
|
+
}): string;
|
|
38
|
+
exchangeCodeForTokens(input: {
|
|
39
|
+
tokenEndpoint: string;
|
|
40
|
+
code: string;
|
|
41
|
+
redirectUri: string;
|
|
42
|
+
codeVerifier: string;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}): Promise<TokenResponse>;
|
|
45
|
+
refreshAccessToken(input: {
|
|
46
|
+
tokenEndpoint: string;
|
|
47
|
+
refreshToken: string;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
}): Promise<TokenResponse>;
|
|
50
|
+
revokeToken(input: {
|
|
51
|
+
revocationEndpoint: string;
|
|
52
|
+
token: string;
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
}): Promise<boolean>;
|
|
55
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { BRAINMCP_CLI_CLIENT_ID, BRAINMCP_CLI_ALLOWED_SCOPES, BRAINMCP_CLI_DEFAULT_SCOPES, BRAIN_MCP_ENDPOINT, } from '../agent-config.js';
|
|
2
|
+
import { validateHttpUrl, withRequestDeadline } from './http.js';
|
|
3
|
+
export function grantedCliScopes(requested, tokenScope) {
|
|
4
|
+
const allowed = new Set(BRAINMCP_CLI_ALLOWED_SCOPES);
|
|
5
|
+
const raw = tokenScope === undefined ? requested : tokenScope.split(/\s+/).filter(Boolean);
|
|
6
|
+
if (raw.some((scope) => !allowed.has(scope) || !requested.includes(scope))) {
|
|
7
|
+
throw new Error('The OAuth server granted unrequested or disallowed CLI scopes.');
|
|
8
|
+
}
|
|
9
|
+
const granted = [...new Set(raw)];
|
|
10
|
+
if (requested.some((scope) => !granted.includes(scope))) {
|
|
11
|
+
throw new Error('The OAuth server did not grant required CLI scopes.');
|
|
12
|
+
}
|
|
13
|
+
return granted;
|
|
14
|
+
}
|
|
15
|
+
function validateTokenResponse(value) {
|
|
16
|
+
const token = value;
|
|
17
|
+
if (!token || typeof token.access_token !== 'string' || !token.access_token.trim() ||
|
|
18
|
+
typeof token.token_type !== 'string' || token.token_type.toLowerCase() !== 'bearer' ||
|
|
19
|
+
(token.refresh_token !== undefined && (typeof token.refresh_token !== 'string' || !token.refresh_token.trim())) ||
|
|
20
|
+
(token.scope !== undefined && typeof token.scope !== 'string') ||
|
|
21
|
+
(token.expires_in !== undefined && (typeof token.expires_in !== 'number' || !Number.isFinite(token.expires_in) || token.expires_in <= 0))) {
|
|
22
|
+
throw new Error('OAuth server returned an invalid token response.');
|
|
23
|
+
}
|
|
24
|
+
return token;
|
|
25
|
+
}
|
|
26
|
+
export const DEFAULT_ISSUER = 'https://mcp.brainmcp.ai';
|
|
27
|
+
export class OAuthClient {
|
|
28
|
+
issuer;
|
|
29
|
+
clientId;
|
|
30
|
+
fetchFn;
|
|
31
|
+
timeoutMs;
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
this.issuer = (options.issuerUrl ?? process.env.BRAINMCP_API_URL ?? DEFAULT_ISSUER).replace(/\/+$/, '');
|
|
34
|
+
this.clientId = options.clientId ?? BRAINMCP_CLI_CLIENT_ID;
|
|
35
|
+
this.fetchFn = options.fetchFn ?? fetch;
|
|
36
|
+
this.timeoutMs = options.timeoutMs ?? 10_000;
|
|
37
|
+
validateHttpUrl(this.issuer);
|
|
38
|
+
}
|
|
39
|
+
async discoverEndpoints(signal) {
|
|
40
|
+
const discoveryUrl = `${this.issuer}/.well-known/oauth-authorization-server`;
|
|
41
|
+
return withRequestDeadline(this.timeoutMs, signal, async (requestSignal) => {
|
|
42
|
+
const res = await this.fetchFn(discoveryUrl, { signal: requestSignal, redirect: 'error' });
|
|
43
|
+
if (res.ok) {
|
|
44
|
+
const meta = (await res.json());
|
|
45
|
+
if (meta && typeof meta === 'object' && !Array.isArray(meta)) {
|
|
46
|
+
const endpoints = {
|
|
47
|
+
issuer: meta.issuer ?? this.issuer,
|
|
48
|
+
authorizationEndpoint: meta.authorization_endpoint ?? `${this.issuer}/api/auth/oauth2/authorize`,
|
|
49
|
+
tokenEndpoint: meta.token_endpoint ?? `${this.issuer}/api/auth/oauth2/token`,
|
|
50
|
+
revocationEndpoint: meta.revocation_endpoint ?? `${this.issuer}/api/auth/oauth2/revoke`,
|
|
51
|
+
};
|
|
52
|
+
for (const endpoint of Object.values(endpoints))
|
|
53
|
+
validateHttpUrl(endpoint, this.issuer);
|
|
54
|
+
return endpoints;
|
|
55
|
+
}
|
|
56
|
+
throw new Error('OAuth server returned invalid discovery metadata.');
|
|
57
|
+
}
|
|
58
|
+
if (res.status !== 404)
|
|
59
|
+
throw new Error(`OAuth discovery failed (status ${res.status}).`);
|
|
60
|
+
return {
|
|
61
|
+
issuer: this.issuer,
|
|
62
|
+
authorizationEndpoint: `${this.issuer}/api/auth/oauth2/authorize`,
|
|
63
|
+
tokenEndpoint: `${this.issuer}/api/auth/oauth2/token`,
|
|
64
|
+
revocationEndpoint: `${this.issuer}/api/auth/oauth2/revoke`,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
buildAuthorizationUrl(input) {
|
|
69
|
+
const scopes = input.scopes ?? [...BRAINMCP_CLI_DEFAULT_SCOPES];
|
|
70
|
+
const url = validateHttpUrl(input.authorizationEndpoint, this.issuer);
|
|
71
|
+
url.searchParams.set('response_type', 'code');
|
|
72
|
+
url.searchParams.set('client_id', this.clientId);
|
|
73
|
+
url.searchParams.set('redirect_uri', input.redirectUri);
|
|
74
|
+
url.searchParams.set('scope', scopes.join(' '));
|
|
75
|
+
url.searchParams.set('state', input.pkce.state);
|
|
76
|
+
url.searchParams.set('code_challenge', input.pkce.challenge);
|
|
77
|
+
url.searchParams.set('code_challenge_method', input.pkce.method);
|
|
78
|
+
url.searchParams.set('prompt', 'consent');
|
|
79
|
+
url.searchParams.set('resource', BRAIN_MCP_ENDPOINT);
|
|
80
|
+
return url.toString();
|
|
81
|
+
}
|
|
82
|
+
async exchangeCodeForTokens(input) {
|
|
83
|
+
const body = new URLSearchParams({
|
|
84
|
+
grant_type: 'authorization_code',
|
|
85
|
+
client_id: this.clientId,
|
|
86
|
+
code: input.code,
|
|
87
|
+
redirect_uri: input.redirectUri,
|
|
88
|
+
code_verifier: input.codeVerifier,
|
|
89
|
+
resource: BRAIN_MCP_ENDPOINT,
|
|
90
|
+
});
|
|
91
|
+
validateHttpUrl(input.tokenEndpoint, this.issuer);
|
|
92
|
+
return withRequestDeadline(this.timeoutMs, input.signal, async (signal) => {
|
|
93
|
+
const res = await this.fetchFn(input.tokenEndpoint, {
|
|
94
|
+
signal,
|
|
95
|
+
redirect: 'error',
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: {
|
|
98
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
99
|
+
Accept: 'application/json',
|
|
100
|
+
},
|
|
101
|
+
body: body.toString(),
|
|
102
|
+
});
|
|
103
|
+
if (!res.ok) {
|
|
104
|
+
throw new Error(`Token exchange failed (status ${res.status}).`);
|
|
105
|
+
}
|
|
106
|
+
return validateTokenResponse(await res.json());
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async refreshAccessToken(input) {
|
|
110
|
+
const body = new URLSearchParams({
|
|
111
|
+
grant_type: 'refresh_token',
|
|
112
|
+
client_id: this.clientId,
|
|
113
|
+
refresh_token: input.refreshToken,
|
|
114
|
+
resource: BRAIN_MCP_ENDPOINT,
|
|
115
|
+
});
|
|
116
|
+
validateHttpUrl(input.tokenEndpoint, this.issuer);
|
|
117
|
+
return withRequestDeadline(this.timeoutMs, input.signal, async (signal) => {
|
|
118
|
+
const res = await this.fetchFn(input.tokenEndpoint, {
|
|
119
|
+
signal,
|
|
120
|
+
redirect: 'error',
|
|
121
|
+
method: 'POST',
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
124
|
+
Accept: 'application/json',
|
|
125
|
+
},
|
|
126
|
+
body: body.toString(),
|
|
127
|
+
});
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
throw new Error(`Token refresh failed (status ${res.status}).`);
|
|
130
|
+
}
|
|
131
|
+
return validateTokenResponse(await res.json());
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async revokeToken(input) {
|
|
135
|
+
const body = new URLSearchParams({
|
|
136
|
+
client_id: this.clientId,
|
|
137
|
+
token: input.token,
|
|
138
|
+
});
|
|
139
|
+
validateHttpUrl(input.revocationEndpoint, this.issuer);
|
|
140
|
+
return withRequestDeadline(this.timeoutMs, input.signal, async (signal) => {
|
|
141
|
+
const res = await this.fetchFn(input.revocationEndpoint, {
|
|
142
|
+
signal,
|
|
143
|
+
redirect: 'error',
|
|
144
|
+
method: 'POST',
|
|
145
|
+
headers: {
|
|
146
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
147
|
+
},
|
|
148
|
+
body: body.toString(),
|
|
149
|
+
});
|
|
150
|
+
return res.ok;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=oauth-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-client.js","sourceRoot":"","sources":["../../src/lib/oauth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface PkcePair {
|
|
2
|
+
verifier: string;
|
|
3
|
+
challenge: string;
|
|
4
|
+
method: 'S256';
|
|
5
|
+
state: string;
|
|
6
|
+
}
|
|
7
|
+
export type RandomSource = (bytes: number) => Buffer;
|
|
8
|
+
export declare function base64UrlEncode(buffer: Buffer): string;
|
|
9
|
+
/**
|
|
10
|
+
* Generate PKCE verifier, challenge (S256), and state (AHI-032).
|
|
11
|
+
* Optional randomSource allows deterministic testing vectors.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generatePkce(randomSource?: RandomSource): PkcePair;
|
|
14
|
+
export declare function computeS256Challenge(verifier: string): string;
|
package/dist/lib/pkce.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
export function base64UrlEncode(buffer) {
|
|
3
|
+
return buffer
|
|
4
|
+
.toString('base64')
|
|
5
|
+
.replace(/\+/g, '-')
|
|
6
|
+
.replace(/\//g, '_')
|
|
7
|
+
.replace(/=+$/, '');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate PKCE verifier, challenge (S256), and state (AHI-032).
|
|
11
|
+
* Optional randomSource allows deterministic testing vectors.
|
|
12
|
+
*/
|
|
13
|
+
export function generatePkce(randomSource = randomBytes) {
|
|
14
|
+
// RFC 7636: verifier length between 43 and 128 characters
|
|
15
|
+
// 32 bytes of entropy encoded as base64url gives 43 chars
|
|
16
|
+
const verifierBytes = randomSource(32);
|
|
17
|
+
const verifier = base64UrlEncode(verifierBytes);
|
|
18
|
+
const hash = createHash('sha256').update(verifier, 'ascii').digest();
|
|
19
|
+
const challenge = base64UrlEncode(hash);
|
|
20
|
+
const stateBytes = randomSource(24);
|
|
21
|
+
const state = base64UrlEncode(stateBytes);
|
|
22
|
+
return {
|
|
23
|
+
verifier,
|
|
24
|
+
challenge,
|
|
25
|
+
method: 'S256',
|
|
26
|
+
state,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function computeS256Challenge(verifier) {
|
|
30
|
+
const hash = createHash('sha256').update(verifier, 'ascii').digest();
|
|
31
|
+
return base64UrlEncode(hash);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/lib/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAWtD,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM;SACV,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,eAA6B,WAAW;IACnE,0DAA0D;IAC1D,0DAA0D;IAC1D,MAAM,aAAa,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAEhD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IACrE,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAE1C,OAAO;QACL,QAAQ;QACR,SAAS;QACT,MAAM,EAAE,MAAM;QACd,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IACrE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const LEGACY_VAULT_ACCOUNT = "oauth";
|
|
2
|
+
export declare function vaultAccountKey(accountId: string): string;
|
|
3
|
+
export interface SecretVault {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
isAvailable(): Promise<boolean>;
|
|
6
|
+
getSecret(key?: string): Promise<string | null>;
|
|
7
|
+
setSecret(value: string, key?: string): Promise<void>;
|
|
8
|
+
deleteSecret(key?: string): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare class MemorySecretVault implements SecretVault {
|
|
11
|
+
readonly name = "memory";
|
|
12
|
+
private readonly secrets;
|
|
13
|
+
available: boolean;
|
|
14
|
+
isAvailable(): Promise<boolean>;
|
|
15
|
+
getSecret(key?: string): Promise<string | null>;
|
|
16
|
+
setSecret(value: string, key?: string): Promise<void>;
|
|
17
|
+
deleteSecret(key?: string): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare class UnavailableSecretVault implements SecretVault {
|
|
20
|
+
readonly name = "unavailable";
|
|
21
|
+
isAvailable(): Promise<boolean>;
|
|
22
|
+
getSecret(): Promise<string | null>;
|
|
23
|
+
setSecret(): Promise<void>;
|
|
24
|
+
deleteSecret(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function createPlatformVault(): SecretVault;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { execFile, spawn } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
const VAULT_SERVICE = 'brainmcp.credentials';
|
|
5
|
+
export const LEGACY_VAULT_ACCOUNT = 'oauth';
|
|
6
|
+
const VAULT_ACCOUNT = LEGACY_VAULT_ACCOUNT;
|
|
7
|
+
const EXEC_TIMEOUT_MS = 4_000;
|
|
8
|
+
export function vaultAccountKey(accountId) {
|
|
9
|
+
return `oauth:${accountId}`;
|
|
10
|
+
}
|
|
11
|
+
export class MemorySecretVault {
|
|
12
|
+
name = 'memory';
|
|
13
|
+
secrets = new Map();
|
|
14
|
+
available = true;
|
|
15
|
+
async isAvailable() {
|
|
16
|
+
return this.available;
|
|
17
|
+
}
|
|
18
|
+
async getSecret(key = VAULT_ACCOUNT) {
|
|
19
|
+
return this.secrets.get(key) ?? null;
|
|
20
|
+
}
|
|
21
|
+
async setSecret(value, key = VAULT_ACCOUNT) {
|
|
22
|
+
this.secrets.set(key, value);
|
|
23
|
+
}
|
|
24
|
+
async deleteSecret(key = VAULT_ACCOUNT) {
|
|
25
|
+
this.secrets.delete(key);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class UnavailableSecretVault {
|
|
29
|
+
name = 'unavailable';
|
|
30
|
+
async isAvailable() {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
async getSecret() {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
async setSecret() {
|
|
37
|
+
throw new Error('OS credential vault is unavailable.');
|
|
38
|
+
}
|
|
39
|
+
async deleteSecret() { }
|
|
40
|
+
}
|
|
41
|
+
class MacosSecurityVault {
|
|
42
|
+
name = 'macos-keychain';
|
|
43
|
+
async isAvailable() {
|
|
44
|
+
try {
|
|
45
|
+
await execFileAsync('which', ['security'], { timeout: EXEC_TIMEOUT_MS });
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async getSecret(key = VAULT_ACCOUNT) {
|
|
53
|
+
try {
|
|
54
|
+
const { stdout } = await execFileAsync('security', ['find-generic-password', '-s', VAULT_SERVICE, '-a', key, '-w'], { timeout: EXEC_TIMEOUT_MS });
|
|
55
|
+
const value = stdout.trim();
|
|
56
|
+
if (!value)
|
|
57
|
+
return null;
|
|
58
|
+
if (value.startsWith('{'))
|
|
59
|
+
return value;
|
|
60
|
+
if (/^[0-9a-fA-F]+$/.test(value) && value.length % 2 === 0) {
|
|
61
|
+
const decoded = Buffer.from(value, 'hex').toString('utf8');
|
|
62
|
+
return decoded.length > 0 ? decoded : null;
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async setSecret(value, key = VAULT_ACCOUNT) {
|
|
71
|
+
const hex = Buffer.from(value, 'utf8').toString('hex');
|
|
72
|
+
await new Promise((resolve, reject) => {
|
|
73
|
+
const child = spawn('security', ['-i'], { stdio: ['pipe', 'ignore', 'ignore'] });
|
|
74
|
+
const timer = setTimeout(() => {
|
|
75
|
+
child.kill('SIGKILL');
|
|
76
|
+
reject(new Error('macOS keychain store timed out'));
|
|
77
|
+
}, EXEC_TIMEOUT_MS);
|
|
78
|
+
const done = (fn) => {
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
fn();
|
|
81
|
+
};
|
|
82
|
+
child.on('error', (error) => done(() => reject(error)));
|
|
83
|
+
child.on('close', (code) => {
|
|
84
|
+
if (code === 0)
|
|
85
|
+
done(() => resolve());
|
|
86
|
+
else
|
|
87
|
+
done(() => reject(new Error('macOS keychain store failed')));
|
|
88
|
+
});
|
|
89
|
+
child.stdin.write(`add-generic-password -U -s ${VAULT_SERVICE} -a ${key} -w ${hex}\n`);
|
|
90
|
+
child.stdin.end();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async deleteSecret(key = VAULT_ACCOUNT) {
|
|
94
|
+
try {
|
|
95
|
+
await execFileAsync('security', ['delete-generic-password', '-s', VAULT_SERVICE, '-a', key], { timeout: EXEC_TIMEOUT_MS });
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Missing item is success for logout.
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
class LinuxSecretToolVault {
|
|
103
|
+
name = 'libsecret';
|
|
104
|
+
async isAvailable() {
|
|
105
|
+
try {
|
|
106
|
+
await execFileAsync('which', ['secret-tool'], { timeout: EXEC_TIMEOUT_MS });
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async getSecret(key = VAULT_ACCOUNT) {
|
|
114
|
+
try {
|
|
115
|
+
const { stdout } = await execFileAsync('secret-tool', ['lookup', 'service', VAULT_SERVICE, 'account', key], { timeout: EXEC_TIMEOUT_MS });
|
|
116
|
+
const value = stdout.trim();
|
|
117
|
+
return value.length > 0 ? value : null;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async setSecret(value, key = VAULT_ACCOUNT) {
|
|
124
|
+
await new Promise((resolve, reject) => {
|
|
125
|
+
const child = spawn('secret-tool', ['store', '--label', 'BrainMCP CLI', 'service', VAULT_SERVICE, 'account', key], { stdio: ['pipe', 'ignore', 'ignore'] });
|
|
126
|
+
const timer = setTimeout(() => {
|
|
127
|
+
child.kill('SIGKILL');
|
|
128
|
+
reject(new Error('secret-tool store timed out'));
|
|
129
|
+
}, EXEC_TIMEOUT_MS);
|
|
130
|
+
const done = (fn) => {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
fn();
|
|
133
|
+
};
|
|
134
|
+
child.on('error', (error) => done(() => reject(error)));
|
|
135
|
+
child.on('close', (code) => {
|
|
136
|
+
if (code === 0)
|
|
137
|
+
done(() => resolve());
|
|
138
|
+
else
|
|
139
|
+
done(() => reject(new Error('secret-tool store failed')));
|
|
140
|
+
});
|
|
141
|
+
child.stdin.write(value);
|
|
142
|
+
child.stdin.end();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async deleteSecret(key = VAULT_ACCOUNT) {
|
|
146
|
+
try {
|
|
147
|
+
await execFileAsync('secret-tool', ['clear', 'service', VAULT_SERVICE, 'account', key], { timeout: EXEC_TIMEOUT_MS });
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Missing item is success for logout.
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
class WindowsCredentialVault {
|
|
155
|
+
name = 'windows-credential-manager';
|
|
156
|
+
async isAvailable() {
|
|
157
|
+
return process.platform === 'win32';
|
|
158
|
+
}
|
|
159
|
+
async getSecret(key = VAULT_ACCOUNT) {
|
|
160
|
+
try {
|
|
161
|
+
const { stdout } = await execFileAsync('powershell.exe', [
|
|
162
|
+
'-NoProfile',
|
|
163
|
+
'-Command',
|
|
164
|
+
`try { $v = New-Object Windows.Security.Credentials.PasswordVault; ($v.Retrieve('${VAULT_SERVICE}','${key}')).Password } catch { '' }`,
|
|
165
|
+
], { timeout: EXEC_TIMEOUT_MS });
|
|
166
|
+
const value = stdout.trim();
|
|
167
|
+
return value.length > 0 ? value : null;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async setSecret(value, key = VAULT_ACCOUNT) {
|
|
174
|
+
await new Promise((resolve, reject) => {
|
|
175
|
+
const child = spawn('powershell.exe', [
|
|
176
|
+
'-NoProfile',
|
|
177
|
+
'-Command',
|
|
178
|
+
`$svc='${VAULT_SERVICE}'; $acct='${key}'; $p=[Console]::In.ReadToEnd(); $v=New-Object Windows.Security.Credentials.PasswordVault; try { $v.Remove($v.Retrieve($svc,$acct)) } catch {}; $v.Add((New-Object Windows.Security.Credentials.PasswordCredential($svc,$acct,$p)))`,
|
|
179
|
+
], { stdio: ['pipe', 'ignore', 'ignore'] });
|
|
180
|
+
const timer = setTimeout(() => {
|
|
181
|
+
child.kill('SIGKILL');
|
|
182
|
+
reject(new Error('Windows PasswordVault store timed out'));
|
|
183
|
+
}, EXEC_TIMEOUT_MS);
|
|
184
|
+
const done = (fn) => {
|
|
185
|
+
clearTimeout(timer);
|
|
186
|
+
fn();
|
|
187
|
+
};
|
|
188
|
+
child.on('error', (error) => done(() => reject(error)));
|
|
189
|
+
child.on('close', (code) => {
|
|
190
|
+
if (code === 0)
|
|
191
|
+
done(() => resolve());
|
|
192
|
+
else
|
|
193
|
+
done(() => reject(new Error('Windows PasswordVault store failed')));
|
|
194
|
+
});
|
|
195
|
+
child.stdin.write(value);
|
|
196
|
+
child.stdin.end();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
async deleteSecret(key = VAULT_ACCOUNT) {
|
|
200
|
+
try {
|
|
201
|
+
await execFileAsync('powershell.exe', [
|
|
202
|
+
'-NoProfile',
|
|
203
|
+
'-Command',
|
|
204
|
+
`try { $v = New-Object Windows.Security.Credentials.PasswordVault; $v.Remove($v.Retrieve('${VAULT_SERVICE}','${key}')) } catch {}`,
|
|
205
|
+
], { timeout: EXEC_TIMEOUT_MS });
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// ignore
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export function createPlatformVault() {
|
|
213
|
+
if (process.platform === 'darwin')
|
|
214
|
+
return new MacosSecurityVault();
|
|
215
|
+
if (process.platform === 'linux')
|
|
216
|
+
return new LinuxSecretToolVault();
|
|
217
|
+
if (process.platform === 'win32')
|
|
218
|
+
return new WindowsCredentialVault();
|
|
219
|
+
return new UnavailableSecretVault();
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../../src/lib/vault.ts"],"names":[],"mappings":"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"}
|