@databasin/mcp-client 0.2.0-beta.1 → 0.2.1
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 +36 -30
- package/dist/auth-schema.d.ts +23 -0
- package/dist/auth-schema.d.ts.map +1 -0
- package/dist/auth-schema.js +42 -0
- package/dist/auth-schema.js.map +1 -0
- package/dist/auth-tools.d.ts +10 -0
- package/dist/auth-tools.d.ts.map +1 -0
- package/dist/auth-tools.js +60 -0
- package/dist/auth-tools.js.map +1 -0
- package/dist/auth.d.ts +13 -74
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +16 -228
- package/dist/auth.js.map +1 -1
- package/dist/auth0-store.d.ts +14 -0
- package/dist/auth0-store.d.ts.map +1 -0
- package/dist/auth0-store.js +78 -0
- package/dist/auth0-store.js.map +1 -0
- package/dist/auth0-token.d.ts +3 -0
- package/dist/auth0-token.d.ts.map +1 -0
- package/dist/auth0-token.js +13 -0
- package/dist/auth0-token.js.map +1 -0
- package/dist/auth0.d.ts +41 -0
- package/dist/auth0.d.ts.map +1 -0
- package/dist/auth0.js +236 -0
- package/dist/auth0.js.map +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -2
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -2
- package/dist/config.js.map +1 -1
- package/dist/entra-auth.d.ts +84 -0
- package/dist/entra-auth.d.ts.map +1 -0
- package/dist/entra-auth.js +234 -0
- package/dist/entra-auth.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/login-url.d.ts +2 -0
- package/dist/login-url.d.ts.map +1 -1
- package/dist/login-url.js +14 -0
- package/dist/login-url.js.map +1 -1
- package/dist/mcp-endpoint.d.ts +5 -0
- package/dist/mcp-endpoint.d.ts.map +1 -0
- package/dist/mcp-endpoint.js +22 -0
- package/dist/mcp-endpoint.js.map +1 -0
- package/dist/proxy-tools.d.ts +5 -0
- package/dist/proxy-tools.d.ts.map +1 -0
- package/dist/proxy-tools.js +39 -0
- package/dist/proxy-tools.js.map +1 -0
- package/dist/remote-mcp.d.ts +27 -0
- package/dist/remote-mcp.d.ts.map +1 -0
- package/dist/remote-mcp.js +70 -0
- package/dist/remote-mcp.js.map +1 -0
- package/dist/server.d.ts +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +17 -7
- package/dist/server.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +7 -3
- package/dist/abort.d.ts +0 -5
- package/dist/abort.d.ts.map +0 -1
- package/dist/abort.js +0 -25
- package/dist/abort.js.map +0 -1
- package/dist/api-client.d.ts +0 -58
- package/dist/api-client.d.ts.map +0 -1
- package/dist/api-client.js +0 -151
- package/dist/api-client.js.map +0 -1
- package/dist/api-contract.d.ts +0 -59
- package/dist/api-contract.d.ts.map +0 -1
- package/dist/api-contract.js +0 -47
- package/dist/api-contract.js.map +0 -1
- package/dist/api-profile.d.ts +0 -5
- package/dist/api-profile.d.ts.map +0 -1
- package/dist/api-profile.js +0 -38
- package/dist/api-profile.js.map +0 -1
- package/dist/api-request.d.ts +0 -27
- package/dist/api-request.d.ts.map +0 -1
- package/dist/api-request.js +0 -147
- package/dist/api-request.js.map +0 -1
- package/dist/api-response.d.ts +0 -9
- package/dist/api-response.d.ts.map +0 -1
- package/dist/api-response.js +0 -206
- package/dist/api-response.js.map +0 -1
- package/dist/schemas.d.ts +0 -431
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js +0 -289
- package/dist/schemas.js.map +0 -1
- package/dist/tools.d.ts +0 -28
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -328
- package/dist/tools.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# DataBasin MCP Client
|
|
2
2
|
|
|
3
|
-
Local stdio MCP
|
|
3
|
+
Local stdio MCP proxy for DataBasin. It uses Auth0 device sign-in, keeps tokens in OS-protected credential storage, and connects to DataBasin's Streamable HTTP MCP endpoint with the official MCP SDK.
|
|
4
4
|
|
|
5
5
|
Production is the default. The non-production profile is selected with `--environment np`.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Version 0.2.1 authentication fix
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Version `0.2.1` adds Auth0 login using the providers enabled for the DataBasin MCP native application. Version `0.2.0` supported only direct Microsoft Entra login; its cached sessions do not establish an Auth0 login. After upgrading, sign in again. Existing Entra credentials are neither reused nor deleted. The true MCP transport, support tickets, and notifications remain unchanged. Production is the default:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y @databasin/mcp-client@0.2.
|
|
13
|
-
npx -y @databasin/mcp-client@0.2.
|
|
12
|
+
npx -y @databasin/mcp-client@0.2.1 doctor
|
|
13
|
+
npx -y @databasin/mcp-client@0.2.1 login
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
The
|
|
16
|
+
The client requires Node.js 22.20+ or Node.js 24 and an available OS-protected credential store. `doctor` reports the selected fixed profile, runtime support, credential-store availability, and sign-in state; it never prints account identity, tokens, or credentials.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
For non-production, use the same stable package with the NP profile:
|
|
19
19
|
|
|
20
|
-
| Host | NP
|
|
20
|
+
| Host | NP setup |
|
|
21
21
|
| --- | --- |
|
|
22
|
-
| Codex | `codex mcp add databasin-np -- npx -y @databasin/mcp-client@0.2.
|
|
23
|
-
| Claude Code | `claude mcp add --transport stdio --scope user databasin-np -- npx -y @databasin/mcp-client@0.2.
|
|
22
|
+
| Codex | `codex mcp add databasin-np -- npx -y @databasin/mcp-client@0.2.1 --environment np` |
|
|
23
|
+
| Claude Code | `claude mcp add --transport stdio --scope user databasin-np -- npx -y @databasin/mcp-client@0.2.1 --environment np` |
|
|
24
24
|
| Claude Desktop / Cursor-compatible config | Use the `mcpServers` JSON below |
|
|
25
25
|
| VS Code | Use the `servers` JSON below in user or workspace `mcp.json` |
|
|
26
26
|
| OpenCode v2 | Use the `mcp.servers` JSON below in `opencode.jsonc` |
|
|
@@ -33,7 +33,7 @@ Claude Desktop and other hosts that accept the common `mcpServers` shape:
|
|
|
33
33
|
"databasin-np": {
|
|
34
34
|
"type": "stdio",
|
|
35
35
|
"command": "npx",
|
|
36
|
-
"args": ["-y", "@databasin/mcp-client@0.2.
|
|
36
|
+
"args": ["-y", "@databasin/mcp-client@0.2.1", "--environment", "np"]
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -47,7 +47,7 @@ VS Code `mcp.json`:
|
|
|
47
47
|
"databasinNp": {
|
|
48
48
|
"type": "stdio",
|
|
49
49
|
"command": "npx",
|
|
50
|
-
"args": ["-y", "@databasin/mcp-client@0.2.
|
|
50
|
+
"args": ["-y", "@databasin/mcp-client@0.2.1", "--environment", "np"]
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -62,19 +62,21 @@ OpenCode v2 `opencode.jsonc`:
|
|
|
62
62
|
"servers": {
|
|
63
63
|
"databasin-np": {
|
|
64
64
|
"type": "local",
|
|
65
|
-
"command": ["npx", "-y", "@databasin/mcp-client@0.2.
|
|
65
|
+
"command": ["npx", "-y", "@databasin/mcp-client@0.2.1", "--environment", "np"]
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
On native Windows, a host that cannot launch `npx` directly should use `cmd` with arguments beginning `[/c, npx, ...]` (JSON string form: `["/c", "npx", ...]`). Restart the host after changing its MCP configuration so it refreshes the
|
|
72
|
+
On native Windows, a host that cannot launch `npx` directly should use `cmd` with arguments beginning `[/c, npx, ...]` (JSON string form: `["/c", "npx", ...]`). Restart the host after changing its MCP configuration so it refreshes the server-owned tool inventory.
|
|
73
73
|
|
|
74
|
-
The only remote
|
|
74
|
+
The only remote MCP endpoints are:
|
|
75
75
|
|
|
76
|
-
- Production: `https://databasin.cloud/
|
|
77
|
-
- NP: `https://databasin-ui-np.grayriver-813df174.centralus.azurecontainerapps.io/
|
|
76
|
+
- Production: `https://databasin.cloud/mcp`
|
|
77
|
+
- NP: `https://databasin-ui-np.grayriver-813df174.centralus.azurecontainerapps.io/mcp`
|
|
78
|
+
|
|
79
|
+
The downstream connection pins MCP `2026-07-28` and has no REST or legacy-protocol fallback. Tool discovery and listing are public protocol operations. The client obtains a local access token only for `tools/call`, adds it as a bearer credential to that request, and rejects HTTP redirects so credentials cannot cross origins.
|
|
78
80
|
|
|
79
81
|
## Install and connect
|
|
80
82
|
|
|
@@ -105,15 +107,17 @@ To use non-production:
|
|
|
105
107
|
npx -y @databasin/mcp-client --environment np
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
The assistant can call `databasin_login` and give you the
|
|
110
|
+
The assistant can call `databasin_login` and give you the DataBasin Auth0 activation URL and a short-lived user code. Enter credentials only on the sign-in page or the identity provider it redirects you to. The client never sends credentials or tokens through MCP tool output.
|
|
111
|
+
|
|
112
|
+
Auth0 login output is restricted to `https://databasin.us.auth0.com/activate`; both CLI and assistant login use device authorization. Raw device codes and tokens remain private to the client. Authentication requests reject redirects; unexpected login hosts, schemes, paths, queries, ports, and fragments are rejected. No callback URL, client secret, or password is configured in the plugin.
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
Auth0 access tokens undergo RS256 signature verification against the pinned tenant JWKS, plus issuer, environment-specific API audience, authorized client, subject, and expiry checks. Refresh tokens are stored only in the OS-protected store, separately by provider, environment, client, and audience. Refresh-token rotation is serialized across processes. Logout clears this client's local Auth0 session and cancels pending login; it does not sign out the website or erase legacy Entra sessions. The server independently validates tokens and authorizes every product operation. Entra support remains available in the code for explicitly configured non-Auth0 profiles; built-in hosted profiles do not silently fall back to it.
|
|
111
115
|
|
|
112
|
-
|
|
116
|
+
Automatic renewal requires both the native application's Refresh Token grant and the API's Allow Offline Access setting. The client requests `offline_access`; if Auth0 does not issue a refresh token, it requires sign-in again when the access token expires. It does not silently substitute another provider or keep expired credentials working.
|
|
113
117
|
|
|
114
118
|
## Tools
|
|
115
119
|
|
|
116
|
-
The
|
|
120
|
+
The production server currently exposes twenty product tools, plus this client's two local authentication helpers (twenty-two total). Product tools are discovered dynamically from the remote DataBasin MCP server and mirrored over local stdio. Their names, descriptions, annotations, input/output schemas, and timeout metadata are server-owned; this package does not keep a second product-tool contract. The current server catalog is:
|
|
117
121
|
|
|
118
122
|
- `databasin_get_capabilities` — fetch the server-owned capability allowlist.
|
|
119
123
|
- `databasin_get_context` — fetch authorized project and connector metadata.
|
|
@@ -127,19 +131,21 @@ The MCP server exposes thirteen tools in two deliberately separate groups. Eleve
|
|
|
127
131
|
- `databasin_cancel_query` — request cancellation and report the server’s truthful state.
|
|
128
132
|
- `databasin_run_assistant` — run the read-only DataBasin assistant (a server-side Claude Code agent) that browses metadata and runs DataBasin skills over multiple steps to answer a natural-language request.
|
|
129
133
|
|
|
130
|
-
|
|
134
|
+
Support tools are also discovered: `databasin_get_support_context`, `databasin_list_support_tickets`, `databasin_get_support_ticket`, `databasin_create_support_ticket`, `databasin_add_support_ticket_message`, `databasin_update_support_ticket`, `databasin_list_support_notifications`, `databasin_mark_support_notification_read`, and `databasin_mark_all_support_notifications_read`. Support operations include writes; follow their server-owned schemas and annotations. Ticket/message data includes authorized email fields, and optional values may be null.
|
|
135
|
+
|
|
136
|
+
The other two tools, `databasin_auth_status` and `databasin_login`, are client-local authentication helpers. They interact with Auth0 and the OS credential store; they are not part of the remote product catalog.
|
|
131
137
|
|
|
132
138
|
No organization configuration is required. Unscoped `databasin_get_context` and `databasin_search` discover metadata only across organizations the signed-in user is authorized to access. A project-scoped search must include its `institutionId`; account discovery is not a wildcard and never broadens server-side authorization.
|
|
133
139
|
|
|
134
|
-
The client does not expose arbitrary SQL, shell commands, connector credentials, arbitrary URLs, or arbitrary headers.
|
|
140
|
+
The client does not expose arbitrary SQL, shell commands, connector credentials, arbitrary URLs, or arbitrary headers. The remote server validates product inputs, authorization, output safety, query policy, and response bounds. `databasin_run_query` accepts only a single read-only `SELECT`/`WITH` statement under that server-owned contract. Every product success is the MCP result returned by the server, including its structured `{ "data": T, "correlationId": "..." }` payload.
|
|
135
141
|
|
|
136
|
-
`databasin_run_agent` accepts
|
|
142
|
+
`databasin_run_agent` accepts the scope and execution fields advertised in its discovered schema and always uses the server-owned `metadata_readonly` profile. The remote MCP tool owns run creation, bounded polling, cancellation on MCP abort, authorization rechecks, and any idempotency behavior; the local proxy performs one `tools/call` and forwards its cancellation signal.
|
|
137
143
|
|
|
138
144
|
Agent status, result, and cancellation responses include the complete server-authorized scope. A canonical run contains `runId`, the three scope IDs (nullable where optional), `profile`, `status`, bounded `result`/`error`, and `createdAt`/`updatedAt`. Cancellation reports the state returned by the server and does not imply completion before the server says `cancelled`.
|
|
139
145
|
|
|
140
|
-
`databasin_run_query` accepts
|
|
146
|
+
`databasin_run_query` accepts the bounded connector, SQL, and row-limit fields in the discovered schema. The remote MCP tool owns its bounded polling and timeout behavior. Status and cancellation remain explicit tools for follow-up. A canonical query result contains `queryId`, `connectorId`, `status`, bounded `columns`/`data`/`rowCount`, `truncated`, and `error`.
|
|
141
147
|
|
|
142
|
-
`databasin_run_assistant`
|
|
148
|
+
`databasin_run_assistant` remains the server's bounded, read-only assistant operation. It is metadata-and-skills only; use `databasin_run_query` for SQL. The server advertises the accepted input and output schemas plus the call timeout in MCP metadata, and the client mirrors them without local copies. This transport change does not replace or modify the server's existing Claude Agent SDK runtime.
|
|
143
149
|
|
|
144
150
|
## CLI fallback
|
|
145
151
|
|
|
@@ -164,12 +170,12 @@ npm run verify:package
|
|
|
164
170
|
|
|
165
171
|
`npm run verify` runs the TypeScript check, unit tests, build, and stdio child-process E2E. CI runs those checks on Node 22 and 24 across Linux, macOS, and Windows, audits production dependencies, and verifies the exact package allowlist with `npm pack --dry-run --json`.
|
|
166
172
|
|
|
167
|
-
Release qualification uses an exact local tarball, never a mutable dist-tag. After `npm pack`, an authorized tester with an existing
|
|
173
|
+
Release qualification uses an exact local tarball, never a mutable dist-tag. After `npm pack`, an authorized tester with an existing production session can run the read-only qualification:
|
|
168
174
|
|
|
169
175
|
```bash
|
|
170
|
-
|
|
176
|
+
DATABASIN_MCP_TARBALL=./databasin-mcp-client-0.2.1.tgz npm run qualify:package
|
|
171
177
|
```
|
|
172
178
|
|
|
173
|
-
|
|
179
|
+
Set `DATABASIN_MCP_QUALIFY_ENVIRONMENT=np` to qualify against NP instead. This check installs the exact artifact in a temporary directory, starts its stdio executable, checks local sign-in and the twenty-two-tool inventory, and calls only context/search/support read operations. It never creates agent jobs, executes SQL, or changes support data, and does not print credentials or business content. The old `qualify:np` script remains only for historical beta lifecycle qualification.
|
|
174
180
|
|
|
175
|
-
|
|
181
|
+
An authentication release requires a fresh Auth0 device login, signed-token validation, secure persistence across client restarts, refresh-token renewal, and authorized MCP calls against the target environment. Cached Microsoft sessions and mocked login tests are not substitutes for this release gate. Qualifying production does not claim that non-production login or every enabled identity provider was tested.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const AssistantAuthOutputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3
|
+
status: z.ZodLiteral<"pending">;
|
|
4
|
+
environment: z.ZodEnum<{
|
|
5
|
+
prod: "prod";
|
|
6
|
+
np: "np";
|
|
7
|
+
}>;
|
|
8
|
+
loginUrl: z.ZodNullable<z.ZodString>;
|
|
9
|
+
userCode: z.ZodOptional<z.ZodString>;
|
|
10
|
+
expiresAt: z.ZodOptional<z.ZodISODateTime>;
|
|
11
|
+
message: z.ZodString;
|
|
12
|
+
}, z.core.$strict>, ...z.ZodObject<{
|
|
13
|
+
status: z.ZodLiteral<"authenticated" | "not_authenticated" | "failed">;
|
|
14
|
+
environment: z.ZodEnum<{
|
|
15
|
+
prod: "prod";
|
|
16
|
+
np: "np";
|
|
17
|
+
}>;
|
|
18
|
+
loginUrl: z.ZodNull;
|
|
19
|
+
userCode: z.ZodOptional<z.ZodNever>;
|
|
20
|
+
expiresAt: z.ZodOptional<z.ZodNever>;
|
|
21
|
+
message: z.ZodString;
|
|
22
|
+
}, z.core.$strict>[]], "status">;
|
|
23
|
+
//# sourceMappingURL=auth-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-schema.d.ts","sourceRoot":"","sources":["../src/auth-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoBxB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;gCAuBpC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { validateAssistantLoginUrl } from './login-url.js';
|
|
3
|
+
const authEnvironment = z.enum(['prod', 'np']);
|
|
4
|
+
const URL_LIKE_AUTH_MESSAGE = /(?:\b(?:https?|hxxps?|ftp|file|data|javascript)\s*:\s*(?:[/\\]\s*){0,2}|\bwww\s*(?:\.|\[\.\]|\(\.\))|(?:\b|@)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.|\[\.\]|\(\.\)))+[a-z]{2,63}(?=\b|[/:?#])|\b(?:localhost|(?:\d{1,3}\.){3}\d{1,3})(?=[:/\s]|$))/iu;
|
|
5
|
+
const authMessage = z.string().max(1_000).refine((value) => !URL_LIKE_AUTH_MESSAGE.test(normalizeAuthMessage(value)), 'The authentication message was rejected.');
|
|
6
|
+
const safeDeviceLoginUrl = z.string().max(4_096).superRefine((value, context) => {
|
|
7
|
+
try {
|
|
8
|
+
validateAssistantLoginUrl(value);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
context.addIssue({ code: 'custom', message: 'The authentication result was rejected.' });
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
export const AssistantAuthOutputSchema = z.discriminatedUnion('status', [
|
|
15
|
+
z.object({
|
|
16
|
+
status: z.literal('pending'),
|
|
17
|
+
environment: authEnvironment,
|
|
18
|
+
loginUrl: safeDeviceLoginUrl.nullable(),
|
|
19
|
+
userCode: z.string().trim().regex(/^[A-Z0-9-]{4,32}$/iu).optional(),
|
|
20
|
+
expiresAt: z.iso.datetime().optional(),
|
|
21
|
+
message: authMessage
|
|
22
|
+
}).strict(),
|
|
23
|
+
...['authenticated', 'not_authenticated', 'failed'].map((status) => z.object({
|
|
24
|
+
status: z.literal(status),
|
|
25
|
+
environment: authEnvironment,
|
|
26
|
+
loginUrl: z.null(),
|
|
27
|
+
userCode: z.never().optional(),
|
|
28
|
+
expiresAt: z.never().optional(),
|
|
29
|
+
message: authMessage
|
|
30
|
+
}).strict())
|
|
31
|
+
]).superRefine((value, context) => {
|
|
32
|
+
if (value.status !== 'pending')
|
|
33
|
+
return;
|
|
34
|
+
const hasPrompt = value.loginUrl !== null;
|
|
35
|
+
if (hasPrompt !== (value.userCode !== undefined) || hasPrompt !== (value.expiresAt !== undefined)) {
|
|
36
|
+
context.addIssue({ code: 'custom', message: 'The authentication result has an invalid pending state.' });
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
function normalizeAuthMessage(value) {
|
|
40
|
+
return value.normalize('NFKC').replace(/[\u200B-\u200D\u2060\uFEFF]/gu, '').replace(/\s+/gu, ' ');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=auth-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-schema.js","sourceRoot":"","sources":["../src/auth-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AAC/C,MAAM,qBAAqB,GACzB,2PAA2P,CAAC;AAE9P,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,EACnE,0CAA0C,CAC3C,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IAC9E,IAAI,CAAC;QACH,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACtE,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QAC5B,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,kBAAkB,CAAC,QAAQ,EAAE;QACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;QACnE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;QACtC,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC,MAAM,EAAE;IACX,GAAI,CAAC,eAAe,EAAE,mBAAmB,EAAE,QAAQ,CAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACtF,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACzB,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE;QAClB,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;QAC9B,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;QAC/B,OAAO,EAAE,WAAW;KACrB,CAAC,CAAC,MAAM,EAAE,CAAC;CACb,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO;IACvC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC1C,IAAI,SAAS,KAAK,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,IAAI,SAAS,KAAK,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,CAAC;QAClG,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,yDAAyD,EAAE,CAAC,CAAC;IAC3G,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,SAAS,oBAAoB,CAAC,KAAa;IACzC,OAAO,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACpG,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
import type { AssistantAuthResult } from './auth.js';
|
|
3
|
+
export declare const LOCAL_AUTH_TOOL_NAMES: readonly ["databasin_auth_status", "databasin_login"];
|
|
4
|
+
type AuthTools = Readonly<{
|
|
5
|
+
startLogin(): Promise<AssistantAuthResult>;
|
|
6
|
+
getLoginStatus(): Promise<AssistantAuthResult>;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function registerAuthTools(server: McpServer, auth: AuthTools): void;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=auth-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-tools.d.ts","sourceRoot":"","sources":["../src/auth-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAsB,MAAM,8BAA8B,CAAC;AAE7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAMrD,eAAO,MAAM,qBAAqB,uDAGvB,CAAC;AAEZ,KAAK,SAAS,GAAG,QAAQ,CAAC;IACxB,UAAU,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3C,cAAc,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAChD,CAAC,CAAC;AAKH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAgB1E"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z, ZodError } from 'zod';
|
|
2
|
+
import { AssistantAuthOutputSchema } from './auth-schema.js';
|
|
3
|
+
import { safeCorrelationId } from './correlation.js';
|
|
4
|
+
import { DataBasinError, publicError } from './errors.js';
|
|
5
|
+
import { assertSafeOutput, sanitizeOutput } from './safety.js';
|
|
6
|
+
export const LOCAL_AUTH_TOOL_NAMES = Object.freeze([
|
|
7
|
+
'databasin_auth_status',
|
|
8
|
+
'databasin_login'
|
|
9
|
+
]);
|
|
10
|
+
const emptyInput = z.object({}).strict();
|
|
11
|
+
const annotations = { readOnlyHint: true, destructiveHint: false, openWorldHint: false };
|
|
12
|
+
export function registerAuthTools(server, auth) {
|
|
13
|
+
server.registerTool(LOCAL_AUTH_TOOL_NAMES[0], {
|
|
14
|
+
title: 'Check DataBasin sign-in',
|
|
15
|
+
description: 'Check local sign-in state without returning account identity or credentials.',
|
|
16
|
+
inputSchema: emptyInput,
|
|
17
|
+
outputSchema: AssistantAuthOutputSchema,
|
|
18
|
+
annotations
|
|
19
|
+
}, async (_input, context) => authToolResult(() => auth.getLoginStatus(), context));
|
|
20
|
+
server.registerTool(LOCAL_AUTH_TOOL_NAMES[1], {
|
|
21
|
+
title: 'Sign in to DataBasin',
|
|
22
|
+
description: 'Start DataBasin device sign-in. Enter credentials only on the approved sign-in page; never provide credentials in chat.',
|
|
23
|
+
inputSchema: emptyInput,
|
|
24
|
+
outputSchema: AssistantAuthOutputSchema,
|
|
25
|
+
annotations: { ...annotations, readOnlyHint: false, openWorldHint: true }
|
|
26
|
+
}, async (_input, context) => authToolResult(() => auth.startLogin(), context));
|
|
27
|
+
}
|
|
28
|
+
async function authToolResult(operation, _context) {
|
|
29
|
+
try {
|
|
30
|
+
const output = AssistantAuthOutputSchema.parse(sanitizeOutput(await operation()));
|
|
31
|
+
const result = { ...output, message: authOutputMessage(output) };
|
|
32
|
+
assertSafeOutput(result);
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
35
|
+
structuredContent: result
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const normalized = error instanceof ZodError
|
|
40
|
+
? new DataBasinError('INVALID_ARGUMENT', error.issues[0]?.message ?? 'The tool arguments are invalid.')
|
|
41
|
+
: error;
|
|
42
|
+
const visible = publicError(normalized);
|
|
43
|
+
const { correlationId, ...publicFields } = visible;
|
|
44
|
+
const safe = { ...publicFields, correlationId: safeCorrelationId(correlationId) };
|
|
45
|
+
return { content: [{ type: 'text', text: JSON.stringify(safe) }], isError: true };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function authOutputMessage(output) {
|
|
49
|
+
if (output.status === 'pending') {
|
|
50
|
+
return output.loginUrl === null
|
|
51
|
+
? 'DataBasin is preparing the device sign-in instructions.'
|
|
52
|
+
: 'DataBasin device sign-in is ready. Use the approved login URL and user code, then call databasin_auth_status.';
|
|
53
|
+
}
|
|
54
|
+
if (output.status === 'authenticated')
|
|
55
|
+
return 'DataBasin sign-in is complete.';
|
|
56
|
+
if (output.status === 'not_authenticated')
|
|
57
|
+
return 'DataBasin is not signed in. Call databasin_login to begin.';
|
|
58
|
+
return 'DataBasin sign-in did not complete. Call databasin_login to try again.';
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=auth-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-tools.js","sourceRoot":"","sources":["../src/auth-tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAElC,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC;IACjD,uBAAuB;IACvB,iBAAiB;CACT,CAAC,CAAC;AAOZ,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AACzC,MAAM,WAAW,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAEzF,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,IAAe;IAClE,MAAM,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE;QAC5C,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,8EAA8E;QAC3F,WAAW,EAAE,UAAU;QACvB,YAAY,EAAE,yBAAyB;QACvC,WAAW;KACZ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpF,MAAM,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE;QAC5C,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,yHAAyH;QACtI,WAAW,EAAE,UAAU;QACvB,YAAY,EAAE,yBAAyB;QACvC,WAAW,EAAE,EAAE,GAAG,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;KAC1E,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,SAA6C,EAC7C,QAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QACjE,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,iBAAiB,EAAE,MAAM;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,UAAU,GAAG,KAAK,YAAY,QAAQ;YAC1C,CAAC,CAAC,IAAI,cAAc,CAAC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,iCAAiC,CAAC;YACvG,CAAC,CAAC,KAAK,CAAC;QACV,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,EAAE,aAAa,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;QACnD,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,EAAE,aAAa,EAAE,iBAAiB,CAAC,aAAa,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAa,EAAE,CAAC;IACtG,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAA0E;IACnG,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,QAAQ,KAAK,IAAI;YAC7B,CAAC,CAAC,yDAAyD;YAC3D,CAAC,CAAC,+GAA+G,CAAC;IACtH,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,eAAe;QAAE,OAAO,gCAAgC,CAAC;IAC/E,IAAI,MAAM,CAAC,MAAM,KAAK,mBAAmB;QAAE,OAAO,4DAA4D,CAAC;IAC/G,OAAO,wEAAwE,CAAC;AAClF,CAAC"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,84 +1,23 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type
|
|
3
|
-
import {
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
environment: DataBasinEnvironment;
|
|
7
|
-
username?: string;
|
|
8
|
-
}
|
|
9
|
-
export type AssistantAuthState = 'authenticated' | 'pending' | 'not_authenticated' | 'failed';
|
|
10
|
-
interface AssistantAuthResultBase {
|
|
11
|
-
environment: DataBasinEnvironment;
|
|
12
|
-
message: string;
|
|
13
|
-
}
|
|
14
|
-
interface PendingAssistantAuthResult extends AssistantAuthResultBase {
|
|
15
|
-
status: 'pending';
|
|
16
|
-
loginUrl: string | null;
|
|
17
|
-
userCode?: string;
|
|
18
|
-
expiresAt?: string;
|
|
19
|
-
}
|
|
20
|
-
interface SettledAssistantAuthResult extends AssistantAuthResultBase {
|
|
21
|
-
status: Exclude<AssistantAuthState, 'pending'>;
|
|
22
|
-
loginUrl: null;
|
|
23
|
-
userCode?: never;
|
|
24
|
-
expiresAt?: never;
|
|
25
|
-
}
|
|
26
|
-
export type AssistantAuthResult = PendingAssistantAuthResult | SettledAssistantAuthResult;
|
|
27
|
-
export interface PublicClientLike {
|
|
28
|
-
getAllAccounts(): Promise<AccountInfo[]>;
|
|
29
|
-
acquireTokenSilent(request: {
|
|
30
|
-
account: AccountInfo;
|
|
31
|
-
scopes: string[];
|
|
32
|
-
}): Promise<AuthenticationResult>;
|
|
33
|
-
acquireTokenInteractive(request: {
|
|
34
|
-
scopes: string[];
|
|
35
|
-
openBrowser: (url: string) => Promise<void>;
|
|
36
|
-
prompt?: string;
|
|
37
|
-
successTemplate?: string;
|
|
38
|
-
errorTemplate?: string;
|
|
39
|
-
}): Promise<AuthenticationResult>;
|
|
40
|
-
acquireTokenByDeviceCode(request: {
|
|
41
|
-
scopes: string[];
|
|
42
|
-
timeout?: number;
|
|
43
|
-
cancel?: boolean;
|
|
44
|
-
deviceCodeCallback: (response: RawDeviceCodeResponse) => void;
|
|
45
|
-
}): Promise<AuthenticationResult | null>;
|
|
46
|
-
signOut(request: {
|
|
47
|
-
account: AccountInfo;
|
|
48
|
-
}): Promise<void>;
|
|
49
|
-
}
|
|
1
|
+
import { type Auth0Options } from './auth0.js';
|
|
2
|
+
import { type AuthManagerOptions as EntraOptions } from './entra-auth.js';
|
|
3
|
+
import type { DataBasinProfile } from './config.js';
|
|
4
|
+
export type { AuthStatus, AssistantAuthState, AssistantAuthResult, PublicClientLike } from './entra-auth.js';
|
|
5
|
+
export { createSecurePublicClient } from './credential-store.js';
|
|
50
6
|
export interface AuthManagerOptions {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
now?: () => number;
|
|
7
|
+
auth0?: Auth0Options;
|
|
8
|
+
entra?: EntraOptions;
|
|
54
9
|
}
|
|
10
|
+
/** Use the configured provider. Never treat a cached Entra login as an Auth0 session. */
|
|
55
11
|
export declare class AuthManager {
|
|
56
12
|
readonly profile: DataBasinProfile;
|
|
57
|
-
private
|
|
58
|
-
private tokenPromise;
|
|
59
|
-
private activeLogin;
|
|
60
|
-
private lastLoginFailed;
|
|
61
|
-
private readonly createClient;
|
|
62
|
-
private readonly openBrowser;
|
|
63
|
-
private readonly now;
|
|
13
|
+
private readonly provider;
|
|
64
14
|
constructor(profile: DataBasinProfile, options?: AuthManagerOptions);
|
|
65
15
|
getAccessToken(): Promise<string>;
|
|
66
|
-
login(): Promise<AuthStatus>;
|
|
67
|
-
startLogin(): Promise<AssistantAuthResult>;
|
|
16
|
+
login(): Promise<import("./entra-auth.js").AuthStatus>;
|
|
17
|
+
startLogin(): Promise<import("./entra-auth.js").AssistantAuthResult>;
|
|
18
|
+
getLoginStatus(): Promise<import("./entra-auth.js").AssistantAuthResult>;
|
|
68
19
|
cancelPendingLogin(): void;
|
|
69
|
-
getLoginStatus(): Promise<AssistantAuthResult>;
|
|
70
|
-
private pendingAssistantResult;
|
|
71
|
-
private cachedAssistantResult;
|
|
72
|
-
private failedAssistantResult;
|
|
73
|
-
private beginDeviceLogin;
|
|
74
|
-
private performDeviceLogin;
|
|
75
|
-
private performInteractiveLogin;
|
|
76
|
-
private completeLogin;
|
|
77
|
-
private assistantResult;
|
|
78
20
|
logout(): Promise<number>;
|
|
79
|
-
status(): Promise<AuthStatus>;
|
|
80
|
-
private acquireSilent;
|
|
81
|
-
private client;
|
|
21
|
+
status(): Promise<import("./entra-auth.js").AuthStatus>;
|
|
82
22
|
}
|
|
83
|
-
export { createSecurePublicClient } from './credential-store.js';
|
|
84
23
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAoB,KAAK,kBAAkB,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC7G,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,MAAM,WAAW,kBAAkB;IAAG,KAAK,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAA;CAAE;AAElF,yFAAyF;AACzF,qBAAa,WAAW;IAEV,QAAQ,CAAC,OAAO,EAAE,gBAAgB;IAD9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;gBACtC,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAE,kBAAuB;IAKhF,cAAc;IACd,KAAK;IACL,UAAU;IACV,cAAc;IACd,kBAAkB;IAClB,MAAM;IACN,MAAM;CACP"}
|