@malloy-publisher/server 0.0.76 → 0.0.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/assets/RenderedResult-BAZuT25g-etaZB-YF.js +2 -0
- package/dist/app/assets/index-BKC-ikb3.css +1 -0
- package/dist/app/assets/index-BsMlh93-.js +210 -0
- package/dist/app/assets/index-BsXDwHRS.js +671 -0
- package/dist/app/assets/index-DQrKrnRW.js +432 -0
- package/dist/app/assets/index.umd-DaHgfkHn.js +2078 -0
- package/dist/app/index.html +2 -2
- package/dist/server.js +4319 -185
- package/dxt/malloy_bridge.py +354 -0
- package/dxt/manifest.json +22 -0
- package/malloy_mcp.dxt +0 -0
- package/package.json +2 -1
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tools/discovery_tools.ts +258 -0
- package/src/mcp/tools/execute_query_tool.ts +14 -10
- package/src/service/model.ts +11 -0
- package/src/service/package.spec.ts +3 -0
- package/src/service/package.ts +12 -0
- package/dist/app/assets/RenderedResult-DXlUZo0k-lc5JU6CQ.js +0 -1
- package/dist/app/assets/index--hbjs-yl.js +0 -3414
- package/dist/app/assets/index-C127D7lT.css +0 -1
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import {
|
|
3
|
-
McpError,
|
|
4
|
-
ErrorCode,
|
|
5
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
6
3
|
import { z } from "zod";
|
|
7
4
|
import { ProjectStore } from "../../service/project_store";
|
|
8
5
|
import { getModelForQuery } from "../handler_utils";
|
|
@@ -13,16 +10,23 @@ import { buildMalloyUri } from "../handler_utils";
|
|
|
13
10
|
// Zod shape defining required/optional params for executeQuery
|
|
14
11
|
const executeQueryShape = {
|
|
15
12
|
// projectName is required; other fields mirror SDK expectations
|
|
16
|
-
projectName: z
|
|
17
|
-
|
|
13
|
+
projectName: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe(
|
|
16
|
+
"Project name. Project names are listed in the malloy resource list.",
|
|
17
|
+
),
|
|
18
|
+
packageName: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe(
|
|
21
|
+
"Package containing the model. Package names are listed in the malloy resource list.",
|
|
22
|
+
),
|
|
18
23
|
modelPath: z.string().describe("Path to the .malloy model file"),
|
|
19
24
|
query: z.string().optional().describe("Ad-hoc Malloy query code"),
|
|
20
25
|
sourceName: z.string().optional().describe("Source name for a view"),
|
|
21
26
|
queryName: z.string().optional().describe("Named query or view"),
|
|
22
27
|
};
|
|
23
28
|
|
|
24
|
-
//
|
|
25
|
-
type ExecuteQueryParams = z.infer<z.ZodObject<typeof executeQueryShape>>;
|
|
29
|
+
// Type inference is handled automatically by the MCP server based on the executeQueryShape
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* Registers the malloy/executeQuery tool with the MCP server.
|
|
@@ -32,11 +36,11 @@ export function registerExecuteQueryTool(
|
|
|
32
36
|
projectStore: ProjectStore,
|
|
33
37
|
): void {
|
|
34
38
|
mcpServer.tool(
|
|
35
|
-
"
|
|
39
|
+
"malloy_executeQuery",
|
|
36
40
|
"Executes a Malloy query (either ad-hoc or a named query/view defined in a model) against the specified model and returns the results as JSON.",
|
|
37
41
|
executeQueryShape,
|
|
38
42
|
/** Handles requests for the malloy/executeQuery tool */
|
|
39
|
-
async (params
|
|
43
|
+
async (params) => {
|
|
40
44
|
// Destructure projectName as well
|
|
41
45
|
const {
|
|
42
46
|
projectName,
|
package/src/service/model.ts
CHANGED
|
@@ -633,4 +633,15 @@ export class Model {
|
|
|
633
633
|
public getModelType(): ModelType {
|
|
634
634
|
return this.modelType;
|
|
635
635
|
}
|
|
636
|
+
|
|
637
|
+
public async getFileText(packagePath: string): Promise<string> {
|
|
638
|
+
const fullPath = path.join(packagePath, this.modelPath);
|
|
639
|
+
try {
|
|
640
|
+
return await fs.readFile(fullPath, "utf8");
|
|
641
|
+
} catch {
|
|
642
|
+
throw new ModelNotFoundError(
|
|
643
|
+
`Model file not found: ${this.modelPath}`,
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
636
647
|
}
|
|
@@ -47,7 +47,9 @@ describe("service/package", () => {
|
|
|
47
47
|
it("should create a package instance", async () => {
|
|
48
48
|
// Using 'as any' for simplified mock Map value in test
|
|
49
49
|
const pkg = new Package(
|
|
50
|
+
"testProject",
|
|
50
51
|
"testPackage",
|
|
52
|
+
testPackageDirectory,
|
|
51
53
|
{ name: "testPackage", description: "Test package" },
|
|
52
54
|
[],
|
|
53
55
|
new Map([
|
|
@@ -133,6 +135,7 @@ describe("service/package", () => {
|
|
|
133
135
|
const packageInstance = new Package(
|
|
134
136
|
"testProject",
|
|
135
137
|
"testPackage",
|
|
138
|
+
testPackageDirectory,
|
|
136
139
|
{ name: "testPackage", description: "Test package" },
|
|
137
140
|
[],
|
|
138
141
|
new Map([
|
package/src/service/package.ts
CHANGED
|
@@ -37,6 +37,7 @@ export class Package {
|
|
|
37
37
|
private databases: ApiDatabase[];
|
|
38
38
|
private models: Map<string, Model> = new Map();
|
|
39
39
|
private scheduler: Scheduler | undefined;
|
|
40
|
+
private packagePath: string;
|
|
40
41
|
private static meter = metrics.getMeter("publisher");
|
|
41
42
|
private static packageLoadHistogram = this.meter.createHistogram(
|
|
42
43
|
"malloy_package_load_duration",
|
|
@@ -49,6 +50,7 @@ export class Package {
|
|
|
49
50
|
constructor(
|
|
50
51
|
projectName: string,
|
|
51
52
|
packageName: string,
|
|
53
|
+
packagePath: string,
|
|
52
54
|
packageMetadata: ApiPackage,
|
|
53
55
|
databases: ApiDatabase[],
|
|
54
56
|
models: Map<string, Model>,
|
|
@@ -56,6 +58,7 @@ export class Package {
|
|
|
56
58
|
) {
|
|
57
59
|
this.projectName = projectName;
|
|
58
60
|
this.packageName = packageName;
|
|
61
|
+
this.packagePath = packagePath;
|
|
59
62
|
this.packageMetadata = packageMetadata;
|
|
60
63
|
this.databases = databases;
|
|
61
64
|
this.models = models;
|
|
@@ -106,6 +109,7 @@ export class Package {
|
|
|
106
109
|
return new Package(
|
|
107
110
|
projectName,
|
|
108
111
|
packageName,
|
|
112
|
+
packagePath,
|
|
109
113
|
packageConfig,
|
|
110
114
|
databases,
|
|
111
115
|
models,
|
|
@@ -143,6 +147,14 @@ export class Package {
|
|
|
143
147
|
return this.models.get(modelPath);
|
|
144
148
|
}
|
|
145
149
|
|
|
150
|
+
public async getModelFileText(modelPath: string): Promise<string> {
|
|
151
|
+
const model = this.getModel(modelPath);
|
|
152
|
+
if (!model) {
|
|
153
|
+
throw new Error(`Model not found: ${modelPath}`);
|
|
154
|
+
}
|
|
155
|
+
return await model.getFileText(this.packagePath);
|
|
156
|
+
}
|
|
157
|
+
|
|
146
158
|
public async listModels(): Promise<ApiModel[]> {
|
|
147
159
|
const values = await Promise.all(
|
|
148
160
|
Array.from(this.models.keys())
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r,i as y,j as b}from"./index--hbjs-yl.js";function w({result:o,height:E,isFillElement:c,onSizeChange:f,onDrill:p}){const e=r.useRef(null),[d,h]=r.useState(!1),[m,x]=r.useState(!1),[g,v]=r.useState(!1),n=r.useRef(null),t=r.useRef(null);if(r.useLayoutEffect(()=>{if(e.current&&o&&!m){x(!0),n.current||(n.current=new Promise(s=>{t.current=s}));const u=new y.MalloyRenderer({onClick:p}).createViz();for(;e.current.firstChild;)e.current.removeChild(e.current.firstChild);const l=new MutationObserver(s=>{for(const i of s)if(i.type==="childList"&&i.addedNodes.length>0&&Array.from(i.addedNodes).some(a=>a.nodeType===Node.ELEMENT_NODE)){l.disconnect(),setTimeout(()=>{h(!0),t.current&&(t.current(),t.current=null,n.current=null)},50);break}});if(e.current){l.observe(e.current,{childList:!0,subtree:!0,characterData:!0});try{u.setResult(JSON.parse(o)),u.render(e.current)}catch(s){console.error("Error rendering visualization:",s),l.disconnect(),h(!0),t.current&&(t.current(),t.current=null,n.current=null)}}}},[o,p,m]),r.useEffect(()=>{h(!1),x(!1),n.current=null,t.current=null},[o]),m&&!d&&n.current)throw n.current;return r.useEffect(()=>{if(!e.current||!d)return;const u=e.current,l=()=>{if(u){const a=u.offsetHeight;a>0?f&&f(a):c&&u.firstChild&&(u.firstChild.offsetHeight==0?c(!0):c(!1))}},s=setTimeout(l,100);let i=null;return g||(i=new MutationObserver(l),i.observe(u,{childList:!0,subtree:!0,attributes:!0})),()=>{clearTimeout(s),i?.disconnect()}},[f,o,c,d]),b.jsx("div",{ref:e,style:{width:"100%",height:E?`${E}px`:"100%"}})}export{w as default};
|