Skip to main content
Glama
index.ts18.6 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from "@modelcontextprotocol/sdk/types.js"; import { ResearchTreeManager } from "./research-tree.js"; const server = new Server( { name: "tiling-trees-mcp", version: "0.3.0", }, { capabilities: { tools: {}, }, } ); const treeManager = new ResearchTreeManager(); // Define available tools const TOOLS: Tool[] = [ { name: "create_tree", description: "Create a new tiling tree to explore a problem/challenge. The tree starts with a root tile representing the complete solution space, which you'll then split recursively using MECE (Mutually Exclusive, Collectively Exhaustive) principles.", inputSchema: { type: "object", properties: { name: { type: "string", description: "Name for this tiling tree", }, problemStatement: { type: "string", description: "The problem or challenge to explore (e.g., 'How can we reduce carbon emissions in transportation?')", }, }, required: ["name", "problemStatement"], }, }, { name: "split_tile", description: "Split a tile into MECE (Mutually Exclusive, Collectively Exhaustive) subsets using a specific attribute/dimension. This is the core operation of the tiling trees method - partitioning the solution space systematically. Use physics/math-oriented splits when possible.", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile to split", }, splitAttribute: { type: "string", description: "The attribute/dimension used to split (e.g., 'energy source', 'scale', 'physical mechanism', 'timeframe')", }, splitRationale: { type: "string", description: "Why this attribute was chosen for splitting", }, subsets: { type: "array", items: { type: "object", properties: { title: { type: "string" }, description: { type: "string", description: "Precise definition of this subset to ensure no overlap with siblings", }, isLeaf: { type: "boolean", description: "True if this is a concrete idea/project (leaf node)", }, }, required: ["title", "description"], }, description: "The mutually exclusive and collectively exhaustive subsets", }, }, required: ["tileId", "splitAttribute", "splitRationale", "subsets"], }, }, { name: "add_tiles_to_split", description: "Add additional tiles to an existing split (when you realize a category was missed). This invalidates the MECE validation and requires re-verification.", inputSchema: { type: "object", properties: { parentId: { type: "string", description: "ID of the parent tile", }, newTiles: { type: "array", items: { type: "object", properties: { title: { type: "string" }, description: { type: "string" }, isLeaf: { type: "boolean" }, }, required: ["title", "description"], }, description: "New tiles to add to the split", }, }, required: ["parentId", "newTiles"], }, }, { name: "mark_mece", description: "Mark a split as validated for MECE (Mutually Exclusive, Collectively Exhaustive) properties. Verify that the children completely cover the parent space with no overlaps.", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile whose split to validate", }, isMECE: { type: "boolean", description: "Whether the split is truly MECE", }, coverageNotes: { type: "string", description: "Notes on the completeness and exclusivity of the split", }, }, required: ["tileId", "isMECE"], }, }, { name: "evaluate_tile", description: "Evaluate a leaf tile (concrete idea/project) on impact, feasibility, and uniqueness. Include any calculations or pilot studies performed.", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile to evaluate", }, impact: { type: "number", description: "Impact rating (1-10 scale)", minimum: 1, maximum: 10, }, feasibility: { type: "number", description: "Feasibility rating (1-10 scale)", minimum: 1, maximum: 10, }, uniqueness: { type: "number", description: "Uniqueness rating (1-10 scale)", minimum: 1, maximum: 10, }, timeframe: { type: "string", description: "Expected timeframe (e.g., '1-2 years', '5-10 years')", }, notes: { type: "string", description: "Additional evaluation notes", }, calculationsOrPilots: { type: "string", description: "Calculations or pilot studies performed to evaluate this idea", }, }, required: ["tileId"], }, }, { name: "update_tile", description: "Update a tile's information (title, description, split attributes, etc.)", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile to update", }, title: { type: "string", description: "New title", }, description: { type: "string", description: "New description (precise definition)", }, splitAttribute: { type: "string", description: "Updated split attribute", }, splitRationale: { type: "string", description: "Updated split rationale", }, isLeaf: { type: "boolean", description: "Mark as leaf node", }, }, required: ["tileId"], }, }, { name: "get_trees", description: "Get all tiling trees", inputSchema: { type: "object", properties: {}, }, }, { name: "get_tile", description: "Get details of a specific tile", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile", }, }, required: ["tileId"], }, }, { name: "explore_path", description: "Explore the tree structure from a specific tile, showing the hierarchical breakdown", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile to explore from", }, depth: { type: "number", description: "How many levels deep to explore (default: 10)", }, }, required: ["tileId"], }, }, { name: "get_leaf_tiles", description: "Get all leaf tiles (concrete ideas/projects) from a tree", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "Optional tree ID to filter by", }, }, }, }, { name: "get_unexplored_tiles", description: "Get tiles that haven't been split yet - these are gaps in your solution space exploration", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "Optional tree ID to filter by", }, }, }, }, { name: "get_top_leaves", description: "Get the highest-rated leaf tiles based on evaluation criteria", inputSchema: { type: "object", properties: { criteria: { type: "string", enum: ["impact", "feasibility", "uniqueness", "combined"], description: "Criteria to sort by", }, limit: { type: "number", description: "Number of results to return (default: 10)", }, treeId: { type: "string", description: "Optional tree ID to filter by", }, }, required: ["criteria"], }, }, { name: "search_tiles", description: "Search for tiles by content", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query", }, treeId: { type: "string", description: "Optional tree ID to filter by", }, }, required: ["query"], }, }, { name: "get_coverage_analysis", description: "Analyze the completeness of solution space exploration for a tree. Shows unexplored branches, unvalidated splits, and suggestions for next steps.", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "ID of the tree to analyze", }, }, required: ["treeId"], }, }, { name: "get_statistics", description: "Get overall statistics about all tiling trees", inputSchema: { type: "object", properties: {}, }, }, { name: "export_tree", description: "Export a tiling tree in various formats for visualization or documentation", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "ID of the tree to export", }, format: { type: "string", enum: ["json", "markdown", "mermaid", "dot"], description: "Export format", }, }, required: ["treeId", "format"], }, }, { name: "validate_split_quality", description: "Validate split quality and detect common antipatterns (vague language, catch-all buckets, mixed dimensions, retroactive splitting, incomplete coverage). Returns a detailed quality report with issues and recommendations.", inputSchema: { type: "object", properties: { tileId: { type: "string", description: "ID of the tile whose split to validate", }, }, required: ["tileId"], }, }, { name: "get_tree_validation_report", description: "Get validation report for all splits in a tree. Identifies antipatterns and provides an overall quality score. Use this after building a tree to check for common failure modes.", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "ID of the tree to validate", }, }, required: ["treeId"], }, }, ]; // Handle tool list requests server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS, })); // Handle tool execution server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { if (!args) { throw new Error("No arguments provided"); } switch (name) { case "create_tree": { const result = treeManager.createTree( args.name as string, args.problemStatement as string ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "split_tile": { const result = treeManager.splitTile( args.tileId as string, args.splitAttribute as string, args.splitRationale as string, args.subsets as any[] ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "add_tiles_to_split": { const result = treeManager.addTilesToSplit( args.parentId as string, args.newTiles as any[] ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "mark_mece": { const result = treeManager.markMECE( args.tileId as string, args.isMECE as boolean, args.coverageNotes as string | undefined ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "evaluate_tile": { const result = treeManager.evaluateTile(args.tileId as string, { impact: args.impact as number | undefined, feasibility: args.feasibility as number | undefined, uniqueness: args.uniqueness as number | undefined, timeframe: args.timeframe as string | undefined, notes: args.notes as string | undefined, calculationsOrPilots: args.calculationsOrPilots as string | undefined, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "update_tile": { const result = treeManager.updateTile(args.tileId as string, { title: args.title as string | undefined, description: args.description as string | undefined, splitAttribute: args.splitAttribute as string | undefined, splitRationale: args.splitRationale as string | undefined, isLeaf: args.isLeaf as boolean | undefined, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_trees": { const result = treeManager.getTrees(); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_tile": { const result = treeManager.getTile(args.tileId as string); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "explore_path": { const result = treeManager.explorePath( args.tileId as string, args.depth as number | undefined ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_leaf_tiles": { const result = treeManager.getLeafTiles(args.treeId as string | undefined); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_unexplored_tiles": { const result = treeManager.getUnexploredTiles( args.treeId as string | undefined ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_top_leaves": { const result = treeManager.getTopLeaves( args.criteria as any, args.limit as number | undefined, args.treeId as string | undefined ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "search_tiles": { const result = treeManager.search( args.query as string, args.treeId as string | undefined ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_coverage_analysis": { const result = treeManager.getCoverageAnalysis(args.treeId as string); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_statistics": { const result = treeManager.getStatistics(); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "export_tree": { const result = treeManager.export( args.format as any, args.treeId as string ); return { content: [ { type: "text", text: result, }, ], }; } case "validate_split_quality": { const result = treeManager.validateSplitQuality(args.tileId as string); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "get_tree_validation_report": { const result = treeManager.getTreeValidationReport(args.treeId as string); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error: ${errorMessage}`, }, ], isError: true, }; } }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Tiling Trees MCP server running on stdio"); } main().catch((error) => { console.error("Server error:", error); process.exit(1); });

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/k-chrispens/tiling-trees-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server