@malloy-publisher/server 0.0.382-dev → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.docker.md +145 -20
  2. package/README.md +65 -12
  3. package/dist/app/api-doc.html +5 -0
  4. package/dist/app/api-doc.yaml +3903 -583
  5. package/dist/app/assets/EnvironmentPage-DiUgLuCH.js +1 -0
  6. package/dist/app/assets/HomePage-MhhjhnFj.js +1 -0
  7. package/dist/app/assets/LightMode-BEyvNUzT.js +1 -0
  8. package/dist/app/assets/MainPage-D4Cfee9o.js +2 -0
  9. package/dist/app/assets/MaterializationsPage-nGgGqwSN.js +1 -0
  10. package/dist/app/assets/ModelPage-DLAcEw-F.js +1 -0
  11. package/dist/app/assets/PackagePage-Df0ikH7w.js +1 -0
  12. package/dist/app/assets/RouteError-BFQwtroH.js +1 -0
  13. package/dist/app/assets/ThemeEditorPage-OoskoQYN.js +1 -0
  14. package/dist/app/assets/WorkbookPage-CpFgvUDC.js +1 -0
  15. package/dist/app/assets/{core-CjeTkq8O.es-BqRc6yhC.js → core-lb28vQkR.es-BoVSOc75.js} +1 -1
  16. package/dist/app/assets/github-dark-DenFmJkN.es-DHJKELXO.js +1 -0
  17. package/dist/app/assets/index-5eLCcNmP.css +1 -0
  18. package/dist/app/assets/index-6ypuFH6g.js +1774 -0
  19. package/dist/app/assets/index-B8pnU_V_.js +615 -0
  20. package/dist/app/assets/index-BImcHmVP.js +1 -0
  21. package/dist/app/assets/index-DSoCUF-f.js +2725 -0
  22. package/dist/app/assets/index-DfqzSItA.js +2 -0
  23. package/dist/app/assets/index-w_0OQJgZ.js +23 -0
  24. package/dist/app/index.html +8 -4
  25. package/dist/cpufeatures-1yrn0vtw.node +0 -0
  26. package/dist/default-publisher.config.json +23 -0
  27. package/dist/{instrumentation.js → instrumentation.mjs} +10631 -10573
  28. package/dist/package_load_worker.mjs +15219 -0
  29. package/dist/runtime/publisher.js +331 -0
  30. package/dist/{server.js → server.mjs} +115548 -49590
  31. package/dist/sshcrypto-vd2k5hq9.node +0 -0
  32. package/package.json +41 -28
  33. package/publisher.config.example.bigquery.json +33 -0
  34. package/publisher.config.example.duckdb.json +23 -0
  35. package/.eslintrc.json +0 -44
  36. package/.prettierignore +0 -1
  37. package/.prettierrc +0 -4
  38. package/build.ts +0 -38
  39. package/dist/app/assets/HomePage-Dn3E4CuB.js +0 -1
  40. package/dist/app/assets/MainPage-BzB3yoqi.js +0 -2
  41. package/dist/app/assets/ModelPage-C9O_sAXT.js +0 -1
  42. package/dist/app/assets/PackagePage-DcxKEjBX.js +0 -1
  43. package/dist/app/assets/ProjectPage-BDj307rF.js +0 -1
  44. package/dist/app/assets/RouteError-DAShbVCG.js +0 -1
  45. package/dist/app/assets/WorkbookPage-Cs_XYEaB.js +0 -1
  46. package/dist/app/assets/index-15BOvhp0.js +0 -456
  47. package/dist/app/assets/index-Bb2jqquW.js +0 -676
  48. package/dist/app/assets/index-CMlGQMcl.css +0 -1
  49. package/dist/app/assets/index-D68X76-7.js +0 -1276
  50. package/dist/app/assets/index.umd-DGBekgSu.js +0 -1145
  51. package/dxt/malloy_bridge.py +0 -354
  52. package/dxt/manifest.json +0 -22
  53. package/eslint.config.mjs +0 -76
  54. package/k6-tests/README.md +0 -144
  55. package/k6-tests/bun.lock +0 -797
  56. package/k6-tests/load-test/load-test-crud-connections.ts +0 -263
  57. package/k6-tests/load-test/load-test-crud-packages.ts +0 -461
  58. package/k6-tests/load-test/load-test-crud-projects.ts +0 -160
  59. package/k6-tests/load-test/load-test-crud.ts +0 -142
  60. package/k6-tests/load-test/load-test.ts +0 -784
  61. package/k6-tests/package.json +0 -27
  62. package/k6-tests/scripts/run-with-otel.sh +0 -50
  63. package/k6-tests/smoke-test/smoke-test.ts +0 -158
  64. package/k6-tests/tsconfig.json +0 -29
  65. package/k6-tests/utils/client_factory.ts +0 -128
  66. package/k6-tests/utils/common.ts +0 -489
  67. package/k6-tests/utils/logger.ts +0 -62
  68. package/k6-tests/utils/types.d.ts +0 -35
  69. package/malloy_mcp.dxt +0 -0
  70. package/publisher.config.json +0 -33
  71. package/src/config.spec.ts +0 -850
  72. package/src/config.ts +0 -305
  73. package/src/constants.ts +0 -10
  74. package/src/controller/compile.controller.ts +0 -35
  75. package/src/controller/connection.controller.ts +0 -515
  76. package/src/controller/database.controller.ts +0 -21
  77. package/src/controller/manifest.controller.ts +0 -29
  78. package/src/controller/materialization.controller.ts +0 -125
  79. package/src/controller/model.controller.ts +0 -107
  80. package/src/controller/package.controller.ts +0 -182
  81. package/src/controller/query.controller.ts +0 -60
  82. package/src/controller/watch-mode.controller.ts +0 -98
  83. package/src/data_styles.ts +0 -71
  84. package/src/dto/connection.dto.spec.ts +0 -131
  85. package/src/dto/connection.dto.ts +0 -174
  86. package/src/dto/index.ts +0 -2
  87. package/src/dto/package.dto.spec.ts +0 -42
  88. package/src/dto/package.dto.ts +0 -12
  89. package/src/dto/validate.spec.ts +0 -76
  90. package/src/dto/validate.ts +0 -31
  91. package/src/errors.ts +0 -116
  92. package/src/health.ts +0 -189
  93. package/src/instrumentation.ts +0 -148
  94. package/src/logger.ts +0 -154
  95. package/src/mcp/error_messages.ts +0 -199
  96. package/src/mcp/handler_utils.ts +0 -239
  97. package/src/mcp/mcp_constants.ts +0 -22
  98. package/src/mcp/prompts/handlers.ts +0 -84
  99. package/src/mcp/prompts/index.ts +0 -11
  100. package/src/mcp/prompts/prompt_definitions.ts +0 -160
  101. package/src/mcp/prompts/prompt_service.ts +0 -67
  102. package/src/mcp/prompts/utils.ts +0 -62
  103. package/src/mcp/resource_metadata.ts +0 -47
  104. package/src/mcp/resources/model_resource.ts +0 -153
  105. package/src/mcp/resources/notebook_resource.ts +0 -137
  106. package/src/mcp/resources/package_resource.ts +0 -370
  107. package/src/mcp/resources/project_resource.ts +0 -184
  108. package/src/mcp/resources/query_resource.ts +0 -117
  109. package/src/mcp/resources/source_resource.ts +0 -141
  110. package/src/mcp/resources/view_resource.ts +0 -136
  111. package/src/mcp/server.ts +0 -62
  112. package/src/mcp/tools/discovery_tools.ts +0 -258
  113. package/src/mcp/tools/execute_query_tool.ts +0 -265
  114. package/src/server.ts +0 -1195
  115. package/src/service/connection.spec.ts +0 -1331
  116. package/src/service/connection.ts +0 -1511
  117. package/src/service/connection_service.spec.ts +0 -641
  118. package/src/service/connection_service.ts +0 -181
  119. package/src/service/db_utils.spec.ts +0 -714
  120. package/src/service/db_utils.ts +0 -1227
  121. package/src/service/filter.spec.ts +0 -447
  122. package/src/service/filter.ts +0 -337
  123. package/src/service/filter_integration.spec.ts +0 -825
  124. package/src/service/gcs_s3_utils.ts +0 -427
  125. package/src/service/manifest_service.spec.ts +0 -201
  126. package/src/service/manifest_service.ts +0 -106
  127. package/src/service/materialization_service.spec.ts +0 -648
  128. package/src/service/materialization_service.ts +0 -929
  129. package/src/service/materialized_table_gc.spec.ts +0 -383
  130. package/src/service/materialized_table_gc.ts +0 -279
  131. package/src/service/model.spec.ts +0 -257
  132. package/src/service/model.ts +0 -1069
  133. package/src/service/package.spec.ts +0 -236
  134. package/src/service/package.ts +0 -463
  135. package/src/service/project.ts +0 -681
  136. package/src/service/project_compile.spec.ts +0 -197
  137. package/src/service/project_store.spec.ts +0 -859
  138. package/src/service/project_store.ts +0 -1531
  139. package/src/service/quoting.ts +0 -41
  140. package/src/service/resolve_project.ts +0 -13
  141. package/src/storage/BaseRepository.ts +0 -31
  142. package/src/storage/DatabaseInterface.ts +0 -180
  143. package/src/storage/StorageManager.mock.ts +0 -59
  144. package/src/storage/StorageManager.ts +0 -210
  145. package/src/storage/duckdb/ConnectionRepository.ts +0 -141
  146. package/src/storage/duckdb/DuckDBConnection.ts +0 -177
  147. package/src/storage/duckdb/DuckDBManifestStore.ts +0 -70
  148. package/src/storage/duckdb/DuckDBRepository.ts +0 -224
  149. package/src/storage/duckdb/ManifestRepository.ts +0 -119
  150. package/src/storage/duckdb/MaterializationRepository.ts +0 -249
  151. package/src/storage/duckdb/PackageRepository.ts +0 -135
  152. package/src/storage/duckdb/ProjectRepository.ts +0 -148
  153. package/src/storage/duckdb/manifest_store.spec.ts +0 -133
  154. package/src/storage/duckdb/schema.ts +0 -147
  155. package/src/storage/ducklake/DuckLakeManifestStore.ts +0 -146
  156. package/src/utils.ts +0 -13
  157. package/tests/fixtures/persist-test/data/orders.csv +0 -5
  158. package/tests/fixtures/persist-test/persist_test.malloy +0 -11
  159. package/tests/fixtures/persist-test/publisher.json +0 -5
  160. package/tests/fixtures/publisher.config.json +0 -15
  161. package/tests/harness/e2e.ts +0 -96
  162. package/tests/harness/mcp_test_setup.ts +0 -344
  163. package/tests/harness/mocks.ts +0 -37
  164. package/tests/harness/rest_e2e.ts +0 -68
  165. package/tests/harness/uris.ts +0 -31
  166. package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +0 -470
  167. package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +0 -434
  168. package/tests/integration/mcp/mcp_resource.integration.spec.ts +0 -663
  169. package/tests/integration/mcp/mcp_transport.integration.spec.ts +0 -122
  170. package/tests/integration/mcp/setup.spec.ts +0 -5
  171. package/tests/unit/duckdb/attached_databases.test.ts +0 -1132
  172. package/tests/unit/ducklake/ducklake.test.ts +0 -950
  173. package/tests/unit/mcp/prompt_definitions.test.ts +0 -102
  174. package/tests/unit/mcp/prompt_happy.test.ts +0 -51
  175. package/tsconfig.json +0 -32
