@malloy-publisher/server 0.0.225 → 0.0.227

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +2 -11
  2. package/dist/app/api-doc.yaml +29 -24
  3. package/dist/app/assets/{EnvironmentPage-DYTeXDll.js → EnvironmentPage-DvOJ7L_b.js} +1 -1
  4. package/dist/app/assets/{HomePage-pDK2BPJY.js → HomePage-CXguJsXS.js} +1 -1
  5. package/dist/app/assets/{LightMode-C2bwGPY1.js → LightMode-ZsshUznu.js} +1 -1
  6. package/dist/app/assets/{MainPage-WtBulMH_.js → MainPage-BIe0VwBa.js} +2 -2
  7. package/dist/app/assets/{MaterializationsPage-hMgOtflG.js → MaterializationsPage-BuZ6UJVx.js} +1 -1
  8. package/dist/app/assets/{ModelPage-B2N5kYII.js → ModelPage-DsPf-s8B.js} +1 -1
  9. package/dist/app/assets/{PackagePage-CEN90nQG.js → PackagePage-CEVNAKZa.js} +1 -1
  10. package/dist/app/assets/{RouteError-BG2c5Zf0.js → RouteError-Chn7lL96.js} +1 -1
  11. package/dist/app/assets/{ThemeEditorPage-DNfeUwEZ.js → ThemeEditorPage-DWC_FdNU.js} +1 -1
  12. package/dist/app/assets/{WorkbookPage-NKI1BhFS.js → WorkbookPage-CGrsFz8p.js} +1 -1
  13. package/dist/app/assets/{core-C6anj5c0.es-DDLHqpzt.js → core-vVgoO8IR.es-BD_THWs_.js} +1 -1
  14. package/dist/app/assets/{index-DMQtnaf4.js → index-BioohWQj.js} +1 -1
  15. package/dist/app/assets/{index-CzNqKMVl.js → index-D6YtyiJ0.js} +1 -1
  16. package/dist/app/assets/{index-C6gZ6sSY.js → index-DNUZpnaa.js} +4 -4
  17. package/dist/app/assets/{index-JXgvyZna.js → index-gEWxu09x.js} +1 -1
  18. package/dist/app/index.html +1 -1
  19. package/dist/instrumentation.mjs +71 -15
  20. package/dist/package_load_worker.mjs +169 -40
  21. package/dist/server.mjs +782 -7050
  22. package/package.json +1 -4
  23. package/src/controller/package.controller.spec.ts +17 -17
  24. package/src/controller/package.controller.ts +7 -6
  25. package/src/health.ts +3 -8
  26. package/src/logger.spec.ts +193 -0
  27. package/src/logger.ts +115 -18
  28. package/src/mcp/error_messages.ts +8 -37
  29. package/src/mcp/handler_utils.ts +10 -129
  30. package/src/mcp/mcp_constants.ts +0 -16
  31. package/src/mcp/{agent_server.protocol.spec.ts → server.protocol.spec.ts} +14 -12
  32. package/src/mcp/server.ts +29 -37
  33. package/src/mcp/skills/build_skills_bundle.ts +1 -1
  34. package/src/mcp/skills/skills_bundle.json +1 -1
  35. package/src/mcp/tools/docs_search_tool.ts +1 -1
  36. package/src/mcp/tools/execute_query_tool.ts +2 -2
  37. package/src/mcp/tools/get_context_eval.ts +3 -3
  38. package/src/mcp/tools/get_context_tool.spec.ts +196 -1
  39. package/src/mcp/tools/get_context_tool.ts +165 -67
  40. package/src/package_load/package_load_pool.ts +8 -1
  41. package/src/package_load/package_load_worker.ts +75 -24
  42. package/src/package_load/protocol.ts +21 -1
  43. package/src/package_load/rpc_wait_accountant.spec.ts +109 -0
  44. package/src/package_load/rpc_wait_accountant.ts +76 -0
  45. package/src/package_load_metrics.spec.ts +114 -0
  46. package/src/package_load_metrics.ts +127 -0
  47. package/src/pg_helpers.spec.ts +2 -206
  48. package/src/pg_helpers.ts +4 -120
  49. package/src/server.ts +0 -16
  50. package/src/service/build_plan.spec.ts +42 -60
  51. package/src/service/build_plan.ts +37 -61
  52. package/src/service/environment.ts +5 -1
  53. package/src/service/materialization_test_fixtures.ts +6 -8
  54. package/src/service/package.ts +165 -86
  55. package/src/service/package_manifest.spec.ts +22 -1
  56. package/src/service/package_manifest.ts +29 -0
  57. package/src/service/persistence_policy.spec.ts +234 -0
  58. package/src/test_helpers/metrics_harness.ts +40 -0
  59. package/tests/harness/mcp_test_setup.ts +1 -1
  60. package/tests/integration/mcp/mcp_transport.integration.spec.ts +7 -31
  61. package/tests/integration/watch-mode/watch_mode.integration.spec.ts +0 -6
  62. package/dxt/malloy_bridge.py +0 -354
  63. package/dxt/manifest.json +0 -22
  64. package/src/dto/connection.dto.spec.ts +0 -186
  65. package/src/dto/connection.dto.ts +0 -308
  66. package/src/dto/index.ts +0 -2
  67. package/src/dto/package.dto.spec.ts +0 -42
  68. package/src/dto/package.dto.ts +0 -27
  69. package/src/dto/validate.spec.ts +0 -76
  70. package/src/dto/validate.ts +0 -31
  71. package/src/ducklake_version.spec.ts +0 -43
  72. package/src/ducklake_version.ts +0 -26
  73. package/src/mcp/agent_server.spec.ts +0 -18
  74. package/src/mcp/agent_server.ts +0 -144
  75. package/src/mcp/prompts/handlers.ts +0 -84
  76. package/src/mcp/prompts/index.ts +0 -11
  77. package/src/mcp/prompts/prompt_definitions.ts +0 -160
  78. package/src/mcp/prompts/prompt_service.ts +0 -67
  79. package/src/mcp/prompts/utils.ts +0 -62
  80. package/src/mcp/resource_metadata.ts +0 -47
  81. package/src/mcp/resources/environment_resource.ts +0 -187
  82. package/src/mcp/resources/model_resource.ts +0 -155
  83. package/src/mcp/resources/notebook_resource.ts +0 -137
  84. package/src/mcp/resources/package_resource.ts +0 -373
  85. package/src/mcp/resources/query_resource.ts +0 -122
  86. package/src/mcp/resources/source_resource.ts +0 -141
  87. package/src/mcp/resources/view_resource.ts +0 -136
  88. package/src/mcp/tools/discovery_tools.ts +0 -280
  89. package/src/service/materialization_cron_gate.spec.ts +0 -181
  90. package/src/storage/BaseRepository.ts +0 -31
  91. package/src/storage/StorageManager.mock.ts +0 -50
  92. package/tests/harness/e2e.ts +0 -96
  93. package/tests/harness/mocks.ts +0 -39
  94. package/tests/harness/uris.ts +0 -31
  95. package/tests/integration/mcp/mcp_resource.integration.spec.ts +0 -655
  96. package/tests/integration/mcp/setup.spec.ts +0 -5
  97. package/tests/unit/mcp/prompt_definitions.test.ts +0 -102
  98. package/tests/unit/mcp/prompt_happy.test.ts +0 -51
