@malloy-publisher/server 0.0.226 → 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 (69) hide show
  1. package/README.md +2 -11
  2. package/dist/package_load_worker.mjs +86 -24
  3. package/dist/server.mjs +655 -6994
  4. package/package.json +1 -4
  5. package/src/health.ts +3 -8
  6. package/src/mcp/error_messages.ts +8 -37
  7. package/src/mcp/handler_utils.ts +10 -129
  8. package/src/mcp/mcp_constants.ts +0 -16
  9. package/src/mcp/{agent_server.protocol.spec.ts → server.protocol.spec.ts} +14 -12
  10. package/src/mcp/server.ts +29 -37
  11. package/src/mcp/skills/build_skills_bundle.ts +1 -1
  12. package/src/mcp/skills/skills_bundle.json +1 -1
  13. package/src/mcp/tools/docs_search_tool.ts +1 -1
  14. package/src/mcp/tools/execute_query_tool.ts +2 -2
  15. package/src/mcp/tools/get_context_eval.ts +3 -3
  16. package/src/mcp/tools/get_context_tool.spec.ts +196 -1
  17. package/src/mcp/tools/get_context_tool.ts +165 -67
  18. package/src/package_load/package_load_pool.ts +3 -0
  19. package/src/package_load/package_load_worker.ts +68 -24
  20. package/src/package_load/protocol.ts +16 -0
  21. package/src/package_load/rpc_wait_accountant.spec.ts +109 -0
  22. package/src/package_load/rpc_wait_accountant.ts +76 -0
  23. package/src/package_load_metrics.spec.ts +114 -0
  24. package/src/package_load_metrics.ts +127 -0
  25. package/src/pg_helpers.spec.ts +2 -206
  26. package/src/pg_helpers.ts +4 -120
  27. package/src/server.ts +0 -16
  28. package/src/service/environment.ts +1 -1
  29. package/src/service/package.ts +82 -42
  30. package/src/test_helpers/metrics_harness.ts +40 -0
  31. package/tests/harness/mcp_test_setup.ts +1 -1
  32. package/tests/integration/mcp/mcp_transport.integration.spec.ts +7 -31
  33. package/tests/integration/watch-mode/watch_mode.integration.spec.ts +0 -6
  34. package/dxt/malloy_bridge.py +0 -354
  35. package/dxt/manifest.json +0 -22
  36. package/src/dto/connection.dto.spec.ts +0 -186
  37. package/src/dto/connection.dto.ts +0 -308
  38. package/src/dto/index.ts +0 -2
  39. package/src/dto/package.dto.spec.ts +0 -42
  40. package/src/dto/package.dto.ts +0 -27
  41. package/src/dto/validate.spec.ts +0 -76
  42. package/src/dto/validate.ts +0 -31
  43. package/src/ducklake_version.spec.ts +0 -43
  44. package/src/ducklake_version.ts +0 -26
  45. package/src/mcp/agent_server.spec.ts +0 -18
  46. package/src/mcp/agent_server.ts +0 -144
  47. package/src/mcp/prompts/handlers.ts +0 -84
  48. package/src/mcp/prompts/index.ts +0 -11
  49. package/src/mcp/prompts/prompt_definitions.ts +0 -160
  50. package/src/mcp/prompts/prompt_service.ts +0 -67
  51. package/src/mcp/prompts/utils.ts +0 -62
  52. package/src/mcp/resource_metadata.ts +0 -47
  53. package/src/mcp/resources/environment_resource.ts +0 -187
  54. package/src/mcp/resources/model_resource.ts +0 -155
  55. package/src/mcp/resources/notebook_resource.ts +0 -137
  56. package/src/mcp/resources/package_resource.ts +0 -373
  57. package/src/mcp/resources/query_resource.ts +0 -122
  58. package/src/mcp/resources/source_resource.ts +0 -141
  59. package/src/mcp/resources/view_resource.ts +0 -136
  60. package/src/mcp/tools/discovery_tools.ts +0 -280
  61. package/src/storage/BaseRepository.ts +0 -31
  62. package/src/storage/StorageManager.mock.ts +0 -50
  63. package/tests/harness/e2e.ts +0 -96
  64. package/tests/harness/mocks.ts +0 -39
  65. package/tests/harness/uris.ts +0 -31
  66. package/tests/integration/mcp/mcp_resource.integration.spec.ts +0 -655
  67. package/tests/integration/mcp/setup.spec.ts +0 -5
  68. package/tests/unit/mcp/prompt_definitions.test.ts +0 -102
  69. package/tests/unit/mcp/prompt_happy.test.ts +0 -51
