Skip to main content
Glama
moldsim
by moldsim

compare_materials

Compare 2-4 polymer materials side-by-side to evaluate processing, thermal, and mechanical properties. Identifies key differences between thermoplastics to support material selection decisions for injection molding.

Instructions

Compare 2-4 materials side-by-side. Returns a table of processing, thermal, and mechanical properties with key differences highlighted. Available materials: abs-generic, pp-homo, pp-copo, pa6, pa66, pa66-gf30, pc, pc-abs, pom, hdpe, ldpe, pmma, pbt, pbt-gf30, pet, ps, hips, tpu, san, asa, ppe-ps

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
materialsYesList of material IDs to compare (e.g., ["abs-generic", "pc", "pa66-gf30"])

Implementation Reference

  • Main compareMaterials function - takes materialIds array, validates input (2-4 materials), looks up materials, and generates a formatted comparison table with processing, thermal, and mechanical properties plus key differences analysis
    export function compareMaterials(materialIds: string[]): string {
      if (materialIds.length < 2) {
        return 'Please provide at least 2 material IDs to compare.';
      }
      if (materialIds.length > 4) {
        return 'Maximum 4 materials can be compared at once. Please reduce the list.';
      }
    
      const results: { query: string; material: Material | null }[] = materialIds.map(id => {
        const matches = findMaterial(id);
        return { query: id, material: matches[0] ?? null };
      });
    
      const notFound = results.filter(r => !r.material);
      if (notFound.length > 0) {
        return [
          `Materials not found: ${notFound.map(r => `"${r.query}"`).join(', ')}`,
          '',
          'Use get_material_properties to list available material IDs.',
        ].join('\n');
      }
    
      const mats = results.map(r => r.material!);
      const lines: string[] = [];
    
      lines.push(`# Material Comparison: ${mats.map(m => m.name).join(' vs ')}\n`);
    
      // General info
      lines.push('## General');
      lines.push(row('Family', mats.map(m => m.family)));
      lines.push(row('Type', mats.map(m => m.type)));
      lines.push(row('Filler', mats.map(m => m.filler ? `${m.filler} (${m.filler_pct}%)` : '—')));
    
      // Processing window
      lines.push('\n## Processing Window');
      lines.push(row('Melt temp range', mats.map(m => `${m.processing.melt_temp_min_C}–${m.processing.melt_temp_max_C}°C`)));
      lines.push(row('Melt temp (rec)', mats.map(m => `${m.processing.melt_temp_recommended_C}°C`)));
      lines.push(row('Mold temp range', mats.map(m => `${m.processing.mold_temp_min_C}–${m.processing.mold_temp_max_C}°C`)));
      lines.push(row('Mold temp (rec)', mats.map(m => `${m.processing.mold_temp_recommended_C}°C`)));
      lines.push(row('Max shear rate', mats.map(m => `${m.processing.max_shear_rate_1_s} 1/s`)));
      lines.push(row('Drying', mats.map(m =>
        m.processing.drying_temp_C != null
          ? `${m.processing.drying_temp_C}°C / ${m.processing.drying_time_hr}h`
          : 'Not required'
      )));
      lines.push(row('Max residence', mats.map(m => `${m.processing.max_residence_time_min} min`)));
    
      // Thermal
      lines.push('\n## Thermal Properties');
      lines.push(row('Conductivity', mats.map(m => `${m.thermal.thermal_conductivity_W_mK} W/(m·K)`)));
      lines.push(row('Specific heat', mats.map(m => `${m.thermal.specific_heat_J_kgK} J/(kg·K)`)));
      lines.push(row('Density', mats.map(m => `${m.thermal.density_kg_m3} kg/m³`)));
      lines.push(row('Ejection temp', mats.map(m => `${m.thermal.ejection_temp_C}°C`)));
      lines.push(row('No-flow temp', mats.map(m => `${m.thermal.no_flow_temp_C}°C`)));
    
      // Mechanical
      lines.push('\n## Mechanical Properties');
      lines.push(row('Tensile strength', mats.map(m => `${m.mechanical.tensile_strength_MPa} MPa`)));
      lines.push(row('Flexural modulus', mats.map(m => `${m.mechanical.flexural_modulus_MPa} MPa`)));
      lines.push(row('Elongation', mats.map(m => `${m.mechanical.elongation_at_break_pct}%`)));
      lines.push(row('HDT @ 1.8 MPa', mats.map(m => `${m.mechanical.HDT_at_1_8MPa_C}°C`)));
      lines.push(row('Shrinkage', mats.map(m => `${m.mechanical.shrinkage_pct_min}–${m.mechanical.shrinkage_pct_max}%`)));
    
      // Key differences
      lines.push('\n## Key Differences');
      lines.push(...generateKeyDifferences(mats));
    
      lines.push('\n---');
      lines.push('*Data from MoldSim MCP material database. Verify against supplier datasheets for your specific grade.*');
    
      return lines.join('\n');
    }
  • src/server.ts:79-88 (registration)
    Tool registration for compare_materials using server.tool() with Zod schema validation - registers with MCP server
    server.tool(
      'compare_materials',
      `Compare 2-4 materials side-by-side. Returns a table of processing, thermal, and mechanical properties with key differences highlighted. Available materials: ${listMaterials().map(m => m.id).join(', ')}`,
      {
        materials: z.array(z.string()).min(2).max(4).describe('List of material IDs to compare (e.g., ["abs-generic", "pc", "pa66-gf30"])'),
      },
      async ({ materials }) => ({
        content: [{ type: 'text', text: compareMaterials(materials) }],
      })
    );
  • Zod input validation schema for compare_materials - validates materials array must have 2-4 string items
    {
      materials: z.array(z.string()).min(2).max(4).describe('List of material IDs to compare (e.g., ["abs-generic", "pc", "pa66-gf30"])'),
    },
  • Material interface/type definition used by compareMaterials - defines structure for material properties including processing, thermal, and mechanical data
    export interface Material {
      id: string;
      name: string;
      family: string;
      type: 'amorphous' | 'semi-crystalline';
      filler?: string;
      filler_pct?: number;
      mfi_g_10min?: number;
      mfi_condition?: string;
      cross_wlf: CrossWLF;
      tait_pvt: TaitPVT;
      thermal: ThermalProperties;
      processing: ProcessingWindow;
      mechanical: MechanicalProperties;
      notes: string;
    }
  • findMaterial helper function - searches material database by ID/name/family with scoring, returns array of matching Material objects
    export function findMaterial(query: string): Material[] {
      const q = query.toLowerCase().replace(/[^a-z0-9]/g, '');
      if (!q) return [];
    
      const norm = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, '');
      const scored = MATERIALS.map(m => {
        const id = norm(m.id);
        const name = norm(m.name);
        const family = norm(m.family);
        const filler = norm(m.filler ?? '');
    
        if (id === q) return { m, score: 100 };
        if (id.startsWith(q) || q.startsWith(id)) return { m, score: 80 };
        if (id.includes(q) || name.includes(q)) return { m, score: 60 };
        if (family === q) return { m, score: 50 };
        if (family.includes(q)) return { m, score: 30 };
        if (filler.length > 0 && filler.includes(q)) return { m, score: 20 };
        return { m, score: 0 };
      }).filter(({ score }) => score > 0);

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.4.3

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description carries the full burden. It discloses the output (table of properties with differences) and lists available materials, but does not mention whether the operation is read-only, side effects, or data freshness. Adequate but not thorough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no fluff. The first sentence states the core action and output, the second lists available inputs. Well front-loaded and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, no output schema), the description adequately explains input, output, and available options. Sibling tools provide context (e.g., get_material_properties for single material). Slight lack of detail on return format but acceptable without output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'materials' is fully described in the schema (100% coverage). The tool description adds value by listing available material IDs, going beyond the schema's example. Baseline 3 is elevated due to this extra context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool compares 2-4 materials side-by-side, returns a table of processing, thermal, and mechanical properties with key differences highlighted. It also lists available materials, making the purpose specific and distinct from sibling tools like get_material_properties.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly indicates usage for comparing multiple materials but does not explicitly state when to use this tool over alternatives (e.g., get_material_properties for single material). No exclusions or clear context for when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.