@@ -1,187 +0,0 @@
1
- import {
2
- McpServer,
3
- ResourceTemplate,
4
- } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import type { ListResourcesResult } from "@modelcontextprotocol/sdk/types.js"; // Needed for list return type
6
- import { logger } from "../../logger";
7
- import { EnvironmentStore } from "../../service/environment_store";
8
- import { getInternalError, getNotFoundError } from "../error_messages"; // Needed for error handling in list AND get
9
- import { handleResourceGet, McpGetResourceError } from "../handler_utils";
10
- import { RESOURCE_METADATA } from "../resource_metadata";
11
-
12
- // Define an interface for the package object augmented with environment name
13
- interface PackageWithEnvironment {
14
- name?: string;
15
- // Add other relevant package properties if needed
16
- environmentName: string;
17
- }
18
-
19
- /**
20
- * Registers the Malloy environment resource type with the MCP server (URI scheme malloy://environment/...).
21
- * Lists packages across environments and resolves environment metadata on read.
22
- */
23
- export function registerEnvironmentResource(
24
- mcpServer: McpServer,
25
- environmentStore: EnvironmentStore,
26
- ): void {
27
- mcpServer.resource(
28
- "environment",
29
- new ResourceTemplate("malloy://environment/{environmentName}", {
30
- /**
31
- * Handles ListResources requests.
32
- * If environmentName is specified, lists packages for that environment (only 'home' supported).
33
- * If environmentName is not specified (general ListResources call), lists packages for the default 'home' environment.
34
- */
35
- list: async (/* extra: ListEnvironmentExtra - Deleted */): Promise<ListResourcesResult> => {
36
- logger.info(
37
- "[MCP LOG] Entering ListResources (environment) handler (listing ALL packages)...",
38
- );
39
- // Ignore parameters from 'extra' as URI path params aren't passed to list handlers.
40
-
41
- try {
42
- const allEnvironments =
43
- await environmentStore.listEnvironments();
44
- logger.info(
45
- `[MCP LOG] Found ${allEnvironments.length} environments defined.`,
46
- );
47
-
48
- const packagePromises = allEnvironments.map(async (env) => {
49
- try {
50
- logger.info(
51
- `[MCP LOG] Getting environment '${env.name}' to list its packages...`,
52
- );
53
- const environmentInstance =
54
- await environmentStore.getEnvironment(env.name!, false);
55
- const packages = await environmentInstance.listPackages();
56
- logger.info(
57
- `[MCP LOG] Found ${packages.length} packages in environment '${env.name}'.`,
58
- );
59
- // Return packages along with their environment name for URI construction
60
- return packages.map((pkg) => ({
61
- ...pkg,
62
- environmentName: env.name,
63
- }));
64
- } catch (environmentError) {
65
- logger.error(
66
- `[MCP Server Error] Error getting/listing packages for environment ${env.name}:`,
67
- { error: environmentError },
68
- );
69
- return []; // Return empty array for this environment on error
70
- }
71
- });
72
-
73
- const results = await Promise.allSettled(packagePromises);
74
- const allPackagesWithEnvironmentName = results
75
- .filter((result) => result.status === "fulfilled")
76
- .flatMap(
77
- (result) =>
78
- (
79
- result as PromiseFulfilledResult<
80
- PackageWithEnvironment[]
81
- >
82
- ).value,
83
- );
84
-
85
- logger.info(
86
- `[MCP LOG] Total packages found across all environments: ${allPackagesWithEnvironmentName.length}`,
87
- );
88
-
89
- const packageMetadata = RESOURCE_METADATA.package;
90
- const mappedResources = allPackagesWithEnvironmentName.map(
91
- (pkg) => {
92
- const name = pkg.name || "unknown";
93
- // Construct URI using the package's specific environmentName
94
- const uri = `malloy://environment/${pkg.environmentName}/package/${name}`;
95
- return {
96
- uri: uri,
97
- name: name,
98
- type: "package",
99
- description: packageMetadata?.description as
100
- | string
101
- | undefined,
102
- metadata: packageMetadata,
103
- };
104
- },
105
- );
106
-
107
- logger.info(
108
- `[MCP LOG] ListResources (environment): Returning ${mappedResources.length} package resources.`,
109
- );
110
- return {
111
- resources: mappedResources,
112
- };
113
- } catch (error) {
114
- // Catch errors from environmentStore.listEnvironments() itself
115
- logger.error(`[MCP Server Error] Error listing environments:`, {
116
- error,
117
- });
118
- const errorDetails = getInternalError(
119
- `ListResources (environment - initial list)`,
120
- error,
121
- );
122
- logger.error("MCP ListResources (environment) error:", {
123
- error: errorDetails.message,
124
- });
125
- logger.info(
126
- "[MCP LOG] ListResources (environment): Returning empty on error listing environments.",
127
- );
128
- return { resources: [] };
129
- }
130
- },
131
- }),
132
- /** Handles GetResource requests for Malloy environments */
133
- (uri, params) =>
134
- handleResourceGet(
135
- uri,
136
- params,
137
- "environment",
138
- async ({ environmentName }: { environmentName?: unknown }) => {
139
- logger.info(
140
- `[MCP LOG] Entering GetResource (environment) handler for environmentName: ${environmentName}`,
141
- );
142
- // Validate environment name parameter
143
- if (typeof environmentName !== "string") {
144
- logger.error(
145
- "[MCP LOG] GetResource (environment): Invalid environment name param.",
146
- );
147
- throw new Error("Invalid environment name parameter.");
148
- }
149
-
150
- try {
151
- logger.info(
152
- `[MCP LOG] GetResource: Getting environment '${environmentName}'...`,
153
- );
154
- // Get the environment instance, but we might not need its metadata directly
155
- await environmentStore.getEnvironment(environmentName, false);
156
- // Construct the definition object expected by the test
157
- const definition = { name: environmentName };
158
- logger.info(
159
- `[MCP LOG] GetResource (environment): Returning definition for '${environmentName}'.`,
160
- );
161
- // Return the explicit definition structure
162
- return definition;
163
- } catch (error) {
164
- logger.error(
165
- `[MCP LOG] GetResource (environment): Error caught for '${environmentName}':`,
166
- { error },
167
- );
168
- // Catch expected errors from this specific resource logic
169
- if (error instanceof Error) {
170
- // Use getNotFoundError for the specific environment not found case
171
- // or a generic message for the invalid param case.
172
- const errorDetails = getNotFoundError(
173
- error.message.includes("not found")
174
- ? `Environment '${environmentName}'` // More specific context
175
- : `Invalid environment identifier provided for URI ${uri.href}`, // Generic but informative
176
- );
177
- // Re-throw structured error for handleResourceGet to catch
178
- throw new McpGetResourceError(errorDetails);
179
- }
180
- // Re-throw unexpected errors to be caught by handleResourceGet's generic handler
181
- throw error;
182
- }
183
- },
184
- RESOURCE_METADATA.environment,
185
- ),
186
- );
187
- }
@@ -1,155 +0,0 @@
1
- import {
2
- McpServer,
3
- ResourceTemplate,
4
- } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import { EnvironmentStore } from "../../service/environment_store";
6
- import {
7
- ModelNotFoundError,
8
- PackageNotFoundError,
9
- ModelCompilationError,
10
- } from "../../errors";
11
- import { handleResourceGet, McpGetResourceError } from "../handler_utils";
12
- import { RESOURCE_METADATA } from "../resource_metadata";
13
- import {
14
- getNotFoundError,
15
- getMalloyErrorDetails,
16
- getInternalError,
17
- } from "../error_messages";
18
- import type { components } from "../../api"; // Import the components type
19
-
20
- /**
21
- * Registers the Malloy Model resource type with the MCP server.
22
- * Handles getting details for a specific model.
23
- */
24
- export function registerModelResource(
25
- mcpServer: McpServer,
26
- environmentStore: EnvironmentStore,
27
- ): void {
28
- mcpServer.resource(
29
- "model",
30
- new ResourceTemplate(
31
- "malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}",
32
- { list: undefined }, // No list handler for individual models
33
- ),
34
- /** Handles GetResource requests for specific Malloy Models */
35
- (uri, params) =>
36
- handleResourceGet(
37
- uri,
38
- params,
39
- "model",
40
- async ({
41
- environmentName,
42
- packageName,
43
- modelPath,
44
- }: {
45
- environmentName?: unknown;
46
- packageName?: unknown;
47
- modelPath?: unknown;
48
- }) => {
49
- try {
50
- // Validate all parameters
51
- if (typeof environmentName !== "string") {
52
- throw new Error("Invalid environment name parameter.");
53
- }
54
- if (typeof packageName !== "string") {
55
- throw new Error("Invalid package name parameter.");
56
- }
57
- if (typeof modelPath !== "string") {
58
- throw new Error("Invalid model path parameter.");
59
- }
60
-
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
- false,
66
- );
67
- // getPackage can throw PackageNotFoundError
68
- const pkg = await environment.getPackage(packageName, false);
69
- // getModel is SYNCHRONOUS
70
- const modelInstance = pkg.getModel(modelPath);
71
- // *** END UPDATED LOGIC ***
72
-
73
- if (
74
- !modelInstance ||
75
- modelInstance.getModelType() === "notebook"
76
- ) {
77
- // Explicitly throw the expected error if not found or wrong type
78
- throw new ModelNotFoundError(modelPath);
79
- }
80
-
81
- // modelInstance.getModel() is ASYNC and can throw ModelCompilationError
82
- const compiledModelDefinition: components["schemas"]["CompiledModel"] =
83
- await modelInstance.getModel();
84
-
85
- // Strip implicit filters from agent-facing responses
86
- if (compiledModelDefinition.sources) {
87
- for (const source of compiledModelDefinition.sources) {
88
- if (source.filters) {
89
- source.filters = source.filters.filter(
90
- (f) => !f.implicit,
91
- );
92
- }
93
- }
94
- }
95
-
96
- return compiledModelDefinition;
97
- } catch (error) {
98
- let errorDetails;
99
- // Provide specific context for error messages
100
- // Use validated string parameters here
101
- const safeEnvironmentName =
102
- typeof environmentName === "string"
103
- ? environmentName
104
- : "unknown";
105
- const safePackageName =
106
- typeof packageName === "string" ? packageName : "unknown";
107
- const safeModelPath =
108
- typeof modelPath === "string" ? modelPath : "unknown";
109
-
110
- const notFoundContext = `Model '${safeModelPath}' in package '${safePackageName}' for environment '${safeEnvironmentName}'`;
111
- const malloyErrorContext = `${safeEnvironmentName}/${safePackageName}/${safeModelPath}`;
112
-
113
- if (error instanceof PackageNotFoundError) {
114
- // Package not found during getPackage call
115
- errorDetails = getNotFoundError(
116
- `Package '${safePackageName}' in environment '${safeEnvironmentName}'`,
117
- );
118
- } else if (error instanceof ModelNotFoundError) {
119
- // Model not found (either from getModel or type check)
120
- errorDetails = getNotFoundError(notFoundContext);
121
- } else if (error instanceof ModelCompilationError) {
122
- // Compilation error when fetching model definition
123
- errorDetails = getMalloyErrorDetails(
124
- "GetResource (model)",
125
- malloyErrorContext,
126
- error,
127
- );
128
- } else if (error instanceof Error) {
129
- // Catch invalid param errors or other generic errors
130
- // Provide a clearer message differentiating param errors
131
- if (error.message.includes("parameter")) {
132
- errorDetails = getNotFoundError(
133
- `Invalid identifier parameter provided for URI ${uri.href}: ${error.message}`,
134
- );
135
- } else {
136
- errorDetails = getInternalError(
137
- "GetResource (model) - Unexpected Error",
138
- error,
139
- );
140
- }
141
- } else {
142
- // Fallback for truly unexpected non-Error throws
143
- errorDetails = getInternalError(
144
- "GetResource (model)",
145
- error,
146
- );
147
- }
148
- // Wrap and re-throw for handleResourceGet
149
- throw new McpGetResourceError(errorDetails);
150
- }
151
- },
152
- RESOURCE_METADATA.model,
153
- ),
154
- );
155
- }
@@ -1,137 +0,0 @@
1
- import {
2
- McpServer,
3
- ResourceTemplate,
4
- } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import { URL } from "url";
6
- import type { components } from "../../api"; // Need this for CompiledModel type
7
- import {
8
- ModelCompilationError,
9
- ModelNotFoundError,
10
- PackageNotFoundError,
11
- } from "../../errors";
12
- import { logger } from "../../logger";
13
- import { EnvironmentStore } from "../../service/environment_store";
14
- import {
15
- getInternalError,
16
- getMalloyErrorDetails,
17
- getNotFoundError,
18
- } from "../error_messages";
19
- import { handleResourceGet, McpGetResourceError } from "../handler_utils";
20
- import { RESOURCE_METADATA } from "../resource_metadata";
21
-
22
- // Define the expected parameter types
23
- type NotebookParams = {
24
- environmentName?: unknown;
25
- packageName?: unknown;
26
- notebookName?: unknown;
27
- };
28
-
29
- /**
30
- * Registers the Malloy Notebook resource type.
31
- * Handles getting details for a specific notebook.
32
- */
33
- export function registerNotebookResource(
34
- mcpServer: McpServer,
35
- environmentStore: EnvironmentStore,
36
- ): void {
37
- mcpServer.resource(
38
- "notebook",
39
- new ResourceTemplate(
40
- "malloy://environment/{environmentName}/package/{packageName}/notebooks/{notebookName}",
41
- { list: undefined }, // Listing notebooks is not supported via this template
42
- ),
43
- (uri, params) =>
44
- handleResourceGet(
45
- uri,
46
- params as NotebookParams,
47
- "notebook",
48
- async (
49
- { environmentName, packageName, notebookName }: NotebookParams,
50
- uri: URL,
51
- ) => {
52
- if (
53
- typeof environmentName !== "string" ||
54
- typeof packageName !== "string" ||
55
- typeof notebookName !== "string"
56
- ) {
57
- throw new Error("Invalid parameters for notebook resource.");
58
- }
59
-
60
- let modelInstance;
61
- try {
62
- const environment = await environmentStore.getEnvironment(
63
- environmentName,
64
- false,
65
- );
66
- const pkg = await environment.getPackage(packageName, false);
67
- // Get the model instance using the notebookName as the path
68
- modelInstance = pkg.getModel(notebookName);
69
-
70
- // Check if it exists and is actually a notebook
71
- if (
72
- !modelInstance ||
73
- modelInstance.getModelType() !== "notebook"
74
- ) {
75
- const isNotebookError =
76
- modelInstance?.getModelType() !== "notebook";
77
- const errorDetails = getNotFoundError(
78
- `Notebook '${notebookName}' in package '${packageName}' environment '${environmentName}'${
79
- isNotebookError ? " (not a .malloynb file)" : ""
80
- }`,
81
- );
82
- throw new McpGetResourceError(errorDetails);
83
- }
84
-
85
- // Now try to get the actual notebook content
86
- const notebookContent: components["schemas"]["RawNotebook"] =
87
- await modelInstance.getNotebook();
88
- return notebookContent;
89
- } catch (error) {
90
- if (error instanceof McpGetResourceError) {
91
- throw error; // Re-throw if already formatted by checks above
92
- }
93
-
94
- // Handle specific errors like PackageNotFoundError or ModelCompilationError
95
- if (error instanceof PackageNotFoundError) {
96
- throw new McpGetResourceError(
97
- getNotFoundError(
98
- `Package '${packageName}' in environment '${environmentName}'`,
99
- ),
100
- );
101
- }
102
- // Handle ModelCompilationError from modelInstance.getModel()
103
- if (error instanceof ModelCompilationError) {
104
- const malloyErrorContext = `${environmentName}/${packageName}/${notebookName}`;
105
- throw new McpGetResourceError(
106
- getMalloyErrorDetails(
107
- "GetResource (notebook compilation)",
108
- malloyErrorContext,
109
- error,
110
- ),
111
- );
112
- }
113
- // Handle ModelNotFoundError specifically from pkg.getModel()
114
- if (error instanceof ModelNotFoundError) {
115
- throw new McpGetResourceError(
116
- getNotFoundError(
117
- `Notebook '${notebookName}' not found in package '${packageName}' environment '${environmentName}'`,
118
- ),
119
- );
120
- }
121
-
122
- // Handle other unexpected errors
123
- logger.error(
124
- `[MCP Server Error] Error fetching notebook '${notebookName}' from ${uri.href}:`,
125
- { error },
126
- );
127
- const fallbackErrorDetails = getInternalError(
128
- `GetResource (notebook: ${uri.href})`,
129
- error,
130
- );
131
- throw new McpGetResourceError(fallbackErrorDetails);
132
- }
133
- },
134
- RESOURCE_METADATA.notebook,
135
- ),
136
- );
137
- }