@@ -1,373 +0,0 @@
1
- import {
2
- McpServer,
3
- ResourceTemplate,
4
- } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import { ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
6
- import { URL } from "url";
7
- import { PackageNotFoundError } from "../../errors";
8
- import { logger } from "../../logger";
9
- import { EnvironmentStore } from "../../service/environment_store";
10
- import {
11
- getInternalError,
12
- getNotFoundError,
13
- type ErrorDetails,
14
- } from "../error_messages";
15
- import {
16
- buildMalloyUri,
17
- handleResourceGet,
18
- McpGetResourceError,
19
- } from "../handler_utils";
20
- import { RESOURCE_METADATA } from "../resource_metadata";
21
-
22
- // *** Define handleGetPackageContents function ***
23
- async function handleGetPackageContents(
24
- uri: URL,
25
- params: { environmentName?: string; packageName?: string },
26
- environmentStore: EnvironmentStore,
27
- ) {
28
- try {
29
- const { environmentName, packageName } = params;
30
- if (typeof environmentName !== "string" || environmentName === "") {
31
- throw new Error("Invalid environment name parameter.");
32
- }
33
- if (typeof packageName !== "string" || packageName === "") {
34
- throw new Error("Invalid package name parameter.");
35
- }
36
-
37
- const environment = await environmentStore.getEnvironment(
38
- environmentName,
39
- false,
40
- );
41
- const packageInstance = await environment.getPackage(packageName, false);
42
-
43
- // Use listModels() which returns { path: string, type: 'source' | 'notebook' }[]
44
- const entries = await packageInstance.listModels();
45
-
46
- // Use a type that includes metadata explicitly
47
- const resourceDefinitions: { uri: string; metadata: unknown }[] = [];
48
-
49
- for (const entry of entries) {
50
- const entryPath = entry.path; // e.g., "flights.malloy", "overview.malloynb"
51
- // @ts-expect-error TODO: Fix missing type in API
52
- const entryType = entry.type; // 'source' or 'notebook'
53
-
54
- if (typeof entryPath !== "string" || entryPath === "") {
55
- logger.warn(
56
- `[MCP Server Warning] Skipping entry in package ${packageName} with invalid path:`,
57
- entry,
58
- );
59
- continue;
60
- }
61
-
62
- // Common components for URI building
63
- const baseUriComponents = {
64
- environment: environmentName,
65
- package: packageName,
66
- };
67
-
68
- switch (entryType) {
69
- case "notebook": {
70
- const resourceMetadata = RESOURCE_METADATA.notebook;
71
- if (!resourceMetadata) {
72
- logger.warn(
73
- `[MCP Server Warning] No metadata found for entry type 'notebook' path ${entryPath} in package ${packageName}`,
74
- );
75
- continue;
76
- }
77
- const notebookUri = buildMalloyUri({
78
- ...baseUriComponents,
79
- resourceType: "notebooks",
80
- resourceName: entryPath,
81
- });
82
- resourceDefinitions.push({
83
- uri: notebookUri,
84
- metadata: resourceMetadata,
85
- });
86
- break;
87
- }
88
- case "source": {
89
- // 1. Add the source file itself
90
- const sourceResourceMetadata = RESOURCE_METADATA.source;
91
- if (!sourceResourceMetadata) {
92
- logger.warn(
93
- `[MCP Server Warning] No metadata found for entry type 'source' path ${entryPath} in package ${packageName}`,
94
- );
95
- // Continue processing views even if source metadata is missing
96
- } else {
97
- const sourceUri = buildMalloyUri({
98
- ...baseUriComponents,
99
- resourceType: "sources", // Use 'sources' type for the source file resource
100
- resourceName: entryPath,
101
- });
102
- resourceDefinitions.push({
103
- uri: sourceUri,
104
- metadata: sourceResourceMetadata,
105
- });
106
- }
107
-
108
- // 2. Try to load the model to find views within it
109
- try {
110
- const model = await packageInstance.getModel(entryPath); // Await the promise
111
- if (model) {
112
- // Ensure model exists before proceeding
113
- const modelSources = model.getSources(); // This should be synchronous if model is loaded
114
-
115
- if (modelSources && Array.isArray(modelSources)) {
116
- for (const source of modelSources) {
117
- if (source.views && Array.isArray(source.views)) {
118
- for (const view of source.views) {
119
- const viewResourceMetadata =
120
- RESOURCE_METADATA.view;
121
- if (!viewResourceMetadata) {
122
- logger.warn(
123
- `[MCP Server Warning] No metadata found for entry type 'view' named '${view.name}' in source '${source.name}'`,
124
- );
125
- continue;
126
- }
127
- // Build the nested view URI using the helper
128
- const viewUri = buildMalloyUri({
129
- ...baseUriComponents,
130
- resourceType: "models", // Base is the model
131
- resourceName: entryPath, // Model file path
132
- subResourceType: "views",
133
- subResourceName: view.name,
134
- });
135
- resourceDefinitions.push({
136
- uri: viewUri,
137
- metadata: viewResourceMetadata,
138
- });
139
- }
140
- }
141
- }
142
- } else {
143
- logger.warn(
144
- `[MCP Server Warning] Could not retrieve sources or sources is not an array for model ${entryPath}`,
145
- );
146
- }
147
- } else {
148
- logger.warn(
149
- `[MCP Server Warning] Could not load model for path ${entryPath} to extract views.`,
150
- );
151
- }
152
- } catch (modelLoadError) {
153
- // Log error if model loading fails, but continue processing other files
154
- logger.warn(
155
- `[MCP Server Warning] Failed to load model ${entryPath} to extract views: ${modelLoadError instanceof Error ? modelLoadError.message : String(modelLoadError)}`,
156
- );
157
- }
158
- break;
159
- }
160
- default:
161
- logger.warn(
162
- `[MCP Server Warning] Unknown entry type '${entryType}' for path ${entryPath} in package ${packageName}`,
163
- );
164
- continue; // Skip unknown types
165
- }
166
- }
167
-
168
- return resourceDefinitions; // handleResourceGet will stringify this
169
- } catch (error) {
170
- let errorDetails;
171
- if (error instanceof PackageNotFoundError) {
172
- errorDetails = getNotFoundError(
173
- `Package for contents listing matching URI '${uri.href}'`,
174
- );
175
- } else if (
176
- error instanceof Error &&
177
- (error.message.includes("Invalid package name") ||
178
- error.message.includes("Invalid environment name"))
179
- ) {
180
- errorDetails = getNotFoundError(
181
- `Invalid environment/package identifier in URI '${uri.href}'`,
182
- );
183
- } else {
184
- logger.error(
185
- `[MCP Server Error] Error getting package contents for ${uri.href}:`,
186
- { error },
187
- );
188
- errorDetails = getInternalError(
189
- `GetResource (package contents: ${uri.href})`,
190
- error,
191
- );
192
- }
193
- throw new McpGetResourceError(errorDetails);
194
- }
195
- }
196
-
197
- /**
198
- * Registers the Malloy Package resource type with the MCP server.
199
- * Handles listing models/notebooks/sources within packages and getting package details.
200
- */
201
- export function registerPackageResource(
202
- mcpServer: McpServer,
203
- environmentStore: EnvironmentStore,
204
- ): void {
205
- // Define the expected parameter type for the read callback
206
- type ReadPackageParams = {
207
- fsPath?: string; // Expect string
208
- environmentName?: string; // Expect string
209
- packageName?: string; // Expect string
210
- };
211
-
212
- mcpServer.resource(
213
- "package",
214
- new ResourceTemplate(
215
- "malloy://environment/{environmentName}/package/{packageName}",
216
- {
217
- list: undefined, // TODO: Implement and add listAllPackages here if needed
218
- },
219
- ),
220
- (uri, params) =>
221
- handleResourceGet(
222
- uri,
223
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
- params as ReadPackageParams, // Cast params to the updated type
225
- "package",
226
- async ({
227
- environmentName,
228
- packageName,
229
- }: {
230
- // Keep unknown here as it reflects the raw input possibility
231
- // before validation inside the async function
232
- environmentName?: unknown;
233
- packageName?: unknown;
234
- }) => {
235
- try {
236
- if (typeof environmentName !== "string") {
237
- throw new Error("Invalid environment name parameter.");
238
- }
239
- if (typeof packageName !== "string") {
240
- throw new Error("Invalid package name parameter.");
241
- }
242
- const environment = await environmentStore.getEnvironment(
243
- environmentName,
244
- false,
245
- );
246
- const pkg = await environment.getPackage(packageName, false);
247
- return pkg.getPackageMetadata();
248
- } catch (error) {
249
- let errorDetails;
250
- if (error instanceof PackageNotFoundError) {
251
- errorDetails = getNotFoundError(
252
- `Package resource matching URI '${uri.href}'`,
253
- );
254
- } else if (
255
- error instanceof Error &&
256
- (error.message.includes("Invalid package name") ||
257
- error.message.includes("Invalid environment name"))
258
- ) {
259
- errorDetails = getNotFoundError(
260
- `Invalid environment/package identifier in URI '${uri.href}'`,
261
- );
262
- } else {
263
- errorDetails = getInternalError(
264
- `GetResource (package: ${uri.href})`,
265
- error,
266
- );
267
- }
268
- throw new McpGetResourceError(errorDetails);
269
- }
270
- },
271
- RESOURCE_METADATA.package,
272
- ),
273
- );
274
-
275
- // *** Register Package Contents Resource ***
276
- mcpServer.resource(
277
- "package-contents",
278
- new ResourceTemplate(
279
- "malloy://environment/{environmentName}/package/{packageName}/contents",
280
- {
281
- // Contents are listed via GetResource on this specific URI,
282
- // so no general list callback needed here.
283
- list: undefined,
284
- },
285
- ),
286
- // Custom handler because the response format is just the array, not {definition, metadata}
287
- async (
288
- uri: URL,
289
- params: ReadPackageParams,
290
- ): Promise<ReadResourceResult> => {
291
- try {
292
- // Reuse param validation/typing
293
- const validatedParams = params as ReadPackageParams;
294
-
295
- // Get the array of resource definitions
296
- const resourceDefinitions = await handleGetPackageContents(
297
- uri,
298
- validatedParams,
299
- environmentStore,
300
- );
301
-
302
- // Return the array directly as JSON content
303
- return {
304
- contents: [
305
- {
306
- type: "application/json",
307
- uri: uri.href,
308
- text: JSON.stringify(resourceDefinitions, null, 2),
309
- },
310
- ],
311
- };
312
- } catch (error) {
313
- logger.error(
314
- `[MCP Server Error] Error reading package contents ${uri.href}:`,
315
- { error },
316
- );
317
-
318
- let errorDetails: ErrorDetails;
319
-
320
- // Check if it's the specific error thrown by handleGetPackageContents
321
- if (error instanceof McpGetResourceError) {
322
- // Specifically check if it's a 'not found' error from the inner handler
323
- if (error.message.includes("not found")) {
324
- // Re-use the not found details directly
325
- errorDetails = error.details;
326
- } else {
327
- // It was a different McpGetResourceError (e.g., internal from inner handler)
328
- errorDetails = error.details;
329
- }
330
- } else if (error instanceof PackageNotFoundError) {
331
- // Handle PackageNotFoundError specifically if it bubbles up here
332
- errorDetails = getNotFoundError(
333
- `Package for contents listing matching URI '${uri.href}'`,
334
- );
335
- } else if (
336
- error instanceof Error &&
337
- (error.message.includes("Invalid package name") ||
338
- error.message.includes("Invalid environment name"))
339
- ) {
340
- // Handle invalid identifier errors specifically
341
- errorDetails = getNotFoundError(
342
- `Invalid environment/package identifier in URI '${uri.href}'`,
343
- );
344
- } else {
345
- // Handle other unexpected errors
346
- errorDetails = getInternalError(
347
- `GetResource (package contents: ${uri.href})`,
348
- error,
349
- );
350
- }
351
-
352
- // Format the error response
353
- return {
354
- isError: true,
355
- contents: [
356
- {
357
- type: "application/json",
358
- uri: uri.href,
359
- text: JSON.stringify(
360
- {
361
- error: errorDetails.message,
362
- suggestions: errorDetails.suggestions,
363
- },
364
- null,
365
- 2,
366
- ),
367
- },
368
- ],
369
- };
370
- }
371
- },
372
- );
373
- }
@@ -1,122 +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 Query definition type
7
- import { ModelCompilationError } from "../../errors";
8
- import { logger } from "../../logger";
9
- import { EnvironmentStore } from "../../service/environment_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 QueryParams = {
24
- environmentName?: unknown;
25
- packageName?: unknown;
26
- modelPath?: unknown;
27
- queryName?: unknown;
28
- };
29
-
30
- /**
31
- * Registers the Malloy Query resource type (nested within a Model).
32
- */
33
- export function registerQueryResource(
34
- mcpServer: McpServer,
35
- environmentStore: EnvironmentStore,
36
- ): void {
37
- mcpServer.resource(
38
- "query",
39
- new ResourceTemplate(
40
- "malloy://environment/{environmentName}/package/{packageName}/models/{modelPath}/queries/{queryName}",
41
- { list: undefined }, // Listing queries is not supported via this template
42
- ),
43
- (uri, params) =>
44
- handleResourceGet(
45
- uri,
46
- params as QueryParams,
47
- "query",
48
- async (
49
- {
50
- environmentName,
51
- packageName,
52
- modelPath,
53
- queryName,
54
- }: QueryParams,
55
- uri: URL,
56
- ) => {
57
- if (
58
- typeof environmentName !== "string" ||
59
- typeof packageName !== "string" ||
60
- typeof modelPath !== "string" ||
61
- typeof queryName !== "string"
62
- ) {
63
- throw new Error("Invalid parameters for query resource.");
64
- }
65
-
66
- try {
67
- const modelResult = await getModelForQuery(
68
- environmentStore,
69
- environmentName,
70
- packageName,
71
- modelPath,
72
- );
73
- if ("error" in modelResult) {
74
- throw new McpGetResourceError(modelResult.error);
75
- }
76
- const { model } = modelResult;
77
-
78
- // Attempt to get the query definition from the model
79
- const queries = await model.getQueries(); // Assuming this method exists
80
- if (!queries) {
81
- throw new Error("Could not retrieve queries from model.");
82
- }
83
- const query = queries.find(
84
- (q: components["schemas"]["Query"]) =>
85
- q.name === queryName,
86
- );
87
-
88
- if (!query) {
89
- // Specific "Query not found" error
90
- const errorDetails = getNotFoundError(
91
- `Query '${queryName}' in model '${modelPath}' package '${packageName}' environment '${environmentName}'`,
92
- );
93
- throw new McpGetResourceError(errorDetails);
94
- }
95
- return query;
96
- } catch (error) {
97
- if (error instanceof McpGetResourceError) {
98
- throw error; // Re-throw already formatted
99
- }
100
- if (error instanceof ModelCompilationError) {
101
- const errorDetails = getMalloyErrorDetails(
102
- "GetResource (query - model compilation)",
103
- `${environmentName}/${packageName}/${modelPath}`,
104
- error,
105
- );
106
- throw new McpGetResourceError(errorDetails);
107
- }
108
- logger.error(
109
- `[MCP Server Error] Error fetching query '${queryName}' from ${uri.href}:`,
110
- { error },
111
- );
112
- const fallbackErrorDetails = getInternalError(
113
- `GetResource (query: ${uri.href})`,
114
- error,
115
- );
116
- throw new McpGetResourceError(fallbackErrorDetails);
117
- }
118
- },
119
- RESOURCE_METADATA.query,
120
- ),
121
- );
122
- }
@@ -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 { EnvironmentStore } from "../../service/environment_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
- environmentName?: 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
- environmentStore: EnvironmentStore,
37
- ): void {
38
- mcpServer.resource(
39
- "source",
40
- new ResourceTemplate(
41
- "malloy://environment/{environmentName}/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
- environmentName,
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 environmentName !== "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
- environmentStore,
76
- environmentName,
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}' environment '${environmentName}'`,
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
- `${environmentName}/${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
- }