Get Filament
get_filamentLook up detailed filament information by ID or name, with manufacturer and material filters to resolve ambiguous names.
Instructions
Get detailed information about a specific filament. Prefer lookup by ID (the [ID ] value returned by search_filaments) — that is the only unambiguous key. Name lookups are accepted but many filaments share the same name (e.g. "Black", "Jade White") because SpoolmanDB names are often colour-only; if a name is ambiguous you will get back a disambiguation list with IDs. You can pass manufacturer and material alongside name to narrow the match, or pass the full search_filaments display label (e.g. "[ID 1234] Bambu Lab — PLA — Jade White") in the name field and it will be parsed.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Filament ID (preferred — copy the [ID N] value from search_filaments). Accepts either a number or a numeric string (LLM clients often serialise IDs as strings). | |
| name | No | Filament name. Accepts the bare name field (e.g. "Jade White"), or a full display label like "[ID 1234] Bambu Lab — PLA — Jade White". | |
| manufacturer | No | Optional disambiguator when looking up by name. | |
| material | No | Optional material disambiguator when looking up by name (e.g. "PLA", "PETG"). |
Implementation Reference
- src/tools/get-filament.ts:110-218 (handler)Registers the 'get_filament' MCP tool with server, including input schema (id, name, manufacturer, material) and the async handler that performs filament lookup by ID or by name with disambiguation.
export function registerGetFilament( server: McpServer, db: Database.Database, ): void { server.registerTool( 'get_filament', { title: 'Get Filament', description: 'Get detailed information about a specific filament. Prefer lookup by ID (the [ID <n>] value returned by search_filaments) — that is the only unambiguous key. Name lookups are accepted but many filaments share the same name (e.g. "Black", "Jade White") because SpoolmanDB names are often colour-only; if a name is ambiguous you will get back a disambiguation list with IDs. You can pass `manufacturer` and `material` alongside `name` to narrow the match, or pass the full search_filaments display label (e.g. "[ID 1234] Bambu Lab — PLA — Jade White") in the `name` field and it will be parsed.', inputSchema: { id: z .union([ z.number().int().nonnegative(), z .string() .regex(/^\d+$/, 'id must be a non-negative integer') .transform((s) => Number.parseInt(s, 10)), ]) .optional() .describe( 'Filament ID (preferred — copy the [ID N] value from search_filaments). Accepts either a number or a numeric string (LLM clients often serialise IDs as strings).', ), name: z .string() .optional() .describe( 'Filament name. Accepts the bare name field (e.g. "Jade White"), or a full display label like "[ID 1234] Bambu Lab — PLA — Jade White".', ), manufacturer: z .string() .optional() .describe('Optional disambiguator when looking up by name.'), material: z .string() .optional() .describe( 'Optional material disambiguator when looking up by name (e.g. "PLA", "PETG").', ), }, }, async ({ id, name, manufacturer, material }) => { let filament: FilamentRow | null = null; // 1. Direct ID lookup wins. if (id != null) { filament = getFilamentById(db, id); } else if (name != null) { // 2. Try parsing a display label first — it may contain an ID and/or // manufacturer + material that uniquely identify the filament. const parsed = parseDisplayLabel(name); if (parsed?.id != null) { filament = getFilamentById(db, parsed.id); } else { const effectiveName = parsed?.name ?? name; const effectiveMfg = manufacturer ?? parsed?.manufacturer; const effectiveMaterial = material ?? parsed?.material; const matches = findFilamentsByName( db, effectiveName, effectiveMfg, effectiveMaterial, ); if (matches.length === 1) { filament = matches[0]; } else if (matches.length > 1) { return { isError: true, content: [ { type: 'text' as const, text: formatDisambiguation(matches, effectiveName), }, ], }; } } } else { return { isError: true, content: [ { type: 'text' as const, text: 'Please provide either an id or name. Use search_filaments to find filaments first — every result includes an [ID N] value to copy.', }, ], }; } if (!filament) { return { isError: true, content: [ { type: 'text' as const, text: `Filament not found. Try using search_filaments to find the correct ID, then pass that ID directly.`, }, ], }; } return { content: [ { type: 'text' as const, text: formatFilamentDetail(filament) }, ], }; }, ); } - src/tools/get-filament.ts:120-149 (schema)Input schema for get_filament: accepts optional id (number or numeric string), optional name (bare name or full display label), optional manufacturer and material for disambiguation.
inputSchema: { id: z .union([ z.number().int().nonnegative(), z .string() .regex(/^\d+$/, 'id must be a non-negative integer') .transform((s) => Number.parseInt(s, 10)), ]) .optional() .describe( 'Filament ID (preferred — copy the [ID N] value from search_filaments). Accepts either a number or a numeric string (LLM clients often serialise IDs as strings).', ), name: z .string() .optional() .describe( 'Filament name. Accepts the bare name field (e.g. "Jade White"), or a full display label like "[ID 1234] Bambu Lab — PLA — Jade White".', ), manufacturer: z .string() .optional() .describe('Optional disambiguator when looking up by name.'), material: z .string() .optional() .describe( 'Optional material disambiguator when looking up by name (e.g. "PLA", "PETG").', ), }, - src/server.ts:44-44 (registration)Registration call in the server setup: calls registerGetFilament (imported from src/tools/get-filament.ts) to register the tool on the MCP server.
registerGetFilament(server, db); - src/tools/get-filament.ts:16-45 (helper)Parses a search_filaments display label like '[ID 1234] Bambu Lab — PLA — Jade White' back into its components (id, manufacturer, material, name).
export function parseDisplayLabel(input: string): { id?: number; manufacturer?: string; material?: string; name?: string; } | null { const trimmed = input.trim(); // Try to extract a leading "[ID N]" prefix. const idMatch = trimmed.match(/^\[ID\s+(\d+)\]\s*(.*)$/); let rest = trimmed; let id: number | undefined; if (idMatch) { id = Number(idMatch[1]); rest = idMatch[2].trim(); } // Split on em dash with surrounding spaces. Hyphen-minus also tolerated. const parts = rest.split(/\s+[—–-]\s+/); if (parts.length === 3) { return { id, manufacturer: parts[0].trim(), material: parts[1].trim(), name: parts[2].trim(), }; } if (id != null) { return { id }; } return null; } - src/tools/get-filament.ts:93-108 (helper)Formats a disambiguation message listing multiple filament matches with their IDs, manufacturer, material, name, and diameter when a name lookup is ambiguous.
function formatDisambiguation(rows: FilamentRow[], name: string): string { const lines: string[] = []; lines.push( `Multiple filaments match name "${name}" (${rows.length} matches). Use the ID with get_filament for an exact match, or pass manufacturer/material to disambiguate:`, ); lines.push(''); for (const r of rows.slice(0, 25)) { lines.push( `- [ID ${r.id}] ${r.manufacturer_name} — ${r.material_name} — ${r.name} (${r.diameter}mm)`, ); } if (rows.length > 25) { lines.push(`... and ${rows.length - 25} more.`); } return lines.join('\n'); }