import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { BirstClient } from "../../client/birstClient.js";
import { z } from "zod";
// Response types
interface BqlMetadata {
bql: string;
columnDescriptions?: string[];
debug?: Record<string, unknown>;
}
interface GenerateBqlResponse {
bqlMetadata: BqlMetadata;
traces?: string[];
}
const inputSchema = z.object({
query: z.string().describe(
"Natural language question about the data (e.g., 'Show me sales by region for 2024')"
),
spaceId: z.string().describe("The Birst space ID to query against"),
spaceName: z.string().optional().describe(
"Optional space name (spaceId takes priority if both provided)"
),
});
export function registerGenerateBql(server: McpServer, client: BirstClient): void {
server.tool(
"birst_generate_bql",
"Convert natural language queries to BQL (Birst Query Language). Use this to translate user questions about data into executable queries.",
inputSchema.shape,
async (args) => {
const { query, spaceId, spaceName } = inputSchema.parse(args);
const headers: Record<string, string> = {};
if (spaceName) {
headers["spaceName"] = spaceName;
}
const response = await client.genai<GenerateBqlResponse>("/generate-bql/", {
method: "POST",
body: {
request: query,
spaceId,
},
headers,
});
const bql = response.bqlMetadata?.bql || "";
const columnDescriptions = response.bqlMetadata?.columnDescriptions || [];
return {
content: [
{
type: "text" as const,
text: JSON.stringify(
{
success: true,
bql,
columnDescriptions,
traces: response.traces,
},
null,
2
),
},
],
};
}
);
}