@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.
- package/README.md +108 -0
- package/dist/api-client.d.ts +43 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +154 -0
- package/dist/api-client.js.map +1 -0
- package/dist/auth.d.ts +73 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +234 -0
- package/dist/auth.js.map +1 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +34 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +131 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +45 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/mappers.d.ts +56 -0
- package/dist/mappers.d.ts.map +1 -0
- package/dist/mappers.js +171 -0
- package/dist/mappers.js.map +1 -0
- package/dist/safety.d.ts +3 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +27 -0
- package/dist/safety.js.map +1 -0
- package/dist/schemas.d.ts +154 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +102 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +35 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +17 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +117 -0
- package/dist/tools.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- 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
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|