@@ -1,141 +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";
7
- import { ModelCompilationError } from "../../errors";
8
- import { logger } from "../../logger";
9
- import { ProjectStore } from "../../service/project_store";
10
- import {
11
- getInternalError,
12
- getMalloyErrorDetails,
13
- getNotFoundError,
14
- } from "../error_messages";
15
- import {
16
- getModelForQuery,
17
- handleResourceGet,
18
- McpGetResourceError,
19
- } from "../handler_utils";
20
- import { RESOURCE_METADATA } from "../resource_metadata";
21
-
22
- // Define the expected parameter types for this resource
23
- type SourceParams = {
24
- projectName?: unknown;
25
- packageName?: unknown;
26
- modelPath?: unknown;
27
- sourceName?: unknown;
28
- };
29
-
30
- /**
31
- * Registers the Malloy Source resource type (nested within a Model).
32
- * Handles getting details for a specific source.
33
- */
34
- export function registerSourceResource(
35
- mcpServer: McpServer,
36
- projectStore: ProjectStore,
37
- ): void {
38
- mcpServer.resource(
39
- "source",
40
- new ResourceTemplate(
41
- "malloy://project/{projectName}/package/{packageName}/models/{modelPath}/sources/{sourceName}",
42
- { list: undefined }, // Listing sources directly is not supported via this template
43
- ),
44
- /** Handles GetResource requests for specific Sources within a Model */
45
- (uri, params) =>
46
- handleResourceGet(
47
- uri,
48
- params as SourceParams, // Cast params
49
- "source",
50
- // Define the getData async callback
51
- async (
52
- {
53
- projectName,
54
- packageName,
55
- modelPath,
56
- sourceName,
57
- }: SourceParams, // Use defined type
58
- // Add type for uri
59
- uri: URL,
60
- ) => {
61
- // Input validation
62
- if (
63
- typeof projectName !== "string" ||
64
- typeof packageName !== "string" ||
65
- typeof modelPath !== "string" ||
66
- typeof sourceName !== "string"
67
- ) {
68
- // Throw simple error, handleResourceGet will wrap it
69
- throw new Error("Invalid parameters for source resource.");
70
- }
71
-
72
- try {
73
- // Use the imported getModelForQuery
74
- const modelResult = await getModelForQuery(
75
- projectStore,
76
- projectName,
77
- packageName,
78
- modelPath,
79
- );
80
-
81
- // Handle error case from getModelForQuery
82
- if ("error" in modelResult) {
83
- throw new McpGetResourceError(modelResult.error);
84
- }
85
- const { model } = modelResult;
86
-
87
- const sources = await model.getSources();
88
- // Add check for undefined sources
89
- if (!sources) {
90
- throw new Error("Could not retrieve sources from model.");
91
- }
92
- const source = sources.find(
93
- (s: components["schemas"]["Source"]) =>
94
- s.name === sourceName,
95
- );
96
-
97
- if (!source) {
98
- const errorDetails = getNotFoundError(
99
- `Source '${sourceName}' in model '${modelPath}' package '${packageName}' project '${projectName}'`,
100
- );
101
- throw new McpGetResourceError(errorDetails);
102
- }
103
-
104
- // Strip implicit filters from agent-facing responses
105
- if (source.filters) {
106
- source.filters = source.filters.filter((f) => !f.implicit);
107
- }
108
-
109
- return source;
110
- } catch (error) {
111
- // Catch errors from getModelForQuery or finding the source
112
- if (error instanceof McpGetResourceError) {
113
- throw error; // Re-throw already formatted errors
114
- }
115
- // Check if it's a compilation error (likely from getModel call within getModelForQuery)
116
- if (error instanceof ModelCompilationError) {
117
- const errorDetails = getMalloyErrorDetails(
118
- "GetResource (source - model compilation)",
119
- `${projectName}/${packageName}/${modelPath}`,
120
- error,
121
- );
122
- throw new McpGetResourceError(errorDetails);
123
- }
124
- // Handle other potential errors (e.g., invalid params error from initial check)
125
- logger.error(
126
- `[MCP Server Error] Error fetching source '${sourceName}' from ${uri.href}:`,
127
- { error },
128
- );
129
- // Fallback: Use getInternalError for unexpected issues
130
- // Or getNotFoundError if it's likely a resource access issue
131
- const fallbackErrorDetails = getInternalError(
132
- `GetResource (source: ${uri.href})`,
133
- error,
134
- );
135
- throw new McpGetResourceError(fallbackErrorDetails);
136
- }
137
- },
138
- RESOURCE_METADATA.source, // Use source-specific metadata
139
- ),
140
- );
141
- }
@@ -1,136 +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 View definition type
7
- import { ModelCompilationError } from "../../errors";
8
- import { logger } from "../../logger";
9
- import { ProjectStore } from "../../service/project_store";
10
- import {
11
- getInternalError,
12
- getMalloyErrorDetails,
13
- getNotFoundError,
14
- } from "../error_messages";
15
- import {
16
- getModelForQuery,
17
- handleResourceGet,
18
- McpGetResourceError,
19
- } from "../handler_utils";
20
- import { RESOURCE_METADATA } from "../resource_metadata";
21
-
22
- // Define the expected parameter types
23
- type ViewParams = {
24
- projectName?: unknown;
25
- packageName?: unknown;
26
- modelPath?: unknown;
27
- sourceName?: unknown;
28
- viewName?: unknown;
29
- };
30
-
31
- /**
32
- * Registers the Malloy View resource type (nested within a Source).
33
- */
34
- export function registerViewResource(
35
- mcpServer: McpServer,
36
- projectStore: ProjectStore,
37
- ): void {
38
- mcpServer.resource(
39
- "view",
40
- new ResourceTemplate(
41
- "malloy://project/{projectName}/package/{packageName}/models/{modelPath}/sources/{sourceName}/views/{viewName}",
42
- { list: undefined }, // Listing views is not supported via this template
43
- ),
44
- (uri, params) =>
45
- handleResourceGet(
46
- uri,
47
- params as ViewParams,
48
- "view",
49
- async (
50
- {
51
- projectName,
52
- packageName,
53
- modelPath,
54
- sourceName,
55
- viewName,
56
- }: ViewParams,
57
- uri: URL,
58
- ) => {
59
- if (
60
- typeof projectName !== "string" ||
61
- typeof packageName !== "string" ||
62
- typeof modelPath !== "string" ||
63
- typeof sourceName !== "string" ||
64
- typeof viewName !== "string"
65
- ) {
66
- throw new Error("Invalid parameters for view resource.");
67
- }
68
-
69
- try {
70
- const modelResult = await getModelForQuery(
71
- projectStore,
72
- projectName,
73
- packageName,
74
- modelPath,
75
- );
76
- if ("error" in modelResult) {
77
- throw new McpGetResourceError(modelResult.error);
78
- }
79
- const { model } = modelResult;
80
-
81
- const sources = await model.getSources();
82
- if (!sources) {
83
- throw new Error("Could not retrieve sources from model.");
84
- }
85
- const source = sources.find(
86
- (s: components["schemas"]["Source"]) =>
87
- s.name === sourceName,
88
- );
89
- if (!source) {
90
- throw new McpGetResourceError(
91
- getNotFoundError(
92
- `Source '${sourceName}' in model '${modelPath}' package '${packageName}' project '${projectName}'`,
93
- ),
94
- );
95
- }
96
-
97
- // Find the view within the source
98
- const view = source.views?.find(
99
- (v: components["schemas"]["View"]) => v.name === viewName,
100
- );
101
-
102
- if (!view) {
103
- // Specific "View not found" error
104
- const errorDetails = getNotFoundError(
105
- `View '${viewName}' in source '${sourceName}' model '${modelPath}' package '${packageName}' project '${projectName}'`,
106
- );
107
- throw new McpGetResourceError(errorDetails);
108
- }
109
- return view;
110
- } catch (error) {
111
- if (error instanceof McpGetResourceError) {
112
- throw error; // Re-throw already formatted
113
- }
114
- if (error instanceof ModelCompilationError) {
115
- const errorDetails = getMalloyErrorDetails(
116
- "GetResource (view - model compilation)",
117
- `${projectName}/${packageName}/${modelPath}`,
118
- error,
119
- );
120
- throw new McpGetResourceError(errorDetails);
121
- }
122
- logger.error(
123
- `[MCP Server Error] Error fetching view '${viewName}' from ${uri.href}:`,
124
- { error },
125
- );
126
- const fallbackErrorDetails = getInternalError(
127
- `GetResource (view: ${uri.href})`,
128
- error,
129
- );
130
- throw new McpGetResourceError(fallbackErrorDetails);
131
- }
132
- },
133
- RESOURCE_METADATA.view,
134
- ),
135
- );
136
- }
package/src/mcp/server.ts DELETED
@@ -1,62 +0,0 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { ProjectStore } from "../service/project_store";
3
-
4
- import { formatDuration, logger } from "../logger";
5
- import { registerPromptCapability } from "./prompts/prompt_service.js";
6
- import { registerModelResource } from "./resources/model_resource";
7
- import { registerNotebookResource } from "./resources/notebook_resource";
8
- import { registerPackageResource } from "./resources/package_resource";
9
- import { registerProjectResource } from "./resources/project_resource";
10
- import { registerQueryResource } from "./resources/query_resource";
11
- import { registerSourceResource } from "./resources/source_resource";
12
- import { registerViewResource } from "./resources/view_resource";
13
- import { registerTools } from "./tools/discovery_tools";
14
- import { registerExecuteQueryTool } from "./tools/execute_query_tool";
15
-
16
- export const testServerInfo = {
17
- name: "malloy-publisher-mcp-server",
18
- version: "0.0.1",
19
- displayName: "Malloy Publisher MCP Server",
20
- description: "Provides access to Malloy models and query execution via MCP.",
21
- };
22
-
23
- export function initializeMcpServer(projectStore: ProjectStore): McpServer {
24
- logger.info("[MCP Init] Starting initializeMcpServer...");
25
- const startTime = performance.now();
26
-
27
- const mcpServer = new McpServer(testServerInfo);
28
-
29
- logger.info("[MCP Init] Registering project resource...");
30
- registerProjectResource(mcpServer, projectStore);
31
- logger.info("[MCP Init] Registering package resource...");
32
- registerPackageResource(mcpServer, projectStore);
33
-
34
- // Register more specific templates first
35
- logger.info("[MCP Init] Registering notebook resource...");
36
- registerNotebookResource(mcpServer, projectStore);
37
- logger.info("[MCP Init] Registering source resource...");
38
- registerSourceResource(mcpServer, projectStore);
39
- logger.info("[MCP Init] Registering query resource...");
40
- registerQueryResource(mcpServer, projectStore);
41
- logger.info("[MCP Init] Registering view resource...");
42
- registerViewResource(mcpServer, projectStore);
43
-
44
- // Register the general model template last among resource types
45
- logger.info("[MCP Init] Registering model resource...");
46
- registerModelResource(mcpServer, projectStore);
47
-
48
- logger.info("[MCP Init] Registering executeQuery tool...");
49
- registerExecuteQueryTool(mcpServer, projectStore);
50
-
51
- registerTools(mcpServer, projectStore);
52
-
53
- logger.info("[MCP Init] Registering prompt capability...");
54
- registerPromptCapability(mcpServer, projectStore);
55
-
56
- const endTime = performance.now();
57
- logger.info(`[MCP Init] Finished initializeMcpServer`, {
58
- duration: formatDuration(endTime - startTime),
59
- });
60
-
61
- return mcpServer;
62
- }
@@ -1,258 +0,0 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { z } from "zod";
3
- import { ProjectStore } from "../../service/project_store";
4
- import { buildMalloyUri } from "../handler_utils";
5
-
6
- const listPackagesShape = {
7
- // projectName is required; other fields mirror SDK expectations
8
- projectName: z
9
- .string()
10
- .describe(
11
- "Project name. Project names are listed in the listProjects tool.",
12
- ),
13
- };
14
- type listPackagesParams = z.infer<z.ZodObject<typeof listPackagesShape>>;
15
-
16
- const getModelsShape = {
17
- // projectName is required; other fields mirror SDK expectations
18
- projectName: z
19
- .string()
20
- .describe(
21
- "Project name. Project names are listed in the listProjects tool.",
22
- ),
23
- packageName: z
24
- .string()
25
- .describe(
26
- "Package name. Package names are listed in the listPackages tool.",
27
- ),
28
- };
29
- type getModelsParams = z.infer<z.ZodObject<typeof getModelsShape>>;
30
-
31
- const getModelTextShape = {
32
- projectName: z
33
- .string()
34
- .describe(
35
- "Project name. Project names are listed in the listProjects tool.",
36
- ),
37
- packageName: z
38
- .string()
39
- .describe(
40
- "Package name. Package names are listed in the listPackages tool.",
41
- ),
42
- modelPath: z
43
- .string()
44
- .describe(
45
- "Model path. Model paths are listed in the malloy_packageGet tool.",
46
- ),
47
- };
48
- type getModelTextParams = z.infer<z.ZodObject<typeof getModelTextShape>>;
49
-
50
- /**
51
- * Registers the Malloy Project resource type with the MCP server.
52
- * Handles getting details for the hardcoded 'home' project and listing packages within it.
53
- */
54
- export function registerTools(
55
- mcpServer: McpServer,
56
- projectStore: ProjectStore,
57
- ): void {
58
- mcpServer.tool(
59
- "malloy_projectList",
60
- "Lists all Malloy projects",
61
- {},
62
- async () => {
63
- console.log(
64
- "[MCP LOG] Entering ListResources (project) handler (listing ALL packages)...",
65
- );
66
- const allProjects = await Promise.all(
67
- (await projectStore.listProjects())
68
- .filter((project) => project.name)
69
- .map((project) => ({
70
- name: project.name,
71
- project: projectStore.getProject(project.name!, false),
72
- })),
73
- );
74
-
75
- console.log(`[MCP LOG] Found ${allProjects.length} projects defined.`);
76
-
77
- const mappedResources = await Promise.all(
78
- allProjects.map(async (project) => {
79
- const name = project.name;
80
- const projectInstance = await project.project;
81
- const metadata = await projectInstance.reloadProjectMetadata();
82
- const readme = metadata.readme;
83
- return {
84
- name,
85
- type: "project",
86
- description: readme || "NO Description available",
87
- };
88
- }),
89
- );
90
- // console.log(mappedResources);
91
- console.log(
92
- `[MCP LOG] ListResources (project): Returning ${mappedResources.length} package resources.`,
93
- );
94
- return {
95
- content: [
96
- {
97
- type: "resource",
98
- resource: {
99
- type: "application/json",
100
- uri: buildMalloyUri({}, "project"),
101
- text: JSON.stringify(mappedResources),
102
- },
103
- },
104
- ],
105
- };
106
- },
107
- );
108
-
109
- mcpServer.tool(
110
- "malloy_packageList",
111
- "Lists all Malloy packages within a project",
112
- listPackagesShape,
113
- async (params: listPackagesParams) => {
114
- const { projectName } = params;
115
- console.log(
116
- "[MCP LOG] Entering ListResources (project) handler (listing ALL packages)...",
117
- );
118
- const project = await projectStore.getProject(projectName, false);
119
- const packages = await project.listPackages();
120
- console.log(`[MCP LOG] Found ${packages.length} packages defined.`);
121
- const mappedResources = packages.map((pkg) => ({
122
- modelPath: pkg.name,
123
- type: "package",
124
- description: pkg.description,
125
- }));
126
- console.log(
127
- `[MCP LOG] ListResources (project): Returning ${mappedResources.length} package resources.`,
128
- );
129
- return {
130
- content: [
131
- {
132
- type: "resource",
133
- resource: {
134
- type: "application/json",
135
- uri: buildMalloyUri({ project: projectName }, "package"),
136
- text: JSON.stringify(mappedResources),
137
- },
138
- },
139
- ],
140
- };
141
- },
142
- );
143
-
144
- mcpServer.tool(
145
- "malloy_packageGet",
146
- "Lists resources within a package",
147
- getModelsShape,
148
- async (params: getModelsParams) => {
149
- const { projectName, packageName } = params;
150
- console.log(
151
- "[MCP LOG] Entering GetResources (project) handler (listing ALL packages)...",
152
- );
153
- const project = await projectStore.getProject(projectName, false);
154
- const pkg = await project.getPackage(packageName, false);
155
- const models = await pkg.listModels();
156
- console.log(`[MCP LOG] Found ${models.length} models defined.`);
157
- const mappedResources = models.map((model) => ({
158
- name: model.path,
159
- type: "model",
160
- }));
161
- console.log(
162
- `[MCP LOG] ListResources (project): Returning ${mappedResources.length} package resources.`,
163
- );
164
- return {
165
- content: [
166
- {
167
- type: "resource",
168
- resource: {
169
- type: "application/json",
170
- uri: buildMalloyUri(
171
- { project: projectName, package: packageName },
172
- "model",
173
- ),
174
- text: JSON.stringify(mappedResources),
175
- },
176
- },
177
- ],
178
- };
179
- },
180
- );
181
-
182
- mcpServer.tool(
183
- "malloy_modelGetText",
184
- "Gets the raw text content of a model file",
185
- getModelTextShape,
186
- async (params: getModelTextParams) => {
187
- const { projectName, packageName, modelPath } = params;
188
- console.log(
189
- `[MCP LOG] Entering GetModelText handler for ${projectName}/${packageName}/${modelPath}...`,
190
- );
191
-
192
- try {
193
- const project = await projectStore.getProject(projectName, false);
194
- const pkg = await project.getPackage(packageName, false);
195
- const model = pkg.getModel(modelPath);
196
-
197
- if (!model) {
198
- console.log(
199
- "model not found",
200
- modelPath,
201
- "in ",
202
- pkg.listModels(),
203
- );
204
- throw new Error(`Model not found: ${modelPath}`);
205
- }
206
-
207
- // Use the new getModelFileText method
208
- const fileText = await pkg.getModelFileText(modelPath);
209
-
210
- console.log(
211
- `[MCP LOG] Successfully retrieved model text for ${modelPath}`,
212
- );
213
- return {
214
- content: [
215
- {
216
- type: "resource",
217
- resource: {
218
- type: "text/plain",
219
- uri: buildMalloyUri(
220
- {
221
- project: projectName,
222
- package: packageName,
223
- model: modelPath,
224
- },
225
- "model-text",
226
- ),
227
- text: fileText,
228
- },
229
- },
230
- ],
231
- };
232
- } catch (error) {
233
- console.error(`[MCP LOG] Error retrieving model text: ${error}`);
234
- const errorMessage =
235
- error instanceof Error ? error.message : "Unknown error";
236
- return {
237
- content: [
238
- {
239
- type: "resource",
240
- resource: {
241
- type: "text/plain",
242
- uri: buildMalloyUri(
243
- {
244
- project: projectName,
245
- package: packageName,
246
- model: modelPath,
247
- },
248
- "model-text",
249
- ),
250
- text: `Error: ${errorMessage}`,
251
- },
252
- },
253
- ],
254
- };
255
- }
256
- },
257
- );
258
- }