@databasin/mcp-client 0.1.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.
Files changed (54) hide show
  1. package/README.md +108 -0
  2. package/dist/api-client.d.ts +43 -0
  3. package/dist/api-client.d.ts.map +1 -0
  4. package/dist/api-client.js +154 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/auth.d.ts +73 -0
  7. package/dist/auth.d.ts.map +1 -0
  8. package/dist/auth.js +234 -0
  9. package/dist/auth.js.map +1 -0
  10. package/dist/browser.d.ts +2 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +34 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/cli.d.ts +11 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +131 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/config.d.ts +14 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +45 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/errors.d.ts +13 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +20 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +3 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/mappers.d.ts +56 -0
  31. package/dist/mappers.d.ts.map +1 -0
  32. package/dist/mappers.js +171 -0
  33. package/dist/mappers.js.map +1 -0
  34. package/dist/safety.d.ts +3 -0
  35. package/dist/safety.d.ts.map +1 -0
  36. package/dist/safety.js +27 -0
  37. package/dist/safety.js.map +1 -0
  38. package/dist/schemas.d.ts +154 -0
  39. package/dist/schemas.d.ts.map +1 -0
  40. package/dist/schemas.js +102 -0
  41. package/dist/schemas.js.map +1 -0
  42. package/dist/server.d.ts +23 -0
  43. package/dist/server.d.ts.map +1 -0
  44. package/dist/server.js +35 -0
  45. package/dist/server.js.map +1 -0
  46. package/dist/tools.d.ts +17 -0
  47. package/dist/tools.d.ts.map +1 -0
  48. package/dist/tools.js +117 -0
  49. package/dist/tools.js.map +1 -0
  50. package/dist/version.d.ts +2 -0
  51. package/dist/version.d.ts.map +1 -0
  52. package/dist/version.js +2 -0
  53. package/dist/version.js.map +1 -0
  54. package/package.json +61 -0
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # DataBasin MCP Client
2
+
3
+ Run DataBasin tools locally in Codex, Claude Code, and other MCP clients. The package uses stdio locally and calls the remote DataBasin API over HTTPS as the signed-in user.
4
+
5
+ Production is the default. Users do not need to configure an API URL, tenant ID, client ID, scope, bearer token, callback port, or client secret.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js 22.14 or newer
10
+ - A DataBasin account
11
+ - A supported OS credential store: Windows DPAPI, macOS Keychain, or Linux Secret Service/LibSecret
12
+
13
+ ## Sign in with your assistant
14
+
15
+ After adding the MCP server, ask your assistant to connect to DataBasin. It can:
16
+
17
+ 1. Call `databasin_auth_status` to check the local session.
18
+ 2. Call `databasin_login` when sign-in is needed. It returns Microsoft's short-lived device-login URL and user code immediately.
19
+ 3. Give you that URL and code. You can complete sign-in from any browser or device, after which the assistant calls `databasin_auth_status` again.
20
+
21
+ Enter credentials only on Microsoft's page. The assistant receives the intentionally displayable, short-lived device user code, but never receives the password, OAuth device code, authorization code, access token, refresh token, or signed-in account identity.
22
+
23
+ The CLI remains available as a fallback:
24
+
25
+ ```bash
26
+ npx -y @databasin/mcp-client login
27
+ ```
28
+
29
+ Assistant-driven login uses Microsoft's OAuth device authorization flow. CLI fallback uses Authorization Code with PKCE and an ephemeral `http://localhost` loopback callback. Both use a public client; no client secret is installed on the user's machine. MSAL stores and refreshes the session in the operating system credential store.
30
+
31
+ Check or clear the session:
32
+
33
+ ```bash
34
+ npx -y @databasin/mcp-client status
35
+ npx -y @databasin/mcp-client logout
36
+ ```
37
+
38
+ ## Codex
39
+
40
+ ```bash
41
+ codex mcp add databasin -- npx -y @databasin/mcp-client
42
+ ```
43
+
44
+ Equivalent `config.toml`:
45
+
46
+ ```toml
47
+ [mcp_servers.databasin]
48
+ command = "npx"
49
+ args = ["-y", "@databasin/mcp-client"]
50
+ ```
51
+
52
+ ## Claude Code
53
+
54
+ ```bash
55
+ claude mcp add --transport stdio --scope user databasin -- npx -y @databasin/mcp-client
56
+ ```
57
+
58
+ Equivalent `.mcp.json` entry:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "databasin": {
64
+ "command": "npx",
65
+ "args": ["-y", "@databasin/mcp-client"]
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Non-production
72
+
73
+ Production is selected when no environment is supplied. To use the DataBasin NP environment, add the option to the MCP command. The assistant-driven login tools automatically use that environment:
74
+
75
+ ```toml
76
+ [mcp_servers.databasin_np]
77
+ command = "npx"
78
+ args = ["-y", "@databasin/mcp-client", "--environment", "np"]
79
+ ```
80
+
81
+ For CLI fallback, run `npx -y @databasin/mcp-client login --environment np`.
82
+
83
+ `test`, `staging`, and `non-production` are accepted aliases for `np`; `production` is accepted as an alias for `prod`.
84
+
85
+ ## Tools
86
+
87
+ - `databasin_auth_status`: check whether the local DataBasin session is authenticated without exposing account identity
88
+ - `databasin_login`: return Microsoft device-login instructions without blocking the assistant
89
+ - `databasin_get_context`: list caller-visible projects and connection identifiers
90
+ - `databasin_search`: search visible pipelines, connectors, and automations
91
+ - `databasin_browse_schema`: browse catalogs, schemas, tables, and columns
92
+ - `databasin_get_operation`: read bounded query status and results
93
+ - `databasin_cancel_operation`: request cancellation of a visible query operation
94
+
95
+ Tool output is bounded and inspected for credential-like fields. API URLs are fixed by the selected release profile, authentication tokens remain inside MSAL, and the agent cannot supply arbitrary URLs or headers.
96
+
97
+ ## Publishing
98
+
99
+ The package publishes only `dist/` and this README. Before publishing:
100
+
101
+ ```bash
102
+ npm ci
103
+ npm run verify
104
+ npm pack --dry-run
105
+ npm publish --access public
106
+ ```
107
+
108
+ Publishing from CI should use npm trusted publishing with provenance. Choose and record DataBasin's approved package license before the first public release; the package is currently marked `UNLICENSED`.
@@ -0,0 +1,43 @@
1
+ import type { DataBasinProfile } from './config.js';
2
+ import type { BrowseSchemaInput, SearchInput } from './schemas.js';
3
+ export interface DataBasinApi {
4
+ getProjects(signal?: AbortSignal): Promise<unknown>;
5
+ getAccessibleConnections(signal?: AbortSignal): Promise<unknown>;
6
+ search(input: SearchInput, signal?: AbortSignal): Promise<unknown>;
7
+ browseSchema(input: BrowseSchemaInput, signal?: AbortSignal): Promise<unknown>;
8
+ getOperation(operationId: string, options: {
9
+ offset: number;
10
+ limit: number;
11
+ }, signal?: AbortSignal): Promise<unknown>;
12
+ cancelOperation(operationId: string, signal?: AbortSignal): Promise<unknown>;
13
+ }
14
+ export interface DataBasinApiClientOptions {
15
+ baseUrl: string;
16
+ auth: {
17
+ profile: DataBasinProfile;
18
+ getAccessToken(): Promise<string>;
19
+ };
20
+ fetchImpl?: typeof fetch;
21
+ maxResponseBytes?: number;
22
+ timeoutMs?: number;
23
+ }
24
+ export declare class DataBasinApiClient implements DataBasinApi {
25
+ private readonly baseUrl;
26
+ private readonly auth;
27
+ private readonly fetchImpl;
28
+ private readonly maxResponseBytes;
29
+ private readonly timeoutMs;
30
+ constructor(options: DataBasinApiClientOptions);
31
+ getProjects(signal?: AbortSignal): Promise<unknown>;
32
+ getAccessibleConnections(signal?: AbortSignal): Promise<unknown>;
33
+ search(input: SearchInput, signal?: AbortSignal): Promise<unknown>;
34
+ browseSchema(input: BrowseSchemaInput, signal?: AbortSignal): Promise<unknown>;
35
+ getOperation(operationId: string, options: {
36
+ offset: number;
37
+ limit: number;
38
+ }, signal?: AbortSignal): Promise<unknown>;
39
+ cancelOperation(operationId: string, signal?: AbortSignal): Promise<unknown>;
40
+ private request;
41
+ }
42
+ export declare function normalizeApiBase(raw: string): string;
43
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKnE,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,wBAAwB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/E,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtH,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACJ,OAAO,EAAE,gBAAgB,CAAC;QAC1B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,EAAE,yBAAyB;IAQ9C,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAInD,wBAAwB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAQlE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAaxE,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAU3H,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;YAI9D,OAAO;CAoCtB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYpD"}
@@ -0,0 +1,154 @@
1
+ import { DataBasinError, LoginRequiredError } from './errors.js';
2
+ export class DataBasinApiClient {
3
+ baseUrl;
4
+ auth;
5
+ fetchImpl;
6
+ maxResponseBytes;
7
+ timeoutMs;
8
+ constructor(options) {
9
+ this.baseUrl = normalizeApiBase(options.baseUrl);
10
+ this.auth = options.auth;
11
+ this.fetchImpl = options.fetchImpl ?? fetch;
12
+ this.maxResponseBytes = options.maxResponseBytes ?? 5_000_000;
13
+ this.timeoutMs = options.timeoutMs ?? 30_000;
14
+ }
15
+ getProjects(signal) {
16
+ return this.request('GET', '/my/projects', undefined, signal);
17
+ }
18
+ getAccessibleConnections(signal) {
19
+ return this.request('GET', '/connections/accessible', undefined, signal);
20
+ }
21
+ search(input, signal) {
22
+ const params = new URLSearchParams({ q: input.q, limit: String(input.limit) });
23
+ if (input.projectId)
24
+ params.set('projectId', input.projectId);
25
+ if (input.organizationId !== undefined)
26
+ params.set('orgId', String(input.organizationId));
27
+ if (input.types?.length)
28
+ params.set('types', input.types.join(','));
29
+ return this.request('GET', `/search?${params.toString()}`, undefined, signal);
30
+ }
31
+ browseSchema(input, signal) {
32
+ const params = new URLSearchParams({ connectorId: String(input.connectorId) });
33
+ let path = '/databasin/catalogs';
34
+ if (input.level !== 'catalogs')
35
+ params.set('catalog', input.catalog);
36
+ if (input.level === 'schemas')
37
+ path = '/databasin/schemas';
38
+ if (input.level === 'tables' || input.level === 'columns') {
39
+ path = input.level === 'tables' ? '/databasin/tables' : '/databasin/columns';
40
+ params.set('schema', input.schema);
41
+ }
42
+ if (input.level === 'columns')
43
+ params.set('table', input.table);
44
+ return this.request('GET', `${path}?${params.toString()}`, undefined, signal);
45
+ }
46
+ async getOperation(operationId, options, signal) {
47
+ const encoded = encodeURIComponent(operationId);
48
+ const status = await this.request('GET', `/databasin/query/${encoded}/status`, undefined, signal, true);
49
+ const statusObject = asRecord(status);
50
+ if (String(statusObject.status ?? '').toLowerCase() !== 'completed')
51
+ return status;
52
+ const params = new URLSearchParams({ offset: String(options.offset), limit: String(options.limit) });
53
+ const results = await this.request('GET', `/databasin/query/${encoded}/results?${params.toString()}`, undefined, signal);
54
+ return { ...statusObject, ...asRecord(results) };
55
+ }
56
+ cancelOperation(operationId, signal) {
57
+ return this.request('POST', `/databasin/query/${encodeURIComponent(operationId)}/cancel`, undefined, signal);
58
+ }
59
+ async request(method, path, body, callerSignal, allowFailedOperation = false) {
60
+ const accessToken = await this.auth.getAccessToken();
61
+ const timeoutSignal = AbortSignal.timeout(this.timeoutMs);
62
+ const signal = callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
63
+ let response;
64
+ try {
65
+ response = await this.fetchImpl(`${this.baseUrl}${path}`, {
66
+ method,
67
+ signal,
68
+ redirect: 'error',
69
+ headers: {
70
+ accept: 'application/json',
71
+ authorization: `Bearer ${accessToken}`,
72
+ ...(body === undefined ? {} : { 'content-type': 'application/json' })
73
+ },
74
+ ...(body === undefined ? {} : { body: JSON.stringify(body) })
75
+ });
76
+ }
77
+ catch {
78
+ throw new DataBasinError('DEPENDENCY_UNAVAILABLE', 'The DataBasin API could not be reached.');
79
+ }
80
+ const payload = await readJson(response, this.maxResponseBytes);
81
+ if (response.ok)
82
+ return payload;
83
+ if (allowFailedOperation && response.status === 500 && isFailedOperation(payload))
84
+ return payload;
85
+ if (response.status === 401)
86
+ throw new LoginRequiredError(this.auth.profile.environment);
87
+ if (response.status === 403)
88
+ throw new DataBasinError('POLICY_DENIED', 'DataBasin denied access to this resource.');
89
+ if (response.status === 404)
90
+ throw new DataBasinError('NOT_FOUND', 'The requested DataBasin resource was not found.');
91
+ if (response.status >= 500)
92
+ throw new DataBasinError('DEPENDENCY_UNAVAILABLE', 'The DataBasin API is temporarily unavailable.');
93
+ throw new DataBasinError('OPERATION_FAILED', `The DataBasin API rejected the request with HTTP ${response.status}.`);
94
+ }
95
+ }
96
+ export function normalizeApiBase(raw) {
97
+ const url = new URL(raw);
98
+ if (url.protocol !== 'https:') {
99
+ throw new Error('The DataBasin API URL must use HTTPS.');
100
+ }
101
+ url.search = '';
102
+ url.hash = '';
103
+ url.username = '';
104
+ url.password = '';
105
+ const path = url.pathname.replace(/\/+$/u, '');
106
+ url.pathname = path.endsWith('/api') ? path : `${path}/api`;
107
+ return url.toString().replace(/\/$/u, '');
108
+ }
109
+ async function readJson(response, maxBytes) {
110
+ const contentLength = Number(response.headers.get('content-length'));
111
+ if (Number.isFinite(contentLength) && contentLength > maxBytes) {
112
+ throw new DataBasinError('POLICY_DENIED', 'The DataBasin API response exceeded the size limit.');
113
+ }
114
+ if (!response.body)
115
+ return null;
116
+ const reader = response.body.getReader();
117
+ const chunks = [];
118
+ let total = 0;
119
+ while (true) {
120
+ const { done, value } = await reader.read();
121
+ if (done)
122
+ break;
123
+ total += value.byteLength;
124
+ if (total > maxBytes) {
125
+ await reader.cancel();
126
+ throw new DataBasinError('POLICY_DENIED', 'The DataBasin API response exceeded the size limit.');
127
+ }
128
+ chunks.push(value);
129
+ }
130
+ if (total === 0)
131
+ return null;
132
+ const bytes = new Uint8Array(total);
133
+ let offset = 0;
134
+ for (const chunk of chunks) {
135
+ bytes.set(chunk, offset);
136
+ offset += chunk.byteLength;
137
+ }
138
+ try {
139
+ return JSON.parse(new TextDecoder().decode(bytes));
140
+ }
141
+ catch {
142
+ if (response.ok)
143
+ throw new DataBasinError('OPERATION_FAILED', 'The DataBasin API returned an invalid response.');
144
+ return null;
145
+ }
146
+ }
147
+ function asRecord(value) {
148
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
149
+ }
150
+ function isFailedOperation(value) {
151
+ const record = asRecord(value);
152
+ return record.status === 'failed' && typeof record.queryId === 'string' && record.queryId.length > 0;
153
+ }
154
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { type AccountInfo, type AuthenticationResult, type IPublicClientApplication } from '@azure/msal-node';
2
+ import { type DataBasinEnvironment, type DataBasinProfile } from './config.js';
3
+ export interface AuthStatus {
4
+ authenticated: boolean;
5
+ environment: DataBasinEnvironment;
6
+ username?: string;
7
+ }
8
+ export type AssistantAuthState = 'authenticated' | 'pending' | 'not_authenticated' | 'failed';
9
+ export interface AssistantAuthResult {
10
+ status: AssistantAuthState;
11
+ environment: DataBasinEnvironment;
12
+ loginUrl: string | null;
13
+ userCode?: string;
14
+ expiresAt?: string;
15
+ message: string;
16
+ }
17
+ interface DeviceCodePrompt {
18
+ userCode: string;
19
+ verificationUri: string;
20
+ expiresIn: number;
21
+ }
22
+ export interface PublicClientLike {
23
+ getAllAccounts(): Promise<AccountInfo[]>;
24
+ acquireTokenSilent(request: {
25
+ account: AccountInfo;
26
+ scopes: string[];
27
+ }): Promise<AuthenticationResult>;
28
+ acquireTokenInteractive(request: {
29
+ scopes: string[];
30
+ openBrowser: (url: string) => Promise<void>;
31
+ prompt?: string;
32
+ successTemplate?: string;
33
+ errorTemplate?: string;
34
+ }): Promise<AuthenticationResult>;
35
+ acquireTokenByDeviceCode(request: {
36
+ scopes: string[];
37
+ timeout?: number;
38
+ deviceCodeCallback: (response: DeviceCodePrompt) => void;
39
+ }): Promise<AuthenticationResult | null>;
40
+ signOut(request: {
41
+ account: AccountInfo;
42
+ }): Promise<void>;
43
+ }
44
+ export interface AuthManagerOptions {
45
+ createClient?: () => Promise<PublicClientLike>;
46
+ openBrowser?: (url: string) => Promise<void>;
47
+ }
48
+ export declare class AuthManager {
49
+ readonly profile: DataBasinProfile;
50
+ private clientPromise;
51
+ private tokenPromise;
52
+ private activeLogin;
53
+ private lastLoginFailed;
54
+ private readonly createClient;
55
+ private readonly openBrowser;
56
+ constructor(profile: DataBasinProfile, options?: AuthManagerOptions);
57
+ getAccessToken(): Promise<string>;
58
+ login(): Promise<AuthStatus>;
59
+ startLogin(): Promise<AssistantAuthResult>;
60
+ getLoginStatus(): Promise<AssistantAuthResult>;
61
+ private beginDeviceLogin;
62
+ private performDeviceLogin;
63
+ private performInteractiveLogin;
64
+ private completeLogin;
65
+ private assistantResult;
66
+ logout(): Promise<number>;
67
+ status(): Promise<AuthStatus>;
68
+ private acquireSilent;
69
+ private client;
70
+ }
71
+ export declare function createSecurePublicClient(profile: DataBasinProfile): Promise<IPublicClientApplication>;
72
+ export {};
73
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/auth.js ADDED
@@ -0,0 +1,234 @@
1
+ import { mkdir } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node';
5
+ import { DataProtectionScope, PersistenceCachePlugin, PersistenceCreator } from '@azure/msal-node-extensions';
6
+ import { openSystemBrowser } from './browser.js';
7
+ import { authorityFor } from './config.js';
8
+ import { DataBasinError, LoginRequiredError } from './errors.js';
9
+ export class AuthManager {
10
+ profile;
11
+ clientPromise;
12
+ tokenPromise;
13
+ activeLogin;
14
+ lastLoginFailed = false;
15
+ createClient;
16
+ openBrowser;
17
+ constructor(profile, options = {}) {
18
+ this.profile = profile;
19
+ this.createClient = options.createClient ?? (() => createSecurePublicClient(profile));
20
+ this.openBrowser = options.openBrowser ?? openSystemBrowser;
21
+ }
22
+ async getAccessToken() {
23
+ this.tokenPromise ??= this.acquireSilent().finally(() => {
24
+ this.tokenPromise = undefined;
25
+ });
26
+ return this.tokenPromise;
27
+ }
28
+ async login() {
29
+ return this.performInteractiveLogin(this.openBrowser);
30
+ }
31
+ async startLogin() {
32
+ const status = await this.getLoginStatus();
33
+ if (status.status === 'authenticated' || status.status === 'pending')
34
+ return status;
35
+ const login = this.beginDeviceLogin();
36
+ const outcome = await Promise.race([
37
+ login.prompted.then((prompt) => ({ state: 'prompted', prompt })),
38
+ login.completion.then(() => ({ state: 'completed' }), () => ({ state: 'failed' }))
39
+ ]);
40
+ if (outcome.state === 'completed') {
41
+ return this.assistantResult('authenticated', null, `DataBasin ${this.profile.label} sign-in is complete.`);
42
+ }
43
+ if (outcome.state === 'failed') {
44
+ return this.assistantResult('failed', null, `DataBasin ${this.profile.label} sign-in did not complete. Call databasin_login to try again.`);
45
+ }
46
+ return this.assistantResult('pending', outcome.prompt.verificationUri, `Open the Microsoft sign-in URL on any device and enter code ${outcome.prompt.userCode}. Then call databasin_auth_status.`, outcome.prompt.userCode, login.expiresAt);
47
+ }
48
+ async getLoginStatus() {
49
+ const login = this.activeLogin;
50
+ if (login) {
51
+ return this.assistantResult('pending', login.prompt?.verificationUri ?? null, login.prompt
52
+ ? `Open the Microsoft sign-in URL on any device and enter code ${login.prompt.userCode}.`
53
+ : 'Microsoft is preparing the device sign-in instructions.', login.prompt?.userCode, login.expiresAt);
54
+ }
55
+ const cachedStatus = await this.status();
56
+ if (cachedStatus.authenticated) {
57
+ try {
58
+ await this.getAccessToken();
59
+ return this.assistantResult('authenticated', null, `DataBasin ${this.profile.label} is signed in.`);
60
+ }
61
+ catch (error) {
62
+ if (!(error instanceof DataBasinError) || error.code !== 'UNAUTHENTICATED')
63
+ throw error;
64
+ }
65
+ }
66
+ if (this.lastLoginFailed) {
67
+ return this.assistantResult('failed', null, `DataBasin ${this.profile.label} sign-in did not complete. Call databasin_login to try again.`);
68
+ }
69
+ return this.assistantResult('not_authenticated', null, `DataBasin ${this.profile.label} is not signed in. Call databasin_login to begin.`);
70
+ }
71
+ beginDeviceLogin() {
72
+ if (this.activeLogin)
73
+ return this.activeLogin;
74
+ this.lastLoginFailed = false;
75
+ let resolvePrompted = () => undefined;
76
+ const login = {
77
+ prompted: new Promise((resolve) => {
78
+ resolvePrompted = resolve;
79
+ }),
80
+ completion: Promise.resolve({ authenticated: false, environment: this.profile.environment }),
81
+ prompt: undefined,
82
+ expiresAt: undefined
83
+ };
84
+ login.completion = this.performDeviceLogin((prompt) => {
85
+ login.prompt = prompt;
86
+ login.expiresAt = new Date(Date.now() + prompt.expiresIn * 1_000).toISOString();
87
+ resolvePrompted(prompt);
88
+ }).catch((error) => {
89
+ this.lastLoginFailed = true;
90
+ throw error;
91
+ }).finally(() => {
92
+ if (this.activeLogin === login)
93
+ this.activeLogin = undefined;
94
+ });
95
+ this.activeLogin = login;
96
+ void login.completion.catch(() => undefined);
97
+ return login;
98
+ }
99
+ async performDeviceLogin(onPrompt) {
100
+ const client = await this.client();
101
+ let result;
102
+ try {
103
+ result = await client.acquireTokenByDeviceCode({
104
+ scopes: [...this.profile.scopes],
105
+ timeout: 900,
106
+ deviceCodeCallback: onPrompt
107
+ });
108
+ }
109
+ catch {
110
+ throw new DataBasinError('UNAUTHENTICATED', `DataBasin ${this.profile.label} sign-in did not complete.`);
111
+ }
112
+ return this.completeLogin(client, result);
113
+ }
114
+ async performInteractiveLogin(openBrowser) {
115
+ const client = await this.client();
116
+ let result;
117
+ try {
118
+ result = await client.acquireTokenInteractive({
119
+ scopes: [...this.profile.scopes],
120
+ openBrowser,
121
+ prompt: 'select_account',
122
+ successTemplate: successPage(this.profile.label),
123
+ errorTemplate: errorPage()
124
+ });
125
+ }
126
+ catch {
127
+ throw new DataBasinError('UNAUTHENTICATED', `DataBasin ${this.profile.label} sign-in did not complete.`);
128
+ }
129
+ return this.completeLogin(client, result);
130
+ }
131
+ async completeLogin(client, result) {
132
+ if (!result?.account || !result.accessToken) {
133
+ throw new DataBasinError('UNAUTHENTICATED', 'Microsoft Entra did not return a usable DataBasin session.');
134
+ }
135
+ const accounts = await client.getAllAccounts();
136
+ await Promise.all(accounts
137
+ .filter((account) => account.homeAccountId !== result.account?.homeAccountId)
138
+ .map((account) => client.signOut({ account })));
139
+ return {
140
+ authenticated: true,
141
+ environment: this.profile.environment,
142
+ username: result.account.username
143
+ };
144
+ }
145
+ assistantResult(status, loginUrl, message, userCode, expiresAt) {
146
+ return {
147
+ status,
148
+ environment: this.profile.environment,
149
+ loginUrl,
150
+ ...(userCode ? { userCode } : {}),
151
+ ...(expiresAt ? { expiresAt } : {}),
152
+ message
153
+ };
154
+ }
155
+ async logout() {
156
+ const client = await this.client();
157
+ const accounts = await client.getAllAccounts();
158
+ await Promise.all(accounts.map((account) => client.signOut({ account })));
159
+ return accounts.length;
160
+ }
161
+ async status() {
162
+ const accounts = await (await this.client()).getAllAccounts();
163
+ const account = selectAccount(accounts, this.profile.tenantId);
164
+ return account
165
+ ? { authenticated: true, environment: this.profile.environment, username: account.username }
166
+ : { authenticated: false, environment: this.profile.environment };
167
+ }
168
+ async acquireSilent() {
169
+ const client = await this.client();
170
+ const account = selectAccount(await client.getAllAccounts(), this.profile.tenantId);
171
+ if (!account)
172
+ throw new LoginRequiredError(this.profile.environment);
173
+ try {
174
+ const result = await client.acquireTokenSilent({ account, scopes: [...this.profile.scopes] });
175
+ if (!result.accessToken)
176
+ throw new LoginRequiredError(this.profile.environment);
177
+ return result.accessToken;
178
+ }
179
+ catch (error) {
180
+ if (error instanceof InteractionRequiredAuthError) {
181
+ throw new LoginRequiredError(this.profile.environment);
182
+ }
183
+ throw new DataBasinError('UNAUTHENTICATED', `The DataBasin ${this.profile.label} session could not be refreshed. Sign in again.`);
184
+ }
185
+ }
186
+ client() {
187
+ this.clientPromise ??= this.createClient().catch((error) => {
188
+ this.clientPromise = undefined;
189
+ const detail = error instanceof Error && error.message.includes('libsecret')
190
+ ? ' Install or unlock the system keyring and try again.'
191
+ : '';
192
+ throw new DataBasinError('UNAUTHENTICATED', `Secure DataBasin credential storage is unavailable.${detail}`);
193
+ });
194
+ return this.clientPromise;
195
+ }
196
+ }
197
+ export async function createSecurePublicClient(profile) {
198
+ const cacheDirectory = join(homedir(), '.databasin', 'mcp', 'auth', profile.environment);
199
+ await mkdir(cacheDirectory, { recursive: true, mode: 0o700 });
200
+ const persistence = await PersistenceCreator.createPersistence({
201
+ cachePath: join(cacheDirectory, 'msal-cache.lock'),
202
+ dataProtectionScope: DataProtectionScope.CurrentUser,
203
+ serviceName: 'com.databasin.mcp',
204
+ accountName: profile.environment,
205
+ usePlaintextFileOnLinux: false
206
+ });
207
+ const configuration = {
208
+ auth: {
209
+ clientId: profile.clientId,
210
+ authority: authorityFor(profile)
211
+ },
212
+ cache: {
213
+ cachePlugin: new PersistenceCachePlugin(persistence)
214
+ },
215
+ system: {
216
+ loggerOptions: {
217
+ piiLoggingEnabled: false,
218
+ logLevel: 0,
219
+ loggerCallback: () => undefined
220
+ }
221
+ }
222
+ };
223
+ return new PublicClientApplication(configuration);
224
+ }
225
+ function selectAccount(accounts, tenantId) {
226
+ return accounts.find((account) => account.tenantId.toLowerCase() === tenantId.toLowerCase()) ?? accounts[0];
227
+ }
228
+ function successPage(label) {
229
+ return `<!doctype html><html><body><h1>DataBasin sign-in complete</h1><p>You are signed in to ${label}. You can close this window.</p></body></html>`;
230
+ }
231
+ function errorPage() {
232
+ return '<!doctype html><html><body><h1>DataBasin sign-in failed</h1><p>Return to your assistant or terminal and try again.</p></body></html>';
233
+ }
234
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function openSystemBrowser(rawUrl: string): Promise<void>;
2
+ //# sourceMappingURL=browser.d.ts.map