upload_content
Upload text content for RAG indexing to make it searchable in a knowledge base. The tool processes content and adds metadata for information retrieval.
Instructions
Upload text content to the FileSearchStore for RAG indexing. The content will be processed and made searchable.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Text content to upload to the knowledge base | |
| displayName | Yes | Display name for the content in the store | |
| metadata | No | Custom metadata as key-value pairs. Values can be strings or numbers. Maximum 20 entries per document. Example: {"category": "guide", "year": 2025} |
Implementation Reference
- The execute method that implements the core logic of the upload_content tool. It ensures the FileSearchStore exists, prepares upload arguments including metadata conversion, calls geminiClient.uploadContent, and returns a structured response.async execute( args: UploadContentArgs, ): Promise<MCPToolResponse<UploadContentResult>> { const { geminiClient, storeDisplayName } = this.context; // Ensure store exists const store = await geminiClient.ensureStore(storeDisplayName); // Upload content const uploadArgs: { storeName: string; content: string; displayName: string; metadata?: CustomMetadata[]; } = { storeName: store.name, content: args.content, displayName: args.displayName, }; if (args.metadata) { uploadArgs.metadata = convertMetadataInput(args.metadata); } const result = await geminiClient.uploadContent(uploadArgs); return { success: true, message: `Content uploaded successfully: ${args.displayName}`, data: { documentName: result.documentName, displayName: args.displayName, storeName: store.name, contentLength: args.content.length, }, }; }
- Zod input schema validation for the upload_content tool parameters: content, displayName, and optional metadata.getInputSchema() { return z.object({ content: z .string() .min(1) .describe("Text content to upload to the knowledge base"), displayName: z .string() .min(1) .describe("Display name for the content in the store"), metadata: z .record(z.union([z.string(), z.number()])) .optional() .describe( "Custom metadata as key-value pairs. Values can be strings or numbers. Maximum 20 entries per document. Example: {\"category\": \"guide\", \"year\": 2025}", ), }); }
- src/server/tool-registry.ts:24-36 (registration)ToolRegistry.initialize creates an instance of UploadContentTool and stores it in the toolInstances map for later registration.initialize(context: ToolContext): void { // Manual tool registration for safety and explicit review const tools: Tool[] = [ new UploadFileTool(context), new UploadContentTool(context), new QueryTool(context), ]; for (const tool of tools) { this.toolInstances.set(tool.name, tool); } console.log(`✅ ToolRegistry initialized with ${String(this.toolInstances.size)} tools`);
- src/server/tool-registry.ts:43-56 (registration)ToolRegistry.setupToolHandlers registers each tool (including upload_content) with the MCP server using the tool's name, description, inputSchema from getInputSchema(), and bound handler method from BaseTool.setupToolHandlers(): void { for (const tool of this.toolInstances.values()) { // Pass Zod schema directly to MCP SDK // SDK handles JSON Schema conversion internally for both stdio and HTTP transports this.server.registerTool( tool.name, { description: tool.description, inputSchema: tool.getInputSchema().shape, }, tool.handler.bind(tool) as never, ); this.registeredTools.push(tool.name); }
- src/clients/gemini-client.ts:247-275 (helper)GeminiClient.uploadContent method called by the tool handler to perform the actual content upload to the FileSearchStore as a text/plain blob.async uploadContent(args: { storeName: string; content: string; displayName: string; metadata?: CustomMetadata[]; }): Promise<UploadFileResult> { const encoder = new TextEncoder(); const contentBytes = encoder.encode(args.content); const blob = new Blob([contentBytes], { type: "text/plain" }); const uploadArgs: { storeName: string; blob: Blob; mimeType: string; displayName: string; metadata?: CustomMetadata[]; } = { storeName: args.storeName, blob, mimeType: "text/plain", displayName: args.displayName, }; if (args.metadata) { uploadArgs.metadata = args.metadata; } return await this.uploadBlob(uploadArgs); }