From 2f69fdac2b8d01132f8b6034dcb758bde3cd322a Mon Sep 17 00:00:00 2001 From: Bao Date: Fri, 26 Jun 2026 08:13:18 +0700 Subject: [PATCH] feat(filesystem): support base64 write content --- .../__tests__/structured-content.test.ts | 21 +++++++++++++++++++ src/filesystem/index.ts | 16 +++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/filesystem/__tests__/structured-content.test.ts b/src/filesystem/__tests__/structured-content.test.ts index 4b8f92b0a3..fe48d7b416 100644 --- a/src/filesystem/__tests__/structured-content.test.ts +++ b/src/filesystem/__tests__/structured-content.test.ts @@ -123,6 +123,27 @@ describe('structuredContent schema compliance', () => { }); }); + describe('write_file', () => { + it('should decode content_base64 before writing the file', async () => { + const filePath = path.join(testDir, 'base64-write.md'); + const content = '# Test\n\n`inline code` with "quotes" and ${template} literals.\n'; + + const result = await client.callTool({ + name: 'write_file', + arguments: { + path: filePath, + content_base64: Buffer.from(content, 'utf-8').toString('base64') + } + }); + + expect(result.structuredContent).toBeDefined(); + expect(await fs.readFile(filePath, 'utf-8')).toBe(content); + + const structuredContent = result.structuredContent as { content: unknown }; + expect(structuredContent.content).toContain('Successfully wrote'); + }); + }); + describe('list_directory (control - already working)', () => { it('should return structuredContent.content as a string', async () => { const result = await client.callTool({ diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 7b67e63e58..d754308a8c 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -112,7 +112,8 @@ const ReadMultipleFilesArgsSchema = z.object({ const WriteFileArgsSchema = z.object({ path: z.string(), - content: z.string(), + content: z.string().optional(), + content_base64: z.string().optional(), }); const EditOperation = z.object({ @@ -346,14 +347,23 @@ server.registerTool( "Handles text content with proper encoding. Only works within allowed directories.", inputSchema: { path: z.string(), - content: z.string() + content: z.string().optional(), + content_base64: z.string().optional().describe("Base64-encoded UTF-8 content. Use when content contains characters that are hard to serialize safely in JSON.") }, outputSchema: { content: z.string() }, annotations: { readOnlyHint: false, idempotentHint: true, destructiveHint: true } }, async (args: z.infer) => { const validPath = await validatePath(args.path); - await writeFileContent(validPath, args.content); + const content = args.content_base64 !== undefined + ? Buffer.from(args.content_base64, "base64").toString("utf-8") + : args.content; + + if (content === undefined) { + throw new Error("Must provide either content or content_base64"); + } + + await writeFileContent(validPath, content); const text = `Successfully wrote to ${args.path}`; return { content: [{ type: "text" as const, text }],