@databrainhq/mcp-server 0.3.0-rc.13 → 0.3.0-rc.14
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/.mcp.json +6 -1
- package/dist/apps/server.d.ts +102 -389
- package/dist/apps/server.js +5 -5
- package/dist/apps/stdio.d.ts +1 -2
- package/dist/apps/stdio.js +6 -6
- package/dist/{bundle-TDQXWIPM.js → bundle-QJNCUMNY.js} +2 -2
- package/dist/{chunk-Q5EYDKSA.js → chunk-2F7V6RZR.js} +511 -107
- package/dist/chunk-2F7V6RZR.js.map +1 -0
- package/dist/{chunk-AEQTEE5C.js → chunk-AWICHHDU.js} +153 -61
- package/dist/chunk-AWICHHDU.js.map +1 -0
- package/dist/{chunk-X44C5GW2.js → chunk-CEGHG5U3.js} +59 -18
- package/dist/chunk-CEGHG5U3.js.map +1 -0
- package/dist/{chunk-233VGFHY.js → chunk-NIC5MAGC.js} +317 -147
- package/dist/chunk-NIC5MAGC.js.map +1 -0
- package/dist/{chunk-DTFYHLYN.js → chunk-S65KA3Z7.js} +26 -11
- package/dist/chunk-S65KA3Z7.js.map +1 -0
- package/dist/{chunk-PSJVYD4W.js → chunk-UYFFFAYV.js} +11722 -10560
- package/dist/chunk-UYFFFAYV.js.map +1 -0
- package/dist/{chunk-HCYZN7I3.js → chunk-VQ5G5AZV.js} +10 -7
- package/dist/chunk-VQ5G5AZV.js.map +1 -0
- package/dist/cli.d.ts +16 -15
- package/dist/cli.js +134 -36
- package/dist/cli.js.map +1 -1
- package/dist/custom-chart/custom-runtime.js +6 -6
- package/dist/custom-chart/template/chart.ts +116 -28
- package/dist/custom-chart/template/icon.svg +1 -1
- package/dist/custom-chart/template/manifest.json +66 -12
- package/dist/custom-chart/template/sample-data.json +21 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/{main-VEKNKWL5.js → main-QCBVJSSR.js} +348 -155
- package/dist/main-QCBVJSSR.js.map +1 -0
- package/dist/{test-only-LJGOY2QA.js → test-only-6474NMTR.js} +12 -8
- package/dist/test-only-6474NMTR.js.map +1 -0
- package/package.json +20 -9
- package/dist/chunk-233VGFHY.js.map +0 -1
- package/dist/chunk-AEQTEE5C.js.map +0 -1
- package/dist/chunk-DTFYHLYN.js.map +0 -1
- package/dist/chunk-HCYZN7I3.js.map +0 -1
- package/dist/chunk-PSJVYD4W.js.map +0 -1
- package/dist/chunk-Q5EYDKSA.js.map +0 -1
- package/dist/chunk-X44C5GW2.js.map +0 -1
- package/dist/main-VEKNKWL5.js.map +0 -1
- package/dist/test-only-LJGOY2QA.js.map +0 -1
- /package/dist/{bundle-TDQXWIPM.js.map → bundle-QJNCUMNY.js.map} +0 -0
|
@@ -22,8 +22,8 @@ var HostedAuthError = class extends Error {
|
|
|
22
22
|
|
|
23
23
|
// src/hosted/auth.ts
|
|
24
24
|
import { createHash, timingSafeEqual } from "crypto";
|
|
25
|
-
import { open } from "fs/promises";
|
|
26
25
|
import { constants } from "fs";
|
|
26
|
+
import { open } from "fs/promises";
|
|
27
27
|
import { z } from "zod";
|
|
28
28
|
var identity = z.string().min(1).max(512).regex(/^[^\x00-\x1f\x7f]+$/);
|
|
29
29
|
var workspaceSchema = z.object({ id: identity, name: identity.optional() }).strip();
|
|
@@ -36,7 +36,10 @@ var principalSchema = z.object({
|
|
|
36
36
|
workspaceName: identity.optional(),
|
|
37
37
|
workspaces: z.union([
|
|
38
38
|
z.object({ mode: z.literal("all") }).strip(),
|
|
39
|
-
z.object({
|
|
39
|
+
z.object({
|
|
40
|
+
mode: z.literal("list"),
|
|
41
|
+
ids: z.array(identity).min(1).max(100)
|
|
42
|
+
}).strip()
|
|
40
43
|
]).optional(),
|
|
41
44
|
grantedWorkspaces: z.array(workspaceSchema).max(1e3).optional(),
|
|
42
45
|
// The issuer's own pick; recomputed below from grantedWorkspaces, never trusted on its own.
|
|
@@ -48,8 +51,16 @@ var principalSchema = z.object({
|
|
|
48
51
|
tenantIds: z.array(identity).optional()
|
|
49
52
|
}).strict();
|
|
50
53
|
function normalizeWorkspaces(value) {
|
|
51
|
-
const {
|
|
52
|
-
|
|
54
|
+
const {
|
|
55
|
+
defaultWorkspace: _default,
|
|
56
|
+
workspaceId,
|
|
57
|
+
workspaceName,
|
|
58
|
+
grantedWorkspaces,
|
|
59
|
+
...rest
|
|
60
|
+
} = value;
|
|
61
|
+
const granted = grantedWorkspaces ?? (workspaceId ? [
|
|
62
|
+
workspaceName === void 0 ? { id: workspaceId } : { id: workspaceId, name: workspaceName }
|
|
63
|
+
] : []);
|
|
53
64
|
if (!granted.length || new Set(granted.map((item) => item.id)).size !== granted.length || workspaceId !== void 0 && !granted.some((item) => item.id === workspaceId)) {
|
|
54
65
|
throw new HostedAuthError(401, "invalid_token");
|
|
55
66
|
}
|
|
@@ -74,12 +85,21 @@ var FilePatStore = class {
|
|
|
74
85
|
this.path = path;
|
|
75
86
|
}
|
|
76
87
|
async findByHash(hash) {
|
|
77
|
-
const handle = await open(
|
|
88
|
+
const handle = await open(
|
|
89
|
+
this.path,
|
|
90
|
+
constants.O_RDONLY | constants.O_NOFOLLOW
|
|
91
|
+
);
|
|
78
92
|
try {
|
|
79
93
|
const stat = await handle.stat();
|
|
80
|
-
if (!stat.isFile() || (stat.mode & 63) !== 0 || stat.size > 1048576 || process.getuid && stat.uid !== process.getuid())
|
|
94
|
+
if (!stat.isFile() || (stat.mode & 63) !== 0 || stat.size > 1048576 || process.getuid && stat.uid !== process.getuid())
|
|
95
|
+
throw new Error("Invalid credential store");
|
|
81
96
|
const records = z.array(recordSchema).max(1e3).parse(JSON.parse(await handle.readFile("utf8")));
|
|
82
|
-
const matches = records.filter(
|
|
97
|
+
const matches = records.filter(
|
|
98
|
+
(record) => timingSafeEqual(
|
|
99
|
+
Buffer.from(record.hash, "hex"),
|
|
100
|
+
Buffer.from(hash, "hex")
|
|
101
|
+
)
|
|
102
|
+
);
|
|
83
103
|
if (matches.length > 1) throw new Error("Ambiguous credential store");
|
|
84
104
|
return matches[0];
|
|
85
105
|
} finally {
|
|
@@ -89,28 +109,49 @@ var FilePatStore = class {
|
|
|
89
109
|
};
|
|
90
110
|
function validatePrincipal(value, resource, kind) {
|
|
91
111
|
const parsed = principalSchema.safeParse(value);
|
|
92
|
-
if (!parsed.success || parsed.data.resource !== resource || parsed.data.credentialType !== kind || parsed.data.expiresAt !== void 0 && parsed.data.expiresAt <= Date.now() / 1e3 || kind === "pat" && parsed.success && parsed.data.expiresAt === void 0)
|
|
112
|
+
if (!parsed.success || parsed.data.resource !== resource || parsed.data.credentialType !== kind || parsed.data.expiresAt !== void 0 && parsed.data.expiresAt <= Date.now() / 1e3 || kind === "pat" && parsed.success && parsed.data.expiresAt === void 0)
|
|
113
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
93
114
|
return normalizeWorkspaces(parsed.data);
|
|
94
115
|
}
|
|
95
116
|
function createBearerVerifier(adapter, resource, pats) {
|
|
96
117
|
return async (token) => {
|
|
97
118
|
try {
|
|
98
|
-
if (!/^[A-Za-z0-9._
|
|
119
|
+
if (!/^[A-Za-z0-9._~+/-]+=*$/.test(token) || token.length > 8192)
|
|
120
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
99
121
|
if (!token.startsWith("dbp_")) {
|
|
100
|
-
return validatePrincipal(
|
|
122
|
+
return validatePrincipal(
|
|
123
|
+
await adapter.verifyOAuth(token, resource),
|
|
124
|
+
resource,
|
|
125
|
+
"oauth"
|
|
126
|
+
);
|
|
101
127
|
}
|
|
102
|
-
if (!/^dbp_[A-Za-z0-9_-]{32,}$/.test(token))
|
|
128
|
+
if (!/^dbp_[A-Za-z0-9_-]{32,}$/.test(token))
|
|
129
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
103
130
|
const record = await pats?.findByHash(hashCredential(token));
|
|
104
|
-
if (!record || record.revokedAt !== null || record.hash !== hashCredential(token))
|
|
131
|
+
if (!record || record.revokedAt !== null || record.hash !== hashCredential(token))
|
|
132
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
105
133
|
const stored = validatePrincipal(record.principal, resource, "pat");
|
|
106
|
-
const resolved = validatePrincipal(
|
|
107
|
-
|
|
108
|
-
|
|
134
|
+
const resolved = validatePrincipal(
|
|
135
|
+
await adapter.resolvePatGrant(structuredClone(stored)),
|
|
136
|
+
resource,
|
|
137
|
+
"pat"
|
|
138
|
+
);
|
|
139
|
+
for (const key of [
|
|
140
|
+
"userId",
|
|
141
|
+
"companyId",
|
|
142
|
+
"clientId",
|
|
143
|
+
"resource"
|
|
144
|
+
]) {
|
|
145
|
+
if (resolved[key] !== stored[key])
|
|
146
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
109
147
|
}
|
|
110
|
-
if (resolved.grantedWorkspaces.some(
|
|
148
|
+
if (resolved.grantedWorkspaces.some(
|
|
149
|
+
(item) => !stored.grantedWorkspaces.some((old) => old.id === item.id)
|
|
150
|
+
)) {
|
|
111
151
|
throw new HostedAuthError(401, "invalid_token");
|
|
112
152
|
}
|
|
113
|
-
if (resolved.expiresAt > stored.expiresAt || resolved.scopes.some((scope) => !stored.scopes.includes(scope)) || resolved.tenantIds?.some((id) => !stored.tenantIds?.includes(id)))
|
|
153
|
+
if (resolved.expiresAt > stored.expiresAt || resolved.scopes.some((scope) => !stored.scopes.includes(scope)) || resolved.tenantIds?.some((id) => !stored.tenantIds?.includes(id)))
|
|
154
|
+
throw new HostedAuthError(401, "invalid_token");
|
|
114
155
|
return resolved;
|
|
115
156
|
} catch (error) {
|
|
116
157
|
if (error instanceof HostedAuthError) throw error;
|
|
@@ -127,4 +168,4 @@ export {
|
|
|
127
168
|
FilePatStore,
|
|
128
169
|
createBearerVerifier
|
|
129
170
|
};
|
|
130
|
-
//# sourceMappingURL=chunk-
|
|
171
|
+
//# sourceMappingURL=chunk-CEGHG5U3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hosted/types.ts","../src/hosted/auth.ts"],"sourcesContent":["import type { RequestOptions } from '../client/types.js';\n\nexport const HOSTED_SCOPES = [\n 'mcp:dashboards:read',\n 'mcp:dashboards:write',\n 'mcp:datamarts:read',\n 'mcp:datamarts:write',\n 'mcp:embeds:write',\n 'mcp:query',\n 'mcp:custom-charts:read',\n 'mcp:custom-charts:write',\n] as const;\nexport type HostedScope = (typeof HOSTED_SCOPES)[number];\n\n/** A workspace this sign-in may act in, as the issuer resolved it for this request. */\nexport interface GrantedWorkspace {\n id: string;\n name?: string;\n}\n\n/** What the user approved at consent: a list of workspaces, or every workspace they can access. */\nexport type GrantWorkspaces = { mode: 'all' } | { mode: 'list'; ids: string[] };\n\n/** Only the trusted auth adapter may produce this context. Never populate it from MCP input. */\nexport interface HostedPrincipal {\n actorKind: 'user';\n credentialType: 'oauth' | 'pat';\n userId: string;\n companyId: string;\n /** Set only when exactly one workspace is granted: the default for every call. */\n workspaceId?: string;\n workspaceName?: string;\n /** The grant as approved. Absent from issuers that grant one workspace only. */\n workspaces?: GrantWorkspaces;\n /**\n * Live: the granted workspaces the user can still access, read on every request.\n * Absent only on a principal built before multi-workspace grants (then `workspaceId`).\n */\n grantedWorkspaces?: GrantedWorkspace[];\n /** OAuth application ID, NOT the tenant identifier called clientId by legacy tools. */\n clientId: string;\n resource: string;\n scopes: HostedScope[];\n /** Required for stored PATs. OAuth may delegate expiry to fresh provider validation. */\n expiresAt?: number;\n /** Explicit tenant allow-list resolved by the backend; absent means no tenant access. */\n tenantIds?: string[];\n}\n\nexport interface PatRecord {\n hash: string;\n revokedAt: number | null;\n principal: HostedPrincipal;\n}\n\nexport interface PatStore {\n findByHash(hash: string): Promise<PatRecord | undefined>;\n}\n\n/**\n * Opaque per-request handle from `HostedAdapter.delegate`. It carries nothing a tool,\n * log or serializer can read; only the adapter that made it can act with it.\n */\nexport interface HostedDelegation {\n readonly kind: 'hosted-delegation';\n}\n\n/** Production integration must recheck membership, policy and revocation on every call. */\nexport interface HostedAdapter {\n verifyOAuth(token: string, resource: string): Promise<HostedPrincipal>;\n resolvePatGrant(principal: HostedPrincipal): Promise<HostedPrincipal>;\n /**\n * Optional. Bind this request's verified OAuth bearer to an opaque handle, so\n * executeRequest can act as this user at the configured issuer, which re-verifies\n * the token and enforces workspace, object and role checks on every call.\n */\n delegate?(token: string, principal: HostedPrincipal): HostedDelegation;\n /**\n * Execute as this user/workspace with backend resource and tenant checks and auditing.\n * Receives NO incoming bearer or server service credential: only the opaque handle.\n * Do not impersonate a static service token.\n * Return the raw API result: the shared client performs its usual data unwrapping.\n * `workspace` is the granted workspace this tool call acts in, when one is known; the\n * adapter names it to the issuer and nowhere else.\n */\n executeRequest(\n options: RequestOptions,\n principal: HostedPrincipal,\n delegation?: HostedDelegation,\n workspace?: GrantedWorkspace\n ): Promise<unknown>;\n}\n\nexport interface HostedConfig {\n publicUrl: string;\n issuer: string;\n /** Where the issuer's API is reached, when not at the issuer origin itself. */\n apiUrl?: string;\n port: number;\n bind: string;\n testOnly: boolean;\n}\n\n/** The backend's own status, code and message for a 4xx that is not an auth denial. */\nexport interface HostedErrorDetail {\n status: number;\n code?: string;\n message?: string;\n}\n\nexport class HostedAuthError extends Error {\n constructor(\n public readonly status: 400 | 401 | 403 | 404 | 503,\n public readonly code: string,\n public readonly detail?: HostedErrorDetail\n ) {\n super(code);\n }\n}\n","import { createHash, timingSafeEqual } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport { open } from 'node:fs/promises';\nimport { z } from 'zod';\nimport type {\n HostedAdapter,\n HostedPrincipal,\n PatRecord,\n PatStore,\n} from './types.js';\nimport { HOSTED_SCOPES, HostedAuthError } from './types.js';\n\nconst identity = z\n .string()\n .min(1)\n .max(512)\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Identity validation intentionally rejects control characters.\n .regex(/^[^\\x00-\\x1f\\x7f]+$/);\nconst workspaceSchema = z\n .object({ id: identity, name: identity.optional() })\n .strip();\nexport const principalSchema = z\n .object({\n actorKind: z.literal('user'),\n credentialType: z.enum(['oauth', 'pat']),\n userId: identity,\n companyId: identity,\n workspaceId: identity.optional(),\n workspaceName: identity.optional(),\n workspaces: z\n .union([\n z.object({ mode: z.literal('all') }).strip(),\n z\n .object({\n mode: z.literal('list'),\n ids: z.array(identity).min(1).max(100),\n })\n .strip(),\n ])\n .optional(),\n grantedWorkspaces: z.array(workspaceSchema).max(1000).optional(),\n // The issuer's own pick; recomputed below from grantedWorkspaces, never trusted on its own.\n defaultWorkspace: workspaceSchema.optional(),\n clientId: identity,\n resource: z.string().url(),\n scopes: z.array(z.enum(HOSTED_SCOPES)),\n expiresAt: z.number().finite().positive().optional(),\n tenantIds: z.array(identity).optional(),\n })\n .strict();\n\n/**\n * One shape for every issuer: the live granted list, and `workspaceId`/`workspaceName`\n * only when exactly one workspace is granted (the default for each call). An issuer\n * that grants one workspace sends only `workspaceId`; read that as a one-item list.\n * No workspace left, duplicate ids, or a `workspaceId` outside the list is refused.\n */\nfunction normalizeWorkspaces(\n value: z.infer<typeof principalSchema>\n): HostedPrincipal {\n const {\n defaultWorkspace: _default,\n workspaceId,\n workspaceName,\n grantedWorkspaces,\n ...rest\n } = value;\n const granted =\n grantedWorkspaces ??\n (workspaceId\n ? [\n workspaceName === undefined\n ? { id: workspaceId }\n : { id: workspaceId, name: workspaceName },\n ]\n : []);\n if (\n !granted.length ||\n new Set(granted.map((item) => item.id)).size !== granted.length ||\n (workspaceId !== undefined &&\n !granted.some((item) => item.id === workspaceId))\n ) {\n throw new HostedAuthError(401, 'invalid_token');\n }\n const only = granted.length === 1 ? granted[0] : undefined;\n return {\n ...rest,\n grantedWorkspaces: granted,\n ...(only ? { workspaceId: only.id } : {}),\n ...(only?.name !== undefined ? { workspaceName: only.name } : {}),\n };\n}\nconst recordSchema = z\n .object({\n hash: z.string().regex(/^[a-f0-9]{64}$/),\n revokedAt: z.number().finite().nullable(),\n principal: principalSchema,\n })\n .strict();\n\nexport function hashCredential(token: string): string {\n return createHash('sha256').update(token).digest('hex');\n}\n\n/** Reread on every request: an atomic file replacement revokes immediately, without restart. */\nexport class FilePatStore implements PatStore {\n constructor(private readonly path: string) {}\n async findByHash(hash: string): Promise<PatRecord | undefined> {\n const handle = await open(\n this.path,\n constants.O_RDONLY | constants.O_NOFOLLOW\n );\n try {\n const stat = await handle.stat();\n if (\n !stat.isFile() ||\n (stat.mode & 0o077) !== 0 ||\n stat.size > 1_048_576 ||\n (process.getuid && stat.uid !== process.getuid())\n )\n throw new Error('Invalid credential store');\n const records = z\n .array(recordSchema)\n .max(1000)\n .parse(JSON.parse(await handle.readFile('utf8')));\n const matches = records.filter((record) =>\n timingSafeEqual(\n Buffer.from(record.hash, 'hex'),\n Buffer.from(hash, 'hex')\n )\n );\n // Duplicate records are ambiguous, including an active/revoked pair.\n if (matches.length > 1) throw new Error('Ambiguous credential store');\n return matches[0];\n } finally {\n await handle.close();\n }\n }\n}\n\nfunction validatePrincipal(\n value: unknown,\n resource: string,\n kind: 'oauth' | 'pat'\n): HostedPrincipal {\n const parsed = principalSchema.safeParse(value);\n if (\n !parsed.success ||\n parsed.data.resource !== resource ||\n parsed.data.credentialType !== kind ||\n (parsed.data.expiresAt !== undefined &&\n parsed.data.expiresAt <= Date.now() / 1000) ||\n (kind === 'pat' && parsed.success && parsed.data.expiresAt === undefined)\n )\n throw new HostedAuthError(401, 'invalid_token');\n return normalizeWorkspaces(parsed.data);\n}\n\nexport function createBearerVerifier(\n adapter: HostedAdapter,\n resource: string,\n pats?: PatStore\n) {\n return async (token: string): Promise<HostedPrincipal> => {\n try {\n if (!/^[A-Za-z0-9._~+/-]+=*$/.test(token) || token.length > 8192)\n throw new HostedAuthError(401, 'invalid_token');\n if (!token.startsWith('dbp_')) {\n return validatePrincipal(\n await adapter.verifyOAuth(token, resource),\n resource,\n 'oauth'\n );\n }\n if (!/^dbp_[A-Za-z0-9_-]{32,}$/.test(token))\n throw new HostedAuthError(401, 'invalid_token');\n const record = await pats?.findByHash(hashCredential(token));\n if (\n !record ||\n record.revokedAt !== null ||\n record.hash !== hashCredential(token)\n )\n throw new HostedAuthError(401, 'invalid_token');\n const stored = validatePrincipal(record.principal, resource, 'pat');\n const resolved = validatePrincipal(\n await adapter.resolvePatGrant(structuredClone(stored)),\n resource,\n 'pat'\n );\n // Membership resolution may narrow a stored grant, never move or expand it.\n for (const key of [\n 'userId',\n 'companyId',\n 'clientId',\n 'resource',\n ] as const) {\n if (resolved[key] !== stored[key])\n throw new HostedAuthError(401, 'invalid_token');\n }\n if (\n resolved.grantedWorkspaces!.some(\n (item) => !stored.grantedWorkspaces!.some((old) => old.id === item.id)\n )\n ) {\n throw new HostedAuthError(401, 'invalid_token');\n }\n if (\n resolved.expiresAt! > stored.expiresAt! ||\n resolved.scopes.some((scope) => !stored.scopes.includes(scope)) ||\n resolved.tenantIds?.some((id) => !stored.tenantIds?.includes(id))\n )\n throw new HostedAuthError(401, 'invalid_token');\n return resolved;\n } catch (error) {\n if (error instanceof HostedAuthError) throw error;\n // No raw verifier, filesystem or remote errors can disclose credential values.\n throw new HostedAuthError(401, 'invalid_token');\n }\n };\n}\n"],"mappings":"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","names":[]}
|