@malloy-publisher/server 0.0.382-dev → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.docker.md +145 -20
- package/README.md +65 -12
- package/dist/app/api-doc.html +5 -0
- package/dist/app/api-doc.yaml +3929 -534
- package/dist/app/assets/EnvironmentPage-CHq5BF4l.js +1 -0
- package/dist/app/assets/HomePage-CIp-pJCa.js +1 -0
- package/dist/app/assets/LightMode-mHHPjEeA.js +1 -0
- package/dist/app/assets/MainPage-CylxO5Yu.js +2 -0
- package/dist/app/assets/MaterializationsPage-a0vjqxib.js +1 -0
- package/dist/app/assets/ModelPage-Cz-MrSZQ.js +1 -0
- package/dist/app/assets/PackagePage-Cdg5D7AN.js +1 -0
- package/dist/app/assets/RouteError-B5SIyn6G.js +1 -0
- package/dist/app/assets/ThemeEditorPage-B62rRc-y.js +1 -0
- package/dist/app/assets/WorkbookPage-45cG1Gx6.js +1 -0
- package/dist/app/assets/{core-CjeTkq8O.es-BqRc6yhC.js → core-DyU47reh.es-DY9b3WjS.js} +1 -1
- package/dist/app/assets/github-dark-DenFmJkN.es-DHJKELXO.js +1 -0
- package/dist/app/assets/index-5eLCcNmP.css +1 -0
- package/dist/app/assets/index-C5ClsnS7.js +1774 -0
- package/dist/app/assets/index-DF9tVqwN.js +1 -0
- package/dist/app/assets/index-DSoCUF-f.js +2725 -0
- package/dist/app/assets/index-DgVRz2wm.js +2 -0
- package/dist/app/assets/index-P-pF8nU5.js +632 -0
- package/dist/app/assets/index-w_0OQJgZ.js +23 -0
- package/dist/app/index.html +8 -4
- package/dist/cpufeatures-1yrn0vtw.node +0 -0
- package/dist/default-publisher.config.json +23 -0
- package/dist/{instrumentation.js → instrumentation.mjs} +10631 -10573
- package/dist/package_load_worker.mjs +15219 -0
- package/dist/runtime/publisher.js +331 -0
- package/dist/{server.js → server.mjs} +141276 -74705
- package/dist/sshcrypto-vd2k5hq9.node +0 -0
- package/package.json +41 -28
- package/publisher.config.example.bigquery.json +33 -0
- package/publisher.config.example.duckdb.json +23 -0
- package/.eslintrc.json +0 -44
- package/.prettierignore +0 -1
- package/.prettierrc +0 -4
- package/build.ts +0 -38
- package/dist/app/assets/HomePage-Dn3E4CuB.js +0 -1
- package/dist/app/assets/MainPage-BzB3yoqi.js +0 -2
- package/dist/app/assets/ModelPage-C9O_sAXT.js +0 -1
- package/dist/app/assets/PackagePage-DcxKEjBX.js +0 -1
- package/dist/app/assets/ProjectPage-BDj307rF.js +0 -1
- package/dist/app/assets/RouteError-DAShbVCG.js +0 -1
- package/dist/app/assets/WorkbookPage-Cs_XYEaB.js +0 -1
- package/dist/app/assets/index-15BOvhp0.js +0 -456
- package/dist/app/assets/index-Bb2jqquW.js +0 -676
- package/dist/app/assets/index-CMlGQMcl.css +0 -1
- package/dist/app/assets/index-D68X76-7.js +0 -1276
- package/dist/app/assets/index.umd-DGBekgSu.js +0 -1145
- package/dxt/malloy_bridge.py +0 -354
- package/dxt/manifest.json +0 -22
- package/eslint.config.mjs +0 -76
- package/k6-tests/README.md +0 -144
- package/k6-tests/bun.lock +0 -797
- package/k6-tests/load-test/load-test-crud-connections.ts +0 -263
- package/k6-tests/load-test/load-test-crud-packages.ts +0 -461
- package/k6-tests/load-test/load-test-crud-projects.ts +0 -160
- package/k6-tests/load-test/load-test-crud.ts +0 -142
- package/k6-tests/load-test/load-test.ts +0 -784
- package/k6-tests/package.json +0 -27
- package/k6-tests/scripts/run-with-otel.sh +0 -50
- package/k6-tests/smoke-test/smoke-test.ts +0 -158
- package/k6-tests/tsconfig.json +0 -29
- package/k6-tests/utils/client_factory.ts +0 -128
- package/k6-tests/utils/common.ts +0 -489
- package/k6-tests/utils/logger.ts +0 -62
- package/k6-tests/utils/types.d.ts +0 -35
- package/malloy_mcp.dxt +0 -0
- package/publisher.config.json +0 -33
- package/src/config.spec.ts +0 -850
- package/src/config.ts +0 -305
- package/src/constants.ts +0 -10
- package/src/controller/compile.controller.ts +0 -35
- package/src/controller/connection.controller.ts +0 -515
- package/src/controller/database.controller.ts +0 -21
- package/src/controller/manifest.controller.ts +0 -29
- package/src/controller/materialization.controller.ts +0 -125
- package/src/controller/model.controller.ts +0 -107
- package/src/controller/package.controller.ts +0 -182
- package/src/controller/query.controller.ts +0 -60
- package/src/controller/watch-mode.controller.ts +0 -98
- package/src/data_styles.ts +0 -71
- package/src/dto/connection.dto.spec.ts +0 -131
- package/src/dto/connection.dto.ts +0 -174
- package/src/dto/index.ts +0 -2
- package/src/dto/package.dto.spec.ts +0 -42
- package/src/dto/package.dto.ts +0 -12
- package/src/dto/validate.spec.ts +0 -76
- package/src/dto/validate.ts +0 -31
- package/src/errors.ts +0 -116
- package/src/health.ts +0 -189
- package/src/instrumentation.ts +0 -148
- package/src/logger.ts +0 -154
- package/src/mcp/error_messages.ts +0 -199
- package/src/mcp/handler_utils.ts +0 -239
- package/src/mcp/mcp_constants.ts +0 -22
- package/src/mcp/prompts/handlers.ts +0 -84
- package/src/mcp/prompts/index.ts +0 -11
- package/src/mcp/prompts/prompt_definitions.ts +0 -160
- package/src/mcp/prompts/prompt_service.ts +0 -67
- package/src/mcp/prompts/utils.ts +0 -62
- package/src/mcp/resource_metadata.ts +0 -47
- package/src/mcp/resources/model_resource.ts +0 -153
- package/src/mcp/resources/notebook_resource.ts +0 -137
- package/src/mcp/resources/package_resource.ts +0 -370
- package/src/mcp/resources/project_resource.ts +0 -184
- package/src/mcp/resources/query_resource.ts +0 -117
- package/src/mcp/resources/source_resource.ts +0 -141
- package/src/mcp/resources/view_resource.ts +0 -136
- package/src/mcp/server.ts +0 -62
- package/src/mcp/tools/discovery_tools.ts +0 -258
- package/src/mcp/tools/execute_query_tool.ts +0 -265
- package/src/server.ts +0 -1195
- package/src/service/connection.spec.ts +0 -1331
- package/src/service/connection.ts +0 -1511
- package/src/service/connection_service.spec.ts +0 -641
- package/src/service/connection_service.ts +0 -181
- package/src/service/db_utils.spec.ts +0 -714
- package/src/service/db_utils.ts +0 -1227
- package/src/service/filter.spec.ts +0 -447
- package/src/service/filter.ts +0 -337
- package/src/service/filter_integration.spec.ts +0 -825
- package/src/service/gcs_s3_utils.ts +0 -427
- package/src/service/manifest_service.spec.ts +0 -201
- package/src/service/manifest_service.ts +0 -106
- package/src/service/materialization_service.spec.ts +0 -648
- package/src/service/materialization_service.ts +0 -929
- package/src/service/materialized_table_gc.spec.ts +0 -383
- package/src/service/materialized_table_gc.ts +0 -279
- package/src/service/model.spec.ts +0 -257
- package/src/service/model.ts +0 -1069
- package/src/service/package.spec.ts +0 -236
- package/src/service/package.ts +0 -463
- package/src/service/project.ts +0 -681
- package/src/service/project_compile.spec.ts +0 -197
- package/src/service/project_store.spec.ts +0 -859
- package/src/service/project_store.ts +0 -1531
- package/src/service/quoting.ts +0 -41
- package/src/service/resolve_project.ts +0 -13
- package/src/storage/BaseRepository.ts +0 -31
- package/src/storage/DatabaseInterface.ts +0 -180
- package/src/storage/StorageManager.mock.ts +0 -59
- package/src/storage/StorageManager.ts +0 -210
- package/src/storage/duckdb/ConnectionRepository.ts +0 -141
- package/src/storage/duckdb/DuckDBConnection.ts +0 -177
- package/src/storage/duckdb/DuckDBManifestStore.ts +0 -70
- package/src/storage/duckdb/DuckDBRepository.ts +0 -224
- package/src/storage/duckdb/ManifestRepository.ts +0 -119
- package/src/storage/duckdb/MaterializationRepository.ts +0 -249
- package/src/storage/duckdb/PackageRepository.ts +0 -135
- package/src/storage/duckdb/ProjectRepository.ts +0 -148
- package/src/storage/duckdb/manifest_store.spec.ts +0 -133
- package/src/storage/duckdb/schema.ts +0 -147
- package/src/storage/ducklake/DuckLakeManifestStore.ts +0 -146
- package/src/utils.ts +0 -13
- package/tests/fixtures/persist-test/data/orders.csv +0 -5
- package/tests/fixtures/persist-test/persist_test.malloy +0 -11
- package/tests/fixtures/persist-test/publisher.json +0 -5
- package/tests/fixtures/publisher.config.json +0 -15
- package/tests/harness/e2e.ts +0 -96
- package/tests/harness/mcp_test_setup.ts +0 -344
- package/tests/harness/mocks.ts +0 -37
- package/tests/harness/rest_e2e.ts +0 -68
- package/tests/harness/uris.ts +0 -31
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +0 -470
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +0 -434
- package/tests/integration/mcp/mcp_resource.integration.spec.ts +0 -663
- package/tests/integration/mcp/mcp_transport.integration.spec.ts +0 -122
- package/tests/integration/mcp/setup.spec.ts +0 -5
- package/tests/unit/duckdb/attached_databases.test.ts +0 -1132
- package/tests/unit/ducklake/ducklake.test.ts +0 -950
- package/tests/unit/mcp/prompt_definitions.test.ts +0 -102
- package/tests/unit/mcp/prompt_happy.test.ts +0 -51
- 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
|
-
}
|