tacit_list_files
List and filter documents and files for a building site, including spec sheets, 3D models, BIM files, and maintenance documents to answer questions about available documentation.
Instructions
List documents and files associated with a site.
Returns metadata for files uploaded to a site: spec sheets, maintenance documents, BIM source files, 3D models, and knowledge graph data.
Useful for answering questions like "What documentation exists for this building?" or "Are there spec sheets for this equipment?"
Args:
site_id (string, required): The site ID (from tacit_list_sites)
category (string, optional): Filter by file type. One of: kg-csv, model-3d, bim-source, spec-sheet, maintenance, other
entity_uri (string, optional): Filter by associated entity URI (from GraphQL entity.uri field)
Returns: List of files with name, category, size, and upload date.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| site_id | Yes | Site ID from tacit_list_sites | |
| category | No | Filter by category: kg-csv, model-3d, bim-source, spec-sheet, maintenance, other | |
| entity_uri | No | Filter by entity URI |
Implementation Reference
- src/tools/files.ts:69-129 (handler)The asynchronous handler function that processes the tacit_list_files tool request by fetching site files via the API and formatting them into a markdown list.
async ({ site_id, category, entity_uri }) => { try { const params = new URLSearchParams({ site_id }); if (category) params.set("category", category); if (entity_uri) params.set("entity_uri", entity_uri); const files = await restGet<SiteFile[]>( `/api/files/?${params.toString()}`, ); if (!files.length) { const filter = category ? ` in category "${category}"` : ""; return { content: [ { type: "text" as const, text: `No files found for this site${filter}.`, }, ], }; } const lines = [`# Files (${files.length})`, ""]; // Group by category const grouped = new Map<string, SiteFile[]>(); for (const f of files) { const group = grouped.get(f.category) || []; group.push(f); grouped.set(f.category, group); } for (const [cat, catFiles] of grouped) { const label = CATEGORY_LABELS[cat] || cat; lines.push(`## ${label}`); for (const f of catFiles) { const size = formatBytes(f.size_bytes); const date = new Date(f.created_at).toISOString().split("T")[0]; lines.push(`- **${f.name}** (${size}, uploaded ${date})`); if (f.entity_uri) { lines.push(` Entity: ${f.entity_uri}`); } } lines.push(""); } return { content: [{ type: "text" as const, text: lines.join("\n") }], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }, - src/tools/files.ts:49-61 (schema)The input schema definition for the tacit_list_files tool, using Zod for validation of site_id, category, and entity_uri arguments.
inputSchema: { site_id: z.string().describe("Site ID from tacit_list_sites"), category: z .string() .optional() .describe( "Filter by category: kg-csv, model-3d, bim-source, spec-sheet, maintenance, other", ), entity_uri: z .string() .optional() .describe("Filter by entity URI"), }, - src/tools/files.ts:32-130 (registration)The registration function registerFilesTool, which uses the McpServer to register the tacit_list_files tool.
export function registerFilesTool(server: McpServer): void { server.registerTool( "tacit_list_files", { title: "List Site Files", description: `List documents and files associated with a site. Returns metadata for files uploaded to a site: spec sheets, maintenance documents, BIM source files, 3D models, and knowledge graph data. Useful for answering questions like "What documentation exists for this building?" or "Are there spec sheets for this equipment?" Args: - site_id (string, required): The site ID (from tacit_list_sites) - category (string, optional): Filter by file type. One of: kg-csv, model-3d, bim-source, spec-sheet, maintenance, other - entity_uri (string, optional): Filter by associated entity URI (from GraphQL entity.uri field) Returns: List of files with name, category, size, and upload date.`, inputSchema: { site_id: z.string().describe("Site ID from tacit_list_sites"), category: z .string() .optional() .describe( "Filter by category: kg-csv, model-3d, bim-source, spec-sheet, maintenance, other", ), entity_uri: z .string() .optional() .describe("Filter by entity URI"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ site_id, category, entity_uri }) => { try { const params = new URLSearchParams({ site_id }); if (category) params.set("category", category); if (entity_uri) params.set("entity_uri", entity_uri); const files = await restGet<SiteFile[]>( `/api/files/?${params.toString()}`, ); if (!files.length) { const filter = category ? ` in category "${category}"` : ""; return { content: [ { type: "text" as const, text: `No files found for this site${filter}.`, }, ], }; } const lines = [`# Files (${files.length})`, ""]; // Group by category const grouped = new Map<string, SiteFile[]>(); for (const f of files) { const group = grouped.get(f.category) || []; group.push(f); grouped.set(f.category, group); } for (const [cat, catFiles] of grouped) { const label = CATEGORY_LABELS[cat] || cat; lines.push(`## ${label}`); for (const f of catFiles) { const size = formatBytes(f.size_bytes); const date = new Date(f.created_at).toISOString().split("T")[0]; lines.push(`- **${f.name}** (${size}, uploaded ${date})`); if (f.entity_uri) { lines.push(` Entity: ${f.entity_uri}`); } } lines.push(""); } return { content: [{ type: "text" as const, text: lines.join("\n") }], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }, );