@malloy-publisher/server 0.0.195 → 0.0.196
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/dist/app/api-doc.yaml +213 -214
- package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +1 -0
- package/dist/app/assets/HomePage-DMop21VG.js +1 -0
- package/dist/app/assets/MainPage-BbE8ETz1.js +2 -0
- package/dist/app/assets/ModelPage-D2jvfe3t.js +1 -0
- package/dist/app/assets/PackagePage-BbnhGoD3.js +1 -0
- package/dist/app/assets/{RouteError-DefbDO7F.js → RouteError-D3LGEZ3i.js} +1 -1
- package/dist/app/assets/WorkbookPage-DttVIj4u.js +1 -0
- package/dist/app/assets/{core-BrfQApxh.es-DnvCX4oH.js → core-w79IMXAG.es-Bd0UlzOL.js} +1 -1
- package/dist/app/assets/{index-Bu0ub036.js → index-5K9YjIxF.js} +117 -117
- package/dist/app/assets/{index-CkzK3JIl.js → index-C513UodQ.js} +1 -1
- package/dist/app/assets/{index-CoA6HIGS.js → index-DIgzgp69.js} +1 -1
- package/dist/app/assets/{index.umd-B6Ms2PpL.js → index.umd-BMeMPq_9.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/server.mjs +1976 -1322
- package/package.json +2 -2
- package/publisher.config.json +2 -2
- package/src/config.spec.ts +181 -66
- package/src/config.ts +68 -47
- package/src/controller/compile.controller.ts +10 -7
- package/src/controller/connection.controller.ts +79 -58
- package/src/controller/database.controller.ts +10 -7
- package/src/controller/manifest.controller.ts +23 -14
- package/src/controller/materialization.controller.ts +14 -14
- package/src/controller/model.controller.ts +35 -20
- package/src/controller/package.controller.ts +83 -49
- package/src/controller/query.controller.ts +11 -8
- package/src/controller/watch-mode.controller.ts +35 -29
- package/src/errors.ts +2 -2
- package/src/mcp/error_messages.ts +2 -2
- package/src/mcp/handler_utils.ts +23 -20
- package/src/mcp/mcp_constants.ts +1 -1
- package/src/mcp/prompts/handlers.ts +3 -3
- package/src/mcp/prompts/prompt_service.ts +5 -5
- package/src/mcp/prompts/utils.ts +12 -12
- package/src/mcp/resource_metadata.ts +3 -3
- package/src/mcp/resources/environment_resource.ts +187 -0
- package/src/mcp/resources/model_resource.ts +19 -17
- package/src/mcp/resources/notebook_resource.ts +13 -13
- package/src/mcp/resources/package_resource.ts +30 -27
- package/src/mcp/resources/query_resource.ts +15 -10
- package/src/mcp/resources/source_resource.ts +10 -10
- package/src/mcp/resources/view_resource.ts +11 -11
- package/src/mcp/server.ts +16 -14
- package/src/mcp/tools/discovery_tools.ts +67 -49
- package/src/mcp/tools/execute_query_tool.ts +14 -14
- package/src/server-old.ts +1119 -0
- package/src/server.ts +191 -159
- package/src/service/connection.spec.ts +158 -133
- package/src/service/connection.ts +42 -39
- package/src/service/connection_config.spec.ts +13 -11
- package/src/service/connection_config.ts +28 -19
- package/src/service/connection_service.spec.ts +63 -43
- package/src/service/connection_service.ts +106 -89
- package/src/service/{project.ts → environment.ts} +92 -77
- package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
- package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -83
- package/src/service/{project_store.ts → environment_store.ts} +373 -327
- package/src/service/manifest_service.spec.ts +15 -15
- package/src/service/manifest_service.ts +26 -21
- package/src/service/materialization_service.spec.ts +93 -59
- package/src/service/materialization_service.ts +71 -62
- package/src/service/materialized_table_gc.spec.ts +15 -15
- package/src/service/materialized_table_gc.ts +3 -3
- package/src/service/model.ts +4 -4
- package/src/service/package.spec.ts +2 -2
- package/src/service/package.ts +23 -21
- package/src/service/resolve_environment.ts +15 -0
- package/src/storage/DatabaseInterface.ts +34 -25
- package/src/storage/StorageManager.mock.ts +3 -3
- package/src/storage/StorageManager.ts +64 -28
- package/src/storage/duckdb/ConnectionRepository.ts +13 -11
- package/src/storage/duckdb/DuckDBConnection.ts +1 -1
- package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
- package/src/storage/duckdb/DuckDBRepository.ts +47 -47
- package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
- package/src/storage/duckdb/ManifestRepository.ts +21 -20
- package/src/storage/duckdb/MaterializationRepository.ts +31 -28
- package/src/storage/duckdb/PackageRepository.ts +11 -11
- package/src/storage/duckdb/manifest_store.spec.ts +2 -2
- package/src/storage/duckdb/schema.ts +61 -20
- package/src/storage/ducklake/DuckLakeManifestStore.ts +20 -11
- package/tests/fixtures/publisher.config.json +1 -1
- package/tests/harness/e2e.ts +1 -1
- package/tests/harness/mcp_test_setup.ts +12 -24
- package/tests/harness/mocks.ts +10 -8
- package/tests/harness/rest_e2e.ts +2 -2
- package/tests/integration/legacy_routes/legacy_routes.integration.spec.ts +259 -0
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +28 -49
- package/tests/integration/mcp/mcp_resource.integration.spec.ts +39 -47
- package/tests/integration/mcp/mcp_transport.integration.spec.ts +1 -1
- package/tests/unit/duckdb/attached_databases.test.ts +51 -33
- package/tests/unit/duckdb/legacy_schema_migration.test.ts +194 -0
- package/tests/unit/ducklake/ducklake.test.ts +24 -22
- package/tests/unit/mcp/prompt_happy.test.ts +8 -8
- package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
- package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
- package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
- package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
- package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
- package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
- package/src/mcp/resources/project_resource.ts +0 -184
- package/src/service/resolve_project.ts +0 -13
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
McpServer,
|
|
3
3
|
ResourceTemplate,
|
|
4
4
|
} from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
-
import {
|
|
5
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
6
6
|
import {
|
|
7
7
|
ModelNotFoundError,
|
|
8
8
|
PackageNotFoundError,
|
|
@@ -23,12 +23,12 @@ import type { components } from "../../api"; // Import the components type
|
|
|
23
23
|
*/
|
|
24
24
|
export function registerModelResource(
|
|
25
25
|
mcpServer: McpServer,
|
|
26
|
-
|
|
26
|
+
environmentStore: EnvironmentStore,
|
|
27
27
|
): void {
|
|
28
28
|
mcpServer.resource(
|
|
29
29
|
"model",
|
|
30
30
|
new ResourceTemplate(
|
|
31
|
-
"malloy://
|
|
31
|
+
"malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}",
|
|
32
32
|
{ list: undefined }, // No list handler for individual models
|
|
33
33
|
),
|
|
34
34
|
/** Handles GetResource requests for specific Malloy Models */
|
|
@@ -38,18 +38,18 @@ export function registerModelResource(
|
|
|
38
38
|
params,
|
|
39
39
|
"model",
|
|
40
40
|
async ({
|
|
41
|
-
|
|
41
|
+
environmentName,
|
|
42
42
|
packageName,
|
|
43
43
|
modelPath,
|
|
44
44
|
}: {
|
|
45
|
-
|
|
45
|
+
environmentName?: unknown;
|
|
46
46
|
packageName?: unknown;
|
|
47
47
|
modelPath?: unknown;
|
|
48
48
|
}) => {
|
|
49
49
|
try {
|
|
50
50
|
// Validate all parameters
|
|
51
|
-
if (typeof
|
|
52
|
-
throw new Error("Invalid
|
|
51
|
+
if (typeof environmentName !== "string") {
|
|
52
|
+
throw new Error("Invalid environment name parameter.");
|
|
53
53
|
}
|
|
54
54
|
if (typeof packageName !== "string") {
|
|
55
55
|
throw new Error("Invalid package name parameter.");
|
|
@@ -58,14 +58,14 @@ export function registerModelResource(
|
|
|
58
58
|
throw new Error("Invalid model path parameter.");
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
// *** UPDATED LOGIC using
|
|
62
|
-
//
|
|
63
|
-
const
|
|
64
|
-
|
|
61
|
+
// *** UPDATED LOGIC using EnvironmentStore ***
|
|
62
|
+
// getEnvironment can throw EnvironmentNotFoundError (though unlikely if name is 'home')
|
|
63
|
+
const environment = await environmentStore.getEnvironment(
|
|
64
|
+
environmentName,
|
|
65
65
|
false,
|
|
66
66
|
);
|
|
67
67
|
// getPackage can throw PackageNotFoundError
|
|
68
|
-
const pkg = await
|
|
68
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
69
69
|
// getModel is SYNCHRONOUS
|
|
70
70
|
const modelInstance = pkg.getModel(modelPath);
|
|
71
71
|
// *** END UPDATED LOGIC ***
|
|
@@ -98,20 +98,22 @@ export function registerModelResource(
|
|
|
98
98
|
let errorDetails;
|
|
99
99
|
// Provide specific context for error messages
|
|
100
100
|
// Use validated string parameters here
|
|
101
|
-
const
|
|
102
|
-
typeof
|
|
101
|
+
const safeEnvironmentName =
|
|
102
|
+
typeof environmentName === "string"
|
|
103
|
+
? environmentName
|
|
104
|
+
: "unknown";
|
|
103
105
|
const safePackageName =
|
|
104
106
|
typeof packageName === "string" ? packageName : "unknown";
|
|
105
107
|
const safeModelPath =
|
|
106
108
|
typeof modelPath === "string" ? modelPath : "unknown";
|
|
107
109
|
|
|
108
|
-
const notFoundContext = `Model '${safeModelPath}' in package '${safePackageName}' for
|
|
109
|
-
const malloyErrorContext = `${
|
|
110
|
+
const notFoundContext = `Model '${safeModelPath}' in package '${safePackageName}' for environment '${safeEnvironmentName}'`;
|
|
111
|
+
const malloyErrorContext = `${safeEnvironmentName}/${safePackageName}/${safeModelPath}`;
|
|
110
112
|
|
|
111
113
|
if (error instanceof PackageNotFoundError) {
|
|
112
114
|
// Package not found during getPackage call
|
|
113
115
|
errorDetails = getNotFoundError(
|
|
114
|
-
`Package '${safePackageName}' in
|
|
116
|
+
`Package '${safePackageName}' in environment '${safeEnvironmentName}'`,
|
|
115
117
|
);
|
|
116
118
|
} else if (error instanceof ModelNotFoundError) {
|
|
117
119
|
// Model not found (either from getModel or type check)
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
PackageNotFoundError,
|
|
11
11
|
} from "../../errors";
|
|
12
12
|
import { logger } from "../../logger";
|
|
13
|
-
import {
|
|
13
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
14
14
|
import {
|
|
15
15
|
getInternalError,
|
|
16
16
|
getMalloyErrorDetails,
|
|
@@ -21,7 +21,7 @@ import { RESOURCE_METADATA } from "../resource_metadata";
|
|
|
21
21
|
|
|
22
22
|
// Define the expected parameter types
|
|
23
23
|
type NotebookParams = {
|
|
24
|
-
|
|
24
|
+
environmentName?: unknown;
|
|
25
25
|
packageName?: unknown;
|
|
26
26
|
notebookName?: unknown;
|
|
27
27
|
};
|
|
@@ -32,12 +32,12 @@ type NotebookParams = {
|
|
|
32
32
|
*/
|
|
33
33
|
export function registerNotebookResource(
|
|
34
34
|
mcpServer: McpServer,
|
|
35
|
-
|
|
35
|
+
environmentStore: EnvironmentStore,
|
|
36
36
|
): void {
|
|
37
37
|
mcpServer.resource(
|
|
38
38
|
"notebook",
|
|
39
39
|
new ResourceTemplate(
|
|
40
|
-
"malloy://
|
|
40
|
+
"malloy://environment/{environmentName}/package/{packageName}/notebooks/{notebookName}",
|
|
41
41
|
{ list: undefined }, // Listing notebooks is not supported via this template
|
|
42
42
|
),
|
|
43
43
|
(uri, params) =>
|
|
@@ -46,11 +46,11 @@ export function registerNotebookResource(
|
|
|
46
46
|
params as NotebookParams,
|
|
47
47
|
"notebook",
|
|
48
48
|
async (
|
|
49
|
-
{
|
|
49
|
+
{ environmentName, packageName, notebookName }: NotebookParams,
|
|
50
50
|
uri: URL,
|
|
51
51
|
) => {
|
|
52
52
|
if (
|
|
53
|
-
typeof
|
|
53
|
+
typeof environmentName !== "string" ||
|
|
54
54
|
typeof packageName !== "string" ||
|
|
55
55
|
typeof notebookName !== "string"
|
|
56
56
|
) {
|
|
@@ -59,11 +59,11 @@ export function registerNotebookResource(
|
|
|
59
59
|
|
|
60
60
|
let modelInstance;
|
|
61
61
|
try {
|
|
62
|
-
const
|
|
63
|
-
|
|
62
|
+
const environment = await environmentStore.getEnvironment(
|
|
63
|
+
environmentName,
|
|
64
64
|
false,
|
|
65
65
|
);
|
|
66
|
-
const pkg = await
|
|
66
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
67
67
|
// Get the model instance using the notebookName as the path
|
|
68
68
|
modelInstance = pkg.getModel(notebookName);
|
|
69
69
|
|
|
@@ -75,7 +75,7 @@ export function registerNotebookResource(
|
|
|
75
75
|
const isNotebookError =
|
|
76
76
|
modelInstance?.getModelType() !== "notebook";
|
|
77
77
|
const errorDetails = getNotFoundError(
|
|
78
|
-
`Notebook '${notebookName}' in package '${packageName}'
|
|
78
|
+
`Notebook '${notebookName}' in package '${packageName}' environment '${environmentName}'${
|
|
79
79
|
isNotebookError ? " (not a .malloynb file)" : ""
|
|
80
80
|
}`,
|
|
81
81
|
);
|
|
@@ -95,13 +95,13 @@ export function registerNotebookResource(
|
|
|
95
95
|
if (error instanceof PackageNotFoundError) {
|
|
96
96
|
throw new McpGetResourceError(
|
|
97
97
|
getNotFoundError(
|
|
98
|
-
`Package '${packageName}' in
|
|
98
|
+
`Package '${packageName}' in environment '${environmentName}'`,
|
|
99
99
|
),
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
// Handle ModelCompilationError from modelInstance.getModel()
|
|
103
103
|
if (error instanceof ModelCompilationError) {
|
|
104
|
-
const malloyErrorContext = `${
|
|
104
|
+
const malloyErrorContext = `${environmentName}/${packageName}/${notebookName}`;
|
|
105
105
|
throw new McpGetResourceError(
|
|
106
106
|
getMalloyErrorDetails(
|
|
107
107
|
"GetResource (notebook compilation)",
|
|
@@ -114,7 +114,7 @@ export function registerNotebookResource(
|
|
|
114
114
|
if (error instanceof ModelNotFoundError) {
|
|
115
115
|
throw new McpGetResourceError(
|
|
116
116
|
getNotFoundError(
|
|
117
|
-
`Notebook '${notebookName}' not found in package '${packageName}'
|
|
117
|
+
`Notebook '${notebookName}' not found in package '${packageName}' environment '${environmentName}'`,
|
|
118
118
|
),
|
|
119
119
|
);
|
|
120
120
|
}
|
|
@@ -6,7 +6,7 @@ import { ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
|
|
|
6
6
|
import { URL } from "url";
|
|
7
7
|
import { PackageNotFoundError } from "../../errors";
|
|
8
8
|
import { logger } from "../../logger";
|
|
9
|
-
import {
|
|
9
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
10
10
|
import {
|
|
11
11
|
getInternalError,
|
|
12
12
|
getNotFoundError,
|
|
@@ -22,20 +22,23 @@ import { RESOURCE_METADATA } from "../resource_metadata";
|
|
|
22
22
|
// *** Define handleGetPackageContents function ***
|
|
23
23
|
async function handleGetPackageContents(
|
|
24
24
|
uri: URL,
|
|
25
|
-
params: {
|
|
26
|
-
|
|
25
|
+
params: { environmentName?: string; packageName?: string },
|
|
26
|
+
environmentStore: EnvironmentStore,
|
|
27
27
|
) {
|
|
28
28
|
try {
|
|
29
|
-
const {
|
|
30
|
-
if (typeof
|
|
31
|
-
throw new Error("Invalid
|
|
29
|
+
const { environmentName, packageName } = params;
|
|
30
|
+
if (typeof environmentName !== "string" || environmentName === "") {
|
|
31
|
+
throw new Error("Invalid environment name parameter.");
|
|
32
32
|
}
|
|
33
33
|
if (typeof packageName !== "string" || packageName === "") {
|
|
34
34
|
throw new Error("Invalid package name parameter.");
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const environment = await environmentStore.getEnvironment(
|
|
38
|
+
environmentName,
|
|
39
|
+
false,
|
|
40
|
+
);
|
|
41
|
+
const packageInstance = await environment.getPackage(packageName, false);
|
|
39
42
|
|
|
40
43
|
// Use listModels() which returns { path: string, type: 'source' | 'notebook' }[]
|
|
41
44
|
const entries = await packageInstance.listModels();
|
|
@@ -58,7 +61,7 @@ async function handleGetPackageContents(
|
|
|
58
61
|
|
|
59
62
|
// Common components for URI building
|
|
60
63
|
const baseUriComponents = {
|
|
61
|
-
|
|
64
|
+
environment: environmentName,
|
|
62
65
|
package: packageName,
|
|
63
66
|
};
|
|
64
67
|
|
|
@@ -172,10 +175,10 @@ async function handleGetPackageContents(
|
|
|
172
175
|
} else if (
|
|
173
176
|
error instanceof Error &&
|
|
174
177
|
(error.message.includes("Invalid package name") ||
|
|
175
|
-
error.message.includes("Invalid
|
|
178
|
+
error.message.includes("Invalid environment name"))
|
|
176
179
|
) {
|
|
177
180
|
errorDetails = getNotFoundError(
|
|
178
|
-
`Invalid
|
|
181
|
+
`Invalid environment/package identifier in URI '${uri.href}'`,
|
|
179
182
|
);
|
|
180
183
|
} else {
|
|
181
184
|
logger.error(
|
|
@@ -197,19 +200,19 @@ async function handleGetPackageContents(
|
|
|
197
200
|
*/
|
|
198
201
|
export function registerPackageResource(
|
|
199
202
|
mcpServer: McpServer,
|
|
200
|
-
|
|
203
|
+
environmentStore: EnvironmentStore,
|
|
201
204
|
): void {
|
|
202
205
|
// Define the expected parameter type for the read callback
|
|
203
206
|
type ReadPackageParams = {
|
|
204
207
|
fsPath?: string; // Expect string
|
|
205
|
-
|
|
208
|
+
environmentName?: string; // Expect string
|
|
206
209
|
packageName?: string; // Expect string
|
|
207
210
|
};
|
|
208
211
|
|
|
209
212
|
mcpServer.resource(
|
|
210
213
|
"package",
|
|
211
214
|
new ResourceTemplate(
|
|
212
|
-
"malloy://
|
|
215
|
+
"malloy://environment/{environmentName}/package/{packageName}",
|
|
213
216
|
{
|
|
214
217
|
list: undefined, // TODO: Implement and add listAllPackages here if needed
|
|
215
218
|
},
|
|
@@ -221,26 +224,26 @@ export function registerPackageResource(
|
|
|
221
224
|
params as ReadPackageParams, // Cast params to the updated type
|
|
222
225
|
"package",
|
|
223
226
|
async ({
|
|
224
|
-
|
|
227
|
+
environmentName,
|
|
225
228
|
packageName,
|
|
226
229
|
}: {
|
|
227
230
|
// Keep unknown here as it reflects the raw input possibility
|
|
228
231
|
// before validation inside the async function
|
|
229
|
-
|
|
232
|
+
environmentName?: unknown;
|
|
230
233
|
packageName?: unknown;
|
|
231
234
|
}) => {
|
|
232
235
|
try {
|
|
233
|
-
if (typeof
|
|
234
|
-
throw new Error("Invalid
|
|
236
|
+
if (typeof environmentName !== "string") {
|
|
237
|
+
throw new Error("Invalid environment name parameter.");
|
|
235
238
|
}
|
|
236
239
|
if (typeof packageName !== "string") {
|
|
237
240
|
throw new Error("Invalid package name parameter.");
|
|
238
241
|
}
|
|
239
|
-
const
|
|
240
|
-
|
|
242
|
+
const environment = await environmentStore.getEnvironment(
|
|
243
|
+
environmentName,
|
|
241
244
|
false,
|
|
242
245
|
);
|
|
243
|
-
const pkg = await
|
|
246
|
+
const pkg = await environment.getPackage(packageName, false);
|
|
244
247
|
return pkg.getPackageMetadata();
|
|
245
248
|
} catch (error) {
|
|
246
249
|
let errorDetails;
|
|
@@ -251,10 +254,10 @@ export function registerPackageResource(
|
|
|
251
254
|
} else if (
|
|
252
255
|
error instanceof Error &&
|
|
253
256
|
(error.message.includes("Invalid package name") ||
|
|
254
|
-
error.message.includes("Invalid
|
|
257
|
+
error.message.includes("Invalid environment name"))
|
|
255
258
|
) {
|
|
256
259
|
errorDetails = getNotFoundError(
|
|
257
|
-
`Invalid
|
|
260
|
+
`Invalid environment/package identifier in URI '${uri.href}'`,
|
|
258
261
|
);
|
|
259
262
|
} else {
|
|
260
263
|
errorDetails = getInternalError(
|
|
@@ -273,7 +276,7 @@ export function registerPackageResource(
|
|
|
273
276
|
mcpServer.resource(
|
|
274
277
|
"package-contents",
|
|
275
278
|
new ResourceTemplate(
|
|
276
|
-
"malloy://
|
|
279
|
+
"malloy://environment/{environmentName}/package/{packageName}/contents",
|
|
277
280
|
{
|
|
278
281
|
// Contents are listed via GetResource on this specific URI,
|
|
279
282
|
// so no general list callback needed here.
|
|
@@ -293,7 +296,7 @@ export function registerPackageResource(
|
|
|
293
296
|
const resourceDefinitions = await handleGetPackageContents(
|
|
294
297
|
uri,
|
|
295
298
|
validatedParams,
|
|
296
|
-
|
|
299
|
+
environmentStore,
|
|
297
300
|
);
|
|
298
301
|
|
|
299
302
|
// Return the array directly as JSON content
|
|
@@ -332,11 +335,11 @@ export function registerPackageResource(
|
|
|
332
335
|
} else if (
|
|
333
336
|
error instanceof Error &&
|
|
334
337
|
(error.message.includes("Invalid package name") ||
|
|
335
|
-
error.message.includes("Invalid
|
|
338
|
+
error.message.includes("Invalid environment name"))
|
|
336
339
|
) {
|
|
337
340
|
// Handle invalid identifier errors specifically
|
|
338
341
|
errorDetails = getNotFoundError(
|
|
339
|
-
`Invalid
|
|
342
|
+
`Invalid environment/package identifier in URI '${uri.href}'`,
|
|
340
343
|
);
|
|
341
344
|
} else {
|
|
342
345
|
// Handle other unexpected errors
|
|
@@ -6,7 +6,7 @@ import { URL } from "url";
|
|
|
6
6
|
import type { components } from "../../api"; // Need this for Query definition type
|
|
7
7
|
import { ModelCompilationError } from "../../errors";
|
|
8
8
|
import { logger } from "../../logger";
|
|
9
|
-
import {
|
|
9
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
10
10
|
import {
|
|
11
11
|
getInternalError,
|
|
12
12
|
getMalloyErrorDetails,
|
|
@@ -21,7 +21,7 @@ import { RESOURCE_METADATA } from "../resource_metadata";
|
|
|
21
21
|
|
|
22
22
|
// Define the expected parameter types
|
|
23
23
|
type QueryParams = {
|
|
24
|
-
|
|
24
|
+
environmentName?: unknown;
|
|
25
25
|
packageName?: unknown;
|
|
26
26
|
modelPath?: unknown;
|
|
27
27
|
queryName?: unknown;
|
|
@@ -32,12 +32,12 @@ type QueryParams = {
|
|
|
32
32
|
*/
|
|
33
33
|
export function registerQueryResource(
|
|
34
34
|
mcpServer: McpServer,
|
|
35
|
-
|
|
35
|
+
environmentStore: EnvironmentStore,
|
|
36
36
|
): void {
|
|
37
37
|
mcpServer.resource(
|
|
38
38
|
"query",
|
|
39
39
|
new ResourceTemplate(
|
|
40
|
-
"malloy://
|
|
40
|
+
"malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}/queries/{queryName}",
|
|
41
41
|
{ list: undefined }, // Listing queries is not supported via this template
|
|
42
42
|
),
|
|
43
43
|
(uri, params) =>
|
|
@@ -46,11 +46,16 @@ export function registerQueryResource(
|
|
|
46
46
|
params as QueryParams,
|
|
47
47
|
"query",
|
|
48
48
|
async (
|
|
49
|
-
{
|
|
49
|
+
{
|
|
50
|
+
environmentName,
|
|
51
|
+
packageName,
|
|
52
|
+
modelPath,
|
|
53
|
+
queryName,
|
|
54
|
+
}: QueryParams,
|
|
50
55
|
uri: URL,
|
|
51
56
|
) => {
|
|
52
57
|
if (
|
|
53
|
-
typeof
|
|
58
|
+
typeof environmentName !== "string" ||
|
|
54
59
|
typeof packageName !== "string" ||
|
|
55
60
|
typeof modelPath !== "string" ||
|
|
56
61
|
typeof queryName !== "string"
|
|
@@ -60,8 +65,8 @@ export function registerQueryResource(
|
|
|
60
65
|
|
|
61
66
|
try {
|
|
62
67
|
const modelResult = await getModelForQuery(
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
environmentStore,
|
|
69
|
+
environmentName,
|
|
65
70
|
packageName,
|
|
66
71
|
modelPath,
|
|
67
72
|
);
|
|
@@ -83,7 +88,7 @@ export function registerQueryResource(
|
|
|
83
88
|
if (!query) {
|
|
84
89
|
// Specific "Query not found" error
|
|
85
90
|
const errorDetails = getNotFoundError(
|
|
86
|
-
`Query '${queryName}' in model '${modelPath}' package '${packageName}'
|
|
91
|
+
`Query '${queryName}' in model '${modelPath}' package '${packageName}' environment '${environmentName}'`,
|
|
87
92
|
);
|
|
88
93
|
throw new McpGetResourceError(errorDetails);
|
|
89
94
|
}
|
|
@@ -95,7 +100,7 @@ export function registerQueryResource(
|
|
|
95
100
|
if (error instanceof ModelCompilationError) {
|
|
96
101
|
const errorDetails = getMalloyErrorDetails(
|
|
97
102
|
"GetResource (query - model compilation)",
|
|
98
|
-
`${
|
|
103
|
+
`${environmentName}/${packageName}/${modelPath}`,
|
|
99
104
|
error,
|
|
100
105
|
);
|
|
101
106
|
throw new McpGetResourceError(errorDetails);
|
|
@@ -6,7 +6,7 @@ import { URL } from "url";
|
|
|
6
6
|
import type { components } from "../../api";
|
|
7
7
|
import { ModelCompilationError } from "../../errors";
|
|
8
8
|
import { logger } from "../../logger";
|
|
9
|
-
import {
|
|
9
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
10
10
|
import {
|
|
11
11
|
getInternalError,
|
|
12
12
|
getMalloyErrorDetails,
|
|
@@ -21,7 +21,7 @@ import { RESOURCE_METADATA } from "../resource_metadata";
|
|
|
21
21
|
|
|
22
22
|
// Define the expected parameter types for this resource
|
|
23
23
|
type SourceParams = {
|
|
24
|
-
|
|
24
|
+
environmentName?: unknown;
|
|
25
25
|
packageName?: unknown;
|
|
26
26
|
modelPath?: unknown;
|
|
27
27
|
sourceName?: unknown;
|
|
@@ -33,12 +33,12 @@ type SourceParams = {
|
|
|
33
33
|
*/
|
|
34
34
|
export function registerSourceResource(
|
|
35
35
|
mcpServer: McpServer,
|
|
36
|
-
|
|
36
|
+
environmentStore: EnvironmentStore,
|
|
37
37
|
): void {
|
|
38
38
|
mcpServer.resource(
|
|
39
39
|
"source",
|
|
40
40
|
new ResourceTemplate(
|
|
41
|
-
"malloy://
|
|
41
|
+
"malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}/sources/{sourceName}",
|
|
42
42
|
{ list: undefined }, // Listing sources directly is not supported via this template
|
|
43
43
|
),
|
|
44
44
|
/** Handles GetResource requests for specific Sources within a Model */
|
|
@@ -50,7 +50,7 @@ export function registerSourceResource(
|
|
|
50
50
|
// Define the getData async callback
|
|
51
51
|
async (
|
|
52
52
|
{
|
|
53
|
-
|
|
53
|
+
environmentName,
|
|
54
54
|
packageName,
|
|
55
55
|
modelPath,
|
|
56
56
|
sourceName,
|
|
@@ -60,7 +60,7 @@ export function registerSourceResource(
|
|
|
60
60
|
) => {
|
|
61
61
|
// Input validation
|
|
62
62
|
if (
|
|
63
|
-
typeof
|
|
63
|
+
typeof environmentName !== "string" ||
|
|
64
64
|
typeof packageName !== "string" ||
|
|
65
65
|
typeof modelPath !== "string" ||
|
|
66
66
|
typeof sourceName !== "string"
|
|
@@ -72,8 +72,8 @@ export function registerSourceResource(
|
|
|
72
72
|
try {
|
|
73
73
|
// Use the imported getModelForQuery
|
|
74
74
|
const modelResult = await getModelForQuery(
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
environmentStore,
|
|
76
|
+
environmentName,
|
|
77
77
|
packageName,
|
|
78
78
|
modelPath,
|
|
79
79
|
);
|
|
@@ -96,7 +96,7 @@ export function registerSourceResource(
|
|
|
96
96
|
|
|
97
97
|
if (!source) {
|
|
98
98
|
const errorDetails = getNotFoundError(
|
|
99
|
-
`Source '${sourceName}' in model '${modelPath}' package '${packageName}'
|
|
99
|
+
`Source '${sourceName}' in model '${modelPath}' package '${packageName}' environment '${environmentName}'`,
|
|
100
100
|
);
|
|
101
101
|
throw new McpGetResourceError(errorDetails);
|
|
102
102
|
}
|
|
@@ -116,7 +116,7 @@ export function registerSourceResource(
|
|
|
116
116
|
if (error instanceof ModelCompilationError) {
|
|
117
117
|
const errorDetails = getMalloyErrorDetails(
|
|
118
118
|
"GetResource (source - model compilation)",
|
|
119
|
-
`${
|
|
119
|
+
`${environmentName}/${packageName}/${modelPath}`,
|
|
120
120
|
error,
|
|
121
121
|
);
|
|
122
122
|
throw new McpGetResourceError(errorDetails);
|
|
@@ -6,7 +6,7 @@ import { URL } from "url";
|
|
|
6
6
|
import type { components } from "../../api"; // Need this for View definition type
|
|
7
7
|
import { ModelCompilationError } from "../../errors";
|
|
8
8
|
import { logger } from "../../logger";
|
|
9
|
-
import {
|
|
9
|
+
import { EnvironmentStore } from "../../service/environment_store";
|
|
10
10
|
import {
|
|
11
11
|
getInternalError,
|
|
12
12
|
getMalloyErrorDetails,
|
|
@@ -21,7 +21,7 @@ import { RESOURCE_METADATA } from "../resource_metadata";
|
|
|
21
21
|
|
|
22
22
|
// Define the expected parameter types
|
|
23
23
|
type ViewParams = {
|
|
24
|
-
|
|
24
|
+
environmentName?: unknown;
|
|
25
25
|
packageName?: unknown;
|
|
26
26
|
modelPath?: unknown;
|
|
27
27
|
sourceName?: unknown;
|
|
@@ -33,12 +33,12 @@ type ViewParams = {
|
|
|
33
33
|
*/
|
|
34
34
|
export function registerViewResource(
|
|
35
35
|
mcpServer: McpServer,
|
|
36
|
-
|
|
36
|
+
environmentStore: EnvironmentStore,
|
|
37
37
|
): void {
|
|
38
38
|
mcpServer.resource(
|
|
39
39
|
"view",
|
|
40
40
|
new ResourceTemplate(
|
|
41
|
-
"malloy://
|
|
41
|
+
"malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}/sources/{sourceName}/views/{viewName}",
|
|
42
42
|
{ list: undefined }, // Listing views is not supported via this template
|
|
43
43
|
),
|
|
44
44
|
(uri, params) =>
|
|
@@ -48,7 +48,7 @@ export function registerViewResource(
|
|
|
48
48
|
"view",
|
|
49
49
|
async (
|
|
50
50
|
{
|
|
51
|
-
|
|
51
|
+
environmentName,
|
|
52
52
|
packageName,
|
|
53
53
|
modelPath,
|
|
54
54
|
sourceName,
|
|
@@ -57,7 +57,7 @@ export function registerViewResource(
|
|
|
57
57
|
uri: URL,
|
|
58
58
|
) => {
|
|
59
59
|
if (
|
|
60
|
-
typeof
|
|
60
|
+
typeof environmentName !== "string" ||
|
|
61
61
|
typeof packageName !== "string" ||
|
|
62
62
|
typeof modelPath !== "string" ||
|
|
63
63
|
typeof sourceName !== "string" ||
|
|
@@ -68,8 +68,8 @@ export function registerViewResource(
|
|
|
68
68
|
|
|
69
69
|
try {
|
|
70
70
|
const modelResult = await getModelForQuery(
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
environmentStore,
|
|
72
|
+
environmentName,
|
|
73
73
|
packageName,
|
|
74
74
|
modelPath,
|
|
75
75
|
);
|
|
@@ -89,7 +89,7 @@ export function registerViewResource(
|
|
|
89
89
|
if (!source) {
|
|
90
90
|
throw new McpGetResourceError(
|
|
91
91
|
getNotFoundError(
|
|
92
|
-
`Source '${sourceName}' in model '${modelPath}' package '${packageName}'
|
|
92
|
+
`Source '${sourceName}' in model '${modelPath}' package '${packageName}' environment '${environmentName}'`,
|
|
93
93
|
),
|
|
94
94
|
);
|
|
95
95
|
}
|
|
@@ -102,7 +102,7 @@ export function registerViewResource(
|
|
|
102
102
|
if (!view) {
|
|
103
103
|
// Specific "View not found" error
|
|
104
104
|
const errorDetails = getNotFoundError(
|
|
105
|
-
`View '${viewName}' in source '${sourceName}' model '${modelPath}' package '${packageName}'
|
|
105
|
+
`View '${viewName}' in source '${sourceName}' model '${modelPath}' package '${packageName}' environment '${environmentName}'`,
|
|
106
106
|
);
|
|
107
107
|
throw new McpGetResourceError(errorDetails);
|
|
108
108
|
}
|
|
@@ -114,7 +114,7 @@ export function registerViewResource(
|
|
|
114
114
|
if (error instanceof ModelCompilationError) {
|
|
115
115
|
const errorDetails = getMalloyErrorDetails(
|
|
116
116
|
"GetResource (view - model compilation)",
|
|
117
|
-
`${
|
|
117
|
+
`${environmentName}/${packageName}/${modelPath}`,
|
|
118
118
|
error,
|
|
119
119
|
);
|
|
120
120
|
throw new McpGetResourceError(errorDetails);
|