From 8859108a3ef37c7b6c52609528db3ed57838082f Mon Sep 17 00:00:00 2001 From: baxkspace Date: Wed, 8 Oct 2025 22:16:37 +0900 Subject: [PATCH 01/42] Update user story issue templates --- .github/ISSUE_TEMPLATE/GENERAL.md | 1 + .github/ISSUE_TEMPLATE/user-story---tasks.md | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/user-story---tasks.md diff --git a/.github/ISSUE_TEMPLATE/GENERAL.md b/.github/ISSUE_TEMPLATE/GENERAL.md index 991da020..84cea1c7 100644 --- a/.github/ISSUE_TEMPLATE/GENERAL.md +++ b/.github/ISSUE_TEMPLATE/GENERAL.md @@ -6,6 +6,7 @@ labels: '' assignees: '' --- + diff --git a/.github/ISSUE_TEMPLATE/user-story---tasks.md b/.github/ISSUE_TEMPLATE/user-story---tasks.md new file mode 100644 index 00000000..f8b8a076 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/user-story---tasks.md @@ -0,0 +1,16 @@ +--- +name: user story & tasks +about: user story 및 하위 태스크 작성 +title: 'Onedrive-download/User Story 1.2:' +labels: '' +assignees: '' + +--- + +### 📬 User Story 2 (main title of user story) +#### 개발자로서, ~~ +_부연 설명 및 참고 사항_ + +--- +* **Tasks** + - [ ] task 내용 From 205d739c374e7a5591de43b817505622b71f701d Mon Sep 17 00:00:00 2001 From: hyobin Date: Sun, 12 Oct 2025 03:56:56 +0900 Subject: [PATCH 02/42] First commit, add PPTFontFixAppSettings for PPT Font Fix Configurations --- .../Configurations/PPTFontFixAppSettings.cs | 19 +++++++++++++++++++ .../McpSamples.PptFontFix.HybridApp.csproj | 15 +++++++++++++++ .../Program.cs | 1 + 3 files changed, 35 insertions(+) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs new file mode 100644 index 00000000..d6bcba2d --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -0,0 +1,19 @@ +using McpSamples.Shared.Configurations; + +using Microsoft.OpenApi.Models; + +namespace McpSamples.TodoList.HybridApp.Configurations; + +/// +/// This represents the application settings for ppt-font-fix app. +/// +public class PPTFontFixAppSettings : AppSettings +{ + /// + public override OpenApiInfo OpenApi { get; set; } = new() + { + Title = "MCP PPT Font Fix", + Version = "1.0.0", + Description = "A simple MCP server for managing PPT font fixing." + }; +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj new file mode 100644 index 00000000..d17a0750 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -0,0 +1,15 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -0,0 +1 @@ + \ No newline at end of file From 211f782f4b5190ac380e13e6cde360c9381fc2a3 Mon Sep 17 00:00:00 2001 From: hyobin Date: Sun, 12 Oct 2025 04:05:14 +0900 Subject: [PATCH 03/42] Add README.md --- ppt-font-fix/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ppt-font-fix/README.md diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md new file mode 100644 index 00000000..8c17d346 --- /dev/null +++ b/ppt-font-fix/README.md @@ -0,0 +1,3 @@ +# MCP Server: PPT Font Fix + +This is an MCP server that finds fonts in a .pptx file, analyzes their usages - used, unused, inconsistently used, and fixes it. \ No newline at end of file From 8c2d1447fee7a587a7733893b820eaebc5b0542c Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 12 Oct 2025 23:14:33 +0900 Subject: [PATCH 04/42] feat(ppt-font-fix): Add FontFixService interface and class for open ppt file --- .../Services/PPTFontFixService.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs new file mode 100644 index 00000000..937cf8bd --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -0,0 +1,47 @@ +using DocumentFormat.OpenXml.Packaging; +using Microsoft.Extensions.Logging; +using ModelContextProtocol.Server; + +namespace McpSamples.PptFontFix.HybridApp.Services; + +/// +/// This provides interface for PPT font fixing operations. +/// +public interface IPPTFontFixService +{ + /// + /// open a PPT file. + /// + /// + Task OpenPPTFileAsync(string filePath); +} + +/// +/// This represents the service entity for PPT font fixing. +/// +/// +public class PPTFontFixService(ILogger logger) : IPPTFontFixService +{ + /// + public async Task OpenPPTFileAsync(string filePath) + { + ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); + if (File.Exists(filePath) == false) + { + throw new FileNotFoundException("PPT file does not exist.", filePath); + } + + try + { + var presentationDocument = PresentationDocument.Open(filePath, false); + await Task.CompletedTask; + + logger.LogInformation("PPT file opened successfully: {FilePath}", filePath); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to open PPT file: {FilePath}", filePath); + throw; + } + } +} \ No newline at end of file From f1db1106a6ff36a0e5d826c79646fa54a3280f5d Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Tue, 14 Oct 2025 03:10:01 +0900 Subject: [PATCH 05/42] fix(ppt-font-fix): Change from OpenXML SDK to ShapeCrawler and Add Program.cs for program build --- ppt-font-fix/README.md | 3 +++ .../Configurations/PPTFontFixAppSettings.cs | 19 +++++++++++++++ .../McpSamples.PptFontFix.HybridApp.csproj | 20 ++++++++++++++++ .../Program.cs | 24 +++++++++++++++++++ .../Services/PPTFontFixService.cs | 10 ++++---- 5 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 ppt-font-fix/README.md create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md new file mode 100644 index 00000000..8c17d346 --- /dev/null +++ b/ppt-font-fix/README.md @@ -0,0 +1,3 @@ +# MCP Server: PPT Font Fix + +This is an MCP server that finds fonts in a .pptx file, analyzes their usages - used, unused, inconsistently used, and fixes it. \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs new file mode 100644 index 00000000..247e78e3 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -0,0 +1,19 @@ +using McpSamples.Shared.Configurations; + +using Microsoft.OpenApi.Models; + +namespace McpSamples.PPTFontFix.HybridApp.Configurations; + +/// +/// This represents the application settings for ppt-font-fix app. +/// +public class PPTFontFixAppSettings : AppSettings +{ + /// + public override OpenApiInfo OpenApi { get; set; } = new() + { + Title = "MCP PPT Font Fix", + Version = "1.0.0", + Description = "A simple MCP server for managing PPT font fixing." + }; +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj new file mode 100644 index 00000000..df9a3ba0 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -0,0 +1,20 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs new file mode 100644 index 00000000..8ec69bf2 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using McpSamples.PptFontFix.HybridApp.Services; + +using Microsoft.Extensions.Logging; + +class Program +{ + static async Task Main(string[] args) + { + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddConsole(); + }); + ILogger logger = loggerFactory.CreateLogger(); + + string testFilePath = "test.pptx"; + + var pptService = new PPTFontFixService(logger); + + await pptService.OpenPPTFileAsync(testFilePath); + } +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 937cf8bd..7ff22986 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -1,4 +1,4 @@ -using DocumentFormat.OpenXml.Packaging; +using ShapeCrawler; using Microsoft.Extensions.Logging; using ModelContextProtocol.Server; @@ -33,14 +33,14 @@ public async Task OpenPPTFileAsync(string filePath) try { - var presentationDocument = PresentationDocument.Open(filePath, false); - await Task.CompletedTask; + var presentation = new Presentation(filePath); + logger.LogInformation("PPT file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); - logger.LogInformation("PPT file opened successfully: {FilePath}", filePath); + await Task.CompletedTask; } catch (Exception ex) { - logger.LogError(ex, "Failed to open PPT file: {FilePath}", filePath); + logger.LogError(ex, "Failed to open PPT file with ShapeCrawler: {FilePath}", filePath); throw; } } From 542d7487f9db4a51e9ecd6119a784cb8c37e1d8d Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 20 Oct 2025 05:10:23 +0900 Subject: [PATCH 06/42] fix(ppt-font-fix): set the basic structure --- ppt-font-fix/McpPptFontFix.sln | 53 +++++++++++++++++++ .../Properties/launchSettings.json | 23 ++++++++ .../appsettings.Development.json | 8 +++ .../appsettings.json | 9 ++++ 4 files changed, 93 insertions(+) create mode 100644 ppt-font-fix/McpPptFontFix.sln create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json diff --git a/ppt-font-fix/McpPptFontFix.sln b/ppt-font-fix/McpPptFontFix.sln new file mode 100644 index 00000000..6e2e1de3 --- /dev/null +++ b/ppt-font-fix/McpPptFontFix.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSamples.PptFontFix.HybridApp", "src\McpSamples.PptFontFix.HybridApp\McpSamples.PptFontFix.HybridApp.csproj", "{4E3C401C-B16C-459D-8AFC-896CCF5DBACF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSamples.Shared", "..\shared\McpSamples.Shared\McpSamples.Shared.csproj", "{1F4DA2CA-2377-4800-A275-02F65E68CC2D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x64.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x86.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x86.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|Any CPU.Build.0 = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x64.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x64.Build.0 = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x86.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x86.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x64.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x64.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x86.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x86.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|Any CPU.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x64.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x64.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x86.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} + EndGlobalSection +EndGlobal diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json new file mode 100644 index 00000000..f518aeb2 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7013;http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 1e8686bdc802bad435c7318f57e262febc9906ba Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 20 Oct 2025 05:13:42 +0900 Subject: [PATCH 07/42] fix(ppt-font-fix): Set the basic structure and Tools Directory --- ppt-font-fix/McpPptFontFix.sln | 53 ++++++++++++++++++ .../Properties/launchSettings.json | 23 ++++++++ .../Tools/PPTFontFixTool.cs | 54 +++++++++++++++++++ .../appsettings.Development.json | 8 +++ .../appsettings.json | 9 ++++ 5 files changed, 147 insertions(+) create mode 100644 ppt-font-fix/McpPptFontFix.sln create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json diff --git a/ppt-font-fix/McpPptFontFix.sln b/ppt-font-fix/McpPptFontFix.sln new file mode 100644 index 00000000..6e2e1de3 --- /dev/null +++ b/ppt-font-fix/McpPptFontFix.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSamples.PptFontFix.HybridApp", "src\McpSamples.PptFontFix.HybridApp\McpSamples.PptFontFix.HybridApp.csproj", "{4E3C401C-B16C-459D-8AFC-896CCF5DBACF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McpSamples.Shared", "..\shared\McpSamples.Shared\McpSamples.Shared.csproj", "{1F4DA2CA-2377-4800-A275-02F65E68CC2D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x64.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x86.ActiveCfg = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Debug|x86.Build.0 = Debug|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|Any CPU.Build.0 = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x64.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x64.Build.0 = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x86.ActiveCfg = Release|Any CPU + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF}.Release|x86.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x64.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x64.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x86.ActiveCfg = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Debug|x86.Build.0 = Debug|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|Any CPU.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x64.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x64.Build.0 = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x86.ActiveCfg = Release|Any CPU + {1F4DA2CA-2377-4800-A275-02F65E68CC2D}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4E3C401C-B16C-459D-8AFC-896CCF5DBACF} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} + EndGlobalSection +EndGlobal diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json new file mode 100644 index 00000000..f518aeb2 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7013;http://localhost:5166", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs new file mode 100644 index 00000000..6f4fcea3 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.Logging; +using System.ComponentModel; +using System; +using System.Threading.Tasks; +using McpSamples.PptFontFix.HybridApp.Services; + +using ModelContextProtocol.Server; + +namespace McpSamples.PptFontFix.HybridApp.Tools; + +/// +/// This provides interface for the PPT font fix tool. +/// + +public interface IPPTFontFixTool +{ + /// + /// open a PPT file. + /// + /// + /// Returns the result as a string. + Task OpenPPTFileAsync(string filePath); +} + +/// +/// This represents the tool entity for PPT font fixing. +/// +/// instance. +/// instance. +[McpServerToolType] +public class PPTFontFixTool(IPPTFontFixService service, ILogger logger) : IPPTFontFixTool +{ + /// + [McpServerTool(Name = "open_ppt_file", Title = "Open a PPT File")] + [Description("Opens a PPT file and verifies it using ShapeCrawler.")] + public async Task OpenPPTFileAsync( + [Description("The path of the PPT file to open")] string filePath) + { + try + { + await service.OpenPPTFileAsync(filePath).ConfigureAwait(false); + + logger.LogInformation("PPT file opened successfully: {FilePath}", filePath); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to open PPT file: {FilePath}", filePath); + + return ex.Message; + } + + return null; + } +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 3e1c0f45bec5c19cc7d78580f1f2857f057846db Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 26 Oct 2025 22:03:14 +0900 Subject: [PATCH 08/42] feat(ppt-font-fix): Add ppt file for test to open ppt file --- .../McpSamples.PptFontFix.HybridApp/Program.cs | 4 ++++ .../corrupt_test.pptx | Bin 0 -> 27919 bytes .../McpSamples.PptFontFix.HybridApp/test.pptx | Bin 0 -> 35083 bytes 3 files changed, 4 insertions(+) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 8ec69bf2..2d042a1b 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -15,10 +15,14 @@ static async Task Main(string[] args) }); ILogger logger = loggerFactory.CreateLogger(); + // test.pptx file is normal ppt file for testing + // corrupt_test.pptx file is a corrupted ppt file for testing string testFilePath = "test.pptx"; + string corruptTestFilePath = "corrupt_test.pptx"; var pptService = new PPTFontFixService(logger); await pptService.OpenPPTFileAsync(testFilePath); + await pptService.OpenPPTFileAsync(corruptTestFilePath); } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx new file mode 100644 index 0000000000000000000000000000000000000000..d6fdb48e9eab8f629b97f170895b337f828a0a7a GIT binary patch literal 27919 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 B{SE*C literal 0 HcmV?d00001 diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx new file mode 100644 index 0000000000000000000000000000000000000000..a6f2a1aa6568b07ff02281ba2eaf8c1062780487 GIT binary patch literal 35083 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 Date: Sun, 2 Nov 2025 08:28:12 +0900 Subject: [PATCH 09/42] feat(ppt-font-fix): Add AnalyzeFontsAsync in FontFixService for identify usage of fonts --- .../McpSamples.PptFontFix.HybridApp.csproj | 4 +- .../Models/PPTFontAnalyzeResult.cs | 49 ++++++++ .../Program.cs | 84 +++++++++++-- .../Services/PPTFontFixService.cs | 115 +++++++++++++++++- .../Tools/PPTFontFixTool.cs | 44 ++++++- .../McpSamples.PptFontFix.HybridApp/test.pptx | Bin 35083 -> 40943 bytes 6 files changed, 280 insertions(+), 16 deletions(-) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj index df9a3ba0..c6184090 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs new file mode 100644 index 00000000..41812788 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs @@ -0,0 +1,49 @@ +namespace McpSamples.PptFontFix.HybridApp.Models; + +/// +/// This represents the result of PPT font analysis. +/// + +public class PPTFontAnalyzeResult +{ + /// + /// Gets or sets the list of used fonts in the presentation. + /// + public List UsedFonts { get; set; } = new List(); + + /// + /// Gets or sets the list of unused fonts in the presentation. + /// + public List UnusedFonts { get; set; } = new List(); + + /// + /// Gets or sets the list of inconsistently used fonts in the presentation. + /// + public List InconsistentlyUsedFonts { get; set; } = new List(); + + /// + /// Gets or sets the list of inconsistently used font locations in the presentation. + /// + public List InconsistentFontLocations { get; set; } = new List(); + + /// + /// Gets or sets the list of unused font locations in the presentation. + /// + public List UnusedFontLocations { get; set; } = new List(); +} + +/// +/// This represents the location where a font is used in the presentation. +/// +public class FontUsageLocation +{ + /// + /// Gets or sets the slide number where the font is used. + /// + public int SlideNumber { get; set; } + + /// + /// Gets or sets the shape name where the font is used. + /// + public string ShapeName { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 2d042a1b..1c94a107 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,28 +1,92 @@ using System; using System.IO; using System.Threading.Tasks; -using McpSamples.PptFontFix.HybridApp.Services; - +using McpSamples.PptFontFix.HybridApp.Services; // 서비스 using +using McpSamples.PptFontFix.HybridApp.Models; // 모델 using using Microsoft.Extensions.Logging; +using System.Collections.Generic; // IEnumerable을 위해 추가 +/// +/// This is the code for testing PPT font analysis functionality. +/// class Program { static async Task Main(string[] args) { using var loggerFactory = LoggerFactory.Create(builder => { - builder.AddConsole(); + builder + .AddFilter("McpSamples.PptFontFix.HybridApp.Services", LogLevel.Information) + .AddConsole(); }); + ILogger logger = loggerFactory.CreateLogger(); + IPPTFontFixService fontService = new PPTFontFixService(logger); + + try + { + await fontService.OpenPPTFileAsync("test.pptx"); - // test.pptx file is normal ppt file for testing - // corrupt_test.pptx file is a corrupted ppt file for testing - string testFilePath = "test.pptx"; - string corruptTestFilePath = "corrupt_test.pptx"; + PPTFontAnalyzeResult result = await fontService.AnalyzeFontsAsync(); - var pptService = new PPTFontFixService(logger); + // UsedFonts + Console.WriteLine($"Used (Standard) Fonts ({result.UsedFonts.Count}):"); + if (result.UsedFonts.Any()) + result.UsedFonts.ForEach(font => Console.WriteLine($"- {font}")); + else + Console.WriteLine("(None)"); - await pptService.OpenPPTFileAsync(testFilePath); - await pptService.OpenPPTFileAsync(corruptTestFilePath); + // UnusedFonts + Console.WriteLine($"\nUnused Fonts ({result.UnusedFonts.Count}):"); + if (result.UnusedFonts.Any()) + result.UnusedFonts.ForEach(font => Console.WriteLine($"- {font}")); + else + Console.WriteLine("(None - All fonts are visibly used in non-empty text boxes)"); + + // UnusedFontLocations + Console.WriteLine($"\n[Locations of Empty/Outside Shapes ({result.UnusedFontLocations.Count})]"); + if (result.UnusedFontLocations.Any()) + { + foreach (var location in result.UnusedFontLocations) + { + Console.WriteLine($"- Slide {location.SlideNumber}, Shape: '{location.ShapeName}'"); + } + } + else + { + Console.WriteLine("(None)"); + } + + // InconsistentlyUsedFonts (비일관 폰트) + Console.WriteLine($"Inconsistently Used Fonts ({result.InconsistentlyUsedFonts.Count}):"); + if (result.InconsistentlyUsedFonts.Any()) + { + result.InconsistentlyUsedFonts.ForEach(font => Console.WriteLine($"- {font}")); + + // 비일관 위치 출력 + Console.WriteLine($"\n[Locations of Inconsistent Fonts ({result.InconsistentFontLocations.Count})]"); + if (result.InconsistentFontLocations.Any()) + { + foreach (var location in result.InconsistentFontLocations) + { + Console.WriteLine($"- Slide {location.SlideNumber}, Shape: '{location.ShapeName}'"); + } + } + else + { + Console.WriteLine("(None)"); + } + } + else + { + Console.WriteLine("(None)"); + } + } + catch (Exception ex) + { + Console.WriteLine($"\nAn error occurred"); + Console.WriteLine(ex.Message); + Console.WriteLine(ex.StackTrace); + } } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 7ff22986..6576676a 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -1,6 +1,8 @@ using ShapeCrawler; using Microsoft.Extensions.Logging; using ModelContextProtocol.Server; +using System.Linq; +using McpSamples.PptFontFix.HybridApp.Models; namespace McpSamples.PptFontFix.HybridApp.Services; @@ -14,6 +16,13 @@ public interface IPPTFontFixService /// /// Task OpenPPTFileAsync(string filePath); + + /// + /// Analyze fonts in a PPT file. + /// + /// + /// A classified list of fonts used in the presentation. + Task AnalyzeFontsAsync(); } /// @@ -22,6 +31,7 @@ public interface IPPTFontFixService /// public class PPTFontFixService(ILogger logger) : IPPTFontFixService { + private Presentation? _presentation; /// public async Task OpenPPTFileAsync(string filePath) { @@ -33,7 +43,7 @@ public async Task OpenPPTFileAsync(string filePath) try { - var presentation = new Presentation(filePath); + this._presentation = new Presentation(filePath); logger.LogInformation("PPT file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); await Task.CompletedTask; @@ -44,4 +54,107 @@ public async Task OpenPPTFileAsync(string filePath) throw; } } + + /// + public async Task AnalyzeFontsAsync() + { + if (this._presentation == null) + { + throw new InvalidOperationException("PPT file is not opened. Please open a PPT file before analyzing fonts."); + } + + var totalFontsInSlides = new HashSet(); + var visibleFontUsages = new Dictionary>(); + var result = new PPTFontAnalyzeResult(); + var slideWidth = this._presentation.SlideWidth; + var slideHeight = this._presentation.SlideHeight; + + Action processPortion = (portion, isShapeVisible, isSlideVisible, location) => + { + if (portion.Font == null) return; + string? fontName = portion.Font.LatinName; + if (string.IsNullOrEmpty(fontName)) return; + + totalFontsInSlides.Add(fontName); + + if (isSlideVisible && isShapeVisible) + { + bool isWhitespace = string.IsNullOrWhiteSpace(portion.Text); + if (!isWhitespace) + { + // Count only visible text portions + if (!visibleFontUsages.ContainsKey(fontName)) + { + visibleFontUsages[fontName] = new List(); + } + visibleFontUsages[fontName].Add(location); + } + } + }; + + foreach (var slide in this._presentation.Slides) + { + bool isSlideVisible = !slide.Hidden(); + foreach (var shape in slide.Shapes) + { + var location = new FontUsageLocation { SlideNumber = slide.Number, ShapeName = shape.Name }; + + bool isEmptyBox = shape.TextBox != null && string.IsNullOrWhiteSpace(shape.TextBox.Text); + if (isEmptyBox) + { + logger.LogWarning("[Empty Box Detected] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", + slide.Number, shape.Name); + result.UnusedFontLocations.Add(location); + } + + bool isShapeVisible = !((shape.X + shape.Width) <= 0 || + shape.X >= slideWidth || + (shape.Y + shape.Height) <= 0 || + shape.Y >= slideHeight); + + if (!isShapeVisible && shape.TextBox != null && !isEmptyBox) + { + logger.LogWarning("[Text Shape Outside Slide] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", + slide.Number, shape.Name); + result.UnusedFontLocations.Add(location); + } + + if (shape.TextBox != null) + { + foreach (var portion in shape.TextBox.Paragraphs.SelectMany(p => p.Portions)) + { + processPortion(portion, isShapeVisible, isSlideVisible, location); + } + } + } + } + + var allVisibleFontNames = new HashSet(visibleFontUsages.Keys); + var unusedFonts = new HashSet(totalFontsInSlides); + unusedFonts.ExceptWith(allVisibleFontNames); + result.UnusedFonts = unusedFonts.ToList(); + int standardFontCount = 2; + var sortedVisibleFonts = visibleFontUsages + .OrderByDescending(pair => pair.Value.Count) + .ToList(); + result.UsedFonts = sortedVisibleFonts + .Take(standardFontCount) + .Select(pair => pair.Key) + .ToList(); + var inconsistentPairs = sortedVisibleFonts + .Skip(standardFontCount) + .ToList(); + result.InconsistentlyUsedFonts = inconsistentPairs + .Select(pair => pair.Key) + .ToList(); + result.InconsistentFontLocations = inconsistentPairs + .SelectMany(pair => pair.Value) + .ToList(); + + logger.LogInformation("[Result] Used (Standard) Fonts: {Fonts}", string.Join(", ", result.UsedFonts)); + logger.LogInformation("[Result] Unused Fonts: {Fonts}", string.Join(", ", result.UnusedFonts)); + logger.LogInformation("[Result] Inconsistently Used Fonts: {Fonts}", string.Join(", ", result.InconsistentlyUsedFonts)); + + return await Task.FromResult(result); + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index 6f4fcea3..c9a056c9 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; using McpSamples.PptFontFix.HybridApp.Services; +using McpSamples.PptFontFix.HybridApp.Models; using ModelContextProtocol.Server; @@ -20,6 +21,12 @@ public interface IPPTFontFixTool /// /// Returns the result as a string. Task OpenPPTFileAsync(string filePath); + + /// + /// Analyze fonts in a PPT file. + /// + /// Returns instance. + Task AnalyzeFontsAsync(); } /// @@ -40,15 +47,46 @@ public async Task OpenPPTFileAsync( { await service.OpenPPTFileAsync(filePath).ConfigureAwait(false); - logger.LogInformation("PPT file opened successfully: {FilePath}", filePath); + string successMessage = $"PPT file opened successfully: {filePath}"; + logger.LogInformation(successMessage); + return successMessage; } catch (Exception ex) { logger.LogError(ex, "Failed to open PPT file: {FilePath}", filePath); - return ex.Message; + // throw exception to inform the caller about the failure + throw; } + } - return null; + /// + [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts in PPT File")] + [Description("Analyzes fonts used in the opened PPT file and identifies inconsistencies.")] + public async Task AnalyzeFontsAsync() + { + try + { + // call the service to analyze fonts + PPTFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); + + if (result != null) + { + int count = result.InconsistentlyUsedFonts?.Count ?? 0; + logger.LogInformation("Font analysis completed. Inconsistently used fonts count: {Count}", count); + return result; + } + else + { + logger.LogWarning("Font analysis service returned a null result."); + return new PPTFontAnalyzeResult(); + } + } + catch (Exception ex) + { + // log the error and rethrow + logger.LogError(ex, "Failed to analyze fonts in the PPT file."); + throw; // preserve stack trace + } } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx index a6f2a1aa6568b07ff02281ba2eaf8c1062780487..eaa90ce5de664fdb99f004e2455eb6b7012d62e0 100644 GIT binary patch delta 15518 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 delta 11072 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

#UlavHL?)WmNtw^qTmFMgBN9knL5bw18kLQOY)} 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 From 0bb8fe35b5f99db65bed9449f47ab9f4158e1c40 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 2 Nov 2025 15:26:36 +0900 Subject: [PATCH 10/42] delete some comment --- .../src/McpSamples.PptFontFix.HybridApp/Program.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 1c94a107..c97580da 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,10 +1,10 @@ using System; using System.IO; using System.Threading.Tasks; -using McpSamples.PptFontFix.HybridApp.Services; // 서비스 using -using McpSamples.PptFontFix.HybridApp.Models; // 모델 using +using McpSamples.PptFontFix.HybridApp.Services; +using McpSamples.PptFontFix.HybridApp.Models; using Microsoft.Extensions.Logging; -using System.Collections.Generic; // IEnumerable을 위해 추가 +using System.Collections.Generic; ///

/// This is the code for testing PPT font analysis functionality. @@ -57,13 +57,11 @@ static async Task Main(string[] args) Console.WriteLine("(None)"); } - // InconsistentlyUsedFonts (비일관 폰트) + // InconsistentlyUsedFonts Console.WriteLine($"Inconsistently Used Fonts ({result.InconsistentlyUsedFonts.Count}):"); if (result.InconsistentlyUsedFonts.Any()) { result.InconsistentlyUsedFonts.ForEach(font => Console.WriteLine($"- {font}")); - - // 비일관 위치 출력 Console.WriteLine($"\n[Locations of Inconsistent Fonts ({result.InconsistentFontLocations.Count})]"); if (result.InconsistentFontLocations.Any()) { From 365b75d3fa4d96690827679f8efcc55ae204d0b0 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 3 Nov 2025 16:58:01 +0900 Subject: [PATCH 11/42] renaming file names and namespaces --- ppt-font-fix/.vscode/mcp.http.container.json | 8 +++++ ppt-font-fix/.vscode/mcp.http.local.json | 8 +++++ ppt-font-fix/.vscode/mcp.http.remote.json | 15 ++++++++++ ppt-font-fix/.vscode/mcp.stdio.container.json | 16 ++++++++++ ppt-font-fix/.vscode/mcp.stdio.local.json | 23 ++++++++++++++ .../Configurations/PPTFontFixAppSettings.cs | 4 +-- .../Models/PPTFontAnalyzeResult.cs | 4 +-- .../Program.cs | 12 ++++---- .../Services/PPTFontFixService.cs | 30 +++++++++---------- 9 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 ppt-font-fix/.vscode/mcp.http.container.json create mode 100644 ppt-font-fix/.vscode/mcp.http.local.json create mode 100644 ppt-font-fix/.vscode/mcp.http.remote.json create mode 100644 ppt-font-fix/.vscode/mcp.stdio.container.json create mode 100644 ppt-font-fix/.vscode/mcp.stdio.local.json diff --git a/ppt-font-fix/.vscode/mcp.http.container.json b/ppt-font-fix/.vscode/mcp.http.container.json new file mode 100644 index 00000000..07d88410 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.container.json @@ -0,0 +1,8 @@ +{ + "servers": { + "markdown-to-html": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.http.local.json b/ppt-font-fix/.vscode/mcp.http.local.json new file mode 100644 index 00000000..97175969 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.local.json @@ -0,0 +1,8 @@ +{ + "servers": { + "markdown-to-html": { + "type": "http", + "url": "http://localhost:5280/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.http.remote.json b/ppt-font-fix/.vscode/mcp.http.remote.json new file mode 100644 index 00000000..c9e5e2e1 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.remote.json @@ -0,0 +1,15 @@ +{ + "inputs": [ + { + "type": "promptString", + "id": "acaapp-server-fqdn", + "description": "Azure Container Apps FQDN" + } + ], + "servers": { + "markdown-to-html": { + "type": "http", + "url": "https://${input:acaapp-server-fqdn}/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json new file mode 100644 index 00000000..cfcb5123 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -0,0 +1,16 @@ +{ + "servers": { + "markdown-to-html": { + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "ghcr.io/microsoft/mcp-dotnet-samples/markdown-to-html:latest", + "-tc", + "-p" + ] + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.stdio.local.json b/ppt-font-fix/.vscode/mcp.stdio.local.json new file mode 100644 index 00000000..dfb52c3c --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.stdio.local.json @@ -0,0 +1,23 @@ +{ + "inputs": [ + { + "type": "promptString", + "id": "consoleapp-project-path", + "description": "The absolute path to the console app project Directory" + } + ], + "servers": { + "markdown-to-html": { + "type": "stdio", + "command": "dotnet", + "args": [ + "run", + "--project", + "${input:consoleapp-project-path}", + "--", + "-tc", + "-p" + ] + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs index 247e78e3..44d5f684 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -2,12 +2,12 @@ using Microsoft.OpenApi.Models; -namespace McpSamples.PPTFontFix.HybridApp.Configurations; +namespace McpSamples.PptFontFix.HybridApp.Configurations; /// /// This represents the application settings for ppt-font-fix app. /// -public class PPTFontFixAppSettings : AppSettings +public class PptFontFixAppSettings : AppSettings { /// public override OpenApiInfo OpenApi { get; set; } = new() diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs index 41812788..a930994d 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs @@ -1,10 +1,10 @@ namespace McpSamples.PptFontFix.HybridApp.Models; /// -/// This represents the result of PPT font analysis. +/// This represents the result of Ppt font analysis. /// -public class PPTFontAnalyzeResult +public class PptFontAnalyzeResult { /// /// Gets or sets the list of used fonts in the presentation. diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index c97580da..3f95193f 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Threading.Tasks; using McpSamples.PptFontFix.HybridApp.Services; @@ -7,7 +7,7 @@ using System.Collections.Generic; /// -/// This is the code for testing PPT font analysis functionality. +/// This is the code for testing Ppt font analysis functionality. /// class Program { @@ -20,14 +20,14 @@ static async Task Main(string[] args) .AddConsole(); }); - ILogger logger = loggerFactory.CreateLogger(); - IPPTFontFixService fontService = new PPTFontFixService(logger); + ILogger logger = loggerFactory.CreateLogger(); + IPptFontFixService fontService = new PptFontFixService(logger); try { - await fontService.OpenPPTFileAsync("test.pptx"); + await fontService.OpenPptFileAsync("test.pptx"); - PPTFontAnalyzeResult result = await fontService.AnalyzeFontsAsync(); + PptFontAnalyzeResult result = await fontService.AnalyzeFontsAsync(); // UsedFonts Console.WriteLine($"Used (Standard) Fonts ({result.UsedFonts.Count}):"); diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 6576676a..d1cb7221 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -7,65 +7,65 @@ namespace McpSamples.PptFontFix.HybridApp.Services; /// -/// This provides interface for PPT font fixing operations. +/// This provides interface for Ppt font fixing operations. /// -public interface IPPTFontFixService +public interface IPptFontFixService { /// - /// open a PPT file. + /// open a Ppt file. /// /// - Task OpenPPTFileAsync(string filePath); + Task OpenPptFileAsync(string filePath); /// - /// Analyze fonts in a PPT file. + /// Analyze fonts in a Ppt file. /// /// /// A classified list of fonts used in the presentation. - Task AnalyzeFontsAsync(); + Task AnalyzeFontsAsync(); } /// -/// This represents the service entity for PPT font fixing. +/// This represents the service entity for Ppt font fixing. /// /// -public class PPTFontFixService(ILogger logger) : IPPTFontFixService +public class PptFontFixService(ILogger logger) : IPptFontFixService { private Presentation? _presentation; /// - public async Task OpenPPTFileAsync(string filePath) + public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); if (File.Exists(filePath) == false) { - throw new FileNotFoundException("PPT file does not exist.", filePath); + throw new FileNotFoundException("Ppt file does not exist.", filePath); } try { this._presentation = new Presentation(filePath); - logger.LogInformation("PPT file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); + logger.LogInformation("Ppt file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); await Task.CompletedTask; } catch (Exception ex) { - logger.LogError(ex, "Failed to open PPT file with ShapeCrawler: {FilePath}", filePath); + logger.LogError(ex, "Failed to open Ppt file with ShapeCrawler: {FilePath}", filePath); throw; } } /// - public async Task AnalyzeFontsAsync() + public async Task AnalyzeFontsAsync() { if (this._presentation == null) { - throw new InvalidOperationException("PPT file is not opened. Please open a PPT file before analyzing fonts."); + throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before analyzing fonts."); } var totalFontsInSlides = new HashSet(); var visibleFontUsages = new Dictionary>(); - var result = new PPTFontAnalyzeResult(); + var result = new PptFontAnalyzeResult(); var slideWidth = this._presentation.SlideWidth; var slideHeight = this._presentation.SlideHeight; From b4111cbfca1aebcacfc834786a87a8110d6026f8 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Tue, 4 Nov 2025 04:36:01 +0900 Subject: [PATCH 12/42] Revert "delete some comment" This reverts commit 0bb8fe35b5f99db65bed9449f47ab9f4158e1c40. --- .../src/McpSamples.PptFontFix.HybridApp/Program.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index c97580da..1c94a107 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,10 +1,10 @@ using System; using System.IO; using System.Threading.Tasks; -using McpSamples.PptFontFix.HybridApp.Services; -using McpSamples.PptFontFix.HybridApp.Models; +using McpSamples.PptFontFix.HybridApp.Services; // 서비스 using +using McpSamples.PptFontFix.HybridApp.Models; // 모델 using using Microsoft.Extensions.Logging; -using System.Collections.Generic; +using System.Collections.Generic; // IEnumerable을 위해 추가 /// /// This is the code for testing PPT font analysis functionality. @@ -57,11 +57,13 @@ static async Task Main(string[] args) Console.WriteLine("(None)"); } - // InconsistentlyUsedFonts + // InconsistentlyUsedFonts (비일관 폰트) Console.WriteLine($"Inconsistently Used Fonts ({result.InconsistentlyUsedFonts.Count}):"); if (result.InconsistentlyUsedFonts.Any()) { result.InconsistentlyUsedFonts.ForEach(font => Console.WriteLine($"- {font}")); + + // 비일관 위치 출력 Console.WriteLine($"\n[Locations of Inconsistent Fonts ({result.InconsistentFontLocations.Count})]"); if (result.InconsistentFontLocations.Any()) { From 88572a8ebf68089680d3801624ea8965787355fc Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Tue, 4 Nov 2025 04:45:36 +0900 Subject: [PATCH 13/42] Renaming namespaces and file name, Add Json File, Fix Program.cs --- ppt-font-fix/.vscode/mcp.http.container.json | 8 ++ ppt-font-fix/.vscode/mcp.http.local.json | 8 ++ ppt-font-fix/.vscode/mcp.http.remote.json | 15 +++ ppt-font-fix/.vscode/mcp.stdio.container.json | 16 +++ ppt-font-fix/.vscode/mcp.stdio.local.json | 23 ++++ .../Configurations/PPTFontFixAppSettings.cs | 4 +- .../McpSamples.PptFontFix.HybridApp.csproj | 2 +- .../Models/PPTFontAnalyzeResult.cs | 4 +- .../Program.cs | 101 +++--------------- .../Services/PPTFontFixService.cs | 30 +++--- .../Tools/PPTFontFixTool.cs | 46 ++++---- 11 files changed, 127 insertions(+), 130 deletions(-) create mode 100644 ppt-font-fix/.vscode/mcp.http.container.json create mode 100644 ppt-font-fix/.vscode/mcp.http.local.json create mode 100644 ppt-font-fix/.vscode/mcp.http.remote.json create mode 100644 ppt-font-fix/.vscode/mcp.stdio.container.json create mode 100644 ppt-font-fix/.vscode/mcp.stdio.local.json diff --git a/ppt-font-fix/.vscode/mcp.http.container.json b/ppt-font-fix/.vscode/mcp.http.container.json new file mode 100644 index 00000000..920d570c --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.container.json @@ -0,0 +1,8 @@ +{ + "servers": { + "ppt-font-fix": { + "type": "http", + "url": "http://localhost:8080/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.http.local.json b/ppt-font-fix/.vscode/mcp.http.local.json new file mode 100644 index 00000000..2de7d3c6 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.local.json @@ -0,0 +1,8 @@ +{ + "servers": { + "ppt-font-fix": { + "type": "http", + "url": "http://localhost:5280/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.http.remote.json b/ppt-font-fix/.vscode/mcp.http.remote.json new file mode 100644 index 00000000..497a479e --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.http.remote.json @@ -0,0 +1,15 @@ +{ + "inputs": [ + { + "type": "promptString", + "id": "acaapp-server-fqdn", + "description": "Azure Container Apps FQDN" + } + ], + "servers": { + "ppt-font-fix": { + "type": "http", + "url": "https://${input:acaapp-server-fqdn}/mcp" + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json new file mode 100644 index 00000000..85bc618c --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -0,0 +1,16 @@ +{ + "servers": { + "ppt-font-fix": { + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest", + "-tc", + "-p" + ] + } + } +} diff --git a/ppt-font-fix/.vscode/mcp.stdio.local.json b/ppt-font-fix/.vscode/mcp.stdio.local.json new file mode 100644 index 00000000..8b05f824 --- /dev/null +++ b/ppt-font-fix/.vscode/mcp.stdio.local.json @@ -0,0 +1,23 @@ +{ + "inputs": [ + { + "type": "promptString", + "id": "consoleapp-project-path", + "description": "The absolute path to the console app project Directory" + } + ], + "servers": { + "ppt-font-fix": { + "type": "stdio", + "command": "dotnet", + "args": [ + "run", + "--project", + "${input:consoleapp-project-path}", + "--", + "-tc", + "-p" + ] + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs index 247e78e3..44d5f684 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -2,12 +2,12 @@ using Microsoft.OpenApi.Models; -namespace McpSamples.PPTFontFix.HybridApp.Configurations; +namespace McpSamples.PptFontFix.HybridApp.Configurations; /// /// This represents the application settings for ppt-font-fix app. /// -public class PPTFontFixAppSettings : AppSettings +public class PptFontFixAppSettings : AppSettings { /// public override OpenApiInfo OpenApi { get; set; } = new() diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj index c6184090..83555ca5 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs index 41812788..a930994d 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Models/PPTFontAnalyzeResult.cs @@ -1,10 +1,10 @@ namespace McpSamples.PptFontFix.HybridApp.Models; /// -/// This represents the result of PPT font analysis. +/// This represents the result of Ppt font analysis. /// -public class PPTFontAnalyzeResult +public class PptFontAnalyzeResult { /// /// Gets or sets the list of used fonts in the presentation. diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 1c94a107..98983200 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,92 +1,19 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using McpSamples.PptFontFix.HybridApp.Services; // 서비스 using -using McpSamples.PptFontFix.HybridApp.Models; // 모델 using -using Microsoft.Extensions.Logging; -using System.Collections.Generic; // IEnumerable을 위해 추가 +using McpSamples.PptFontFix.HybridApp.Configurations; +using McpSamples.PptFontFix.HybridApp.Services; +using McpSamples.PptFontFix.HybridApp.Tools; +using McpSamples.Shared.Configurations; +using McpSamples.Shared.Extensions; +using McpSamples.Shared.OpenApi; -/// -/// This is the code for testing PPT font analysis functionality. -/// -class Program -{ - static async Task Main(string[] args) - { - using var loggerFactory = LoggerFactory.Create(builder => - { - builder - .AddFilter("McpSamples.PptFontFix.HybridApp.Services", LogLevel.Information) - .AddConsole(); - }); +var useStreamableHttp = AppSettings.UseStreamableHttp(Environment.GetEnvironmentVariables(), args); - ILogger logger = loggerFactory.CreateLogger(); - IPPTFontFixService fontService = new PPTFontFixService(logger); +IHostApplicationBuilder builder = useStreamableHttp + ? WebApplication.CreateBuilder(args) + : Host.CreateApplicationBuilder(args); - try - { - await fontService.OpenPPTFileAsync("test.pptx"); +builder.Services.AddAppSettings(builder.Configuration, args); +builder.Services.AddSingleton(); - PPTFontAnalyzeResult result = await fontService.AnalyzeFontsAsync(); +IHost app = builder.BuildApp(useStreamableHttp); - // UsedFonts - Console.WriteLine($"Used (Standard) Fonts ({result.UsedFonts.Count}):"); - if (result.UsedFonts.Any()) - result.UsedFonts.ForEach(font => Console.WriteLine($"- {font}")); - else - Console.WriteLine("(None)"); - - // UnusedFonts - Console.WriteLine($"\nUnused Fonts ({result.UnusedFonts.Count}):"); - if (result.UnusedFonts.Any()) - result.UnusedFonts.ForEach(font => Console.WriteLine($"- {font}")); - else - Console.WriteLine("(None - All fonts are visibly used in non-empty text boxes)"); - - // UnusedFontLocations - Console.WriteLine($"\n[Locations of Empty/Outside Shapes ({result.UnusedFontLocations.Count})]"); - if (result.UnusedFontLocations.Any()) - { - foreach (var location in result.UnusedFontLocations) - { - Console.WriteLine($"- Slide {location.SlideNumber}, Shape: '{location.ShapeName}'"); - } - } - else - { - Console.WriteLine("(None)"); - } - - // InconsistentlyUsedFonts (비일관 폰트) - Console.WriteLine($"Inconsistently Used Fonts ({result.InconsistentlyUsedFonts.Count}):"); - if (result.InconsistentlyUsedFonts.Any()) - { - result.InconsistentlyUsedFonts.ForEach(font => Console.WriteLine($"- {font}")); - - // 비일관 위치 출력 - Console.WriteLine($"\n[Locations of Inconsistent Fonts ({result.InconsistentFontLocations.Count})]"); - if (result.InconsistentFontLocations.Any()) - { - foreach (var location in result.InconsistentFontLocations) - { - Console.WriteLine($"- Slide {location.SlideNumber}, Shape: '{location.ShapeName}'"); - } - } - else - { - Console.WriteLine("(None)"); - } - } - else - { - Console.WriteLine("(None)"); - } - } - catch (Exception ex) - { - Console.WriteLine($"\nAn error occurred"); - Console.WriteLine(ex.Message); - Console.WriteLine(ex.StackTrace); - } - } -} \ No newline at end of file +await app.RunAsync(); \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 6576676a..d1cb7221 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -7,65 +7,65 @@ namespace McpSamples.PptFontFix.HybridApp.Services; /// -/// This provides interface for PPT font fixing operations. +/// This provides interface for Ppt font fixing operations. /// -public interface IPPTFontFixService +public interface IPptFontFixService { /// - /// open a PPT file. + /// open a Ppt file. /// /// - Task OpenPPTFileAsync(string filePath); + Task OpenPptFileAsync(string filePath); /// - /// Analyze fonts in a PPT file. + /// Analyze fonts in a Ppt file. /// /// /// A classified list of fonts used in the presentation. - Task AnalyzeFontsAsync(); + Task AnalyzeFontsAsync(); } /// -/// This represents the service entity for PPT font fixing. +/// This represents the service entity for Ppt font fixing. /// /// -public class PPTFontFixService(ILogger logger) : IPPTFontFixService +public class PptFontFixService(ILogger logger) : IPptFontFixService { private Presentation? _presentation; /// - public async Task OpenPPTFileAsync(string filePath) + public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); if (File.Exists(filePath) == false) { - throw new FileNotFoundException("PPT file does not exist.", filePath); + throw new FileNotFoundException("Ppt file does not exist.", filePath); } try { this._presentation = new Presentation(filePath); - logger.LogInformation("PPT file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); + logger.LogInformation("Ppt file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); await Task.CompletedTask; } catch (Exception ex) { - logger.LogError(ex, "Failed to open PPT file with ShapeCrawler: {FilePath}", filePath); + logger.LogError(ex, "Failed to open Ppt file with ShapeCrawler: {FilePath}", filePath); throw; } } /// - public async Task AnalyzeFontsAsync() + public async Task AnalyzeFontsAsync() { if (this._presentation == null) { - throw new InvalidOperationException("PPT file is not opened. Please open a PPT file before analyzing fonts."); + throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before analyzing fonts."); } var totalFontsInSlides = new HashSet(); var visibleFontUsages = new Dictionary>(); - var result = new PPTFontAnalyzeResult(); + var result = new PptFontAnalyzeResult(); var slideWidth = this._presentation.SlideWidth; var slideHeight = this._presentation.SlideHeight; diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index c9a056c9..bc3b2095 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -10,50 +10,50 @@ namespace McpSamples.PptFontFix.HybridApp.Tools; /// -/// This provides interface for the PPT font fix tool. +/// This provides interface for the Ppt font fix tool. /// -public interface IPPTFontFixTool +public interface IPptFontFixTool { /// - /// open a PPT file. + /// open a Ppt file. /// /// /// Returns the result as a string. - Task OpenPPTFileAsync(string filePath); + Task OpenPptFileAsync(string filePath); /// - /// Analyze fonts in a PPT file. + /// Analyze fonts in a Ppt file. /// - /// Returns instance. - Task AnalyzeFontsAsync(); + /// Returns instance. + Task AnalyzeFontsAsync(); } /// -/// This represents the tool entity for PPT font fixing. +/// This represents the tool entity for Ppt font fixing. /// /// instance. -/// instance. +/// instance. [McpServerToolType] -public class PPTFontFixTool(IPPTFontFixService service, ILogger logger) : IPPTFontFixTool +public class PptFontFixTool(IPptFontFixService service, ILogger logger) : IPptFontFixTool { /// - [McpServerTool(Name = "open_ppt_file", Title = "Open a PPT File")] - [Description("Opens a PPT file and verifies it using ShapeCrawler.")] - public async Task OpenPPTFileAsync( - [Description("The path of the PPT file to open")] string filePath) + [McpServerTool(Name = "open_ppt_file", Title = "Open a Ppt File")] + [Description("Opens a Ppt file and verifies it using ShapeCrawler.")] + public async Task OpenPptFileAsync( + [Description("The path of the Ppt file to open")] string filePath) { try { - await service.OpenPPTFileAsync(filePath).ConfigureAwait(false); + await service.OpenPptFileAsync(filePath).ConfigureAwait(false); - string successMessage = $"PPT file opened successfully: {filePath}"; + string successMessage = $"Ppt file opened successfully: {filePath}"; logger.LogInformation(successMessage); return successMessage; } catch (Exception ex) { - logger.LogError(ex, "Failed to open PPT file: {FilePath}", filePath); + logger.LogError(ex, "Failed to open Ppt file: {FilePath}", filePath); // throw exception to inform the caller about the failure throw; @@ -61,14 +61,14 @@ public async Task OpenPPTFileAsync( } /// - [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts in PPT File")] - [Description("Analyzes fonts used in the opened PPT file and identifies inconsistencies.")] - public async Task AnalyzeFontsAsync() + [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts in Ppt File")] + [Description("Analyzes fonts used in the opened Ppt file and identifies inconsistencies.")] + public async Task AnalyzeFontsAsync() { try { // call the service to analyze fonts - PPTFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); + PptFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); if (result != null) { @@ -79,13 +79,13 @@ public async Task AnalyzeFontsAsync() else { logger.LogWarning("Font analysis service returned a null result."); - return new PPTFontAnalyzeResult(); + return new PptFontAnalyzeResult(); } } catch (Exception ex) { // log the error and rethrow - logger.LogError(ex, "Failed to analyze fonts in the PPT file."); + logger.LogError(ex, "Failed to analyze fonts in the Ppt file."); throw; // preserve stack trace } } From 3e0232f03387b15a4960f2d8fd4322b69e7846c2 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Fri, 7 Nov 2025 21:39:26 +0900 Subject: [PATCH 14/42] Add SavePptFileAsync --- ppt-font-fix/.vscode/mcp.http.local.json | 2 +- .../Services/PPTFontFixService.cs | 42 +++++++++++++++--- .../Tools/PPTFontFixTool.cs | 33 ++++++++++++-- .../McpSamples.PptFontFix.HybridApp/test.pptx | Bin 40943 -> 38395 bytes 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/ppt-font-fix/.vscode/mcp.http.local.json b/ppt-font-fix/.vscode/mcp.http.local.json index 2de7d3c6..a6e57a2b 100644 --- a/ppt-font-fix/.vscode/mcp.http.local.json +++ b/ppt-font-fix/.vscode/mcp.http.local.json @@ -2,7 +2,7 @@ "servers": { "ppt-font-fix": { "type": "http", - "url": "http://localhost:5280/mcp" + "url": "http://localhost:5166/mcp" } } } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index d1cb7221..dacf2e19 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -20,9 +20,14 @@ public interface IPptFontFixService /// /// Analyze fonts in a Ppt file. /// - /// /// A classified list of fonts used in the presentation. Task AnalyzeFontsAsync(); + + /// + /// Save the modified Ppt file. + /// + /// + Task SavePptFileAsync(string newFilePath); } /// @@ -82,19 +87,20 @@ public async Task AnalyzeFontsAsync() bool isWhitespace = string.IsNullOrWhiteSpace(portion.Text); if (!isWhitespace) { - // Count only visible text portions - if (!visibleFontUsages.ContainsKey(fontName)) + if (!visibleFontUsages.TryGetValue(fontName, out List? value)) { - visibleFontUsages[fontName] = new List(); + value = []; + visibleFontUsages[fontName] = value; } - visibleFontUsages[fontName].Add(location); + + value.Add(location); } } }; foreach (var slide in this._presentation.Slides) { - bool isSlideVisible = !slide.Hidden(); + bool isSlideVisible = !slide.Hidden(); foreach (var shape in slide.Shapes) { var location = new FontUsageLocation { SlideNumber = slide.Number, ShapeName = shape.Name }; @@ -157,4 +163,28 @@ public async Task AnalyzeFontsAsync() return await Task.FromResult(result); } + + /// + public async Task SavePptFileAsync(string newFilePath) + { + if (this._presentation == null) + { + throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); + } + + ArgumentException.ThrowIfNullOrWhiteSpace(newFilePath, nameof(newFilePath)); + + try + { + this._presentation.Save(newFilePath); + logger.LogInformation("Ppt file saved successfully: {FilePath}", newFilePath); + + await Task.CompletedTask; + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to save Ppt file: {FilePath}", newFilePath); + throw; + } + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index bc3b2095..dd9cba5b 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -27,6 +27,12 @@ public interface IPptFontFixTool /// /// Returns instance. Task AnalyzeFontsAsync(); + + /// + /// Save the modified Ppt file. + /// + /// + Task SavePptFileAsync(string newFilePath); } /// @@ -55,7 +61,6 @@ public async Task OpenPptFileAsync( { logger.LogError(ex, "Failed to open Ppt file: {FilePath}", filePath); - // throw exception to inform the caller about the failure throw; } } @@ -67,7 +72,6 @@ public async Task AnalyzeFontsAsync() { try { - // call the service to analyze fonts PptFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); if (result != null) @@ -84,9 +88,30 @@ public async Task AnalyzeFontsAsync() } catch (Exception ex) { - // log the error and rethrow logger.LogError(ex, "Failed to analyze fonts in the Ppt file."); - throw; // preserve stack trace + throw; + } + } + + /// + [McpServerTool(Name = "save_ppt_file", Title = "Save Modified Ppt File")] + [Description("Saves the modified Ppt file to the specified path.")] + public async Task SavePptFileAsync( + [Description("The path to save the modified Ppt file")] string newFilePath) + { + try + { + await service.SavePptFileAsync(newFilePath).ConfigureAwait(false); + + string successMessage = $"Ppt file saved successfully: {newFilePath}"; + logger.LogInformation(successMessage); + return successMessage; + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to save Ppt file: {FilePath}", newFilePath); + + throw; } } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx index eaa90ce5de664fdb99f004e2455eb6b7012d62e0..19de416cb530614328913abaf7cfecf8facb5c63 100644 GIT binary patch literal 38395 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

^jUa2-c19&iGCZW2LV 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 From 2c9ea84adb5c9cbf8535ff6bb851419499f2d7fe Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 10 Nov 2025 01:19:12 +0900 Subject: [PATCH 15/42] Add RemoveUnusedFontsasync --- .../Services/PPTFontFixService.cs | 49 +++++++++++++++++- .../Tools/PPTFontFixTool.cs | 26 ++++++++++ .../McpSamples.PptFontFix.HybridApp/test.pptx | Bin 38395 -> 40943 bytes 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index dacf2e19..07eb6f42 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -28,6 +28,12 @@ public interface IPptFontFixService ///

/// Task SavePptFileAsync(string newFilePath); + + /// + /// Remove Unused Fonts from the presentation. + /// + /// A list of shape locations to be removed. + Task RemoveUnusedFontsAsync(List locationsToRemove); } /// @@ -163,7 +169,7 @@ public async Task AnalyzeFontsAsync() return await Task.FromResult(result); } - + /// public async Task SavePptFileAsync(string newFilePath) { @@ -187,4 +193,45 @@ public async Task SavePptFileAsync(string newFilePath) throw; } } + + /// + public async Task RemoveUnusedFontsAsync(List locationsToRemove) + { + if (this._presentation == null) + { + throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before removing unused fonts."); + } + + if (locationsToRemove == null || locationsToRemove.Count == 0) + { + logger.LogInformation("No locations provided for removal. Skipping removal process."); + return await Task.FromResult(0); + } + + int removalCount = 0; + + foreach (var location in locationsToRemove) + { + var slide = this._presentation.Slides.FirstOrDefault(s => s.Number == location.SlideNumber); + if (slide == null) + { + logger.LogWarning("Slide number {SlideNumber} not found. Skipping.", location.SlideNumber); + continue; + } + + var shape = slide.Shapes.FirstOrDefault(sh => sh.Name == location.ShapeName); + if (shape == null) + { + logger.LogWarning("Shape name {ShapeName} not found in slide {SlideNumber}. Skipping.", location.ShapeName, location.SlideNumber); + continue; + } + + shape.Remove(); + removalCount++; + logger.LogInformation("Removed shape {ShapeName} from slide {SlideNumber}.", location.ShapeName, location.SlideNumber); + } + + logger.LogInformation("Total shapes removed: {Count}", removalCount); + return await Task.FromResult(removalCount); + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index dd9cba5b..1e707c2f 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -33,6 +33,12 @@ public interface IPptFontFixTool /// /// Task SavePptFileAsync(string newFilePath); + + /// + /// Remove shapes from the presentation. + /// + /// A list of shape locations to be removed. + Task RemoveUnusedFontsAsync(List locationsToRemove); } /// @@ -114,4 +120,24 @@ public async Task SavePptFileAsync( throw; } } + + /// + [McpServerTool(Name = "remove_unused_font_shapes", Title = "Remove Unused Font Shapes")] + [Description("Removes shapes that contain unused fonts (e.g., empty text boxes). Takes the 'unusedFontLocations' list from the analysis result.")] + public async Task RemoveUnusedFontsAsync( + [Description("A list of shape locations (from 'unusedFontLocations') to be removed.")] + List locationsToRemove) + { + try + { + int count = await service.RemoveUnusedFontsAsync(locationsToRemove).ConfigureAwait(false); + logger.LogInformation("RemoveUnusedFontsAsync Tool executed, {Count} shapes removed.", count); + return count; + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to remove unused font shapes."); + throw; + } + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx index 19de416cb530614328913abaf7cfecf8facb5c63..eaa90ce5de664fdb99f004e2455eb6b7012d62e0 100644 GIT binary patch literal 40943 zcmeFZV{|3$zAYZx?l|eFW81cE+crD4osO|$+qP|WoOJBuX21LV$2kAH-#hjh<9<8m z)`zF6)~fpOta|30Kg?S4QlMaHKoCGsKtMo5Kq<~-u>HV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 literal 38395 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 Date: Tue, 11 Nov 2025 22:20:25 +0900 Subject: [PATCH 16/42] Fix inconsistently used fonts --- .../Services/PPTFontFixService.cs | 52 ++++++++++++++++++- .../Tools/PPTFontFixTool.cs | 32 ++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 07eb6f42..ca36b6b3 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -34,6 +34,14 @@ public interface IPptFontFixService ///

/// A list of shape locations to be removed. Task RemoveUnusedFontsAsync(List locationsToRemove); + + /// + /// Replace a font with another font throughout the presentation. + /// + /// The font name to be replaced. + /// The replacement font name. + /// The number of replacements made. + Task ReplaceFontAsync(string fontToReplace, string replacementFont); } /// @@ -193,7 +201,7 @@ public async Task SavePptFileAsync(string newFilePath) throw; } } - + /// public async Task RemoveUnusedFontsAsync(List locationsToRemove) { @@ -234,4 +242,46 @@ public async Task RemoveUnusedFontsAsync(List locationsT logger.LogInformation("Total shapes removed: {Count}", removalCount); return await Task.FromResult(removalCount); } + + /// + public async Task ReplaceFontAsync(string fontToReplace, string replacementFont) + { + if (this._presentation == null) + { + throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before replacing fonts."); + } + + if (string.IsNullOrWhiteSpace(fontToReplace)) + { + throw new ArgumentException("Font to replace cannot be null or whitespace.", nameof(fontToReplace)); + } + + if (string.IsNullOrWhiteSpace(replacementFont)) + { + throw new ArgumentException("Replacement font cannot be null or whitespace.", nameof(replacementFont)); + } + + int replacementCount = 0; + + foreach (var slide in this._presentation.Slides) + { + foreach (var shape in slide.Shapes) + { + if (shape.TextBox != null) + { + foreach (var portion in shape.TextBox.Paragraphs.SelectMany(p => p.Portions)) + { + if (portion.Font != null && string.Equals(portion.Font.LatinName, fontToReplace, StringComparison.OrdinalIgnoreCase)) + { + portion.Font.LatinName = replacementFont; + replacementCount++; + } + } + } + } + } + + logger.LogInformation("Total font replacements made: {Count}", replacementCount); + return await Task.FromResult(replacementCount); + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index 1e707c2f..174663d4 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -39,6 +39,12 @@ public interface IPptFontFixTool /// /// A list of shape locations to be removed. Task RemoveUnusedFontsAsync(List locationsToRemove); + + /// + /// Replace a font with another font throughout the presentation. + /// + /// The font to be replaced. + Task ReplaceFontAsync(string fontToReplace, string replacementFont); } /// @@ -122,10 +128,10 @@ public async Task SavePptFileAsync( } /// - [McpServerTool(Name = "remove_unused_font_shapes", Title = "Remove Unused Font Shapes")] - [Description("Removes shapes that contain unused fonts (e.g., empty text boxes). Takes the 'unusedFontLocations' list from the analysis result.")] + [McpServerTool(Name = "remove_unused_font_shapes", Title = "Remove Unused Font Shapes")] + [Description("Removes shapes that contain unused fonts (e.g., empty text boxes). Takes the 'unusedFontLocations' list from the analysis result.")] public async Task RemoveUnusedFontsAsync( - [Description("A list of shape locations (from 'unusedFontLocations') to be removed.")] + [Description("A list of shape locations (from 'unusedFontLocations') to be removed.")] List locationsToRemove) { try @@ -140,4 +146,24 @@ public async Task RemoveUnusedFontsAsync( throw; } } + + /// + [McpServerTool(Name = "replace_font", Title = "Replace Font Throughout Presentation")] + [Description("Replaces a specified font with another font throughout the presentation.")] + public async Task ReplaceFontAsync( + [Description("The font to be replaced")] string fontToReplace, + [Description("The replacement font")] string replacementFont) + { + try + { + int count = await service.ReplaceFontAsync(fontToReplace, replacementFont).ConfigureAwait(false); + logger.LogInformation("ReplaceFontAsync Tool executed, {Count} instances of '{FontToReplace}' replaced with '{ReplacementFont}'.", count, fontToReplace, replacementFont); + return count; + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to replace font '{FontToReplace}' with '{ReplacementFont}'.", fontToReplace, replacementFont); + throw; + } + } } \ No newline at end of file From fc2dce955ea8242cb4c56931c1f61e557cf62125 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sat, 15 Nov 2025 04:40:44 +0900 Subject: [PATCH 17/42] fix RemoveUnusedFontsAsyns's weakness --- .../Services/PPTFontFixService.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index ca36b6b3..08ae7067 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -51,6 +51,8 @@ public interface IPptFontFixService public class PptFontFixService(ILogger logger) : IPptFontFixService { private Presentation? _presentation; + + private HashSet? _analyzedVisibleFonts; /// public async Task OpenPptFileAsync(string filePath) { @@ -63,6 +65,8 @@ public async Task OpenPptFileAsync(string filePath) try { this._presentation = new Presentation(filePath); + + this._analyzedVisibleFonts = null; logger.LogInformation("Ppt file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); await Task.CompletedTask; @@ -150,6 +154,9 @@ public async Task AnalyzeFontsAsync() } var allVisibleFontNames = new HashSet(visibleFontUsages.Keys); + + this._analyzedVisibleFonts = new HashSet(allVisibleFontNames, StringComparer.OrdinalIgnoreCase); + var unusedFonts = new HashSet(totalFontsInSlides); unusedFonts.ExceptWith(allVisibleFontNames); result.UnusedFonts = unusedFonts.ToList(); @@ -261,6 +268,12 @@ public async Task ReplaceFontAsync(string fontToReplace, string replacement throw new ArgumentException("Replacement font cannot be null or whitespace.", nameof(replacementFont)); } + if (!this._analyzedVisibleFonts.Contains(replacementFont)) + { + throw new ArgumentException($"The font '{replacementFont}' is not a valid font found in the presentation's visible text. Please choose from the analyzed list.", nameof(replacementFont)); + } + + int replacementCount = 0; foreach (var slide in this._presentation.Slides) From df278eab476028707b14353565bf83324de57c96 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 16 Nov 2025 23:22:33 +0900 Subject: [PATCH 18/42] Fix: Reduce the number of tools in PPTFontFixTools.cs, from 5 to 2 --- .../Tools/PPTFontFixTool.cs | 137 +++++------------- 1 file changed, 40 insertions(+), 97 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index 174663d4..c062b84c 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -16,35 +16,21 @@ namespace McpSamples.PptFontFix.HybridApp.Tools; public interface IPptFontFixTool { /// - /// open a Ppt file. - /// - /// - /// Returns the result as a string. - Task OpenPptFileAsync(string filePath); - - /// - /// Analyze fonts in a Ppt file. + /// Opens and analyzes fonts in a specified PPT file. /// + /// The path to be analyzed. /// Returns instance. - Task AnalyzeFontsAsync(); + Task AnalyzePptFileAsync(string filePath); /// - /// Save the modified Ppt file. + /// Updates the PPT file by removing unused fonts, replacing inconsistent fonts, and saving to a new path. /// - /// - Task SavePptFileAsync(string newFilePath); - - /// - /// Remove shapes from the presentation. - /// - /// A list of shape locations to be removed. - Task RemoveUnusedFontsAsync(List locationsToRemove); - - /// - /// Replace a font with another font throughout the presentation. - /// - /// The font to be replaced. - Task ReplaceFontAsync(string fontToReplace, string replacementFont); + /// The font to replace all inconsistent fonts with. + /// The list of inconsistent font names to be replaced. + /// The list of shape locations to be removed. + /// The full path to save the new .pptx file. + /// Returns a success message with the new file path. + Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string newFilePath); } /// @@ -56,36 +42,17 @@ public interface IPptFontFixTool public class PptFontFixTool(IPptFontFixService service, ILogger logger) : IPptFontFixTool { /// - [McpServerTool(Name = "open_ppt_file", Title = "Open a Ppt File")] - [Description("Opens a Ppt file and verifies it using ShapeCrawler.")] - public async Task OpenPptFileAsync( - [Description("The path of the Ppt file to open")] string filePath) + [McpServerTool(Name = "analyze_ppt_file", Title = "Analyze PPT File Fonts")] + [Description("Opens a Ppt file AND analyzes fonts used, identifies inconsistencies.")] + public async Task AnalyzePptFileAsync( + [Description("The path of the Ppt file to open and analyze")] string filePath) { try { await service.OpenPptFileAsync(filePath).ConfigureAwait(false); + logger.LogInformation("Ppt file opened successfully: {FilePath}", filePath); - string successMessage = $"Ppt file opened successfully: {filePath}"; - logger.LogInformation(successMessage); - return successMessage; - } - catch (Exception ex) - { - logger.LogError(ex, "Failed to open Ppt file: {FilePath}", filePath); - - throw; - } - } - - /// - [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts in Ppt File")] - [Description("Analyzes fonts used in the opened Ppt file and identifies inconsistencies.")] - public async Task AnalyzeFontsAsync() - { - try - { PptFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); - if (result != null) { int count = result.InconsistentlyUsedFonts?.Count ?? 0; @@ -100,69 +67,45 @@ public async Task AnalyzeFontsAsync() } catch (Exception ex) { - logger.LogError(ex, "Failed to analyze fonts in the Ppt file."); + logger.LogError(ex, "Failed during Ppt file analysis process for: {FilePath}", filePath); throw; } } /// - [McpServerTool(Name = "save_ppt_file", Title = "Save Modified Ppt File")] - [Description("Saves the modified Ppt file to the specified path.")] - public async Task SavePptFileAsync( - [Description("The path to save the modified Ppt file")] string newFilePath) + [McpServerTool(Name = "update_ppt_file", Title = "Update and Save PPT File")] + [Description("Removes unused fonts, replaces inconsistently used fonts with another font defined within the Ppt file, and saves the file.")] + public async Task UpdatePptFileAsync( + [Description("The replacement font")] string replacementFont, + [Description("The fonts to be replaced")] List inconsistentFontsToReplace, + [Description("A list of shape locations (from analysis result) to be removed")] List locationsToRemove, + [Description("The full path to save the modified Ppt file")] string newFilePath) { try { - await service.SavePptFileAsync(newFilePath).ConfigureAwait(false); + int removalCount = await service.RemoveUnusedFontsAsync(locationsToRemove).ConfigureAwait(false); + logger.LogInformation("{Count} unused font shapes removed.", removalCount); - string successMessage = $"Ppt file saved successfully: {newFilePath}"; - logger.LogInformation(successMessage); - return successMessage; - } - catch (Exception ex) - { - logger.LogError(ex, "Failed to save Ppt file: {FilePath}", newFilePath); + int totalReplacementCount = 0; + if (inconsistentFontsToReplace != null) + { + foreach (var fontToReplace in inconsistentFontsToReplace) + { + int count = await service.ReplaceFontAsync(fontToReplace, replacementFont).ConfigureAwait(false); + totalReplacementCount += count; + } + } + logger.LogInformation("{Count} instances of inconsistent fonts replaced with '{ReplacementFont}'.", totalReplacementCount, replacementFont); - throw; - } - } + await service.SavePptFileAsync(newFilePath).ConfigureAwait(false); + logger.LogInformation("Ppt file saved successfully: {FilePath}", newFilePath); - /// - [McpServerTool(Name = "remove_unused_font_shapes", Title = "Remove Unused Font Shapes")] - [Description("Removes shapes that contain unused fonts (e.g., empty text boxes). Takes the 'unusedFontLocations' list from the analysis result.")] - public async Task RemoveUnusedFontsAsync( - [Description("A list of shape locations (from 'unusedFontLocations') to be removed.")] - List locationsToRemove) - { - try - { - int count = await service.RemoveUnusedFontsAsync(locationsToRemove).ConfigureAwait(false); - logger.LogInformation("RemoveUnusedFontsAsync Tool executed, {Count} shapes removed.", count); - return count; - } - catch (Exception ex) - { - logger.LogError(ex, "Failed to remove unused font shapes."); - throw; - } - } - - /// - [McpServerTool(Name = "replace_font", Title = "Replace Font Throughout Presentation")] - [Description("Replaces a specified font with another font throughout the presentation.")] - public async Task ReplaceFontAsync( - [Description("The font to be replaced")] string fontToReplace, - [Description("The replacement font")] string replacementFont) - { - try - { - int count = await service.ReplaceFontAsync(fontToReplace, replacementFont).ConfigureAwait(false); - logger.LogInformation("ReplaceFontAsync Tool executed, {Count} instances of '{FontToReplace}' replaced with '{ReplacementFont}'.", count, fontToReplace, replacementFont); - return count; + string successMessage = $"PPT update complete. {removalCount} shapes removed, {totalReplacementCount} fonts replaced. File saved to: {newFilePath}"; + return successMessage; } catch (Exception ex) { - logger.LogError(ex, "Failed to replace font '{FontToReplace}' with '{ReplacementFont}'.", fontToReplace, replacementFont); + logger.LogError(ex, "Failed during Ppt file update process. Save path: {FilePath}", newFilePath); throw; } } From 10881b3530713f8266c65128c85face23ac4ca5d Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 17 Nov 2025 02:41:14 +0900 Subject: [PATCH 19/42] Add Prompt file --- .vscode/mcp.json | 30 +------ Dockerfile.ppt-font-fix | 26 ++++++ .../Prompts/PptFontFixPrompt.cs | 79 +++++++++++++++++++ 3 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 Dockerfile.ppt-font-fix create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 3bd62f4f..a6e57a2b 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,32 +1,8 @@ { "servers": { - "awesome-copilot": { - "type": "stdio", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "ghcr.io/microsoft/mcp-dotnet-samples/awesome-copilot:latest" - ] - }, - "microsoft.docs.mcp": { + "ppt-font-fix": { "type": "http", - "url": "https://learn.microsoft.com/api/mcp" - }, - "github": { - "type": "http", - "url": "https://api.githubcopilot.com/mcp/" - }, - "sequential-thinking": { - "type": "stdio", - "command": "docker", - "args": [ - "run", - "--rm", - "-i", - "mcp/sequentialthinking" - ] + "url": "http://localhost:5166/mcp" } } -} \ No newline at end of file +} diff --git a/Dockerfile.ppt-font-fix b/Dockerfile.ppt-font-fix new file mode 100644 index 00000000..9938f932 --- /dev/null +++ b/Dockerfile.ppt-font-fix @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1 + +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build + +COPY ./shared/McpSamples.Shared /source/shared/McpSamples.Shared +COPY ./ppt-font-fix/src/McpSamples.PptFontFix.HybridApp /source/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp + +WORKDIR /source/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp + +ARG TARGETARCH +RUN case "$TARGETARCH" in \ + "amd64") RID="linux-musl-x64" ;; \ + "arm64") RID="linux-musl-arm64" ;; \ + *) RID="linux-musl-x64" ;; \ + esac && \ + dotnet publish -c Release -o /app -r $RID --self-contained false + +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final + +WORKDIR /app + +COPY --from=build /app . + +USER $APP_UID + +ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs new file mode 100644 index 00000000..9147f6fa --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -0,0 +1,79 @@ +using System.ComponentModel; +using ModelContextProtocol.Server; + +namespace McpSamples.PptFontFix.HybridApp.Prompts; + +/// +/// This provides interfaces for PPT Font Fix prompts. +/// +public interface IPptFontFixPrompt +{ + /// + /// Gets a prompt to call the 'analyze_ppt_file' tool. + /// + /// The full path to the .pptx file to be analyzed. + /// A formatted prompt to start the font analysis. + string GetAnalysisPrompt(string filePath); + + /// + /// Gets a prompt to call the 'update_ppt_file' tool. + /// + /// The font to replace all inconsistent fonts with. + /// The path to save the new file. + /// A formatted prompt to apply all fixes and save. + string GetUpdatePrompt(string replacementFont, string newFilePath); +} + +/// +/// This represents the prompts entity for the PptFontFix 2-Tool system. +/// +[McpServerPromptType] +public class PptFontFixPrompt : IPptFontFixPrompt +{ + /// + [McpServerPrompt(Name = "run_analysis", Title = "Prompt to run PPT font analysis tool")] + [Description("Get a prompt to call the 'analyze_ppt_file' tool, which opens and analyzes a PPT file.")] + public string GetAnalysisPrompt( + [Description("The full path to the .pptx file to be analyzed")] string filePath) + { + return $""" + Please start the PPT font analysis process. + + Here's the process to follow: + + 1. Call the `analyze_ppt_file` tool using the provided file path: `{filePath}`. + 2. Receive the `PptFontAnalyzeResult` object from the tool. + 3. **Store this entire `PptFontAnalyzeResult` object in your context.** (This is essential for the update step). + 4. Present the `UsedFonts` and `InconsistentlyUsedFonts` lists from the result to the user. + 5. Ask the user to choose one (1) font from the `UsedFonts` list to be the new standard font. + """; + } + + /// + [McpServerPrompt(Name = "run_update_and_save", Title = "Prompt to run PPT font update tool")] + [Description("Get a prompt to call the 'update_ppt_file' tool, which fixes fonts and saves the file.")] + public string GetUpdatePrompt( + [Description("The chosen standard font to replace all inconsistent fonts")] string replacementFont, + [Description("The full path to save the new .pptx file")] string newFilePath) + { + return $""" + Please apply all font fixes and save the presentation. + + Here's the process to follow: + + 1. **Recall the `PptFontAnalyzeResult` object** stored in your context from the analysis step. + 2. Extract the following lists from the recalled object: + * `UsedFonts` + * `InconsistentlyUsedFonts` + * `UnusedFontLocations` + 3. **Validate:** Check if the user's chosen `replacementFont` ("{replacementFont}") is present in the `UsedFonts` list. + 4. **If validation fails:** STOP. Inform the user that "{replacementFont}" is not a valid standard font and ask them to choose from the `UsedFonts` list again. + 5. **If validation succeeds:** Call the `update_ppt_file` tool with the following four arguments: + * `replacementFont`: "{replacementFont}" + * `inconsistentFontsToReplace`: The `InconsistentlyUsedFonts` list (from context) + * `locationsToRemove`: The `UnusedFontLocations` list (from context) + * `newFilePath`: "{newFilePath}" + 6. The tool will return a final success string. Present this string directly to the user. + """; + } +} \ No newline at end of file From 2723a98827c689c0f9102510d51f17b1f47c7175 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 23 Nov 2025 06:53:59 +0900 Subject: [PATCH 20/42] Modify and add code for container execution and file transfer, delete some prompts --- .../McpSamples.PptFontFix.HybridApp.csproj | 2 + .../Program.cs | 13 ++ .../Prompts/PptFontFixPrompt.cs | 91 ++++---- .../Services/PPTFontFixService.cs | 201 ++++++++++++++---- .../Tools/PPTFontFixTool.cs | 15 +- 5 files changed, 233 insertions(+), 89 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj index 83555ca5..00b4ffd5 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -5,9 +5,11 @@ net9.0 enable enable + bfd28526-fe6f-46bc-8552-ea87be54575f + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 98983200..06e92df7 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -1,9 +1,12 @@ using McpSamples.PptFontFix.HybridApp.Configurations; using McpSamples.PptFontFix.HybridApp.Services; using McpSamples.PptFontFix.HybridApp.Tools; +using McpSamples.PptFontFix.HybridApp.Prompts; using McpSamples.Shared.Configurations; using McpSamples.Shared.Extensions; using McpSamples.Shared.OpenApi; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; var useStreamableHttp = AppSettings.UseStreamableHttp(Environment.GetEnvironmentVariables(), args); @@ -12,8 +15,18 @@ : Host.CreateApplicationBuilder(args); builder.Services.AddAppSettings(builder.Configuration, args); + +builder.Services.AddHttpContextAccessor(); builder.Services.AddSingleton(); +builder.Services.AddTransient(); +builder.Services.AddSingleton(); + IHost app = builder.BuildApp(useStreamableHttp); +if (app is WebApplication webApp) +{ + webApp.UseStaticFiles(); +} + await app.RunAsync(); \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 9147f6fa..c2343d44 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -9,71 +9,72 @@ namespace McpSamples.PptFontFix.HybridApp.Prompts; public interface IPptFontFixPrompt { /// - /// Gets a prompt to call the 'analyze_ppt_file' tool. + /// Gets a prompt to start the PPT font fix workflow. /// /// The full path to the .pptx file to be analyzed. /// A formatted prompt to start the font analysis. string GetAnalysisPrompt(string filePath); - - /// - /// Gets a prompt to call the 'update_ppt_file' tool. - /// - /// The font to replace all inconsistent fonts with. - /// The path to save the new file. - /// A formatted prompt to apply all fixes and save. - string GetUpdatePrompt(string replacementFont, string newFilePath); } /// -/// This represents the prompts entity for the PptFontFix 2-Tool system. +/// This represents the prompts entity for the PptFontFix system. /// [McpServerPromptType] public class PptFontFixPrompt : IPptFontFixPrompt { /// - [McpServerPrompt(Name = "run_analysis", Title = "Prompt to run PPT font analysis tool")] - [Description("Get a prompt to call the 'analyze_ppt_file' tool, which opens and analyzes a PPT file.")] + [McpServerPrompt(Name = "fix_ppt_fonts", Title = "Start PPT Font Fix Workflow")] + [Description("Analyzes the PPT file and guides the user through the font replacement process.")] public string GetAnalysisPrompt( - [Description("The full path to the .pptx file to be analyzed")] string filePath) + [Description("The full path to the .pptx file (e.g. /files/test.pptx)")] string filePath) { return $""" - Please start the PPT font analysis process. + You are an expert assistant for fixing PowerPoint font issues. + Please execute the following workflow step-by-step: - Here's the process to follow: + ### PHASE 1: ANALYSIS + 1. Call the `analyze_ppt_file` tool with the path: `{filePath}`. + 2. Analyze the result (`PptFontAnalyzeResult`). + 3. **Show the user** the list of `UsedFonts` and `InconsistentlyUsedFonts`. + 4. **Check `UnusedFontLocations`**: + - If `UnusedFontLocations` is empty, skip the option selection and just ask for the Standard Font. + - If `UnusedFontLocations` has items, **Ask the user to make TWO choices**: + + **A. Select a Standard Font:** (Choose one from `UsedFonts`) + + **B. Select an Action Mode:** + 1. **[Fix & Clean]**: Replace fonts AND remove unused/invisible text boxes (Specify the count of items found in `UnusedFontLocations`). + 2. **[Fix Only]**: Replace fonts ONLY. Keep unused text boxes as is. - 1. Call the `analyze_ppt_file` tool using the provided file path: `{filePath}`. - 2. Receive the `PptFontAnalyzeResult` object from the tool. - 3. **Store this entire `PptFontAnalyzeResult` object in your context.** (This is essential for the update step). - 4. Present the `UsedFonts` and `InconsistentlyUsedFonts` lists from the result to the user. - 5. Ask the user to choose one (1) font from the `UsedFonts` list to be the new standard font. - """; - } + ### PHASE 2: UPDATE (Wait for user input) + Once the user replies with their choices, proceed to call `update_ppt_file`. + + **Parameter Logic:** + - `replacementFont`: The font selected by the user. + - `inconsistentFontsToReplace`: The list of inconsistent fonts found in Phase 1. + - `newFileName`: Generate a safe name like "result_fixed.pptx". + + **Critical Logic for `locationsToRemove`:** + - IF User chose **1 (Fix & Clean)**: Pass the `UnusedFontLocations` list found in Phase 1. + - IF User chose **2 (Fix Only)**: Pass an **empty list `[]`**. (Do NOT pass null, pass an empty JSON array). - /// - [McpServerPrompt(Name = "run_update_and_save", Title = "Prompt to run PPT font update tool")] - [Description("Get a prompt to call the 'update_ppt_file' tool, which fixes fonts and saves the file.")] - public string GetUpdatePrompt( - [Description("The chosen standard font to replace all inconsistent fonts")] string replacementFont, - [Description("The full path to save the new .pptx file")] string newFilePath) - { - return $""" - Please apply all font fixes and save the presentation. + ### PHASE 3: RESULT PRESENTATION (CRITICAL!) + The `update_ppt_file` tool will return a result string. Analyze it carefully. - Here's the process to follow: + **CASE A: The result starts with `http` (Web Mode)** + - Render it as a Clickable Markdown Link. + - Format: `👉 [Click here to Download Fixed File](URL)` - 1. **Recall the `PptFontAnalyzeResult` object** stored in your context from the analysis step. - 2. Extract the following lists from the recalled object: - * `UsedFonts` - * `InconsistentlyUsedFonts` - * `UnusedFontLocations` - 3. **Validate:** Check if the user's chosen `replacementFont` ("{replacementFont}") is present in the `UsedFonts` list. - 4. **If validation fails:** STOP. Inform the user that "{replacementFont}" is not a valid standard font and ask them to choose from the `UsedFonts` list again. - 5. **If validation succeeds:** Call the `update_ppt_file` tool with the following four arguments: - * `replacementFont`: "{replacementFont}" - * `inconsistentFontsToReplace`: The `InconsistentlyUsedFonts` list (from context) - * `locationsToRemove`: The `UnusedFontLocations` list (from context) - * `newFilePath`: "{newFilePath}" - 6. The tool will return a final success string. Present this string directly to the user. + **CASE B: The result is a File Path (e.g. `/files/...` or `C:\...`) (Stdio/Local Mode)** + - The user is using VS Code. VS Code automatically detects absolute paths. + - **DO NOT use Markdown syntax** (No `[]` or `()`). + - **DO NOT shorten the path.** Output the full string exactly as returned by the tool. + - Output format: + + ✅ **Task Completed.** + + **File:** + [Insert Raw Full Path Here] """; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 08ae7067..ff7e128f 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -3,6 +3,13 @@ using ModelContextProtocol.Server; using System.Linq; using McpSamples.PptFontFix.HybridApp.Models; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Http; +using System.IO; +using Azure.Storage.Blobs; namespace McpSamples.PptFontFix.HybridApp.Services; @@ -27,7 +34,7 @@ public interface IPptFontFixService /// Save the modified Ppt file. /// /// - Task SavePptFileAsync(string newFilePath); + Task SavePptFileAsync(string newFilePath); /// /// Remove Unused Fonts from the presentation. @@ -48,32 +55,78 @@ public interface IPptFontFixService /// This represents the service entity for Ppt font fixing. /// /// -public class PptFontFixService(ILogger logger) : IPptFontFixService +public class PptFontFixService : IPptFontFixService { + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + private readonly IHostEnvironment _hostEnvironment; + private readonly IWebHostEnvironment? _webHostEnvironment; + private readonly IHttpContextAccessor? _httpContextAccessor; private Presentation? _presentation; private HashSet? _analyzedVisibleFonts; + + public PptFontFixService( + ILogger logger, + IConfiguration configuration, + IHostEnvironment hostEnvironment, + IServiceProvider serviceProvider) + { + _logger = logger; + _configuration = configuration; + _hostEnvironment = hostEnvironment; + _webHostEnvironment = serviceProvider.GetService(); + _httpContextAccessor = serviceProvider.GetService(); + } + /// public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); - if (File.Exists(filePath) == false) + + var searchPaths = new List(); + + searchPaths.Add(filePath); + + string fileName = Path.GetFileName(filePath); + if (filePath.Contains('\\')) fileName = filePath.Split('\\').Last(); + if (filePath.Contains('/')) fileName = filePath.Split('/').Last(); + + searchPaths.Add(Path.Combine("/files", fileName)); + + string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + searchPaths.Add(Path.Combine(baseDir, "generated", fileName)); + + searchPaths.Add(Path.Combine(Path.GetTempPath(), fileName)); + + string? foundPath = null; + foreach (var path in searchPaths) { - throw new FileNotFoundException("Ppt file does not exist.", filePath); + if (File.Exists(path)) + { + foundPath = path; + _logger.LogInformation("✅ File found at: {Path}", foundPath); + break; + } } - try + if (foundPath == null) { - this._presentation = new Presentation(filePath); - - this._analyzedVisibleFonts = null; - logger.LogInformation("Ppt file opened successfully and verified by ShapeCrawler: {FilePath}", filePath); + _logger.LogError("❌ File not found. Searched in: {Paths}", string.Join(", ", searchPaths)); + throw new FileNotFoundException($"Ppt file not found. Searched in /files, /generated, and /tmp inside container.", filePath); + } + try + { + _presentation?.Dispose(); + _presentation = new Presentation(foundPath); + _analyzedVisibleFonts = null; + _logger.LogInformation("Ppt file opened successfully: {FilePath}", foundPath); await Task.CompletedTask; } catch (Exception ex) { - logger.LogError(ex, "Failed to open Ppt file with ShapeCrawler: {FilePath}", filePath); + _logger.LogError(ex, "Failed to open Ppt file."); throw; } } @@ -126,7 +179,7 @@ public async Task AnalyzeFontsAsync() bool isEmptyBox = shape.TextBox != null && string.IsNullOrWhiteSpace(shape.TextBox.Text); if (isEmptyBox) { - logger.LogWarning("[Empty Box Detected] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", + _logger.LogWarning("[Empty Box Detected] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", slide.Number, shape.Name); result.UnusedFontLocations.Add(location); } @@ -138,7 +191,7 @@ public async Task AnalyzeFontsAsync() if (!isShapeVisible && shape.TextBox != null && !isEmptyBox) { - logger.LogWarning("[Text Shape Outside Slide] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", + _logger.LogWarning("[Text Shape Outside Slide] Slide Number: {SlideNumber}, Shape Name: {ShapeName}", slide.Number, shape.Name); result.UnusedFontLocations.Add(location); } @@ -178,34 +231,110 @@ public async Task AnalyzeFontsAsync() .SelectMany(pair => pair.Value) .ToList(); - logger.LogInformation("[Result] Used (Standard) Fonts: {Fonts}", string.Join(", ", result.UsedFonts)); - logger.LogInformation("[Result] Unused Fonts: {Fonts}", string.Join(", ", result.UnusedFonts)); - logger.LogInformation("[Result] Inconsistently Used Fonts: {Fonts}", string.Join(", ", result.InconsistentlyUsedFonts)); + _logger.LogInformation("[Result] Used (Standard) Fonts: {Fonts}", string.Join(", ", result.UsedFonts)); + _logger.LogInformation("[Result] Unused Fonts: {Fonts}", string.Join(", ", result.UnusedFonts)); + _logger.LogInformation("[Result] Inconsistently Used Fonts: {Fonts}", string.Join(", ", result.InconsistentlyUsedFonts)); return await Task.FromResult(result); } /// - public async Task SavePptFileAsync(string newFilePath) + public async Task SavePptFileAsync(string desiredFileName) { - if (this._presentation == null) - { - throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); - } + if (this._presentation == null) throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); + ArgumentException.ThrowIfNullOrWhiteSpace(desiredFileName, nameof(desiredFileName)); - ArgumentException.ThrowIfNullOrWhiteSpace(newFilePath, nameof(newFilePath)); + string safeFileName = Path.GetFileName(desiredFileName); + if (safeFileName.Contains('\\')) safeFileName = safeFileName.Split('\\').Last(); + if (safeFileName.Contains('/')) safeFileName = safeFileName.Split('/').Last(); + safeFileName = safeFileName.Replace(":", "").Trim(); - try - { - this._presentation.Save(newFilePath); - logger.LogInformation("Ppt file saved successfully: {FilePath}", newFilePath); + _logger.LogInformation("Save process started. Target: {SafeName}", safeFileName); - await Task.CompletedTask; - } - catch (Exception ex) + using (var memoryStream = new MemoryStream()) { - logger.LogError(ex, "Failed to save Ppt file: {FilePath}", newFilePath); - throw; + await Task.Run(() => _presentation.Save(memoryStream)); + memoryStream.Position = 0; + + string? azureConnectionString = _configuration["AzureBlobConnectionString"]; + if (!string.IsNullOrEmpty(azureConnectionString)) + { + try + { + _logger.LogInformation("Environment detected: Azure Blob Storage"); + var blobServiceClient = new BlobServiceClient(azureConnectionString); + var containerClient = blobServiceClient.GetBlobContainerClient("generated-files"); + await containerClient.CreateIfNotExistsAsync(); + var blobClient = containerClient.GetBlobClient(safeFileName); + await blobClient.UploadAsync(memoryStream, overwrite: true); + return blobClient.Uri.ToString(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Azure save failed. Falling back to local storage."); + memoryStream.Position = 0; + } + } + string finalPhysicalPath = ""; + string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + string generatedDir = Path.Combine(webRoot, "generated"); + if (!Directory.Exists(generatedDir)) Directory.CreateDirectory(generatedDir); + string webStoragePath = Path.Combine(generatedDir, safeFileName); + + bool isDocker = !OperatingSystem.IsWindows(); + + if (isDocker) + { + _logger.LogInformation("Environment detected: Docker Container"); + + try + { + string syncPath = Path.Combine("/files", safeFileName); + using (var fs = new FileStream(syncPath, FileMode.Create, FileAccess.Write)) + { + await memoryStream.CopyToAsync(fs); + } + File.SetUnixFileMode(syncPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); + + finalPhysicalPath = syncPath; + } + catch (Exception ex) + { + _logger.LogWarning("Could not save to /files volume: {Msg}", ex.Message); + finalPhysicalPath = webStoragePath; + } + + memoryStream.Position = 0; + using (var fs = new FileStream(webStoragePath, FileMode.Create, FileAccess.Write)) + { + await memoryStream.CopyToAsync(fs); + } + File.SetUnixFileMode(webStoragePath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead); + } + else + { + _logger.LogInformation("Environment detected: Local Windows"); + + using (var fs = new FileStream(webStoragePath, FileMode.Create, FileAccess.Write)) + { + await memoryStream.CopyToAsync(fs); + } + + finalPhysicalPath = webStoragePath; + } + + if (_httpContextAccessor?.HttpContext?.Request != null) + { + var request = _httpContextAccessor.HttpContext.Request; + string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; + _logger.LogInformation("✅ Returning Web URL: {Url}", url); + return url; + } + else + { + _logger.LogInformation("✅ Returning Physical Path: {Path}", finalPhysicalPath); + return finalPhysicalPath; + } } } @@ -219,7 +348,7 @@ public async Task RemoveUnusedFontsAsync(List locationsT if (locationsToRemove == null || locationsToRemove.Count == 0) { - logger.LogInformation("No locations provided for removal. Skipping removal process."); + _logger.LogInformation("No locations provided for removal. Skipping removal process."); return await Task.FromResult(0); } @@ -230,23 +359,23 @@ public async Task RemoveUnusedFontsAsync(List locationsT var slide = this._presentation.Slides.FirstOrDefault(s => s.Number == location.SlideNumber); if (slide == null) { - logger.LogWarning("Slide number {SlideNumber} not found. Skipping.", location.SlideNumber); + _logger.LogWarning("Slide number {SlideNumber} not found. Skipping.", location.SlideNumber); continue; } var shape = slide.Shapes.FirstOrDefault(sh => sh.Name == location.ShapeName); if (shape == null) { - logger.LogWarning("Shape name {ShapeName} not found in slide {SlideNumber}. Skipping.", location.ShapeName, location.SlideNumber); + _logger.LogWarning("Shape name {ShapeName} not found in slide {SlideNumber}. Skipping.", location.ShapeName, location.SlideNumber); continue; } shape.Remove(); removalCount++; - logger.LogInformation("Removed shape {ShapeName} from slide {SlideNumber}.", location.ShapeName, location.SlideNumber); + _logger.LogInformation("Removed shape {ShapeName} from slide {SlideNumber}.", location.ShapeName, location.SlideNumber); } - logger.LogInformation("Total shapes removed: {Count}", removalCount); + _logger.LogInformation("Total shapes removed: {Count}", removalCount); return await Task.FromResult(removalCount); } @@ -294,7 +423,7 @@ public async Task ReplaceFontAsync(string fontToReplace, string replacement } } - logger.LogInformation("Total font replacements made: {Count}", replacementCount); + _logger.LogInformation("Total font replacements made: {Count}", replacementCount); return await Task.FromResult(replacementCount); } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index c062b84c..f5997889 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -28,9 +28,9 @@ public interface IPptFontFixTool /// The font to replace all inconsistent fonts with. /// The list of inconsistent font names to be replaced. /// The list of shape locations to be removed. - /// The full path to save the new .pptx file. + /// The full path to save the new .pptx file. /// Returns a success message with the new file path. - Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string newFilePath); + Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string newFileName); } /// @@ -79,7 +79,7 @@ public async Task UpdatePptFileAsync( [Description("The replacement font")] string replacementFont, [Description("The fonts to be replaced")] List inconsistentFontsToReplace, [Description("A list of shape locations (from analysis result) to be removed")] List locationsToRemove, - [Description("The full path to save the modified Ppt file")] string newFilePath) + [Description("The full path to save the modified Ppt file")] string newFileName) { try { @@ -97,15 +97,14 @@ public async Task UpdatePptFileAsync( } logger.LogInformation("{Count} instances of inconsistent fonts replaced with '{ReplacementFont}'.", totalReplacementCount, replacementFont); - await service.SavePptFileAsync(newFilePath).ConfigureAwait(false); - logger.LogInformation("Ppt file saved successfully: {FilePath}", newFilePath); + string accessPath = await service.SavePptFileAsync(newFileName).ConfigureAwait(false); + logger.LogInformation("Ppt file saved successfully: {Path}", accessPath); - string successMessage = $"PPT update complete. {removalCount} shapes removed, {totalReplacementCount} fonts replaced. File saved to: {newFilePath}"; - return successMessage; + return $"PPT update complete. Removed: {removalCount}, Replaced: {totalReplacementCount}. Result: {accessPath}"; } catch (Exception ex) { - logger.LogError(ex, "Failed during Ppt file update process. Save path: {FilePath}", newFilePath); + logger.LogError(ex, "Failed during Ppt file update process. Save name: {FileName}", newFileName); throw; } } From 42cd9d6f5551172f39f34fdac4e20baa93f6f951 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 23 Nov 2025 06:55:36 +0900 Subject: [PATCH 21/42] Add files for Running on Azure --- .../azure.yaml | 16 ++ .../infra/abbreviations.json | 136 +++++++++++++++++ .../infra/main.bicep | 47 ++++++ .../infra/main.parameters.json | 18 +++ .../infra/modules/fetch-container-image.bicep | 8 + .../infra/resources.bicep | 144 ++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml new file mode 100644 index 00000000..ce91d9e5 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml @@ -0,0 +1,16 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json + +name: ppt-font-fix + +metadata: + template: azd-init@1.14.0 + +services: + ppt-font-fix: + project: src/McpSamples.PptFontFix.HybridApp + host: containerapp + language: dotnet + docker: + path: ../../../Dockerfile.ppt-font-fix-azure + context: ../../../ + remoteBuild: true diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json new file mode 100644 index 00000000..1533dee5 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json @@ -0,0 +1,136 @@ +{ + "analysisServicesServers": "as", + "apiManagementService": "apim-", + "appConfigurationStores": "appcs-", + "appManagedEnvironments": "cae-", + "appContainerApps": "ca-", + "authorizationPolicyDefinitions": "policy-", + "automationAutomationAccounts": "aa-", + "blueprintBlueprints": "bp-", + "blueprintBlueprintsArtifacts": "bpa-", + "cacheRedis": "redis-", + "cdnProfiles": "cdnp-", + "cdnProfilesEndpoints": "cdne-", + "cognitiveServicesAccounts": "cog-", + "cognitiveServicesFormRecognizer": "cog-fr-", + "cognitiveServicesTextAnalytics": "cog-ta-", + "computeAvailabilitySets": "avail-", + "computeCloudServices": "cld-", + "computeDiskEncryptionSets": "des", + "computeDisks": "disk", + "computeDisksOs": "osdisk", + "computeGalleries": "gal", + "computeSnapshots": "snap-", + "computeVirtualMachines": "vm", + "computeVirtualMachineScaleSets": "vmss-", + "containerInstanceContainerGroups": "ci", + "containerRegistryRegistries": "cr", + "containerServiceManagedClusters": "aks-", + "databricksWorkspaces": "dbw-", + "dataFactoryFactories": "adf-", + "dataLakeAnalyticsAccounts": "dla", + "dataLakeStoreAccounts": "dls", + "dataMigrationServices": "dms-", + "dBforMySQLServers": "mysql-", + "dBforPostgreSQLServers": "psql-", + "devicesIotHubs": "iot-", + "devicesProvisioningServices": "provs-", + "devicesProvisioningServicesCertificates": "pcert-", + "documentDBDatabaseAccounts": "cosmos-", + "documentDBMongoDatabaseAccounts": "cosmon-", + "eventGridDomains": "evgd-", + "eventGridDomainsTopics": "evgt-", + "eventGridEventSubscriptions": "evgs-", + "eventHubNamespaces": "evhns-", + "eventHubNamespacesEventHubs": "evh-", + "hdInsightClustersHadoop": "hadoop-", + "hdInsightClustersHbase": "hbase-", + "hdInsightClustersKafka": "kafka-", + "hdInsightClustersMl": "mls-", + "hdInsightClustersSpark": "spark-", + "hdInsightClustersStorm": "storm-", + "hybridComputeMachines": "arcs-", + "insightsActionGroups": "ag-", + "insightsComponents": "appi-", + "keyVaultVaults": "kv-", + "kubernetesConnectedClusters": "arck", + "kustoClusters": "dec", + "kustoClustersDatabases": "dedb", + "logicIntegrationAccounts": "ia-", + "logicWorkflows": "logic-", + "machineLearningServicesWorkspaces": "mlw-", + "managedIdentityUserAssignedIdentities": "id-", + "managementManagementGroups": "mg-", + "migrateAssessmentProjects": "migr-", + "networkApplicationGateways": "agw-", + "networkApplicationSecurityGroups": "asg-", + "networkAzureFirewalls": "afw-", + "networkBastionHosts": "bas-", + "networkConnections": "con-", + "networkDnsZones": "dnsz-", + "networkExpressRouteCircuits": "erc-", + "networkFirewallPolicies": "afwp-", + "networkFirewallPoliciesWebApplication": "waf", + "networkFirewallPoliciesRuleGroups": "wafrg", + "networkFrontDoors": "fd-", + "networkFrontdoorWebApplicationFirewallPolicies": "fdfp-", + "networkLoadBalancersExternal": "lbe-", + "networkLoadBalancersInternal": "lbi-", + "networkLoadBalancersInboundNatRules": "rule-", + "networkLocalNetworkGateways": "lgw-", + "networkNatGateways": "ng-", + "networkNetworkInterfaces": "nic-", + "networkNetworkSecurityGroups": "nsg-", + "networkNetworkSecurityGroupsSecurityRules": "nsgsr-", + "networkNetworkWatchers": "nw-", + "networkPrivateDnsZones": "pdnsz-", + "networkPrivateLinkServices": "pl-", + "networkPublicIPAddresses": "pip-", + "networkPublicIPPrefixes": "ippre-", + "networkRouteFilters": "rf-", + "networkRouteTables": "rt-", + "networkRouteTablesRoutes": "udr-", + "networkTrafficManagerProfiles": "traf-", + "networkVirtualNetworkGateways": "vgw-", + "networkVirtualNetworks": "vnet-", + "networkVirtualNetworksSubnets": "snet-", + "networkVirtualNetworksVirtualNetworkPeerings": "peer-", + "networkVirtualWans": "vwan-", + "networkVpnGateways": "vpng-", + "networkVpnGatewaysVpnConnections": "vcn-", + "networkVpnGatewaysVpnSites": "vst-", + "notificationHubsNamespaces": "ntfns-", + "notificationHubsNamespacesNotificationHubs": "ntf-", + "operationalInsightsWorkspaces": "log-", + "portalDashboards": "dash-", + "powerBIDedicatedCapacities": "pbi-", + "purviewAccounts": "pview-", + "recoveryServicesVaults": "rsv-", + "resourcesResourceGroups": "rg-", + "searchSearchServices": "srch-", + "serviceBusNamespaces": "sb-", + "serviceBusNamespacesQueues": "sbq-", + "serviceBusNamespacesTopics": "sbt-", + "serviceEndPointPolicies": "se-", + "serviceFabricClusters": "sf-", + "signalRServiceSignalR": "sigr", + "sqlManagedInstances": "sqlmi-", + "sqlServers": "sql-", + "sqlServersDataWarehouse": "sqldw-", + "sqlServersDatabases": "sqldb-", + "sqlServersDatabasesStretch": "sqlstrdb-", + "storageStorageAccounts": "st", + "storageStorageAccountsVm": "stvm", + "storSimpleManagers": "ssimp", + "streamAnalyticsCluster": "asa-", + "synapseWorkspaces": "syn", + "synapseWorkspacesAnalyticsWorkspaces": "synw", + "synapseWorkspacesSqlPoolsDedicated": "syndp", + "synapseWorkspacesSqlPoolsSpark": "synsp", + "timeSeriesInsightsEnvironments": "tsi-", + "webServerFarms": "plan-", + "webSitesAppService": "app-", + "webSitesAppServiceEnvironment": "ase-", + "webSitesFunctions": "func-", + "webStaticSites": "stapp-" +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep new file mode 100644 index 00000000..8f80e574 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep @@ -0,0 +1,47 @@ +targetScope = 'subscription' + +@minLength(1) +@maxLength(64) +@description('Name of the environment that can be used as part of naming resource convention') +param environmentName string + +@minLength(1) +@description('Primary location for all resources') +param location string + +param mcpPptFontFixExists bool + +@description('Id of the user or app to assign application roles') +param principalId string + +// Tags that should be applied to all resources. +// +// Note that 'azd-service-name' tags should be applied separately to service host resources. +// Example usage: +// tags: union(tags, { 'azd-service-name': }) +var tags = { + 'azd-env-name': environmentName +} + +// Organize resources in a resource group +resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: 'rg-${environmentName}' + location: location + tags: tags +} + +module resources 'resources.bicep' = { + scope: rg + name: 'resources' + params: { + location: location + tags: tags + principalId: principalId + mcpPptFontFixExists: mcpPptFontFixExists + } +} + +output AZURE_CONTAINER_REGISTRY_ENDPOINT string = resources.outputs.AZURE_CONTAINER_REGISTRY_ENDPOINT +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json new file mode 100644 index 00000000..259447e2 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "environmentName": { + "value": "${AZURE_ENV_NAME}" + }, + "location": { + "value": "${AZURE_LOCATION}" + }, + "mcpPptFontFixExists": { + "value": "${SERVICE_MCP_PPT_FONT_FIX_RESOURCE_EXISTS=false}" + }, + "principalId": { + "value": "${AZURE_PRINCIPAL_ID}" + } + } +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep new file mode 100644 index 00000000..78d1e7ee --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep @@ -0,0 +1,8 @@ +param exists bool +param name string + +resource existingApp 'Microsoft.App/containerApps@2023-05-02-preview' existing = if (exists) { + name: name +} + +output containers array = exists ? existingApp.properties.template.containers : [] diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep new file mode 100644 index 00000000..06028c76 --- /dev/null +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep @@ -0,0 +1,144 @@ +@description('The location used for all deployed resources') +param location string = resourceGroup().location + +@description('Tags that will be applied to all resources') +param tags object = {} + +param mcpPptFontFixExists bool + +@description('Id of the user or app to assign application roles') +param principalId string + +var abbrs = loadJsonContent('./abbreviations.json') +var resourceToken = uniqueString(subscription().id, resourceGroup().id, location) + +// Monitor application with Azure Monitor +module monitoring 'br/public:avm/ptn/azd/monitoring:0.1.0' = { + name: 'monitoring' + params: { + logAnalyticsName: '${abbrs.operationalInsightsWorkspaces}${resourceToken}' + applicationInsightsName: '${abbrs.insightsComponents}${resourceToken}' + applicationInsightsDashboardName: '${abbrs.portalDashboards}${resourceToken}' + location: location + tags: tags + } +} + +// Container registry +module containerRegistry 'br/public:avm/res/container-registry/registry:0.1.1' = { + name: 'registry' + params: { + name: '${abbrs.containerRegistryRegistries}${resourceToken}' + location: location + tags: tags + publicNetworkAccess: 'Enabled' + roleAssignments: [ + { + principalId: mcpPptFontFixIdentity.outputs.principalId + principalType: 'ServicePrincipal' + // ACR pull role + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + } + ] + } +} + +// Container apps environment +module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.4.5' = { + name: 'container-apps-environment' + params: { + logAnalyticsWorkspaceResourceId: monitoring.outputs.logAnalyticsWorkspaceResourceId + name: '${abbrs.appManagedEnvironments}${resourceToken}' + location: location + zoneRedundant: false + } +} + +// User assigned identity +module mcpPptFontFixIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { + name: 'mcpPptFontFixIdentity' + params: { + name: '${abbrs.managedIdentityUserAssignedIdentities}mcpPptFontFix-${resourceToken}' + location: location + } +} + +// Azure Container Apps +module mcpPptFontFixFetchLatestImage './modules/fetch-container-image.bicep' = { + name: 'mcpPptFontFix-fetch-image' + params: { + exists: mcpPptFontFixExists + name: 'ppt-font-fix' + } +} + +module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { + name: 'mcpPptFontFix' + params: { + name: 'ppt-font-fix' + ingressTargetPort: 8080 + scaleMinReplicas: 1 + scaleMaxReplicas: 10 + secrets: { + secureList: [ + ] + } + containers: [ + { + image: mcpPptFontFixFetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' + name: 'main' + resources: { + cpu: json('0.5') + memory: '1.0Gi' + } + env: [ + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: monitoring.outputs.applicationInsightsConnectionString + } + { + name: 'AZURE_CLIENT_ID' + value: mcpPptFontFixIdentity.outputs.clientId + } + { + name: 'PORT' + value: '8080' + } + ] + args: [ + '--http' + ] + } + ] + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [ + mcpPptFontFixIdentity.outputs.resourceId + ] + } + registries: [ + { + server: containerRegistry.outputs.loginServer + identity: mcpPptFontFixIdentity.outputs.resourceId + } + ] + corsPolicy: { + allowedOrigins: [ + 'https://make.preview.powerautomate.com' + 'https://make.preview.powerapps.com' + 'https://copilotstudio.preview.microsoft.com' + 'https://make.powerautomate.com' + 'https://make.powerapps.com' + 'https://copilotstudio.microsoft.com' + ] + } + environmentResourceId: containerAppsEnvironment.outputs.resourceId + location: location + tags: union(tags, { 'azd-service-name': 'ppt-font-fix' }) + } +} + +output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID string = mcpPptFontFix.outputs.resourceId +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = mcpPptFontFix.outputs.name +output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = mcpPptFontFix.outputs.fqdn From bce177e73c077bd49f2a20437bc34eb4833d9d0b Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 23 Nov 2025 19:34:33 +0900 Subject: [PATCH 22/42] move file location --- ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/azure.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/azure.yaml (100%) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml b/ppt-font-fix/azure.yaml similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/azure.yaml rename to ppt-font-fix/azure.yaml From caf7cd273e02cb6d18588e6411fa34e3931f1d7a Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sun, 23 Nov 2025 19:36:13 +0900 Subject: [PATCH 23/42] move folder location --- .../McpSamples.PptFontFix.HybridApp => }/infra/abbreviations.json | 0 .../{src/McpSamples.PptFontFix.HybridApp => }/infra/main.bicep | 0 .../infra/main.parameters.json | 0 .../infra/modules/fetch-container-image.bicep | 0 .../McpSamples.PptFontFix.HybridApp => }/infra/resources.bicep | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/infra/abbreviations.json (100%) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/infra/main.bicep (100%) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/infra/main.parameters.json (100%) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/infra/modules/fetch-container-image.bicep (100%) rename ppt-font-fix/{src/McpSamples.PptFontFix.HybridApp => }/infra/resources.bicep (100%) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json b/ppt-font-fix/infra/abbreviations.json similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/abbreviations.json rename to ppt-font-fix/infra/abbreviations.json diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep b/ppt-font-fix/infra/main.bicep similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.bicep rename to ppt-font-fix/infra/main.bicep diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json b/ppt-font-fix/infra/main.parameters.json similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/main.parameters.json rename to ppt-font-fix/infra/main.parameters.json diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep b/ppt-font-fix/infra/modules/fetch-container-image.bicep similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/modules/fetch-container-image.bicep rename to ppt-font-fix/infra/modules/fetch-container-image.bicep diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep b/ppt-font-fix/infra/resources.bicep similarity index 100% rename from ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/infra/resources.bicep rename to ppt-font-fix/infra/resources.bicep From 01198de00382b3f3a926ea8b5d29f6d8ed6c3361 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Tue, 25 Nov 2025 02:21:05 +0900 Subject: [PATCH 24/42] setting for azure running, fix some codes --- ppt-font-fix/.gitignore | 2 + ppt-font-fix/.vscode/mcp.stdio.container.json | 14 ++- ppt-font-fix/infra/resources.bicep | 101 ++++++++++++++++-- .../Prompts/PptFontFixPrompt.cs | 9 +- .../Services/PPTFontFixService.cs | 2 + 5 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 ppt-font-fix/.gitignore diff --git a/ppt-font-fix/.gitignore b/ppt-font-fix/.gitignore new file mode 100644 index 00000000..8483aa73 --- /dev/null +++ b/ppt-font-fix/.gitignore @@ -0,0 +1,2 @@ +.vscode/mcp.json +.azure \ No newline at end of file diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index 85bc618c..7b6d76fb 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -1,4 +1,11 @@ { + "inputs": [ + { + "type": "promptString", + "id": "your-ppt-file-path", + "description": "The absolute path where the PPT file you want to modify is located" + } + ], "servers": { "ppt-font-fix": { "type": "stdio", @@ -7,10 +14,9 @@ "run", "-i", "--rm", - "ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest", - "-tc", - "-p" + "-v", "${input:your-ppt-file-path}:/files", + "ppt-font-fix:latest" ] } } -} +} \ No newline at end of file diff --git a/ppt-font-fix/infra/resources.bicep b/ppt-font-fix/infra/resources.bicep index 06028c76..8a5bd43d 100644 --- a/ppt-font-fix/infra/resources.bicep +++ b/ppt-font-fix/infra/resources.bicep @@ -9,6 +9,8 @@ param mcpPptFontFixExists bool @description('Id of the user or app to assign application roles') param principalId string +var containerAppName = 'ppt-font-fix' + var abbrs = loadJsonContent('./abbreviations.json') var resourceToken = uniqueString(subscription().id, resourceGroup().id, location) @@ -24,7 +26,35 @@ module monitoring 'br/public:avm/ptn/azd/monitoring:0.1.0' = { } } -// Container registry +// Storage +resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { + name: 'st${resourceToken}' + location: location + kind: 'StorageV2' + tags: tags + sku: { + name: 'Standard_LRS' + } + properties: { + largeFileSharesState: 'Enabled' + } +} + +resource storageFileService 'Microsoft.Storage/storageAccounts/fileServices@2022-09-01' = { + parent: storage + name: 'default' +} + +resource storageFileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2022-09-01' = { + parent: storageFileService + name: 'ppt-files' + properties: { + shareQuota: 1024 + enabledProtocols: 'SMB' + } +} + +// Container Registry module containerRegistry 'br/public:avm/res/container-registry/registry:0.1.1' = { name: 'registry' params: { @@ -44,17 +74,44 @@ module containerRegistry 'br/public:avm/res/container-registry/registry:0.1.1' = } // Container apps environment -module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.4.5' = { +module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.3' = { name: 'container-apps-environment' params: { - logAnalyticsWorkspaceResourceId: monitoring.outputs.logAnalyticsWorkspaceResourceId + appInsightsConnectionString: monitoring.outputs.applicationInsightsConnectionString name: '${abbrs.appManagedEnvironments}${resourceToken}' location: location zoneRedundant: false + publicNetworkAccess: 'Enabled' + + workloadProfiles: [ + { + workloadProfileType: 'Consumption' + name: 'Consumption' + } + ] } } -// User assigned identity +resource existingEnv 'Microsoft.App/managedEnvironments@2023-05-01' existing = { + name: '${abbrs.appManagedEnvironments}${resourceToken}' +} + +resource explicitStorageLink 'Microsoft.App/managedEnvironments/storages@2023-05-01' = { + parent: existingEnv + name: 'ppt-storage-link' + properties: { + azureFile: { + accountName: storage.name + shareName: storageFileShare.name + accessMode: 'ReadWrite' + accountKey: storage.listKeys().keys[0].value + } + } + dependsOn: [ + containerAppsEnvironment + ] +} + module mcpPptFontFixIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { name: 'mcpPptFontFixIdentity' params: { @@ -74,8 +131,13 @@ module mcpPptFontFixFetchLatestImage './modules/fetch-container-image.bicep' = { module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { name: 'mcpPptFontFix' + + dependsOn: [ + explicitStorageLink + ] + params: { - name: 'ppt-font-fix' + name: containerAppName ingressTargetPort: 8080 scaleMinReplicas: 1 scaleMaxReplicas: 10 @@ -83,6 +145,13 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { secureList: [ ] } + volumes: [ + { + name: 'ppt-files-volume' + storageType: 'AzureFile' + storageName: 'ppt-storage-link' + } + ] containers: [ { image: mcpPptFontFixFetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' @@ -105,8 +174,12 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { value: '8080' } ] - args: [ - '--http' + args: [ '--http' ] + volumeMounts: [ + { + volumeName: 'ppt-files-volume' + mountPath: '/app/mounts' + } ] } ] @@ -137,6 +210,20 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { tags: union(tags, { 'azd-service-name': 'ppt-font-fix' }) } } +resource authConfig 'Microsoft.App/containerApps/authConfigs@2023-05-01' = { + name: '${containerAppName}/current' + properties: { + platform: { + enabled: false + } + globalValidation: { + unauthenticatedClientAction: 'AllowAnonymous' + } + } + dependsOn: [ + mcpPptFontFix + ] +} output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer output AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID string = mcpPptFontFix.outputs.resourceId diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index c2343d44..7b3a33f8 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -65,16 +65,23 @@ 2. Analyze the result (`PptFontAnalyzeResult`). - Render it as a Clickable Markdown Link. - Format: `👉 [Click here to Download Fixed File](URL)` - **CASE B: The result is a File Path (e.g. `/files/...` or `C:\...`) (Stdio/Local Mode)** + **CASE B: The result is a File Path (e.g. `/files/...`, `/app/...` or `C:\...`) (Stdio/Local Mode)** - The user is using VS Code. VS Code automatically detects absolute paths. - **DO NOT use Markdown syntax** (No `[]` or `()`). - **DO NOT shorten the path.** Output the full string exactly as returned by the tool. + + - **SPECIAL INSTRUCTION FOR CONTAINER PATHS:** + - If the returned path looks like a Linux path (e.g. starts with `/app/` or `/files/`), it is inside the Docker container. + - **Explicitly tell the user:** "This file is saved inside the container volume. Please check your mounted local folder." + - Output format: ✅ **Task Completed.** **File:** [Insert Raw Full Path Here] + + *(If container path, insert hint here)* """; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index ff7e128f..70335a42 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -92,6 +92,8 @@ public async Task OpenPptFileAsync(string filePath) if (filePath.Contains('\\')) fileName = filePath.Split('\\').Last(); if (filePath.Contains('/')) fileName = filePath.Split('/').Last(); + searchPaths.Add(Path.Combine("/app/mounts", fileName)); + searchPaths.Add(Path.Combine("/app", fileName)); searchPaths.Add(Path.Combine("/files", fileName)); string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); From eef7f974ce74d6b493fb308106cb21eb9bdeedda Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Tue, 25 Nov 2025 22:53:14 +0900 Subject: [PATCH 25/42] Add Dockerfiles --- Dockerfile.ppt-font-fix | 4 ++++ Dockerfile.ppt-font-fix-azure | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 Dockerfile.ppt-font-fix-azure diff --git a/Dockerfile.ppt-font-fix b/Dockerfile.ppt-font-fix index 9938f932..96746489 100644 --- a/Dockerfile.ppt-font-fix +++ b/Dockerfile.ppt-font-fix @@ -21,6 +21,10 @@ WORKDIR /app COPY --from=build /app . +RUN mkdir -p /app/wwwroot/generated /files \ + && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /files \ + && chmod 755 /app/wwwroot/generated + USER $APP_UID ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] diff --git a/Dockerfile.ppt-font-fix-azure b/Dockerfile.ppt-font-fix-azure new file mode 100644 index 00000000..2ae3fcb0 --- /dev/null +++ b/Dockerfile.ppt-font-fix-azure @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1 + +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build + +COPY ./shared/McpSamples.Shared /source/shared/McpSamples.Shared +COPY ./ppt-font-fix/src/McpSamples.PptFontFix.HybridApp /source/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp + +WORKDIR /source/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp + +RUN dotnet publish -c Release -o /app --self-contained false + +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final + +WORKDIR /app + +COPY --from=build /app . + +COPY ./ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx /app/test.pptx + +RUN mkdir -p /app/wwwroot/generated && \ + chown -R $APP_UID:$APP_UID /app/wwwroot && \ + chown -R $APP_UID:$APP_UID /app/test.pptx + +USER $APP_UID + +ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] From f27f4097d7681ab614d19c352f8548b4de59f5da Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 1 Dec 2025 06:02:38 +0900 Subject: [PATCH 26/42] change some code to open files of outside the workspace --- ppt-font-fix/.vscode/mcp.stdio.container.json | 1 + ppt-font-fix/infra/main.bicep | 2 + ppt-font-fix/infra/resources.bicep | 23 +++ .../McpSamples.PptFontFix.HybridApp.csproj | 2 +- .../Prompts/PptFontFixPrompt.cs | 179 ++++++++++++------ .../Services/PPTFontFixService.cs | 160 +++++++++++++--- .../Tools/PPTFontFixTool.cs | 11 +- 7 files changed, 291 insertions(+), 87 deletions(-) diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index 7b6d76fb..a1da79b3 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -14,6 +14,7 @@ "run", "-i", "--rm", + "--name", "ppt-font-fix", "-v", "${input:your-ppt-file-path}:/files", "ppt-font-fix:latest" ] diff --git a/ppt-font-fix/infra/main.bicep b/ppt-font-fix/infra/main.bicep index 8f80e574..5e6fbc62 100644 --- a/ppt-font-fix/infra/main.bicep +++ b/ppt-font-fix/infra/main.bicep @@ -45,3 +45,5 @@ output AZURE_CONTAINER_REGISTRY_ENDPOINT string = resources.outputs.AZURE_CONTAI output AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN +output AZURE_STORAGE_ACCOUNT_NAME string = resources.outputs.AZURE_STORAGE_ACCOUNT_NAME +output AZURE_FILE_SHARE_NAME string = resources.outputs.AZURE_FILE_SHARE_NAME diff --git a/ppt-font-fix/infra/resources.bicep b/ppt-font-fix/infra/resources.bicep index 8a5bd43d..5aac680f 100644 --- a/ppt-font-fix/infra/resources.bicep +++ b/ppt-font-fix/infra/resources.bicep @@ -13,6 +13,9 @@ var containerAppName = 'ppt-font-fix' var abbrs = loadJsonContent('./abbreviations.json') var resourceToken = uniqueString(subscription().id, resourceGroup().id, location) +var storageKey = storage.listKeys().keys[0].value +var storageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${storageKey};EndpointSuffix=core.windows.net' + // Monitor application with Azure Monitor module monitoring 'br/public:avm/ptn/azd/monitoring:0.1.0' = { @@ -40,6 +43,19 @@ resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { } } +resource storageBlobService 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = { + parent: storage + name: 'default' +} + +resource generatedFilesContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2022-09-01' = { + parent: storageBlobService + name: 'generated-files' + properties: { + publicAccess: 'None' + } +} + resource storageFileService 'Microsoft.Storage/storageAccounts/fileServices@2022-09-01' = { parent: storage name: 'default' @@ -134,6 +150,7 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { dependsOn: [ explicitStorageLink + storage ] params: { @@ -173,6 +190,10 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { name: 'PORT' value: '8080' } + { + name: 'AzureBlobConnectionString' + value: storageConnectionString + } ] args: [ '--http' ] volumeMounts: [ @@ -229,3 +250,5 @@ output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.logi output AZURE_RESOURCE_MCP_PPT_FONT_FIX_ID string = mcpPptFontFix.outputs.resourceId output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = mcpPptFontFix.outputs.name output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = mcpPptFontFix.outputs.fqdn +output AZURE_STORAGE_ACCOUNT_NAME string = storage.name +output AZURE_FILE_SHARE_NAME string = storageFileShare.name diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj index 00b4ffd5..9423a894 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -11,7 +11,7 @@ - + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 7b3a33f8..ad308081 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -1,5 +1,9 @@ using System.ComponentModel; using ModelContextProtocol.Server; +using System.IO; +using System; +using System.Collections.Generic; +using System.Linq; // Path.GetFileName을 위한 Last() 메서드 사용을 위해 필요 namespace McpSamples.PptFontFix.HybridApp.Prompts; @@ -11,9 +15,8 @@ public interface IPptFontFixPrompt /// /// Gets a prompt to start the PPT font fix workflow. /// - /// The full path to the .pptx file to be analyzed. - /// A formatted prompt to start the font analysis. - string GetAnalysisPrompt(string filePath); + /// The full path to the PPTX file on the host machine or a public URL. + string GetAnalysisPrompt(string hostFilePath); } /// @@ -22,66 +25,126 @@ public interface IPptFontFixPrompt [McpServerPromptType] public class PptFontFixPrompt : IPptFontFixPrompt { + private const string ContainerName = "ppt-font-fix"; + private const string ContainerInputPathBase = "/files"; + private const string AzureDefaultContainer = "generated-files"; + /// [McpServerPrompt(Name = "fix_ppt_fonts", Title = "Start PPT Font Fix Workflow")] - [Description("Analyzes the PPT file and guides the user through the font replacement process.")] + [Description("Generate a structured workflow prompt for analyzing and fixing PPT fonts.")] public string GetAnalysisPrompt( - [Description("The full path to the .pptx file (e.g. /files/test.pptx)")] string filePath) + [Description("The full path to the PPTX file or a public URL.")] string hostFilePath) { + string safePath = hostFilePath.Replace('\\', '/'); + string actualFileName = safePath.Split('/').Last(); + string containerInputPath = $"{ContainerInputPathBase}/{actualFileName}"; + return $""" - You are an expert assistant for fixing PowerPoint font issues. - Please execute the following workflow step-by-step: - - ### PHASE 1: ANALYSIS - 1. Call the `analyze_ppt_file` tool with the path: `{filePath}`. - 2. Analyze the result (`PptFontAnalyzeResult`). - 3. **Show the user** the list of `UsedFonts` and `InconsistentlyUsedFonts`. - 4. **Check `UnusedFontLocations`**: - - If `UnusedFontLocations` is empty, skip the option selection and just ask for the Standard Font. - - If `UnusedFontLocations` has items, **Ask the user to make TWO choices**: - - **A. Select a Standard Font:** (Choose one from `UsedFonts`) - - **B. Select an Action Mode:** - 1. **[Fix & Clean]**: Replace fonts AND remove unused/invisible text boxes (Specify the count of items found in `UnusedFontLocations`). - 2. **[Fix Only]**: Replace fonts ONLY. Keep unused text boxes as is. - - ### PHASE 2: UPDATE (Wait for user input) - Once the user replies with their choices, proceed to call `update_ppt_file`. - - **Parameter Logic:** - - `replacementFont`: The font selected by the user. - - `inconsistentFontsToReplace`: The list of inconsistent fonts found in Phase 1. - - `newFileName`: Generate a safe name like "result_fixed.pptx". - - **Critical Logic for `locationsToRemove`:** - - IF User chose **1 (Fix & Clean)**: Pass the `UnusedFontLocations` list found in Phase 1. - - IF User chose **2 (Fix Only)**: Pass an **empty list `[]`**. (Do NOT pass null, pass an empty JSON array). - - ### PHASE 3: RESULT PRESENTATION (CRITICAL!) - The `update_ppt_file` tool will return a result string. Analyze it carefully. - - **CASE A: The result starts with `http` (Web Mode)** - - Render it as a Clickable Markdown Link. - - Format: `👉 [Click here to Download Fixed File](URL)` - - **CASE B: The result is a File Path (e.g. `/files/...`, `/app/...` or `C:\...`) (Stdio/Local Mode)** - - The user is using VS Code. VS Code automatically detects absolute paths. - - **DO NOT use Markdown syntax** (No `[]` or `()`). - - **DO NOT shorten the path.** Output the full string exactly as returned by the tool. - - - **SPECIAL INSTRUCTION FOR CONTAINER PATHS:** - - If the returned path looks like a Linux path (e.g. starts with `/app/` or `/files/`), it is inside the Docker container. - - **Explicitly tell the user:** "This file is saved inside the container volume. Please check your mounted local folder." - - - Output format: - - ✅ **Task Completed.** - - **File:** - [Insert Raw Full Path Here] - - *(If container path, insert hint here)* + You are the assistant responsible for guiding a complete multi-environment PowerPoint font fix workflow. + Follow the process below exactly and request inputs from the user whenever required. + + ### STEP 0 — Determine Execution Environment + 1. Ask the user: **Where is the MCP server running? (Local / Docker / Azure)** + Store the answer for later branching decisions. + + 2. Apply environment-specific logic: + + **If Local:** + - No file transfer is required. + - Use the original host file path: + `{hostFilePath}` + + **If Azure:** + - Inform the user that the file must be uploaded to Azure Blob Storage. + - Ask for: + - Storage Account Name → `azureAccountName` + - Container Name → `azureContainerName` (default: `{AzureDefaultContainer}`) + - Ask the user whether to allow running the following upload command: + ```bash + az storage blob upload \ + --account-name [azureAccountName] \ + --container-name [azureContainerName] \ + --file "{hostFilePath}" \ + --name "{actualFileName}" \ + --overwrite true + ``` + - If the user allows it, execute the command. + - Use the resulting blob URL: + `https://[azureAccountName].blob.core.windows.net/[azureContainerName]/{actualFileName}` + + **If Docker:** + - Ask the user for the running container ID or name for **{ContainerName}**. + - Ask the user whether to allow this file-copy command: + ```bash + docker cp "{hostFilePath}" [CONTAINER_ID]:{ContainerInputPathBase} + ``` + - If the user allows it, execute the command. + - Use the container path: + `{containerInputPath}` + + Confirm with the user when the file transfer or upload is complete. + + --- + + ### STEP 1 — Analyze Fonts + 1. Call the `analyze_ppt_file` tool. + - Input path depends on environment: + - Local / Azure URL → `{hostFilePath}` + - Docker → `{containerInputPath}` + + 2. After receiving `PptFontAnalyzeResult`, display: + - List of used fonts + - List of inconsistently used fonts + + 3. If `UnusedFontLocations` contains items: + Ask the user to make two selections: + A. **Choose a Standard Font** (from UsedFonts) + B. **Choose an Action Mode:** + 1. Fix & Clean — Replace fonts and remove unused text boxes + 2. Fix Only — Replace fonts only + + --- + + ### STEP 2 — Modify the File + 1. Ask the user where to save the updated file: + + **If Local / Azure Execution:** + - Ask for an output directory path (optional). + - Store as `outputDirectory`. + - If omitted, the server will save to its default directory and return a URL. + + **If Docker Execution:** + - Set `outputDirectory = null`. + - Inform the user that the file will be saved internally at `/files`. + + 2. Call the `update_ppt_file` tool with: + - `replacementFont` — user-selected value + - `inconsistentFontsToReplace` — the list from analysis + - `newFileName` — `"result_fixed_{actualFileName}"` + - `outputDirectory` — user-given directory or null (Docker) + + --- + + ### STEP 3 — Present the Final Output + Inspect the result string returned by `update_ppt_file`. + + **If it begins with `http`:** + - Present it as a clickable markdown link: + `[Click here to download the fixed file](URL)` + + **If it is a local path:** + - If Local/Azure: + Output the full path as returned. + + - If Docker: + - Extract the internal container path (e.g., `/files/result_fixed_test.pptx`). + - Ask the user for the desired directory on the host machine. + - Then provide this copy-out command: + ```bash + docker cp {ContainerName}:[EXTRACTED_CONTAINER_PATH] "[HOST_DESTINATION_PATH]" + ``` + + Task complete. """; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 70335a42..20e26760 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -10,6 +10,8 @@ using Microsoft.AspNetCore.Http; using System.IO; using Azure.Storage.Blobs; +using Azure.Storage.Sas; +using Azure.Storage.Blobs.Specialized; namespace McpSamples.PptFontFix.HybridApp.Services; @@ -33,8 +35,9 @@ public interface IPptFontFixService /// /// Save the modified Ppt file. /// - /// - Task SavePptFileAsync(string newFilePath); + /// The desired file name to save as. + /// The directory path on the host machine to save the modified file. // ✅ 신규 추가 + Task SavePptFileAsync(string desiredFileName, string? outputDirectory = null); /// /// Remove Unused Fonts from the presentation. @@ -63,6 +66,7 @@ public class PptFontFixService : IPptFontFixService private readonly IWebHostEnvironment? _webHostEnvironment; private readonly IHttpContextAccessor? _httpContextAccessor; private Presentation? _presentation; + private readonly BlobServiceClient? _blobServiceClient; private HashSet? _analyzedVisibleFonts; @@ -77,6 +81,13 @@ public PptFontFixService( _hostEnvironment = hostEnvironment; _webHostEnvironment = serviceProvider.GetService(); _httpContextAccessor = serviceProvider.GetService(); + + // Azure Connection String을 사용하여 BlobServiceClient 초기화 시도 + string? azureConnectionString = configuration["AzureBlobConnectionString"]; + if (!string.IsNullOrEmpty(azureConnectionString)) + { + _blobServiceClient = new BlobServiceClient(azureConnectionString); + } } /// @@ -84,21 +95,70 @@ public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); + if (Uri.TryCreate(filePath, UriKind.Absolute, out Uri? uriResult) && + (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) + { + _logger.LogInformation("✅ Detected URL path. Attempting to open from Blob Storage: {Url}", filePath); + + if (_blobServiceClient == null) + { + throw new InvalidOperationException("Cannot open from URL. AzureBlobConnectionString is not configured."); + } + + try + { + // URL에서 컨테이너 이름과 Blob 이름 추출 + // 예: https://stzbfq6f2xfezko.blob.core.windows.net/ppt-files/test2.pptx + // [0] = "", [1] = "ppt-files/", [2] = "test2.pptx" + + // URL Segment는 '/'로 분리되며, 첫 번째는 항상 비어있습니다. + // 컨테이너 이름은 일반적으로 두 번째 세그먼트입니다. + string containerSegment = uriResult.Segments.Skip(1).FirstOrDefault()?.TrimEnd('/') ?? throw new ArgumentException("Invalid Blob URL format: Container name not found.", nameof(filePath)); + string blobName = string.Join("", uriResult.Segments.Skip(2)); + + if (string.IsNullOrEmpty(blobName)) + { + throw new ArgumentException("Invalid Blob URL format: Blob name not found.", nameof(filePath)); + } + + var containerClient = _blobServiceClient.GetBlobContainerClient(containerSegment); + var blobClient = containerClient.GetBlobClient(blobName); + + if (!await blobClient.ExistsAsync()) + { + throw new FileNotFoundException($"Blob file not found in container '{containerSegment}': {blobName}"); + } + + // 메모리 스트림으로 Blob 다운로드 + _presentation?.Dispose(); + var memoryStream = new MemoryStream(); + await blobClient.DownloadToAsync(memoryStream); + memoryStream.Position = 0; + + _presentation = new ShapeCrawler.Presentation(memoryStream); + _analyzedVisibleFonts = null; + _logger.LogInformation("Ppt file opened successfully from Blob."); + return; + } + catch (Exception ex) + { + _logger.LogError(ex, "❌ Failed to open Ppt file from URL."); + throw new InvalidOperationException($"Failed to open Blob file at {filePath}.", ex); + } + } + var searchPaths = new List(); - searchPaths.Add(filePath); + searchPaths.Add(filePath); + + string safePath = filePath.Replace('\\', '/'); + string fileName = safePath.Split('/').Last(); - string fileName = Path.GetFileName(filePath); - if (filePath.Contains('\\')) fileName = filePath.Split('\\').Last(); - if (filePath.Contains('/')) fileName = filePath.Split('/').Last(); - - searchPaths.Add(Path.Combine("/app/mounts", fileName)); searchPaths.Add(Path.Combine("/app", fileName)); searchPaths.Add(Path.Combine("/files", fileName)); string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); searchPaths.Add(Path.Combine(baseDir, "generated", fileName)); - searchPaths.Add(Path.Combine(Path.GetTempPath(), fileName)); string? foundPath = null; @@ -115,13 +175,13 @@ public async Task OpenPptFileAsync(string filePath) if (foundPath == null) { _logger.LogError("❌ File not found. Searched in: {Paths}", string.Join(", ", searchPaths)); - throw new FileNotFoundException($"Ppt file not found. Searched in /files, /generated, and /tmp inside container.", filePath); + throw new FileNotFoundException($"Ppt file not found. File must be accessible at the host path OR successfully copied to the container volume.", filePath); } try { _presentation?.Dispose(); - _presentation = new Presentation(foundPath); + _presentation = new ShapeCrawler.Presentation(foundPath); _analyzedVisibleFonts = null; _logger.LogInformation("Ppt file opened successfully: {FilePath}", foundPath); await Task.CompletedTask; @@ -149,9 +209,29 @@ public async Task AnalyzeFontsAsync() Action processPortion = (portion, isShapeVisible, isSlideVisible, location) => { + if (portion.GetType().Name == "ParagraphLineBreak") + { + return; + } if (portion.Font == null) return; - string? fontName = portion.Font.LatinName; - if (string.IsNullOrEmpty(fontName)) return; + string? fontName = null; + + try + { + fontName = portion.Font.LatinName; + } + catch (NullReferenceException ex) + { + _logger.LogWarning(ex, + "NullReferenceException occurred while getting LatinName for Shape: {ShapeName} in Slide: {SlideNumber}. Skipping portion.", + location.ShapeName, location.SlideNumber); + return; + } + + if (string.IsNullOrEmpty(fontName)) + { + return; + } totalFontsInSlides.Add(fontName); @@ -241,7 +321,7 @@ public async Task AnalyzeFontsAsync() } /// - public async Task SavePptFileAsync(string desiredFileName) + public async Task SavePptFileAsync(string desiredFileName, string? outputDirectory = null) { if (this._presentation == null) throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); ArgumentException.ThrowIfNullOrWhiteSpace(desiredFileName, nameof(desiredFileName)); @@ -269,40 +349,53 @@ public async Task SavePptFileAsync(string desiredFileName) await containerClient.CreateIfNotExistsAsync(); var blobClient = containerClient.GetBlobClient(safeFileName); await blobClient.UploadAsync(memoryStream, overwrite: true); - return blobClient.Uri.ToString(); + var sasBuilder = new BlobSasBuilder() + { + ExpiresOn = DateTimeOffset.UtcNow.AddHours(1), + BlobName = safeFileName, + BlobContainerName = "generated-files", + }; + sasBuilder.SetPermissions(BlobSasPermissions.Read); + + Uri sasUri = blobClient.GenerateSasUri(sasBuilder); + + _logger.LogInformation("✅ Returning Blob URL with SAS token."); + return sasUri.ToString(); } catch (Exception ex) { _logger.LogError(ex, "Azure save failed. Falling back to local storage."); memoryStream.Position = 0; } - } + } string finalPhysicalPath = ""; string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); string generatedDir = Path.Combine(webRoot, "generated"); if (!Directory.Exists(generatedDir)) Directory.CreateDirectory(generatedDir); - string webStoragePath = Path.Combine(generatedDir, safeFileName); - + string webStoragePath = Path.Combine(generatedDir, safeFileName); bool isDocker = !OperatingSystem.IsWindows(); if (isDocker) { _logger.LogInformation("Environment detected: Docker Container"); - + try { string syncPath = Path.Combine("/files", safeFileName); + + memoryStream.Position = 0; using (var fs = new FileStream(syncPath, FileMode.Create, FileAccess.Write)) { await memoryStream.CopyToAsync(fs); + await fs.FlushAsync(); } File.SetUnixFileMode(syncPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); - finalPhysicalPath = syncPath; + finalPhysicalPath = syncPath; } catch (Exception ex) { - _logger.LogWarning("Could not save to /files volume: {Msg}", ex.Message); + _logger.LogError(ex, "FATAL: Could not save to /files volume. Falling back to internal web root."); finalPhysicalPath = webStoragePath; } @@ -317,12 +410,31 @@ public async Task SavePptFileAsync(string desiredFileName) { _logger.LogInformation("Environment detected: Local Windows"); - using (var fs = new FileStream(webStoragePath, FileMode.Create, FileAccess.Write)) + string finalPathToSave; + + if (!string.IsNullOrEmpty(outputDirectory) && Directory.Exists(outputDirectory)) { - await memoryStream.CopyToAsync(fs); + finalPathToSave = Path.Combine(outputDirectory, safeFileName); + _logger.LogInformation("Saving to user-specified path: {Path}", finalPathToSave); + } + else + { + if (!string.IsNullOrEmpty(outputDirectory)) + { + _logger.LogWarning("Specified output directory '{Dir}' does not exist or is invalid. Falling back to default.", outputDirectory); + } + + finalPathToSave = webStoragePath; + _logger.LogInformation("Saving to default webroot path: {Path}", finalPathToSave); } - finalPhysicalPath = webStoragePath; + using (var fs = new FileStream(finalPathToSave, FileMode.Create, FileAccess.Write)) // 👈 finalPathToSave 사용 + { + memoryStream.Position = 0; + await memoryStream.CopyToAsync(fs); + } + + finalPhysicalPath = finalPathToSave; } if (_httpContextAccessor?.HttpContext?.Request != null) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index f5997889..5cbe190c 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -28,9 +28,10 @@ public interface IPptFontFixTool /// The font to replace all inconsistent fonts with. /// The list of inconsistent font names to be replaced. /// The list of shape locations to be removed. + /// The directory path on the host machine to save the modified file. // ✅ 신규 추가 /// The full path to save the new .pptx file. /// Returns a success message with the new file path. - Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string newFileName); + Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string outputDirectory, string newFileName); // ✅ 시그니처 변경 } /// @@ -74,12 +75,13 @@ public async Task AnalyzePptFileAsync( /// [McpServerTool(Name = "update_ppt_file", Title = "Update and Save PPT File")] - [Description("Removes unused fonts, replaces inconsistently used fonts with another font defined within the Ppt file, and saves the file.")] + [Description("Removes unused fonts, replaces inconsistently used fonts with another font defined within the Ppt file, and saves the file to a user-specified path.")] public async Task UpdatePptFileAsync( [Description("The replacement font")] string replacementFont, [Description("The fonts to be replaced")] List inconsistentFontsToReplace, [Description("A list of shape locations (from analysis result) to be removed")] List locationsToRemove, - [Description("The full path to save the modified Ppt file")] string newFileName) + [Description("The directory path on the host machine to save the modified file (e.g., C:\\Users\\Downloads)")] string outputDirectory, // ✅ 신규 파라미터 + [Description("The filename for the modified Ppt file.")] string newFileName) { try { @@ -97,7 +99,8 @@ public async Task UpdatePptFileAsync( } logger.LogInformation("{Count} instances of inconsistent fonts replaced with '{ReplacementFont}'.", totalReplacementCount, replacementFont); - string accessPath = await service.SavePptFileAsync(newFileName).ConfigureAwait(false); + string accessPath = await service.SavePptFileAsync(newFileName, outputDirectory).ConfigureAwait(false); + logger.LogInformation("Ppt file saved successfully: {Path}", accessPath); return $"PPT update complete. Removed: {removalCount}, Replaced: {totalReplacementCount}. Result: {accessPath}"; From d973ae3e66f1146559dceb68df7aa74cfc100541 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 1 Dec 2025 07:29:25 +0900 Subject: [PATCH 27/42] fix some prompt --- ppt-font-fix/infra/main.bicep | 1 + ppt-font-fix/infra/resources.bicep | 1 + .../Prompts/PptFontFixPrompt.cs | 49 ++++++++++++------- .../Services/PPTFontFixService.cs | 1 + 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/ppt-font-fix/infra/main.bicep b/ppt-font-fix/infra/main.bicep index 5e6fbc62..2a4e83ba 100644 --- a/ppt-font-fix/infra/main.bicep +++ b/ppt-font-fix/infra/main.bicep @@ -47,3 +47,4 @@ output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = resources.outputs.AZURE_RES output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = resources.outputs.AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN output AZURE_STORAGE_ACCOUNT_NAME string = resources.outputs.AZURE_STORAGE_ACCOUNT_NAME output AZURE_FILE_SHARE_NAME string = resources.outputs.AZURE_FILE_SHARE_NAME +output AZURE_BLOB_CONTAINER_NAME string = resources.outputs.AZURE_BLOB_CONTAINER_NAME diff --git a/ppt-font-fix/infra/resources.bicep b/ppt-font-fix/infra/resources.bicep index 5aac680f..2c4939c2 100644 --- a/ppt-font-fix/infra/resources.bicep +++ b/ppt-font-fix/infra/resources.bicep @@ -252,3 +252,4 @@ output AZURE_RESOURCE_MCP_PPT_FONT_FIX_NAME string = mcpPptFontFix.outputs.name output AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN string = mcpPptFontFix.outputs.fqdn output AZURE_STORAGE_ACCOUNT_NAME string = storage.name output AZURE_FILE_SHARE_NAME string = storageFileShare.name +output AZURE_BLOB_CONTAINER_NAME string = generatedFilesContainer.name diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index ad308081..a2e76e95 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -28,6 +28,7 @@ public class PptFontFixPrompt : IPptFontFixPrompt private const string ContainerName = "ppt-font-fix"; private const string ContainerInputPathBase = "/files"; private const string AzureDefaultContainer = "generated-files"; + private const string AzureFileShareName = "ppt-files"; /// [McpServerPrompt(Name = "fix_ppt_fonts", Title = "Start PPT Font Fix Workflow")] @@ -55,22 +56,32 @@ Follow the process below exactly and request inputs from the user whenever requi `{hostFilePath}` **If Azure:** - - Inform the user that the file must be uploaded to Azure Blob Storage. - - Ask for: - - Storage Account Name → `azureAccountName` - - Container Name → `azureContainerName` (default: `{AzureDefaultContainer}`) - - Ask the user whether to allow running the following upload command: - ```bash - az storage blob upload \ - --account-name [azureAccountName] \ - --container-name [azureContainerName] \ - --file "{hostFilePath}" \ - --name "{actualFileName}" \ - --overwrite true - ``` - - If the user allows it, execute the command. - - Use the resulting blob URL: - `https://[azureAccountName].blob.core.windows.net/[azureContainerName]/{actualFileName}` + - Inform the user: "**The server cannot directly access your local file path in the Azure environment. You must upload the file to Azure Blob Storage or a File Share and provide the accessible path.**" + - Ask the user: **"Have you already uploaded the file to Azure storage? (Yes/No)"** + - Store the answer as `isUploaded`. + + - **IF `isUploaded` is "No":** + - Inform the user: "**You must run the following command in your terminal to upload the file to Blob Storage.**" + - Ask for: + - Storage Account Name → `azureAccountName` + - Account Key → `azureAccountKey` + - Container Name → `azureContainerName` (default: `{AzureDefaultContainer}`) + - Present the upload command and ask for permission to run it: + ```bash + az storage blob upload \ + --account-name [azureAccountName] \ + --account-key [azureAccountKey] \ + --container-name [azureContainerName] \ + --file "{hostFilePath}" \ + --name "{actualFileName}" \ + --overwrite true + ``` + - If the user allows it, execute the command. + - **Wait for confirmation** that the upload has executed successfully. + + - **FINAL CRITICAL ACTION (Execute regardless of `isUploaded`):** Request the final access path for the server to read the file. + - Ask the user: "**If the file has been uploaded, please provide one of the following:** 1) **Blob URL (including SAS)**, 2) **Blob Path (e.g., `[azureContainerName]/{actualFileName}`)** or 3) **File Share File Name (e.g., `{actualFileName}`)**" + - Store the final input path for the tool as `FINAL_INPUT_PATH = "[User-Provided Path/URL/File Name]"` **If Docker:** - Ask the user for the running container ID or name for **{ContainerName}**. @@ -108,11 +119,15 @@ 2. Fix Only — Replace fonts only ### STEP 2 — Modify the File 1. Ask the user where to save the updated file: - **If Local / Azure Execution:** + **If Local Execution:** - Ask for an output directory path (optional). - Store as `outputDirectory`. - If omitted, the server will save to its default directory and return a URL. + **If Azure Execution:** + - Inform the user: "**The modified file will be saved to Blob Storage and provided as a secure download URL.**" + - Set `outputDirectory = null`. + **If Docker Execution:** - Set `outputDirectory = null`. - Inform the user that the file will be saved internally at `/files`. diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 20e26760..f5ce224b 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -156,6 +156,7 @@ public async Task OpenPptFileAsync(string filePath) searchPaths.Add(Path.Combine("/app", fileName)); searchPaths.Add(Path.Combine("/files", fileName)); + searchPaths.Add(Path.Combine("/app/mounts", fileName)); string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); searchPaths.Add(Path.Combine(baseDir, "generated", fileName)); From c1cface30ec2f5e045a0fdceabe29904af6b43b7 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 1 Dec 2025 21:47:15 +0900 Subject: [PATCH 28/42] add README.md, fix some code --- Dockerfile.ppt-font-fix-azure | 4 - ppt-font-fix/README.md | 229 +++++++++++++++++- .../Services/PPTFontFixService.cs | 7 - .../corrupt_test.pptx | Bin 27919 -> 0 bytes 4 files changed, 228 insertions(+), 12 deletions(-) delete mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx diff --git a/Dockerfile.ppt-font-fix-azure b/Dockerfile.ppt-font-fix-azure index 2ae3fcb0..7d970625 100644 --- a/Dockerfile.ppt-font-fix-azure +++ b/Dockerfile.ppt-font-fix-azure @@ -17,10 +17,6 @@ COPY --from=build /app . COPY ./ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx /app/test.pptx -RUN mkdir -p /app/wwwroot/generated && \ - chown -R $APP_UID:$APP_UID /app/wwwroot && \ - chown -R $APP_UID:$APP_UID /app/test.pptx - USER $APP_UID ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md index 8c17d346..14802c82 100644 --- a/ppt-font-fix/README.md +++ b/ppt-font-fix/README.md @@ -1,3 +1,230 @@ # MCP Server: PPT Font Fix -This is an MCP server that finds fonts in a .pptx file, analyzes their usages - used, unused, inconsistently used, and fixes it. \ No newline at end of file +This is an MCP server that finds fonts in a .pptx file, analyzes their usages - used, unused, inconsistently used, and fixes it. + +## Install + +[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)]() [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)]() + +## Prerequisites + +- [.NET 9 SDK](https://dotnet.microsoft.com/download/dotnet/9.0) +- [Visual Studio Code](https://code.visualstudio.com/) with + - [C# Dev Kit](https://marketplace.visualstudio.com/items/?itemName=ms-dotnettools.csdevkit) extension +- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) +- [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd) +- [Docker Desktop](https://docs.docker.com/get-started/get-docker/) + +## What's Included + +PPT Font Fix MCP server includes: + +| Building Block | Name | Description | Usage | +|----------------|----------------------------|-------------------------------------|-----------------------------| +| Tools          | `analyze_ppt_file`         | Opens and analyzes fonts used in a PPTX file.       | `#analyze_ppt_file` | +| Tools          | `update_ppt_file`          | Replaces inconsistent fonts and saves the modified file.     | `#update_ppt_file` | +| Prompts        | `fix_ppt_fonts`            | Structured workflow to guide file upload and repair process. | `/mcp.ppt-font-fix.fix_ppt_fonts ` | + +## Getting Started + +- [Getting repository root](#getting-repository-root) +- [Running MCP server](#running-mcp-server) + - [On a local machine](#on-a-local-machine) + - [In a container](#in-a-container) + - [On Azure](#on-azure) +- [Connect MCP server to an MCP host/client](#connect-mcp-server-to-an-mcp-hostclient) + - [VS Code + Agent Mode + Local MCP server](#vs-code--agent-mode--local-mcp-server) + +### Getting repository root + +1. Get the repository root. + + ```bash + # bash/zsh + REPOSITORY_ROOT=$(git rev-parse --show-toplevel) + ``` + + ```powershell + # PowerShell + $REPOSITORY_ROOT = git rev-parse --show-toplevel + ``` + +### Running MCP server + +#### On a local machine + +1. Run the MCP server app. + + ```bash + cd $REPOSITORY_ROOT/ppt-font-fix + dotnet run --project ./src/McpSamples.PptFontFix.HybridApp + ``` + + > Make sure take note the absolute directory path of the `McpSamples.PptFontFix.HybridApp` project. + + **Parameters**: + + - `--http`: The switch that indicates to run this MCP server as a streamable HTTP type. When this switch is added, the MCP server URL is `http://localhost:5166`. + + With these parameters, you can run the MCP server like: + + ```bash + dotnet run --project ./src/McpSamples.PptFontFix.HybridApp -- --http + ``` + +#### In a container + +1. Build the MCP server app as a container image. + + ```bash + cd $REPOSITORY_ROOT + docker build -f Dockerfile.ppt-font-fix -t ppt-font-fix:latest . + ``` + +1. Run the MCP server app in a container. + + ```bash + docker run -i --rm -p 8080:8080 ppt-font-fix:latest + ``` + + Alternatively, use the container image from the container registry. + + ```bash + docker run -i --rm -p 8080:8080 ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest + ``` + + **Parameters**: + + - `--http`: The switch that indicates to run this MCP server as a streamable HTTP type. When this switch is added, the MCP server URL is `http://localhost:8080`. + + With these parameters, you can run the MCP server like: + + ```bash + # use local container image + docker run -it --rm -p 8080:8080 -u 0 --name ppt-font-fix ppt-font-fix:latest --http + ``` + + ```bash + # use container image from the container registry + docker run -it --rm -p 8080:8080 -u 0 --name ppt-font-fix ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest --http + ``` + +#### On Azure + +1. Navigate to the directory. + + ```bash + cd $REPOSITORY_ROOT/ppt-font-fix + ``` + +1. Login to Azure. + + ```bash + # Login with Azure Developer CLI + azd auth login + ``` + +1. Deploy the MCP server app to Azure. + + ```bash + azd up + ``` + + While provisioning and deploying, you'll be asked to provide subscription ID, location, environment name. + +1. After the deployment is complete, get the information by running the following commands: + + - Azure Container Apps FQDN: + + ```bash + azd env get-value AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN + ``` + +### Connect MCP server to an MCP host/client + +#### VS Code + Agent Mode + Local MCP server + +1. Copy `mcp.json` to the repository root. + + **For locally running MCP server (STDIO):** + + ```bash + mkdir -p $REPOSITORY_ROOT/.vscode + cp $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.stdio.local.json \ + $REPOSITORY_ROOT/.vscode/mcp.json + ``` + + ```powershell + New-Item -Type Directory -Path $REPOSITORY_ROOT/.vscode -Force + Copy-Item -Path $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.stdio.local.json ` + -Destination $REPOSITORY_ROOT/.vscode/mcp.json -Force + ``` + + **For locally running MCP server (HTTP):** + + ```bash + mkdir -p $REPOSITORY_ROOT/.vscode + cp $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.local.json \ + $REPOSITORY_ROOT/.vscode/mcp.json + ``` + + ```powershell + New-Item -Type Directory -Path $REPOSITORY_ROOT/.vscode -Force + Copy-Item -Path $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.local.json ` + -Destination $REPOSITORY_ROOT/.vscode/mcp.json -Force + ``` + + **For locally running MCP server in a container (STDIO):** + + ```bash + mkdir -p $REPOSITORY_ROOT/.vscode + cp $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.stdio.container.json \ + $REPOSITORY_ROOT/.vscode/mcp.json + ``` + + ```powershell + New-Item -Type Directory -Path $REPOSITORY_ROOT/.vscode -Force + Copy-Item -Path $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.stdio.container.json ` + -Destination $REPOSITORY_ROOT/.vscode/mcp.json -Force + ``` + + **For locally running MCP server in a container (HTTP):** + + ```bash + mkdir -p $REPOSITORY_ROOT/.vscode + cp $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.container.json \ + $REPOSITORY_ROOT/.vscode/mcp.json + ``` + + ```powershell + New-Item -Type Directory -Path $REPOSITORY_ROOT/.vscode -Force + Copy-Item -Path $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.container.json ` + -Destination $REPOSITORY_ROOT/.vscode/mcp.json -Force + ``` + + **For remotely running MCP server in a container (HTTP):** + + ```bash + mkdir -p $REPOSITORY_ROOT/.vscode + cp $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.remote.json \ + $REPOSITORY_ROOT/.vscode/mcp.json + ``` + + ```powershell + New-Item -Type Directory -Path $REPOSITORY_ROOT/.vscode -Force + Copy-Item -Path $REPOSITORY_ROOT/ppt-font-fix/.vscode/mcp.http.remote.json ` + -Destination $REPOSITORY_ROOT/.vscode/mcp.json -Force + ``` + +1. Open Command Palette by typing `F1` or `Ctrl`+`Shift`+`P` on Windows or `Cmd`+`Shift`+`P` on Mac OS, and search `MCP: List Servers`. +1. Choose `ppt-font-fix` then click `Start Server`. +1. When prompted, enter one of the following values: + - The absolute directory path of the `McpSamples.PptFontFix.HybridApp` project + - The FQDN of Azure Container Apps. +1. Enter prompt like: + + ```text + Analyze and Fix the fonts in C:\path\to\presentation.pptx + ``` + +1. Confirm the result. diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index f5ce224b..564e9c1a 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -107,12 +107,6 @@ public async Task OpenPptFileAsync(string filePath) try { - // URL에서 컨테이너 이름과 Blob 이름 추출 - // 예: https://stzbfq6f2xfezko.blob.core.windows.net/ppt-files/test2.pptx - // [0] = "", [1] = "ppt-files/", [2] = "test2.pptx" - - // URL Segment는 '/'로 분리되며, 첫 번째는 항상 비어있습니다. - // 컨테이너 이름은 일반적으로 두 번째 세그먼트입니다. string containerSegment = uriResult.Segments.Skip(1).FirstOrDefault()?.TrimEnd('/') ?? throw new ArgumentException("Invalid Blob URL format: Container name not found.", nameof(filePath)); string blobName = string.Join("", uriResult.Segments.Skip(2)); @@ -129,7 +123,6 @@ public async Task OpenPptFileAsync(string filePath) throw new FileNotFoundException($"Blob file not found in container '{containerSegment}': {blobName}"); } - // 메모리 스트림으로 Blob 다운로드 _presentation?.Dispose(); var memoryStream = new MemoryStream(); await blobClient.DownloadToAsync(memoryStream); diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/corrupt_test.pptx deleted file mode 100644 index d6fdb48e9eab8f629b97f170895b337f828a0a7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27919 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 B{SE*C From 0e9fdfd6064d22208e4c14689a521c1a3cd6cb17 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 1 Dec 2025 22:21:22 +0900 Subject: [PATCH 29/42] fix README and Prompts --- ppt-font-fix/.vscode/mcp.stdio.container.json | 8 -------- ppt-font-fix/README.md | 2 ++ .../Prompts/PptFontFixPrompt.cs | 2 -- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index a1da79b3..316d97cd 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -1,11 +1,4 @@ { - "inputs": [ - { - "type": "promptString", - "id": "your-ppt-file-path", - "description": "The absolute path where the PPT file you want to modify is located" - } - ], "servers": { "ppt-font-fix": { "type": "stdio", @@ -15,7 +8,6 @@ "-i", "--rm", "--name", "ppt-font-fix", - "-v", "${input:your-ppt-file-path}:/files", "ppt-font-fix:latest" ] } diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md index 14802c82..83ae5324 100644 --- a/ppt-font-fix/README.md +++ b/ppt-font-fix/README.md @@ -140,6 +140,8 @@ PPT Font Fix MCP server includes: azd env get-value AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN ``` + If you want to use Azure, you must copy the account key or upload the file to the blob storage on the running server, and copy the URL of the uploaded file. + ### Connect MCP server to an MCP host/client #### VS Code + Agent Mode + Local MCP server diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index a2e76e95..3d207c08 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -158,8 +158,6 @@ Output the full path as returned. ```bash docker cp {ContainerName}:[EXTRACTED_CONTAINER_PATH] "[HOST_DESTINATION_PATH]" ``` - - Task complete. """; } } \ No newline at end of file From 3616c8c27fa7bffcdb89eb60ea54a513adf22dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=9A=A8=EB=B9=88?= <113253581+jewelry14@users.noreply.github.com> Date: Mon, 1 Dec 2025 23:03:23 +0900 Subject: [PATCH 30/42] Delete unnecessary comments --- .../Prompts/PptFontFixPrompt.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 3d207c08..0c120ab4 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -3,7 +3,7 @@ using System.IO; using System; using System.Collections.Generic; -using System.Linq; // Path.GetFileName을 위한 Last() 메서드 사용을 위해 필요 +using System.Linq; namespace McpSamples.PptFontFix.HybridApp.Prompts; @@ -160,4 +160,4 @@ Output the full path as returned. ``` """; } -} \ No newline at end of file +} From bb3dcb41c9f751025129511123e10d01d9a9658c Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Thu, 4 Dec 2025 06:02:10 +0900 Subject: [PATCH 31/42] imsi --- ppt-font-fix/.vscode/mcp.stdio.container.json | 2 +- ppt-font-fix/infra/resources.bicep | 4 + ...\353\263\265\354\202\254\353\263\270.pptx" | Bin 0 -> 40943 bytes ppt-font-fix/input/outtest_result.pptx | Bin 0 -> 38052 bytes ppt-font-fix/input/result_fixed_outtest.pptx | Bin 0 -> 38052 bytes .../Program.cs | 63 +++- .../Prompts/PptFontFixPrompt.cs | 301 +++++++++------- .../Services/PPTFontFixService.cs | 329 +++++++++++------- .../test_result.pptx | Bin 0 -> 38032 bytes ppt-font-fix/test.pptx | Bin 0 -> 40943 bytes 10 files changed, 447 insertions(+), 252 deletions(-) create mode 100644 "ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" create mode 100644 ppt-font-fix/input/outtest_result.pptx create mode 100644 ppt-font-fix/input/result_fixed_outtest.pptx create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx create mode 100644 ppt-font-fix/test.pptx diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index 316d97cd..cc21de8f 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -7,7 +7,7 @@ "run", "-i", "--rm", - "--name", "ppt-font-fix", + "-v", ".\\ppt-font-fix\\input:/files", "ppt-font-fix:latest" ] } diff --git a/ppt-font-fix/infra/resources.bicep b/ppt-font-fix/infra/resources.bicep index 2c4939c2..0ccc3cba 100644 --- a/ppt-font-fix/infra/resources.bicep +++ b/ppt-font-fix/infra/resources.bicep @@ -194,6 +194,10 @@ module mcpPptFontFix 'br/public:avm/res/app/container-app:0.8.0' = { name: 'AzureBlobConnectionString' value: storageConnectionString } + { + name: 'AZURE_FILE_SHARE_MOUNT_PATH' + value: '/app/mounts' + } ] args: [ '--http' ] volumeMounts: [ diff --git "a/ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" "b/ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" new file mode 100644 index 0000000000000000000000000000000000000000..eaa90ce5de664fdb99f004e2455eb6b7012d62e0 GIT binary patch literal 40943 zcmeFZV{|3$zAYZx?l|eFW81cE+crD4osO|$+qP|WoOJBuX21LV$2kAH-#hjh<9<8m z)`zF6)~fpOta|30Kg?S4QlMaHKoCGsKtMo5Kq<~-u>HV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 literal 0 HcmV?d00001 diff --git a/ppt-font-fix/input/outtest_result.pptx b/ppt-font-fix/input/outtest_result.pptx new file mode 100644 index 0000000000000000000000000000000000000000..def7d7702afc6788af69f5531107ba887eb85c57 GIT binary patch literal 38052 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 + { + if (file is null || file.Length == 0) + { + return Results.BadRequest(new { error = "No file uploaded." }); + } + + try + { + using var stream = file.OpenReadStream(); + var tempId = await service.UploadPptFileAsync(stream, file.FileName); + + // LLM(또는 클라이언트)이 이 tempId를 받아서 "temp:{tempId}" 형태로 + // analyze_ppt_file / prompt 인자에 넘기면 됩니다. + return Results.Ok(new { tempId }); + } + catch (Exception ex) + { + return Results.Problem(ex.Message); + } + }) + .DisableAntiforgery(); } await app.RunAsync(); \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 3d207c08..d94cd442 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -40,124 +40,187 @@ public string GetAnalysisPrompt( string actualFileName = safePath.Split('/').Last(); string containerInputPath = $"{ContainerInputPathBase}/{actualFileName}"; - return $""" - You are the assistant responsible for guiding a complete multi-environment PowerPoint font fix workflow. - Follow the process below exactly and request inputs from the user whenever required. - - ### STEP 0 — Determine Execution Environment - 1. Ask the user: **Where is the MCP server running? (Local / Docker / Azure)** - Store the answer for later branching decisions. - - 2. Apply environment-specific logic: - - **If Local:** - - No file transfer is required. - - Use the original host file path: - `{hostFilePath}` - - **If Azure:** - - Inform the user: "**The server cannot directly access your local file path in the Azure environment. You must upload the file to Azure Blob Storage or a File Share and provide the accessible path.**" - - Ask the user: **"Have you already uploaded the file to Azure storage? (Yes/No)"** - - Store the answer as `isUploaded`. - - - **IF `isUploaded` is "No":** - - Inform the user: "**You must run the following command in your terminal to upload the file to Blob Storage.**" - - Ask for: - - Storage Account Name → `azureAccountName` - - Account Key → `azureAccountKey` - - Container Name → `azureContainerName` (default: `{AzureDefaultContainer}`) - - Present the upload command and ask for permission to run it: - ```bash - az storage blob upload \ - --account-name [azureAccountName] \ - --account-key [azureAccountKey] \ - --container-name [azureContainerName] \ - --file "{hostFilePath}" \ - --name "{actualFileName}" \ - --overwrite true - ``` - - If the user allows it, execute the command. - - **Wait for confirmation** that the upload has executed successfully. - - - **FINAL CRITICAL ACTION (Execute regardless of `isUploaded`):** Request the final access path for the server to read the file. - - Ask the user: "**If the file has been uploaded, please provide one of the following:** 1) **Blob URL (including SAS)**, 2) **Blob Path (e.g., `[azureContainerName]/{actualFileName}`)** or 3) **File Share File Name (e.g., `{actualFileName}`)**" - - Store the final input path for the tool as `FINAL_INPUT_PATH = "[User-Provided Path/URL/File Name]"` - - **If Docker:** - - Ask the user for the running container ID or name for **{ContainerName}**. - - Ask the user whether to allow this file-copy command: - ```bash - docker cp "{hostFilePath}" [CONTAINER_ID]:{ContainerInputPathBase} - ``` - - If the user allows it, execute the command. - - Use the container path: - `{containerInputPath}` - - Confirm with the user when the file transfer or upload is complete. - - --- - - ### STEP 1 — Analyze Fonts - 1. Call the `analyze_ppt_file` tool. - - Input path depends on environment: - - Local / Azure URL → `{hostFilePath}` - - Docker → `{containerInputPath}` - - 2. After receiving `PptFontAnalyzeResult`, display: - - List of used fonts - - List of inconsistently used fonts - - 3. If `UnusedFontLocations` contains items: - Ask the user to make two selections: - A. **Choose a Standard Font** (from UsedFonts) - B. **Choose an Action Mode:** - 1. Fix & Clean — Replace fonts and remove unused text boxes - 2. Fix Only — Replace fonts only - - --- - - ### STEP 2 — Modify the File - 1. Ask the user where to save the updated file: - - **If Local Execution:** - - Ask for an output directory path (optional). - - Store as `outputDirectory`. - - If omitted, the server will save to its default directory and return a URL. - - **If Azure Execution:** - - Inform the user: "**The modified file will be saved to Blob Storage and provided as a secure download URL.**" - - Set `outputDirectory = null`. - - **If Docker Execution:** - - Set `outputDirectory = null`. - - Inform the user that the file will be saved internally at `/files`. - - 2. Call the `update_ppt_file` tool with: - - `replacementFont` — user-selected value - - `inconsistentFontsToReplace` — the list from analysis - - `newFileName` — `"result_fixed_{actualFileName}"` - - `outputDirectory` — user-given directory or null (Docker) - - --- - - ### STEP 3 — Present the Final Output - Inspect the result string returned by `update_ppt_file`. - - **If it begins with `http`:** - - Present it as a clickable markdown link: - `[Click here to download the fixed file](URL)` - - **If it is a local path:** - - If Local/Azure: - Output the full path as returned. - - - If Docker: - - Extract the internal container path (e.g., `/files/result_fixed_test.pptx`). - - Ask the user for the desired directory on the host machine. - - Then provide this copy-out command: - ```bash - docker cp {ContainerName}:[EXTRACTED_CONTAINER_PATH] "[HOST_DESTINATION_PATH]" - ``` - """; + return """ +You are the assistant responsible for guiding a complete end-to-end PowerPoint font fix workflow. +Follow the process below exactly and ask the user for any information you need. +Prefer the HTTP upload flow whenever it is available, so that the user can simply choose a local file and let the MCP server handle it. + +The PPT Font Fix MCP server supports: +- HTTP file upload via a `/upload` endpoint, which returns a `tempId` that can be used as `temp:{id}`. +- Opening PPT files from: + - `temp:{id}` (uploaded via `/upload`) + - HTTP/HTTPS URLs backed by Azure Blob Storage + - Local or container paths, including: + - `/app/...` + - `/app/mounts/...` (Azure File Share mount) + - `/files/...` + - `wwwroot/generated/...` + - OS temporary directory + +When saving the updated PPT file, the server: +1. Tries to save into an Azure File Share mounted at `/app/mounts`, under the `generated` folder: + - `/app/mounts/generated/` + - This corresponds to the `generated` folder inside the `ppt-files` File Share in the Storage Account. +2. If the File Share mount is not available, it falls back to `wwwroot/generated/`, + potentially returning an HTTP URL like `https:///generated/` in HTTP mode. +3. On pure local Windows, it can also save directly to a user-provided directory. + +Use this knowledge to guide the user. + +--- + +### STEP 0 — Determine how the server is running and how to provide the PPT file + +1. Ask the user: + **"How is the PPT Font Fix MCP server running? (Local HTTP / Docker HTTP / Azure HTTP / pure stdio local)"** + +2. Decide whether HTTP is available: + + - If the answer includes HTTP (for example: Local HTTP, Docker HTTP, Azure Container Apps, Azure Functions fronted by APIM, etc.), treat it as **HTTP-enabled**. + - If the answer is "pure stdio local" or equivalent, treat it as **non-HTTP**. + +3. If HTTP is available (RECOMMENDED FLOW): + + 1. Ask the user for the **base URL** of the MCP HTTP endpoint, for example: + - `http://localhost:PORT` (local/Docker) + - `https://` (Azure Container Apps — often exposed via `AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN`) + + 2. Explain that the easiest way to send a PPTX from the user's local machine to the MCP server is to call the `/upload` endpoint. + + 3. Provide a concrete `curl` command, using their local PPTX path: + + + curl -X POST "[BASE_URL]/upload" -F "file=@\"[LOCAL_PPTX_PATH]\"" + - `[BASE_URL]` is the HTTP base URL they just provided. + - `[LOCAL_PPTX_PATH]` is the full path to their PPTX file on their machine. + + 4. Ask the user to run this command in their local terminal and wait for the response. + + 5. The server will respond with JSON similar to: + + + { "tempId": "xxxxxxxx" } + 6. Ask the user to paste the returned `tempId`. + + 7. Construct and remember the final input path as: + + - `INPUT_PATH = "temp:" + tempId` + +4. If HTTP is **not** available (pure stdio, no exposed HTTP endpoint): + + 1. Explain: + + > "The server has no HTTP upload endpoint. The PPTX file must be in a path that the server process can read directly (for example: a shared folder, a mounted volume, or a path inside the same machine/container)." + + 2. Ask the user for one of the following: + + - A file path that is directly visible to the server process + (for example, a shared directory or mounted network path), or + - A public HTTP/HTTPS URL from which the server can download the PPTX. + + 3. Store this as: + + - `INPUT_PATH = [user-provided path or URL]` + +5. Clearly confirm the chosen `INPUT_PATH` back to the user before calling tools. + +--- + +### STEP 1 — Analyze fonts in the PPT + +1. Call the `analyze_ppt_file` tool. + + - Use the `INPUT_PATH` decided in STEP 0 as the `filePath` argument. + - In HTTP scenarios this will typically be `temp:{tempId}`. + - In non-HTTP scenarios this may be a local path or URL. + +2. After receiving `PptFontAnalyzeResult`, summarize clearly for the user: + + - `UsedFonts` — the main fonts used in the presentation. + - `InconsistentlyUsedFonts` — fonts that are used in a scattered or inconsistent way. + - Whether there are any `UnusedFontLocations` (empty boxes or off-slide text). + +3. If `UnusedFontLocations` is non-empty, ask the user to make two decisions: + + 1. **Standard font choice** + + - Let the user choose a standard font from the `UsedFonts` list to use as the replacement font. + + 2. **Action mode** + + - **Fix & Clean** — replace inconsistent fonts and remove unused/off-slide shapes. + - **Fix Only** — replace fonts only, and leave all shapes in place. + +--- + +### STEP 2 — Update and save the PPT file + +1. Discuss how the updated file will be saved, based on the environment: + + - **Azure Container Apps (using this sample infra):** + - There is a File Share named `ppt-files` mounted at `/app/mounts`. + - The service saves into `/app/mounts/generated/`. + - The path returned by the tool will be a container-internal path like: + - `/app/mounts/generated/result_fixed_....pptx` + - Explain that this maps directly to the `generated` folder inside the `ppt-files` File Share. + - The user can retrieve the file from: + - Azure Storage Explorer, or + - SMB access to the `ppt-files` share. + - In this case, `outputDirectory` should usually be left empty (null) so the server uses its default File Share mount. + + - **Docker HTTP / Local HTTP without File Share:** + - The service may save into `wwwroot/generated/`. + - If the HTTP context is present, it may return a URL like: + - `http(s):///generated/` + - In this case, the user can simply click the URL to download the fixed PPT. + + - **Pure local Windows:** + - The server can save directly to a user-specified directory on the local machine, if that directory is accessible. + +2. Ask the user: + + - If the server is truly running on their local Windows machine: + - Ask for an optional output directory and store it as `outputDirectory`. + - If the server is running in Azure Container Apps (remote): + - Explain that saving will go to the mounted File Share, and `outputDirectory` can be null. + - If the server is running in Docker: + - Either rely on the internal default, or on a bind mount if they configured one. Do not invent a path; ask the user if they have a specific mount or host directory in mind. + +3. Call the `update_ppt_file` tool with: + + - `replacementFont` — the user-selected standard font. + - `inconsistentFontsToReplace` — the list of fonts to normalize. + - `locationsToRemove` — the list of locations to delete if the user selected **Fix & Clean**; otherwise an empty list. + - `newFileName` — for example: `"result_fixed_[ORIGINAL_FILE_NAME]"`. + - `outputDirectory` — the directory chosen above, or null/empty if using Azure File Share or default internal paths. + +--- + +### STEP 3 — Present the final result to the user + +1. Inspect the string returned by `update_ppt_file`. + +2. If it begins with `http`: + + - Present it as a clickable markdown link: + + `[Click here to download the fixed PPT file](URL)` + +3. If it is a local or container path (not starting with `http`): + + - If the server is running locally and the path is visible from the user's machine: + - Show the full path and instruct the user to open or copy the file directly. + + - If the server is running in Azure Container Apps with the File Share mount: + - Explain that the path is inside the container but backed by the `ppt-files` File Share. + - Tell the user they can open or download the file via: + - Azure Storage Explorer or + - SMB access to the `ppt-files` share. + - Do not assume or run any Azure CLI commands without explicit confirmation. + + - If the server is running in Docker: + - Clarify that the path is inside the container or a mounted volume. + - Tell the user that they can use their container tooling (for example `docker cp` or a bind-mounted directory) to retrieve the file, but do not execute or assume a specific command without their approval. +"""; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 564e9c1a..828de69f 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -9,9 +9,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Http; using System.IO; -using Azure.Storage.Blobs; +using System.Threading; using Azure.Storage.Sas; -using Azure.Storage.Blobs.Specialized; namespace McpSamples.PptFontFix.HybridApp.Services; @@ -20,6 +19,16 @@ namespace McpSamples.PptFontFix.HybridApp.Services; ///

public interface IPptFontFixService { + /// + /// Uploads a PPT file stream to a temporary location on the server and returns a temp ID. + /// The returned temp ID can be used later with the "temp:{id}" pattern in tools. + /// + /// The PPTX file stream. + /// Original file name (for logging only). + /// Cancellation token. + /// Temporary identifier for the uploaded file. + Task UploadPptFileAsync(Stream fileStream, string fileName, CancellationToken cancellationToken = default); + /// /// open a Ppt file. /// @@ -66,7 +75,7 @@ public class PptFontFixService : IPptFontFixService private readonly IWebHostEnvironment? _webHostEnvironment; private readonly IHttpContextAccessor? _httpContextAccessor; private Presentation? _presentation; - private readonly BlobServiceClient? _blobServiceClient; + private readonly string? _fileShareMountPath; private HashSet? _analyzedVisibleFonts; @@ -81,13 +90,30 @@ public PptFontFixService( _hostEnvironment = hostEnvironment; _webHostEnvironment = serviceProvider.GetService(); _httpContextAccessor = serviceProvider.GetService(); + _fileShareMountPath = configuration["AZURE_FILE_SHARE_MOUNT_PATH"]; + + } + + private static string GetTempFilePath(string tempId) + { + // 업로드된 PPT 파일을 저장하는 서버 임시 경로 규칙 + return Path.Combine(Path.GetTempPath(), $"ppt_upload_{tempId}.tmp"); + } + + /// + public async Task UploadPptFileAsync(Stream fileStream, string fileName, CancellationToken cancellationToken = default) + { + var tempId = Guid.NewGuid().ToString("N"); + var tempPath = GetTempFilePath(tempId); + + _logger.LogInformation("Uploading PPT file: {FileName} -> {TempPath}", fileName, tempPath); - // Azure Connection String을 사용하여 BlobServiceClient 초기화 시도 - string? azureConnectionString = configuration["AzureBlobConnectionString"]; - if (!string.IsNullOrEmpty(azureConnectionString)) + using (var outputStream = File.Create(tempPath)) { - _blobServiceClient = new BlobServiceClient(azureConnectionString); + await fileStream.CopyToAsync(outputStream, cancellationToken); } + + return tempId; } /// @@ -95,65 +121,52 @@ public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); - if (Uri.TryCreate(filePath, UriKind.Absolute, out Uri? uriResult) && - (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) + // 0. temp:ID 패턴 처리 (업로드된 PPT 파일) + if (filePath.StartsWith("temp:", StringComparison.OrdinalIgnoreCase)) { - _logger.LogInformation("✅ Detected URL path. Attempting to open from Blob Storage: {Url}", filePath); + var tempId = filePath.Substring(5); + var tempFilePath = GetTempFilePath(tempId); - if (_blobServiceClient == null) + if (!File.Exists(tempFilePath)) { - throw new InvalidOperationException("Cannot open from URL. AzureBlobConnectionString is not configured."); + _logger.LogError("❌ Temp PPT file for ID '{TempId}' not found at {Path}", tempId, tempFilePath); + throw new FileNotFoundException($"The uploaded temporary PPT file for ID '{tempId}' was not found or has expired.", tempFilePath); } try { - string containerSegment = uriResult.Segments.Skip(1).FirstOrDefault()?.TrimEnd('/') ?? throw new ArgumentException("Invalid Blob URL format: Container name not found.", nameof(filePath)); - string blobName = string.Join("", uriResult.Segments.Skip(2)); - - if (string.IsNullOrEmpty(blobName)) - { - throw new ArgumentException("Invalid Blob URL format: Blob name not found.", nameof(filePath)); - } - - var containerClient = _blobServiceClient.GetBlobContainerClient(containerSegment); - var blobClient = containerClient.GetBlobClient(blobName); - - if (!await blobClient.ExistsAsync()) - { - throw new FileNotFoundException($"Blob file not found in container '{containerSegment}': {blobName}"); - } - _presentation?.Dispose(); - var memoryStream = new MemoryStream(); - await blobClient.DownloadToAsync(memoryStream); - memoryStream.Position = 0; - - _presentation = new ShapeCrawler.Presentation(memoryStream); + _presentation = new ShapeCrawler.Presentation(tempFilePath); _analyzedVisibleFonts = null; - _logger.LogInformation("Ppt file opened successfully from Blob."); + _logger.LogInformation("Ppt file opened successfully from temp upload: {Path}", tempFilePath); + await Task.CompletedTask; return; } catch (Exception ex) { - _logger.LogError(ex, "❌ Failed to open Ppt file from URL."); - throw new InvalidOperationException($"Failed to open Blob file at {filePath}.", ex); + _logger.LogError(ex, "Failed to open PPT file from temp path: {Path}", tempFilePath); + throw; } } - var searchPaths = new List(); + var searchPaths = new List { filePath }; + string safeFileName = Path.GetFileName(filePath.Replace('\\', '/')); - searchPaths.Add(filePath); - - string safePath = filePath.Replace('\\', '/'); - string fileName = safePath.Split('/').Last(); - - searchPaths.Add(Path.Combine("/app", fileName)); - searchPaths.Add(Path.Combine("/files", fileName)); - searchPaths.Add(Path.Combine("/app/mounts", fileName)); + // (기존) 컨테이너 내부의 미리 약속된 경로를 탐색 + searchPaths.Add(Path.Combine("/app", safeFileName)); + searchPaths.Add(Path.Combine("/files", safeFileName)); + searchPaths.Add(Path.Combine("/app/mounts", safeFileName)); + // (기존) WebRoot 및 Temp 경로 탐색 string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - searchPaths.Add(Path.Combine(baseDir, "generated", fileName)); - searchPaths.Add(Path.Combine(Path.GetTempPath(), fileName)); + searchPaths.Add(Path.Combine(baseDir, "generated", safeFileName)); + searchPaths.Add(Path.Combine(Path.GetTempPath(), safeFileName)); + + // (신규) File Share Mount Path를 기반으로 파일명으로 직접 접근 시도 + if (!string.IsNullOrEmpty(_fileShareMountPath)) + { + searchPaths.Add(Path.Combine(_fileShareMountPath, "generated", safeFileName)); + } string? foundPath = null; foreach (var path in searchPaths) @@ -165,17 +178,76 @@ public async Task OpenPptFileAsync(string filePath) break; } } + + // 2. 외부 파일 처리 및 마운트 경로로 복사 (가장 중요한 신규 로직) + if (foundPath == null && !Uri.TryCreate(filePath, UriKind.Absolute, out _) && !filePath.StartsWith("temp:", StringComparison.OrdinalIgnoreCase)) + { + // 1) 찾지 못했고, URL이나 Temp ID도 아닐 경우, filePath 자체가 로컬 호스트 경로라고 가정하고 복사를 시도합니다. + + string targetBaseDir; + if (!string.IsNullOrEmpty(_fileShareMountPath)) + { + // File Share 마운트 경로를 사용합니다. + targetBaseDir = Path.Combine(_fileShareMountPath, "uploaded"); + } + else if (File.Exists("/files")) // Docker volume convention check + { + // Docker 볼륨 마운트 경로를 사용합니다. + targetBaseDir = "/files"; + } + else + { + // 최후의 수단으로 Web Root/generated를 사용하거나 예외를 발생시킵니다. + targetBaseDir = Path.Combine(baseDir, "uploaded"); + } + + if (!Directory.Exists(targetBaseDir)) + { + Directory.CreateDirectory(targetBaseDir); + } - if (foundPath == null) + string tempCopyPath = Path.Combine(targetBaseDir, safeFileName); + + try + { + _logger.LogInformation("Attempting to copy file from outside mount ({Source}) to inside mount ({Target})", filePath, tempCopyPath); + // 호스트 경로에 있는 파일을 컨테이너 내부의 마운트 경로로 복사 시도 + // 이는 호스트가 컨테이너의 마운트 디렉토리를 공유하고 있어야 성공합니다. + File.Copy(filePath, tempCopyPath, overwrite: true); + foundPath = tempCopyPath; + _logger.LogInformation("✅ File successfully copied to mount path: {Path}", foundPath); + } + catch (FileNotFoundException) + { + _logger.LogError("❌ File not found at the original path: {Path}. Searched in: {Paths}", filePath, string.Join(", ", searchPaths)); + throw new FileNotFoundException($"Ppt file not found at the original path and could not be copied into the container.", filePath); + } + catch (Exception ex) + { + _logger.LogError(ex, "❌ Failed to copy file from outside mount to inside mount."); + throw new IOException($"Failed to access or copy file from host path '{filePath}' into the container volume.", ex); + } + } + else if (foundPath == null) { _logger.LogError("❌ File not found. Searched in: {Paths}", string.Join(", ", searchPaths)); throw new FileNotFoundException($"Ppt file not found. File must be accessible at the host path OR successfully copied to the container volume.", filePath); } - + + // 3. 파일 열기 (foundPath 사용) try { _presentation?.Dispose(); - _presentation = new ShapeCrawler.Presentation(foundPath); + // 파일을 메모리 스트림으로 읽어와서 ShapeCrawler에 전달하는 방식이 + // 파일 잠금 문제를 피하고 컨테이너 환경에서 안정적입니다. + using (var fs = new FileStream(foundPath, FileMode.Open, FileAccess.Read)) + { + var memoryStream = new MemoryStream(); + await fs.CopyToAsync(memoryStream); + memoryStream.Position = 0; + _presentation = new ShapeCrawler.Presentation(memoryStream); // ShapeCrawler 생성자에 Stream 전달 + } + _analyzedVisibleFonts = null; _logger.LogInformation("Ppt file opened successfully: {FilePath}", foundPath); await Task.CompletedTask; @@ -320,10 +392,8 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu if (this._presentation == null) throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); ArgumentException.ThrowIfNullOrWhiteSpace(desiredFileName, nameof(desiredFileName)); - string safeFileName = Path.GetFileName(desiredFileName); - if (safeFileName.Contains('\\')) safeFileName = safeFileName.Split('\\').Last(); - if (safeFileName.Contains('/')) safeFileName = safeFileName.Split('/').Last(); - safeFileName = safeFileName.Replace(":", "").Trim(); + // 파일 이름 정리 (안전한 파일 이름 추출) + string safeFileName = Path.GetFileName(desiredFileName).Replace(":", "").Trim(); _logger.LogInformation("Save process started. Target: {SafeName}", safeFileName); @@ -332,107 +402,103 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu await Task.Run(() => _presentation.Save(memoryStream)); memoryStream.Position = 0; - string? azureConnectionString = _configuration["AzureBlobConnectionString"]; - if (!string.IsNullOrEmpty(azureConnectionString)) - { - try - { - _logger.LogInformation("Environment detected: Azure Blob Storage"); - var blobServiceClient = new BlobServiceClient(azureConnectionString); - var containerClient = blobServiceClient.GetBlobContainerClient("generated-files"); - await containerClient.CreateIfNotExistsAsync(); - var blobClient = containerClient.GetBlobClient(safeFileName); - await blobClient.UploadAsync(memoryStream, overwrite: true); - var sasBuilder = new BlobSasBuilder() - { - ExpiresOn = DateTimeOffset.UtcNow.AddHours(1), - BlobName = safeFileName, - BlobContainerName = "generated-files", - }; - sasBuilder.SetPermissions(BlobSasPermissions.Read); - - Uri sasUri = blobClient.GenerateSasUri(sasBuilder); - - _logger.LogInformation("✅ Returning Blob URL with SAS token."); - return sasUri.ToString(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Azure save failed. Falling back to local storage."); - memoryStream.Position = 0; - } - } string finalPhysicalPath = ""; - string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - string generatedDir = Path.Combine(webRoot, "generated"); - if (!Directory.Exists(generatedDir)) Directory.CreateDirectory(generatedDir); - string webStoragePath = Path.Combine(generatedDir, safeFileName); - bool isDocker = !OperatingSystem.IsWindows(); + string baseDirectory; - if (isDocker) + bool isContainerEnv = !OperatingSystem.IsWindows() || !string.IsNullOrEmpty(_fileShareMountPath); + bool isHttpMode = _httpContextAccessor?.HttpContext?.Request != null; + + if (isContainerEnv) { - _logger.LogInformation("Environment detected: Docker Container"); - - try + // 1. 저장 기본 경로 결정 (마운트 볼륨 또는 웹 루트) + if (!string.IsNullOrEmpty(_fileShareMountPath)) { - string syncPath = Path.Combine("/files", safeFileName); - - memoryStream.Position = 0; - using (var fs = new FileStream(syncPath, FileMode.Create, FileAccess.Write)) - { - await memoryStream.CopyToAsync(fs); - await fs.FlushAsync(); - } - File.SetUnixFileMode(syncPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); - - finalPhysicalPath = syncPath; + // Azure File Share Mount Path를 사용합니다. (예: /app/mounts/generated) + baseDirectory = Path.Combine(_fileShareMountPath, "generated"); + _logger.LogInformation("Base Path: Azure File Share Mount -> {Path}", baseDirectory); } - catch (Exception ex) - { - _logger.LogError(ex, "FATAL: Could not save to /files volume. Falling back to internal web root."); - finalPhysicalPath = webStoragePath; + // else if (isHttpMode) + // { + // // [HTTP Service Mode]: /files 마운트가 없거나 HTTP 서비스로 실행 중일 때 Web Root 사용 + // string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + // baseDirectory = Path.Combine(webRoot, "generated"); + // _logger.LogInformation("Base Path: HTTP Web Root -> {Path}", baseDirectory); + // } + else if (Directory.Exists("/files")) + { + // [Stdio Container Mode]: HTTP 요청이 없고, /files 볼륨이 마운트되어 있을 때 사용 + baseDirectory = "/files"; // 👈 Stdio 출력 경로 + _logger.LogInformation("Base Path: Stdio Container Volume Mount (/files) -> {Path}", baseDirectory); } - - memoryStream.Position = 0; - using (var fs = new FileStream(webStoragePath, FileMode.Create, FileAccess.Write)) + else { - await memoryStream.CopyToAsync(fs); + // File Share가 없거나 마운트 실패 시, 로컬 웹 루트를 사용합니다. + string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + baseDirectory = Path.Combine(webRoot, "generated"); + _logger.LogInformation("Base Path: Local/Docker Web Root -> {Path}", baseDirectory); } - File.SetUnixFileMode(webStoragePath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead); } else { - _logger.LogInformation("Environment detected: Local Windows"); - - string finalPathToSave; - if (!string.IsNullOrEmpty(outputDirectory) && Directory.Exists(outputDirectory)) { - finalPathToSave = Path.Combine(outputDirectory, safeFileName); - _logger.LogInformation("Saving to user-specified path: {Path}", finalPathToSave); + // 2-1. Stdio/로컬 환경: 사용자가 지정한 outputDirectory 사용 (요청 반영) + baseDirectory = outputDirectory; + _logger.LogInformation("Base Path: Local User Specified -> {Path}", baseDirectory); } else { - if (!string.IsNullOrEmpty(outputDirectory)) - { - _logger.LogWarning("Specified output directory '{Dir}' does not exist or is invalid. Falling back to default.", outputDirectory); - } - - finalPathToSave = webStoragePath; - _logger.LogInformation("Saving to default webroot path: {Path}", finalPathToSave); + // 2-2. Fallback: 로컬 환경이지만 outputDirectory가 없으면 Web Root 사용 + string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + baseDirectory = Path.Combine(webRoot, "generated"); + _logger.LogInformation("Base Path: Local Web Root Fallback -> {Path}", baseDirectory); } - - using (var fs = new FileStream(finalPathToSave, FileMode.Create, FileAccess.Write)) // 👈 finalPathToSave 사용 + } + + // 2. 디렉토리 확인 및 생성 + if (!Directory.Exists(baseDirectory)) + { + try + { + Directory.CreateDirectory(baseDirectory); + } + catch (Exception ex) + { + _logger.LogError(ex, "FATAL: Could not create base directory {Path}.", baseDirectory); + throw; + } + } + + finalPhysicalPath = Path.Combine(baseDirectory, safeFileName); + + // 3. 파일 저장 (마운트 볼륨/웹 루트에 단일 저장) + try + { + memoryStream.Position = 0; + using (var fs = new FileStream(finalPhysicalPath, FileMode.Create, FileAccess.Write)) { - memoryStream.Position = 0; await memoryStream.CopyToAsync(fs); + await fs.FlushAsync(); } - finalPhysicalPath = finalPathToSave; + // Docker/Linux 환경에서 권한 설정 + if (string.IsNullOrEmpty(this._fileShareMountPath)) + { + File.SetUnixFileMode(finalPhysicalPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); + } + + _logger.LogInformation("✅ File successfully saved to mount/web path: {Path}", finalPhysicalPath); + } + catch (Exception ex) + { + _logger.LogError(ex, "FATAL: Could not save file to the final physical path: {Path}", finalPhysicalPath); + throw; } + // 4. 최종 반환: HTTP Context가 있다면 웹 URL을, 없다면 물리적 경로를 반환 if (_httpContextAccessor?.HttpContext?.Request != null) { + // 모든 파일이 'generated' 폴더 아래에 저장되었으므로, 웹 URL 경로는 /generated/{filename}으로 통일 var request = _httpContextAccessor.HttpContext.Request; string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; _logger.LogInformation("✅ Returning Web URL: {Url}", url); @@ -440,7 +506,8 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu } else { - _logger.LogInformation("✅ Returning Physical Path: {Path}", finalPhysicalPath); + // STDIN/STDOUT (stdio) 또는 로컬 실행 환경에서 HTTP Context가 없을 경우 + _logger.LogInformation("✅ Returning Physical Path (No HTTP Context): {Path}", finalPhysicalPath); return finalPhysicalPath; } } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx new file mode 100644 index 0000000000000000000000000000000000000000..e4fb0f723be19188d576297b5beab74ba6acf14a GIT binary patch literal 38032 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 L&SF__Efbi&cO*${UT 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

^jUa2-c19&iGCZW2LV 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 literal 0 HcmV?d00001 From b5b491884c57f2b04011430eca81b7f3414a7928 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Thu, 4 Dec 2025 18:50:22 +0900 Subject: [PATCH 32/42] operate normally except in the action of a prompt --- Dockerfile.ppt-font-fix-azure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.ppt-font-fix-azure b/Dockerfile.ppt-font-fix-azure index 7d970625..74428fba 100644 --- a/Dockerfile.ppt-font-fix-azure +++ b/Dockerfile.ppt-font-fix-azure @@ -15,7 +15,7 @@ WORKDIR /app COPY --from=build /app . -COPY ./ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx /app/test.pptx +RUN mkdir -p /app/wwwroot/generated USER $APP_UID From 1854774be25eeae445e39d93314ef5bbdfd5d529 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Thu, 4 Dec 2025 21:40:15 +0900 Subject: [PATCH 33/42] Fix logic1 --- .vscode/mcp.json | 9 +- Dockerfile.ppt-font-fix | 6 +- Dockerfile.ppt-font-fix-azure | 16 +- ppt-font-fix/.vscode/mcp.stdio.container.json | 5 +- ...\353\263\265\354\202\254\353\263\270.pptx" | Bin 40943 -> 0 bytes ppt-font-fix/input/outtest_result.pptx | Bin 38052 -> 0 bytes ppt-font-fix/input/result_fixed_outtest.pptx | Bin 38052 -> 0 bytes .../Configurations/PPTFontFixAppSettings.cs | 30 ++- .../Program.cs | 136 +++++++--- .../Prompts/PptFontFixPrompt.cs | 236 ++++-------------- .../Services/PPTFontFixService.cs | 216 +++++++--------- .../Tools/PPTFontFixTool.cs | 51 +++- 12 files changed, 333 insertions(+), 372 deletions(-) delete mode 100644 "ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" delete mode 100644 ppt-font-fix/input/outtest_result.pptx delete mode 100644 ppt-font-fix/input/result_fixed_outtest.pptx diff --git a/.vscode/mcp.json b/.vscode/mcp.json index a6e57a2b..497a479e 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,8 +1,15 @@ { + "inputs": [ + { + "type": "promptString", + "id": "acaapp-server-fqdn", + "description": "Azure Container Apps FQDN" + } + ], "servers": { "ppt-font-fix": { "type": "http", - "url": "http://localhost:5166/mcp" + "url": "https://${input:acaapp-server-fqdn}/mcp" } } } diff --git a/Dockerfile.ppt-font-fix b/Dockerfile.ppt-font-fix index 96746489..a7d41ef4 100644 --- a/Dockerfile.ppt-font-fix +++ b/Dockerfile.ppt-font-fix @@ -21,10 +21,10 @@ WORKDIR /app COPY --from=build /app . -RUN mkdir -p /app/wwwroot/generated /files \ - && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /files \ +RUN mkdir -p /app/wwwroot/generated /files /app/workspace\ + && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /files /app/workspace \ && chmod 755 /app/wwwroot/generated USER $APP_UID -ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] +ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] \ No newline at end of file diff --git a/Dockerfile.ppt-font-fix-azure b/Dockerfile.ppt-font-fix-azure index 74428fba..29e2fd1d 100644 --- a/Dockerfile.ppt-font-fix-azure +++ b/Dockerfile.ppt-font-fix-azure @@ -15,8 +15,20 @@ WORKDIR /app COPY --from=build /app . -RUN mkdir -p /app/wwwroot/generated +RUN mkdir -p /app/wwwroot/generated \ + && mkdir -p /app/workspace \ + && mkdir -p /files -USER $APP_UID +ARG UID=$APP_UID + +# 3. 중요: 생성된 디렉토리의 소유권을 $APP_UID에게 변경합니다. +# 이렇게 해야 $APP_UID 사용자가 이 디렉토리에 파일을 쓸 수 있습니다. +# chown -R [사용자 ID]:[그룹 ID] [경로] +RUN chown -R $UID:$UID /app/wwwroot/generated \ + && chown -R $UID:$UID /app/workspace \ + && chown -R $UID:$UID /files + +# 4. 비-루트 사용자로 전환 (기존 코드와 동일) +USER $UID ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index cc21de8f..f48b134a 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -1,4 +1,4 @@ -{ +{ "servers": { "ppt-font-fix": { "type": "stdio", @@ -7,7 +7,8 @@ "run", "-i", "--rm", - "-v", ".\\ppt-font-fix\\input:/files", + "-v", "${workspaceFolder}\\ppt-font-fix\\workspace:/files", + "-e", "HOST_ROOT_PATH=${workspaceFolder}\\ppt-font-fix", "ppt-font-fix:latest" ] } diff --git "a/ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" "b/ppt-font-fix/input/outtest - \353\263\265\354\202\254\353\263\270.pptx" deleted file mode 100644 index eaa90ce5de664fdb99f004e2455eb6b7012d62e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40943 zcmeFZV{|3$zAYZx?l|eFW81cE+crD4osO|$+qP|WoOJBuX21LV$2kAH-#hjh<9<8m z)`zF6)~fpOta|30Kg?S4QlMaHKoCGsKtMo5Kq<~-u>HV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 diff --git a/ppt-font-fix/input/outtest_result.pptx b/ppt-font-fix/input/outtest_result.pptx deleted file mode 100644 index def7d7702afc6788af69f5531107ba887eb85c57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38052 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 + /// The root path for the workspace. + ///

+ public string WorkspacePath { get; set; } = string.Empty; + + /// + /// The path for generated files. + /// + public string GeneratedPath { get; set; } = string.Empty; + + /// + /// The path for specs files. + /// + public string SpecsPath { get; set; } = string.Empty; + + /// + /// Indicates whether the application is running in HTTP mode. + /// + public bool IsHttpMode { get; set; } + /// + /// Indicates whether the application is running in a containerized environment. + /// + public bool IsContainer { get; set; } + /// + /// Indicates whether the application is running in an Azure environment. + /// + public bool IsAzure { get; set; } +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 182c30f0..0d3f0b9e 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -26,68 +26,124 @@ IHost app = builder.BuildApp(useStreamableHttp); -if (app is WebApplication webApp) -{ - // Ensure wwwroot exists for static file hosting (e.g., generated files) - var wwwRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"); - if (!Directory.Exists(wwwRootPath)) - { - Directory.CreateDirectory(wwwRootPath); - } - - webApp.UseStaticFiles(); +var appSettings = app.Services.GetRequiredService(); +InitializeRuntimeSettings(appSettings, useStreamableHttp); - // 파일 업로드 엔드포인트 - // 로컬/리모트 어디에서든 사용자가 PPTX 파일을 업로드하면 tempId를 반환하고, - // 이후 MCP 툴에서는 "temp:{tempId}" 형태로 해당 파일을 참조할 수 있습니다. - var fileShareMountPath = webApp.Configuration["AZURE_FILE_SHARE_MOUNT_PATH"] ?? "/app/mounts"; - - // PptFontFixService에서 파일이 실제로 저장되는 물리적 경로: [마운트 경로]/generated - string physicalPathToGeneratedFiles = Path.Combine(fileShareMountPath, "generated"); - - // 저장 경로가 물리적으로 존재하는지 확인하고 없으면 생성 - if (!Directory.Exists(physicalPathToGeneratedFiles)) +if (useStreamableHttp && app is WebApplication webApp) +{ + // A. 정적 파일 서빙 (다운로드용) + // GeneratedPath(수정된 파일 저장소)가 없으면 생성 + string actualGeneratedPath = Path.Combine(webApp.Environment.WebRootPath, "generated"); + if (!Directory.Exists(actualGeneratedPath)) { - webApp.Logger.LogInformation("Creating physical directory for generated files: {Path}", physicalPathToGeneratedFiles); - Directory.CreateDirectory(physicalPathToGeneratedFiles); + Directory.CreateDirectory(actualGeneratedPath); } - // 마운트된 볼륨 경로를 웹 경로 '/generated'에 매핑하여 파일 서빙을 활성화합니다. + // '/generated' 경로로 들어오는 요청을 WebRootPath의 generated 폴더에 매핑 webApp.UseStaticFiles(new StaticFileOptions { - // 파일이 실제 저장된 물리적 경로를 지정합니다. - FileProvider = new PhysicalFileProvider(physicalPathToGeneratedFiles), - - // FQDN/generated로 들어오는 요청을 위 물리적 경로로 연결합니다. - RequestPath = "/generated" + // 🚨 수정: appSettings.GeneratedPath 대신 실제 wwwroot 경로를 사용 + FileProvider = new PhysicalFileProvider(actualGeneratedPath), + RequestPath = "/generated", + ServeUnknownFileTypes = true }); - - // 파일 업로드 엔드포인트 - // 로컬/리모트 어디에서든 사용자가 PPTX 파일을 업로드하면 tempId를 반환하고, - // 이후 MCP 툴에서는 "temp:{tempId}" 형태로 해당 파일을 참조할 수 있습니다. + // B. 파일 업로드 엔드포인트 추가 (/upload) webApp.MapPost("/upload", async (IFormFile file, IPptFontFixService service) => { + // 1. 입력 유효성 검사 (오류 시 반환) if (file is null || file.Length == 0) { return Results.BadRequest(new { error = "No file uploaded." }); } + // 2. 입력 파일 저장소 (SpecsPath) 확인 및 생성 + var appSettings = webApp.Services.GetRequiredService(); // AppSettings 주입 + if (!Directory.Exists(appSettings.SpecsPath)) + Directory.CreateDirectory(appSettings.SpecsPath); + + // 3. 파일명 추출 및 최종 경로 설정 + var fileName = Path.GetFileName(file.FileName); + var filePath = Path.Combine(appSettings.SpecsPath, fileName); + try { - using var stream = file.OpenReadStream(); - var tempId = await service.UploadPptFileAsync(stream, file.FileName); - - // LLM(또는 클라이언트)이 이 tempId를 받아서 "temp:{tempId}" 형태로 - // analyze_ppt_file / prompt 인자에 넘기면 됩니다. - return Results.Ok(new { tempId }); + // 4. 파일 스트림을 디스크에 직접 저장 + using (var stream = file.OpenReadStream()) + using (var outputStream = File.Create(filePath)) + { + await stream.CopyToAsync(outputStream); + } + + // 5. [수정] 업로드 성공 후, LLM이 참조할 수 있는 최종 파일 경로 반환 + // (Tool이 이 경로를 받아 AnalyzePptFileAsync를 호출함) + return Results.Ok(new { message = "File uploaded successfully.", filePath = filePath }); } catch (Exception ex) { - return Results.Problem(ex.Message); + // 6. 예외 발생 시 반환 + return Results.Problem($"File upload failed: {ex.Message}"); } }) .DisableAntiforgery(); } -await app.RunAsync(); \ No newline at end of file +await app.RunAsync(); + +void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) +{ + // Docker/Azure 환경 변수 확인 + bool isContainer = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; + string? azureAppName = Environment.GetEnvironmentVariable("CONTAINER_APP_NAME"); + bool isAzure = !string.IsNullOrEmpty(azureAppName); + + string baseDirectory; + + if (isContainer) + { + baseDirectory = "/app"; + settings.SpecsPath = Path.Combine(baseDirectory, "files"); + settings.GeneratedPath = Path.Combine(baseDirectory, "workspace", "generated"); + + // WorkspacePath는 SpecsPath의 상위 개념으로 설정 + settings.WorkspacePath = Path.GetDirectoryName(settings.SpecsPath) ?? baseDirectory; + } + + else + { + // [로컬 환경]: 프로젝트 루트 폴더 찾기 + baseDirectory = TryFindProjectRoot(Directory.GetCurrentDirectory()) ?? Directory.GetCurrentDirectory(); + } + + // 작업 공간 경로 설정 + string workspacePath = Path.Combine(baseDirectory, "workspace"); + + // 설정 객체에 값 주입 + settings.WorkspacePath = workspacePath; + settings.SpecsPath = Path.Combine(workspacePath, "inputs"); // 입력 파일 저장소 + settings.GeneratedPath = Path.Combine(workspacePath, "generated"); // 출력 파일 저장소 + settings.IsHttpMode = isHttp; + settings.IsContainer = isContainer; + settings.IsAzure = isAzure; + + // 디렉토리 생성 보장 + if (!Directory.Exists(settings.WorkspacePath)) Directory.CreateDirectory(settings.WorkspacePath); + if (!Directory.Exists(settings.SpecsPath)) Directory.CreateDirectory(settings.SpecsPath); + if (!Directory.Exists(settings.GeneratedPath)) Directory.CreateDirectory(settings.GeneratedPath); +} + +// 프로젝트 루트 탐색 헬퍼 메서드 +string? TryFindProjectRoot(string startPath) +{ + var dir = new DirectoryInfo(startPath); + while (dir != null) + { + // Dockerfile.ppt-font-fix 파일이 있는 곳을 루트로 간주 + if (dir.GetFiles("Dockerfile.ppt-font-fix").Length > 0) + { + return dir.FullName; + } + dir = dir.Parent; + } + return null; +} diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index d94cd442..3977c5b8 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -40,187 +40,59 @@ public string GetAnalysisPrompt( string actualFileName = safePath.Split('/').Last(); string containerInputPath = $"{ContainerInputPathBase}/{actualFileName}"; - return """ -You are the assistant responsible for guiding a complete end-to-end PowerPoint font fix workflow. -Follow the process below exactly and ask the user for any information you need. -Prefer the HTTP upload flow whenever it is available, so that the user can simply choose a local file and let the MCP server handle it. - -The PPT Font Fix MCP server supports: -- HTTP file upload via a `/upload` endpoint, which returns a `tempId` that can be used as `temp:{id}`. -- Opening PPT files from: - - `temp:{id}` (uploaded via `/upload`) - - HTTP/HTTPS URLs backed by Azure Blob Storage - - Local or container paths, including: - - `/app/...` - - `/app/mounts/...` (Azure File Share mount) - - `/files/...` - - `wwwroot/generated/...` - - OS temporary directory - -When saving the updated PPT file, the server: -1. Tries to save into an Azure File Share mounted at `/app/mounts`, under the `generated` folder: - - `/app/mounts/generated/` - - This corresponds to the `generated` folder inside the `ppt-files` File Share in the Storage Account. -2. If the File Share mount is not available, it falls back to `wwwroot/generated/`, - potentially returning an HTTP URL like `https:///generated/` in HTTP mode. -3. On pure local Windows, it can also save directly to a user-provided directory. - -Use this knowledge to guide the user. - ---- - -### STEP 0 — Determine how the server is running and how to provide the PPT file - -1. Ask the user: - **"How is the PPT Font Fix MCP server running? (Local HTTP / Docker HTTP / Azure HTTP / pure stdio local)"** - -2. Decide whether HTTP is available: - - - If the answer includes HTTP (for example: Local HTTP, Docker HTTP, Azure Container Apps, Azure Functions fronted by APIM, etc.), treat it as **HTTP-enabled**. - - If the answer is "pure stdio local" or equivalent, treat it as **non-HTTP**. - -3. If HTTP is available (RECOMMENDED FLOW): - - 1. Ask the user for the **base URL** of the MCP HTTP endpoint, for example: - - `http://localhost:PORT` (local/Docker) - - `https://` (Azure Container Apps — often exposed via `AZURE_RESOURCE_MCP_PPT_FONT_FIX_FQDN`) - - 2. Explain that the easiest way to send a PPTX from the user's local machine to the MCP server is to call the `/upload` endpoint. - - 3. Provide a concrete `curl` command, using their local PPTX path: - - - curl -X POST "[BASE_URL]/upload" -F "file=@\"[LOCAL_PPTX_PATH]\"" - - `[BASE_URL]` is the HTTP base URL they just provided. - - `[LOCAL_PPTX_PATH]` is the full path to their PPTX file on their machine. - - 4. Ask the user to run this command in their local terminal and wait for the response. - - 5. The server will respond with JSON similar to: - - - { "tempId": "xxxxxxxx" } - 6. Ask the user to paste the returned `tempId`. - - 7. Construct and remember the final input path as: - - - `INPUT_PATH = "temp:" + tempId` - -4. If HTTP is **not** available (pure stdio, no exposed HTTP endpoint): - - 1. Explain: - - > "The server has no HTTP upload endpoint. The PPTX file must be in a path that the server process can read directly (for example: a shared folder, a mounted volume, or a path inside the same machine/container)." - - 2. Ask the user for one of the following: - - - A file path that is directly visible to the server process - (for example, a shared directory or mounted network path), or - - A public HTTP/HTTPS URL from which the server can download the PPTX. - - 3. Store this as: - - - `INPUT_PATH = [user-provided path or URL]` - -5. Clearly confirm the chosen `INPUT_PATH` back to the user before calling tools. - ---- - -### STEP 1 — Analyze fonts in the PPT - -1. Call the `analyze_ppt_file` tool. - - - Use the `INPUT_PATH` decided in STEP 0 as the `filePath` argument. - - In HTTP scenarios this will typically be `temp:{tempId}`. - - In non-HTTP scenarios this may be a local path or URL. - -2. After receiving `PptFontAnalyzeResult`, summarize clearly for the user: - - - `UsedFonts` — the main fonts used in the presentation. - - `InconsistentlyUsedFonts` — fonts that are used in a scattered or inconsistent way. - - Whether there are any `UnusedFontLocations` (empty boxes or off-slide text). - -3. If `UnusedFontLocations` is non-empty, ask the user to make two decisions: - - 1. **Standard font choice** - - - Let the user choose a standard font from the `UsedFonts` list to use as the replacement font. - - 2. **Action mode** - - - **Fix & Clean** — replace inconsistent fonts and remove unused/off-slide shapes. - - **Fix Only** — replace fonts only, and leave all shapes in place. - ---- - -### STEP 2 — Update and save the PPT file - -1. Discuss how the updated file will be saved, based on the environment: - - - **Azure Container Apps (using this sample infra):** - - There is a File Share named `ppt-files` mounted at `/app/mounts`. - - The service saves into `/app/mounts/generated/`. - - The path returned by the tool will be a container-internal path like: - - `/app/mounts/generated/result_fixed_....pptx` - - Explain that this maps directly to the `generated` folder inside the `ppt-files` File Share. - - The user can retrieve the file from: - - Azure Storage Explorer, or - - SMB access to the `ppt-files` share. - - In this case, `outputDirectory` should usually be left empty (null) so the server uses its default File Share mount. - - - **Docker HTTP / Local HTTP without File Share:** - - The service may save into `wwwroot/generated/`. - - If the HTTP context is present, it may return a URL like: - - `http(s):///generated/` - - In this case, the user can simply click the URL to download the fixed PPT. - - - **Pure local Windows:** - - The server can save directly to a user-specified directory on the local machine, if that directory is accessible. - -2. Ask the user: - - - If the server is truly running on their local Windows machine: - - Ask for an optional output directory and store it as `outputDirectory`. - - If the server is running in Azure Container Apps (remote): - - Explain that saving will go to the mounted File Share, and `outputDirectory` can be null. - - If the server is running in Docker: - - Either rely on the internal default, or on a bind mount if they configured one. Do not invent a path; ask the user if they have a specific mount or host directory in mind. - -3. Call the `update_ppt_file` tool with: - - - `replacementFont` — the user-selected standard font. - - `inconsistentFontsToReplace` — the list of fonts to normalize. - - `locationsToRemove` — the list of locations to delete if the user selected **Fix & Clean**; otherwise an empty list. - - `newFileName` — for example: `"result_fixed_[ORIGINAL_FILE_NAME]"`. - - `outputDirectory` — the directory chosen above, or null/empty if using Azure File Share or default internal paths. - ---- - -### STEP 3 — Present the final result to the user - -1. Inspect the string returned by `update_ppt_file`. - -2. If it begins with `http`: - - - Present it as a clickable markdown link: - - `[Click here to download the fixed PPT file](URL)` - -3. If it is a local or container path (not starting with `http`): - - - If the server is running locally and the path is visible from the user's machine: - - Show the full path and instruct the user to open or copy the file directly. - - - If the server is running in Azure Container Apps with the File Share mount: - - Explain that the path is inside the container but backed by the `ppt-files` File Share. - - Tell the user they can open or download the file via: - - Azure Storage Explorer or - - SMB access to the `ppt-files` share. - - Do not assume or run any Azure CLI commands without explicit confirmation. - - - If the server is running in Docker: - - Clarify that the path is inside the container or a mounted volume. - - Tell the user that they can use their container tooling (for example `docker cp` or a bind-mounted directory) to retrieve the file, but do not execute or assume a specific command without their approval. -"""; + return $""" + The user wants to fix font issues in the PPT file located at **{hostFilePath}** using the **MCP-based PPT Font Fix Workflow**. + + ### 🎯 Workflow Objective + + 1. Start by using the **Open PPT File** tool to assess the environment (local vs. container access). + 2. If file access fails, guide the user with the necessary **file transfer/copy command** based on the error message. + 3. Once the file is ready, proceed to analyze and fix fonts using the **Analyze PPT File** tool. + 4. Clearly instruct the user on how to access the final resulting file. + + --- + + ### 🛠️ Step 1: Open PPT File (Initial Assessment) + + You must first call the `Open PPT File` tool with `{hostFilePath}`. The goal is to determine if the file is directly accessible (e.g., local host or public URL) or if a container environment requires a transfer. + + * **If local access is successful:** Proceed immediately to Step 2 (Analyze PPT File). + * **If file access fails:** Use the error message returned by the tool to guide the user: + + ### 🚧 Step 1.1: Handling File Access Failure + + 1. **If the message "COPY the file from your local machine path..." is returned (Volume Mounting Scenario):** + * You must suggest the following **local copy command** to the user: + `copy {hostFilePath} [VOLUME_MOUNT_PATH]` + + 2. **If the message "Please execute the appropriate command for your operating system (OS)..." is returned (URL Upload Scenario):** + * You must suggest the appropriate **OS-specific cURL upload command** to the user, using the `uploadUrl` provided in the message: + + ``` + ### 🍎/🐧 macOS & Linux (Example) + + curl -F "file=@{hostFilePath}" uploadUrl + + ### 💻 Windows (PowerShell/CMD Example) + + curl.exe -F "file=@{hostFilePath}" uploadUrl + ``` + + * **Upon successful upload:** You must be prepared to call the **`Analyze PPT File` tool** and pass the **`uploadUrl` as the `url` parameter** in the next step. + + ### ⚙️ Step 2: Analyze PPT File (Analysis and Fix) + + When calling the `Analyze PPT File` tool, handle the **save path** (`savePath`) based on user input: + + * **If the user did not specify a save path:** Leave the `savePath` **empty**. (If this causes an error in the tool, you may use `hostFilePath` as a temporary default path.) + * **If the user specified a desired save path:** Use that path as the `savePath`. + + ### ✅ Step 3: Result Handling and Guidance + + Based on the output returned by the `Analyze PPT File` tool, guide the user on how to access the result: + + * **If the return value starts with `http`:** Present it to the user as a **clickable link**. + * **If the return value is a local/container path:** Instruct the user on the **specific method** required to access the file (e.g., checking a file share, accessing a specific mounted volume). + """; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 828de69f..cab189e0 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -11,6 +11,7 @@ using System.IO; using System.Threading; using Azure.Storage.Sas; +using McpSamples.PptFontFix.HybridApp.Configurations; namespace McpSamples.PptFontFix.HybridApp.Services; @@ -19,21 +20,12 @@ namespace McpSamples.PptFontFix.HybridApp.Services; ///
public interface IPptFontFixService { - /// - /// Uploads a PPT file stream to a temporary location on the server and returns a temp ID. - /// The returned temp ID can be used later with the "temp:{id}" pattern in tools. - /// - /// The PPTX file stream. - /// Original file name (for logging only). - /// Cancellation token. - /// Temporary identifier for the uploaded file. - Task UploadPptFileAsync(Stream fileStream, string fileName, CancellationToken cancellationToken = default); - + /// /// open a Ppt file. /// /// - Task OpenPptFileAsync(string filePath); + Task OpenPptFileAsync(string filePath); /// /// Analyze fonts in a Ppt file. @@ -74,6 +66,7 @@ public class PptFontFixService : IPptFontFixService private readonly IHostEnvironment _hostEnvironment; private readonly IWebHostEnvironment? _webHostEnvironment; private readonly IHttpContextAccessor? _httpContextAccessor; + private readonly PptFontFixAppSettings _settings; private Presentation? _presentation; private readonly string? _fileShareMountPath; @@ -83,6 +76,7 @@ public PptFontFixService( ILogger logger, IConfiguration configuration, IHostEnvironment hostEnvironment, + PptFontFixAppSettings settings, IServiceProvider serviceProvider) { _logger = logger; @@ -91,62 +85,27 @@ public PptFontFixService( _webHostEnvironment = serviceProvider.GetService(); _httpContextAccessor = serviceProvider.GetService(); _fileShareMountPath = configuration["AZURE_FILE_SHARE_MOUNT_PATH"]; - - } - - private static string GetTempFilePath(string tempId) - { - // 업로드된 PPT 파일을 저장하는 서버 임시 경로 규칙 - return Path.Combine(Path.GetTempPath(), $"ppt_upload_{tempId}.tmp"); + _settings = settings; + } + private readonly string? _hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); - /// - public async Task UploadPptFileAsync(Stream fileStream, string fileName, CancellationToken cancellationToken = default) - { - var tempId = Guid.NewGuid().ToString("N"); - var tempPath = GetTempFilePath(tempId); - - _logger.LogInformation("Uploading PPT file: {FileName} -> {TempPath}", fileName, tempPath); - - using (var outputStream = File.Create(tempPath)) - { - await fileStream.CopyToAsync(outputStream, cancellationToken); - } - - return tempId; - } + /// - public async Task OpenPptFileAsync(string filePath) + public async Task OpenPptFileAsync(string filePath) { ArgumentException.ThrowIfNullOrWhiteSpace(filePath, nameof(filePath)); - // 0. temp:ID 패턴 처리 (업로드된 PPT 파일) - if (filePath.StartsWith("temp:", StringComparison.OrdinalIgnoreCase)) - { - var tempId = filePath.Substring(5); - var tempFilePath = GetTempFilePath(tempId); + _presentation?.Dispose(); + _presentation = null; + _analyzedVisibleFonts = null; - if (!File.Exists(tempFilePath)) - { - _logger.LogError("❌ Temp PPT file for ID '{TempId}' not found at {Path}", tempId, tempFilePath); - throw new FileNotFoundException($"The uploaded temporary PPT file for ID '{tempId}' was not found or has expired.", tempFilePath); - } - - try - { - _presentation?.Dispose(); - _presentation = new ShapeCrawler.Presentation(tempFilePath); - _analyzedVisibleFonts = null; - _logger.LogInformation("Ppt file opened successfully from temp upload: {Path}", tempFilePath); - await Task.CompletedTask; - return; - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to open PPT file from temp path: {Path}", tempFilePath); - throw; - } + if (Uri.TryCreate(filePath, UriKind.Absolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) + { + _logger.LogError("File path cannot be a URL. Must be a local or mounted path."); + return "[Error] File Access: Direct URL access is not supported. Please ensure the file is placed in the shared volume."; } var searchPaths = new List { filePath }; @@ -160,7 +119,6 @@ public async Task OpenPptFileAsync(string filePath) // (기존) WebRoot 및 Temp 경로 탐색 string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); searchPaths.Add(Path.Combine(baseDir, "generated", safeFileName)); - searchPaths.Add(Path.Combine(Path.GetTempPath(), safeFileName)); // (신규) File Share Mount Path를 기반으로 파일명으로 직접 접근 시도 if (!string.IsNullOrEmpty(_fileShareMountPath)) @@ -179,83 +137,88 @@ public async Task OpenPptFileAsync(string filePath) } } - // 2. 외부 파일 처리 및 마운트 경로로 복사 (가장 중요한 신규 로직) - if (foundPath == null && !Uri.TryCreate(filePath, UriKind.Absolute, out _) && !filePath.StartsWith("temp:", StringComparison.OrdinalIgnoreCase)) + if (foundPath == null) { - // 1) 찾지 못했고, URL이나 Temp ID도 아닐 경우, filePath 자체가 로컬 호스트 경로라고 가정하고 복사를 시도합니다. - - string targetBaseDir; - if (!string.IsNullOrEmpty(_fileShareMountPath)) + // 2-1. Azure Container Apps (Remote HTTP) 환경 (IsAzure 플래그 사용) + if (_settings.IsAzure && _settings.IsHttpMode) { - // File Share 마운트 경로를 사용합니다. - targetBaseDir = Path.Combine(_fileShareMountPath, "uploaded"); - } - else if (File.Exists("/files")) // Docker volume convention check - { - // Docker 볼륨 마운트 경로를 사용합니다. - targetBaseDir = "/files"; - } - else - { - // 최후의 수단으로 Web Root/generated를 사용하거나 예외를 발생시킵니다. - targetBaseDir = Path.Combine(baseDir, "uploaded"); - } + // [변경] Azure 환경에서는 curl 업로드 가이드 반환 + string uploadUrl = "/upload"; + var request = _httpContextAccessor?.HttpContext?.Request; + if (request != null) + { + uploadUrl = $"{request.Scheme}://{request.Host}/upload"; + } + + return $""" + ⚠️ Action Required: File Upload Needed (Azure Remote) - if (!Directory.Exists(targetBaseDir)) - { - Directory.CreateDirectory(targetBaseDir); - } + I am running in an Azure environment and cannot access your local file `{filePath}` directly. + To proceed, you need to upload the file to the server. - string tempCopyPath = Path.Combine(targetBaseDir, safeFileName); - - try - { - _logger.LogInformation("Attempting to copy file from outside mount ({Source}) to inside mount ({Target})", filePath, tempCopyPath); - // 호스트 경로에 있는 파일을 컨테이너 내부의 마운트 경로로 복사 시도 - // 이는 호스트가 컨테이너의 마운트 디렉토리를 공유하고 있어야 성공합니다. - File.Copy(filePath, tempCopyPath, overwrite: true); - foundPath = tempCopyPath; - _logger.LogInformation("✅ File successfully copied to mount path: {Path}", foundPath); - } - catch (FileNotFoundException) - { - _logger.LogError("❌ File not found at the original path: {Path}. Searched in: {Paths}", filePath, string.Join(", ", searchPaths)); - throw new FileNotFoundException($"Ppt file not found at the original path and could not be copied into the container.", filePath); + Please execute the appropriate command for your operating system (OS) using your terminal or shell tool: + + ### 🍎/🐧 macOS & Linux (Example) + + curl -F "file=@{filePath}" {uploadUrl} + + ### 💻 Windows (PowerShell/CMD Example) + + curl.exe -F "file=@{filePath}" {uploadUrl} + + After the command completes successfully, please call the `open_ppt_file` tool again with the path returned by the upload. + """; } - catch (Exception ex) + // 2-2. Docker Container (Stdio/HTTP Local) 환경 (IsContainer 플래그 사용) + else if (_settings.IsContainer) { - _logger.LogError(ex, "❌ Failed to copy file from outside mount to inside mount."); - throw new IOException($"Failed to access or copy file from host path '{filePath}' into the container volume.", ex); + // [변경] Docker 환경에서는 볼륨 복사(cp) 가이드 반환 + string targetContainerPath = Path.Combine(_settings.SpecsPath, safeFileName); + string targetHostPath = targetContainerPath; + string? hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); + + + if (!string.IsNullOrEmpty(_hostRootPath)) + { + + string normalizedHostRoot = _hostRootPath.Replace('\\', '/').TrimEnd('/'); + + targetHostPath = $"{normalizedHostRoot}/ppt-font-fix/workspace/{safeFileName}"; + } + + return $""" + ⚠️ Action Required: File Synchronization Needed (Docker Container) + + The file '{safeFileName}' (Original path: `{filePath}`) is not currently in the shared volume visible to the container. + To proceed, I need access to this file. + + EXECUTION PLAN (Follow Strictly): + 1. COPY the file from your local machine path (`{filePath}`) + to the host directory mapped to the container volume. + The recommended target path is: `{targetHostPath}` + 2. RETRY the `open_ppt_file` tool immediately with the original file path (`{filePath}`). + """; } - } - else if (foundPath == null) - { + // 2-3. 로컬 환경 또는 기타 오류 + _logger.LogError("❌ File not found. Searched in: {Paths}", string.Join(", ", searchPaths)); - throw new FileNotFoundException($"Ppt file not found. File must be accessible at the host path OR successfully copied to the container volume.", filePath); + // [변경] 원본 코드의 복사 시도/throw 대신 에러 메시지 반환 + return $"[Error] File Not Found: The file '{filePath}' was not found. Please ensure the path is correct and accessible."; } // 3. 파일 열기 (foundPath 사용) try { _presentation?.Dispose(); - // 파일을 메모리 스트림으로 읽어와서 ShapeCrawler에 전달하는 방식이 - // 파일 잠금 문제를 피하고 컨테이너 환경에서 안정적입니다. - using (var fs = new FileStream(foundPath, FileMode.Open, FileAccess.Read)) - { - var memoryStream = new MemoryStream(); - await fs.CopyToAsync(memoryStream); - memoryStream.Position = 0; - _presentation = new ShapeCrawler.Presentation(memoryStream); // ShapeCrawler 생성자에 Stream 전달 - } - - _analyzedVisibleFonts = null; + _presentation = new ShapeCrawler.Presentation(foundPath); + _analyzedVisibleFonts = null; _logger.LogInformation("Ppt file opened successfully: {FilePath}", foundPath); - await Task.CompletedTask; + return "✅ Ppt file opened successfully and ready for analysis."; } catch (Exception ex) { - _logger.LogError(ex, "Failed to open Ppt file."); - throw; + _logger.LogError(ex, "Failed to open Ppt file from path: {Path}", foundPath); + return $"[Error] Failed to open Ppt file: {ex.Message}"; } } @@ -417,13 +380,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu baseDirectory = Path.Combine(_fileShareMountPath, "generated"); _logger.LogInformation("Base Path: Azure File Share Mount -> {Path}", baseDirectory); } - // else if (isHttpMode) - // { - // // [HTTP Service Mode]: /files 마운트가 없거나 HTTP 서비스로 실행 중일 때 Web Root 사용 - // string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - // baseDirectory = Path.Combine(webRoot, "generated"); - // _logger.LogInformation("Base Path: HTTP Web Root -> {Path}", baseDirectory); - // } else if (Directory.Exists("/files")) { // [Stdio Container Mode]: HTTP 요청이 없고, /files 볼륨이 마운트되어 있을 때 사용 @@ -482,10 +438,10 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu } // Docker/Linux 환경에서 권한 설정 - if (string.IsNullOrEmpty(this._fileShareMountPath)) - { - File.SetUnixFileMode(finalPhysicalPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); - } + if (!OperatingSystem.IsWindows() && string.IsNullOrEmpty(this._fileShareMountPath)) + { + File.SetUnixFileMode(finalPhysicalPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); + } _logger.LogInformation("✅ File successfully saved to mount/web path: {Path}", finalPhysicalPath); } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index 5cbe190c..49a97cd5 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -15,12 +15,18 @@ namespace McpSamples.PptFontFix.HybridApp.Tools; public interface IPptFontFixTool { + ////// + /// Opens the specified PPT file and loads it into memory for subsequent analysis. + /// + /// The path to the PPT file. + /// A string message indicating success or an action required instruction for the LLM. + Task OpenPptFileAsync(string filePath); // 🚨 신규 Tool 추가 + /// - /// Opens and analyzes fonts in a specified PPT file. + /// Analyzes fonts in the file currently loaded in memory. /// - /// The path to be analyzed. /// Returns instance. - Task AnalyzePptFileAsync(string filePath); + Task AnalyzeFontsAsync(); // 🚨 기존 AnalyzePptFileAsync를 AnalyzeFontsAsync로 변경 /// /// Updates the PPT file by removing unused fonts, replacing inconsistent fonts, and saving to a new path. @@ -42,17 +48,34 @@ public interface IPptFontFixTool [McpServerToolType] public class PptFontFixTool(IPptFontFixService service, ILogger logger) : IPptFontFixTool { - /// - [McpServerTool(Name = "analyze_ppt_file", Title = "Analyze PPT File Fonts")] - [Description("Opens a Ppt file AND analyzes fonts used, identifies inconsistencies.")] - public async Task AnalyzePptFileAsync( + // 🚨 신규 Tool: open_ppt_file 구현 + [McpServerTool(Name = "open_ppt_file", Title = "Open PPT File")] + [Description("Opens a Ppt file and loads it into memory. Returns action instructions if the file cannot be accessed.")] + public async Task OpenPptFileAsync( [Description("The path of the Ppt file to open and analyze")] string filePath) { - try + // Service의 OpenPptFileAsync를 호출합니다. (이 메서드는 string?을 반환하도록 수정되었음) + string? actionRequiredMessage = await service.OpenPptFileAsync(filePath).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(actionRequiredMessage)) { - await service.OpenPptFileAsync(filePath).ConfigureAwait(false); - logger.LogInformation("Ppt file opened successfully: {FilePath}", filePath); + // Service가 string 메시지를 반환했으므로, 예외 없이 바로 반환합니다. + return actionRequiredMessage; + } + + // 성공 시: + logger.LogInformation("Ppt file opened successfully: {FilePath}", filePath); + return $"PPT file '{filePath}' successfully loaded into memory. You can now call the analyze_fonts tool."; + } + + /// + [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts")] + [Description("Analyzes fonts used in the PPT file currently loaded in memory, identifying inconsistencies.")] + public async Task AnalyzeFontsAsync() // 🚨 Tool 이름 변경 + { + try + { PptFontAnalyzeResult result = await service.AnalyzeFontsAsync().ConfigureAwait(false); if (result != null) { @@ -66,9 +89,15 @@ public async Task AnalyzePptFileAsync( return new PptFontAnalyzeResult(); } } + catch (InvalidOperationException ex) + { + // PPT 파일이 로드되지 않았을 때 (AnalyzeFontsAsync 내부에서 InvalidOperationException을 던질 경우) + logger.LogError(ex, "Analysis failed because the PPT file was not loaded."); + throw; + } catch (Exception ex) { - logger.LogError(ex, "Failed during Ppt file analysis process for: {FilePath}", filePath); + logger.LogError(ex, "Failed during font analysis process."); throw; } } From 1487b3756b8ec79406a3e2eaf9d477033d4fd70b Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Thu, 4 Dec 2025 21:53:59 +0900 Subject: [PATCH 34/42] =?UTF-8?q?docker=EA=B9=8C=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/PPTFontFixService.cs | 70 ++++++++---------- .../wwwroot/generated/outtest_fixed.pptx | Bin 0 -> 38406 bytes ppt-font-fix/workspace/outtest.pptx | Bin 0 -> 40943 bytes ppt-font-fix/workspace/outtest_fixed.pptx | Bin 0 -> 38032 bytes 4 files changed, 31 insertions(+), 39 deletions(-) create mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/wwwroot/generated/outtest_fixed.pptx create mode 100644 ppt-font-fix/workspace/outtest.pptx create mode 100644 ppt-font-fix/workspace/outtest_fixed.pptx diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index cab189e0..dded4646 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -367,49 +367,41 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu string finalPhysicalPath = ""; string baseDirectory; + string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); + string webGeneratedDir = Path.Combine(webRoot, "generated"); // 웹 서비스 경로 bool isContainerEnv = !OperatingSystem.IsWindows() || !string.IsNullOrEmpty(_fileShareMountPath); bool isHttpMode = _httpContextAccessor?.HttpContext?.Request != null; - if (isContainerEnv) - { - // 1. 저장 기본 경로 결정 (마운트 볼륨 또는 웹 루트) - if (!string.IsNullOrEmpty(_fileShareMountPath)) - { - // Azure File Share Mount Path를 사용합니다. (예: /app/mounts/generated) - baseDirectory = Path.Combine(_fileShareMountPath, "generated"); - _logger.LogInformation("Base Path: Azure File Share Mount -> {Path}", baseDirectory); - } - else if (Directory.Exists("/files")) - { - // [Stdio Container Mode]: HTTP 요청이 없고, /files 볼륨이 마운트되어 있을 때 사용 - baseDirectory = "/files"; // 👈 Stdio 출력 경로 - _logger.LogInformation("Base Path: Stdio Container Volume Mount (/files) -> {Path}", baseDirectory); - } - else - { - // File Share가 없거나 마운트 실패 시, 로컬 웹 루트를 사용합니다. - string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - baseDirectory = Path.Combine(webRoot, "generated"); - _logger.LogInformation("Base Path: Local/Docker Web Root -> {Path}", baseDirectory); - } - } - else - { - if (!string.IsNullOrEmpty(outputDirectory) && Directory.Exists(outputDirectory)) - { - // 2-1. Stdio/로컬 환경: 사용자가 지정한 outputDirectory 사용 (요청 반영) - baseDirectory = outputDirectory; - _logger.LogInformation("Base Path: Local User Specified -> {Path}", baseDirectory); - } - else - { - // 2-2. Fallback: 로컬 환경이지만 outputDirectory가 없으면 Web Root 사용 - string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - baseDirectory = Path.Combine(webRoot, "generated"); - _logger.LogInformation("Base Path: Local Web Root Fallback -> {Path}", baseDirectory); - } - } + + if (isHttpMode) +{ + // 💡 HTTP 환경에서는 마운트 경로를 무시하고 웹 서비스 경로만 사용합니다. + baseDirectory = webGeneratedDir; + _logger.LogInformation("Base Path: HTTP Mode detected. Using Web Root -> {Path}", baseDirectory); +} +// 2. HTTP 모드가 아닐 때 (Stdio/Local/마운트 볼륨 모드) +else +{ + if (!string.IsNullOrEmpty(_fileShareMountPath)) + { + // Azure File Share Mount Path를 사용합니다. + baseDirectory = Path.Combine(_fileShareMountPath, "generated"); + _logger.LogInformation("Base Path: File Share Mount (Non-HTTP) -> {Path}", baseDirectory); + } + else if (Directory.Exists("/files")) + { + // Stdio Container Volume Mount (/files)를 사용합니다. + baseDirectory = "/files"; + _logger.LogInformation("Base Path: Stdio Volume Mount (/files) -> {Path}", baseDirectory); + } + else + { + // Fallback으로 웹 루트 경로를 사용합니다. + baseDirectory = webGeneratedDir; + _logger.LogInformation("Base Path: Local/Fallback Web Root -> {Path}", baseDirectory); + } +} // 2. 디렉토리 확인 및 생성 if (!Directory.Exists(baseDirectory)) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/wwwroot/generated/outtest_fixed.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/wwwroot/generated/outtest_fixed.pptx new file mode 100644 index 0000000000000000000000000000000000000000..b15389a443ad92085b3c83e444b8523300ec3823 GIT binary patch literal 38406 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 P;9o3Yx1k&QHV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 literal 0 HcmV?d00001 diff --git a/ppt-font-fix/workspace/outtest_fixed.pptx b/ppt-font-fix/workspace/outtest_fixed.pptx new file mode 100644 index 0000000000000000000000000000000000000000..12896d7e6efa92fa47330e3f87eecde4f56842f5 GIT binary patch literal 38032 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 literal 0 HcmV?d00001 From b4cbc7797adbd4b9f53856255793ec274697fceb Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Thu, 4 Dec 2025 21:57:35 +0900 Subject: [PATCH 35/42] final --- Dockerfile.ppt-font-fix | 4 ++-- .../test_result.pptx | Bin 38032 -> 0 bytes .../wwwroot/generated/outtest_fixed.pptx | Bin 38406 -> 0 bytes ppt-font-fix/workspace/outtest.pptx | Bin 40943 -> 0 bytes ppt-font-fix/workspace/outtest_fixed.pptx | Bin 38032 -> 0 bytes 5 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx delete mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/wwwroot/generated/outtest_fixed.pptx delete mode 100644 ppt-font-fix/workspace/outtest.pptx delete mode 100644 ppt-font-fix/workspace/outtest_fixed.pptx diff --git a/Dockerfile.ppt-font-fix b/Dockerfile.ppt-font-fix index a7d41ef4..b963a56e 100644 --- a/Dockerfile.ppt-font-fix +++ b/Dockerfile.ppt-font-fix @@ -21,8 +21,8 @@ WORKDIR /app COPY --from=build /app . -RUN mkdir -p /app/wwwroot/generated /files /app/workspace\ - && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /files /app/workspace \ +RUN mkdir -p /app/wwwroot/generated /app/workspace\ + && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /app/workspace \ && chmod 755 /app/wwwroot/generated USER $APP_UID diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test_result.pptx deleted file mode 100644 index e4fb0f723be19188d576297b5beab74ba6acf14a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38032 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 L&SF__Efbi&cO*${UT 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 P;9o3Yx1k&QHV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 diff --git a/ppt-font-fix/workspace/outtest_fixed.pptx b/ppt-font-fix/workspace/outtest_fixed.pptx deleted file mode 100644 index 12896d7e6efa92fa47330e3f87eecde4f56842f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38032 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 From 2aab52d5994bcfabc8dba992498368479f0a65af Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sat, 6 Dec 2025 20:06:45 +0900 Subject: [PATCH 36/42] fix prompt 1 --- .vscode/mcp.json | 23 +++--- .../McpSamples.PptFontFix.HybridApp.csproj | 2 +- .../Prompts/PptFontFixPrompt.cs | 82 +++++-------------- .../Services/PPTFontFixService.cs | 73 ++++++++++------- 4 files changed, 77 insertions(+), 103 deletions(-) diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 497a479e..f48b134a 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,15 +1,16 @@ -{ - "inputs": [ - { - "type": "promptString", - "id": "acaapp-server-fqdn", - "description": "Azure Container Apps FQDN" - } - ], +{ "servers": { "ppt-font-fix": { - "type": "http", - "url": "https://${input:acaapp-server-fqdn}/mcp" + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-v", "${workspaceFolder}\\ppt-font-fix\\workspace:/files", + "-e", "HOST_ROOT_PATH=${workspaceFolder}\\ppt-font-fix", + "ppt-font-fix:latest" + ] } } -} +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj index 9423a894..87c917a2 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/McpSamples.PptFontFix.HybridApp.csproj @@ -11,7 +11,7 @@ - + diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 3977c5b8..3723ab89 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -25,74 +25,34 @@ public interface IPptFontFixPrompt [McpServerPromptType] public class PptFontFixPrompt : IPptFontFixPrompt { - private const string ContainerName = "ppt-font-fix"; - private const string ContainerInputPathBase = "/files"; - private const string AzureDefaultContainer = "generated-files"; - private const string AzureFileShareName = "ppt-files"; - + /// [McpServerPrompt(Name = "fix_ppt_fonts", Title = "Start PPT Font Fix Workflow")] [Description("Generate a structured workflow prompt for analyzing and fixing PPT fonts.")] public string GetAnalysisPrompt( [Description("The full path to the PPTX file or a public URL.")] string hostFilePath) { - string safePath = hostFilePath.Replace('\\', '/'); - string actualFileName = safePath.Split('/').Last(); - string containerInputPath = $"{ContainerInputPathBase}/{actualFileName}"; - return $""" - The user wants to fix font issues in the PPT file located at **{hostFilePath}** using the **MCP-based PPT Font Fix Workflow**. - - ### 🎯 Workflow Objective - - 1. Start by using the **Open PPT File** tool to assess the environment (local vs. container access). - 2. If file access fails, guide the user with the necessary **file transfer/copy command** based on the error message. - 3. Once the file is ready, proceed to analyze and fix fonts using the **Analyze PPT File** tool. - 4. Clearly instruct the user on how to access the final resulting file. - - --- - - ### 🛠️ Step 1: Open PPT File (Initial Assessment) - - You must first call the `Open PPT File` tool with `{hostFilePath}`. The goal is to determine if the file is directly accessible (e.g., local host or public URL) or if a container environment requires a transfer. - - * **If local access is successful:** Proceed immediately to Step 2 (Analyze PPT File). - * **If file access fails:** Use the error message returned by the tool to guide the user: - - ### 🚧 Step 1.1: Handling File Access Failure - - 1. **If the message "COPY the file from your local machine path..." is returned (Volume Mounting Scenario):** - * You must suggest the following **local copy command** to the user: - `copy {hostFilePath} [VOLUME_MOUNT_PATH]` - - 2. **If the message "Please execute the appropriate command for your operating system (OS)..." is returned (URL Upload Scenario):** - * You must suggest the appropriate **OS-specific cURL upload command** to the user, using the `uploadUrl` provided in the message: - - ``` - ### 🍎/🐧 macOS & Linux (Example) - - curl -F "file=@{hostFilePath}" uploadUrl - - ### 💻 Windows (PowerShell/CMD Example) - - curl.exe -F "file=@{hostFilePath}" uploadUrl - ``` - - * **Upon successful upload:** You must be prepared to call the **`Analyze PPT File` tool** and pass the **`uploadUrl` as the `url` parameter** in the next step. - - ### ⚙️ Step 2: Analyze PPT File (Analysis and Fix) - - When calling the `Analyze PPT File` tool, handle the **save path** (`savePath`) based on user input: - - * **If the user did not specify a save path:** Leave the `savePath` **empty**. (If this causes an error in the tool, you may use `hostFilePath` as a temporary default path.) - * **If the user specified a desired save path:** Use that path as the `savePath`. - - ### ✅ Step 3: Result Handling and Guidance - - Based on the output returned by the `Analyze PPT File` tool, guide the user on how to access the result: - - * **If the return value starts with `http`:** Present it to the user as a **clickable link**. - * **If the return value is a local/container path:** Instruct the user on the **specific method** required to access the file (e.g., checking a file share, accessing a specific mounted volume). + You are a professional PPT Font Fix helper. + Your task is to open a PPT File, perform font analysis, modification, and storage based on this input (File Path : '{hostFilePath}'. + + ### Order of execution + 1. Use the 'open_ppt_file' tool to verify that the file exists in FilePath. If the file opens without any problems, proceed to the next step. + - If not, use the file system tool to move the file in the File Path that you suggested to a specific path based on the result value returned by the tool. + 2. If the file is opened normally, please analyze the usage status of the font in the PPT file through 'analyze_font' and show the following results. + - List of used fonts + - List of inconsistent used fons + 3. If an item exists in the unused fon: + - Ask the user for two answers. + A. **Choose a Standard Font** (from UsedFonts) + B. **Choose an Action Mode:**: + 3-1. Fix & Clean — Replace fonts and remove unused text boxes + 3-2. Fix Only — Replace fonts only + 4. Ask the user if there is a path they want to save. + - If the user did not answer the desired path: Save it as the default path if the file was opened immediately without any problems in No. 1, and specify the outputDirectory as null if you moved the file in the path you suggested. + ** If the returned path starts with '/files/', the file is stored within the mounted path. If the user has responded to the desired path, this requires a file system tool to copy it from the mounted folder to the file path between the local and the container. If not, it should be notified that it is stored in the mounted folder. (Exists inside workspace) + 5. Report + Provides the download link or file path that the Tool returns. """; } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index dded4646..5474e739 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -183,7 +183,7 @@ I am running in an Azure environment and cannot access your local file `{filePat string normalizedHostRoot = _hostRootPath.Replace('\\', '/').TrimEnd('/'); - targetHostPath = $"{normalizedHostRoot}/ppt-font-fix/workspace/{safeFileName}"; + targetHostPath = $"{normalizedHostRoot}/workspace/{safeFileName}"; } return $""" @@ -373,35 +373,41 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu bool isContainerEnv = !OperatingSystem.IsWindows() || !string.IsNullOrEmpty(_fileShareMountPath); bool isHttpMode = _httpContextAccessor?.HttpContext?.Request != null; - - if (isHttpMode) -{ - // 💡 HTTP 환경에서는 마운트 경로를 무시하고 웹 서비스 경로만 사용합니다. - baseDirectory = webGeneratedDir; - _logger.LogInformation("Base Path: HTTP Mode detected. Using Web Root -> {Path}", baseDirectory); -} -// 2. HTTP 모드가 아닐 때 (Stdio/Local/마운트 볼륨 모드) -else -{ - if (!string.IsNullOrEmpty(_fileShareMountPath)) - { - // Azure File Share Mount Path를 사용합니다. - baseDirectory = Path.Combine(_fileShareMountPath, "generated"); - _logger.LogInformation("Base Path: File Share Mount (Non-HTTP) -> {Path}", baseDirectory); - } - else if (Directory.Exists("/files")) - { - // Stdio Container Volume Mount (/files)를 사용합니다. - baseDirectory = "/files"; - _logger.LogInformation("Base Path: Stdio Volume Mount (/files) -> {Path}", baseDirectory); - } - else - { - // Fallback으로 웹 루트 경로를 사용합니다. - baseDirectory = webGeneratedDir; - _logger.LogInformation("Base Path: Local/Fallback Web Root -> {Path}", baseDirectory); - } -} + if (!string.IsNullOrEmpty(outputDirectory) && !isContainerEnv) + { + baseDirectory = outputDirectory; + _logger.LogInformation("Base Path: User Provided Output Directory -> {Path}", baseDirectory); + } + else + { + if (isHttpMode) + { + // 💡 HTTP 환경에서는 마운트 경로를 무시하고 웹 서비스 경로만 사용합니다. + baseDirectory = webGeneratedDir; + _logger.LogInformation("Base Path: HTTP Mode detected. Using Web Root -> {Path}", baseDirectory); + } + else + { + if (!string.IsNullOrEmpty(_fileShareMountPath)) + { + // Azure File Share Mount Path를 사용합니다. + baseDirectory = Path.Combine(_fileShareMountPath, "generated"); + _logger.LogInformation("Base Path: File Share Mount (Non-HTTP) -> {Path}", baseDirectory); + } + else if (Directory.Exists("/files")) + { + // Stdio Container Volume Mount (/files)를 사용합니다. + baseDirectory = "/files"; + _logger.LogInformation("Base Path: Stdio Volume Mount (/files) -> {Path}", baseDirectory); + } + else + { + // 로컬 환경에서는 웹 루트의 generated 폴더를 사용합니다. + baseDirectory = webGeneratedDir; + _logger.LogInformation("Base Path: Local Environment Web Root -> {Path}", baseDirectory); + } + } + } // 2. 디렉토리 확인 및 생성 if (!Directory.Exists(baseDirectory)) @@ -446,7 +452,14 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu // 4. 최종 반환: HTTP Context가 있다면 웹 URL을, 없다면 물리적 경로를 반환 if (_httpContextAccessor?.HttpContext?.Request != null) { + if (!string.IsNullOrEmpty(outputDirectory) && !finalPhysicalPath.StartsWith(webRoot, StringComparison.OrdinalIgnoreCase)) + { + // 사용자 지정 경로가 웹으로 접근 불가능할 경우 물리적 경로 반환 + _logger.LogWarning("User-specified path is outside of WebRoot. Returning Physical Path: {Path}", finalPhysicalPath); + return finalPhysicalPath; + } // 모든 파일이 'generated' 폴더 아래에 저장되었으므로, 웹 URL 경로는 /generated/{filename}으로 통일 + string relativePath = Path.GetRelativePath(webRoot, finalPhysicalPath).Replace('\\', '/'); var request = _httpContextAccessor.HttpContext.Request; string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; _logger.LogInformation("✅ Returning Web URL: {Url}", url); From a88a5fc8e9a5c5e2f41aa293011fdbd8aa2cc49e Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sat, 6 Dec 2025 21:16:41 +0900 Subject: [PATCH 37/42] fix some prompt --- .../Prompts/PptFontFixPrompt.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 3723ab89..6ec286f9 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -39,6 +39,7 @@ You are a professional PPT Font Fix helper. ### Order of execution 1. Use the 'open_ppt_file' tool to verify that the file exists in FilePath. If the file opens without any problems, proceed to the next step. - If not, use the file system tool to move the file in the File Path that you suggested to a specific path based on the result value returned by the tool. + - If Tool returns 'curl' command, use the file system tool to download the file from the public URL to the specific path. 2. If the file is opened normally, please analyze the usage status of the font in the PPT file through 'analyze_font' and show the following results. - List of used fonts - List of inconsistent used fons @@ -46,8 +47,8 @@ You are a professional PPT Font Fix helper. - Ask the user for two answers. A. **Choose a Standard Font** (from UsedFonts) B. **Choose an Action Mode:**: - 3-1. Fix & Clean — Replace fonts and remove unused text boxes - 3-2. Fix Only — Replace fonts only + 1. Fix & Clean — Replace fonts and remove unused text boxes + 2. Fix Only — Replace fonts only 4. Ask the user if there is a path they want to save. - If the user did not answer the desired path: Save it as the default path if the file was opened immediately without any problems in No. 1, and specify the outputDirectory as null if you moved the file in the path you suggested. ** If the returned path starts with '/files/', the file is stored within the mounted path. If the user has responded to the desired path, this requires a file system tool to copy it from the mounted folder to the file path between the local and the container. If not, it should be notified that it is stored in the mounted folder. (Exists inside workspace) From c16aa4dd739593cef50a571e0e3ea31f4e1db6b0 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 8 Dec 2025 04:48:53 +0900 Subject: [PATCH 38/42] save in workspace/generated --- .vscode/mcp.json | 12 +---- Dockerfile.ppt-font-fix | 8 ++-- ppt-font-fix/.vscode/mcp.stdio.container.json | 12 +++-- ppt-font-fix/.vscode/mcp.stdio.local.json | 5 +-- .../Configurations/PPTFontFixAppSettings.cs | 4 +- .../Program.cs | 44 ++++++++++--------- .../Prompts/PptFontFixPrompt.cs | 6 ++- .../Services/PPTFontFixService.cs | 11 +++-- 8 files changed, 52 insertions(+), 50 deletions(-) diff --git a/.vscode/mcp.json b/.vscode/mcp.json index f48b134a..921e3dad 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,16 +1,8 @@ { "servers": { "ppt-font-fix": { - "type": "stdio", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-v", "${workspaceFolder}\\ppt-font-fix\\workspace:/files", - "-e", "HOST_ROOT_PATH=${workspaceFolder}\\ppt-font-fix", - "ppt-font-fix:latest" - ] + "type": "http", + "url": "http://localhost:8080/mcp" } } } \ No newline at end of file diff --git a/Dockerfile.ppt-font-fix b/Dockerfile.ppt-font-fix index b963a56e..23208641 100644 --- a/Dockerfile.ppt-font-fix +++ b/Dockerfile.ppt-font-fix @@ -21,9 +21,11 @@ WORKDIR /app COPY --from=build /app . -RUN mkdir -p /app/wwwroot/generated /app/workspace\ - && chown -R $APP_UID:$APP_UID /app/wwwroot/generated /app/workspace \ - && chmod 755 /app/wwwroot/generated +RUN mkdir -p /app/wwwroot/generated /app/workspace && \ + mkdir -p /files/input && \ + mkdir -p /files/output && \ + chown -R $APP_UID:$APP_UID /app/wwwroot/generated /app/workspace && \ + chmod 755 /app/wwwroot/generated USER $APP_UID diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index f48b134a..7b6d76fb 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -1,4 +1,11 @@ -{ +{ + "inputs": [ + { + "type": "promptString", + "id": "your-ppt-file-path", + "description": "The absolute path where the PPT file you want to modify is located" + } + ], "servers": { "ppt-font-fix": { "type": "stdio", @@ -7,8 +14,7 @@ "run", "-i", "--rm", - "-v", "${workspaceFolder}\\ppt-font-fix\\workspace:/files", - "-e", "HOST_ROOT_PATH=${workspaceFolder}\\ppt-font-fix", + "-v", "${input:your-ppt-file-path}:/files", "ppt-font-fix:latest" ] } diff --git a/ppt-font-fix/.vscode/mcp.stdio.local.json b/ppt-font-fix/.vscode/mcp.stdio.local.json index 8b05f824..98daeec1 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.local.json +++ b/ppt-font-fix/.vscode/mcp.stdio.local.json @@ -13,10 +13,7 @@ "args": [ "run", "--project", - "${input:consoleapp-project-path}", - "--", - "-tc", - "-p" + "${input:consoleapp-project-path}" ] } } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs index 47c9dadd..fce56428 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -28,9 +28,9 @@ public class PptFontFixAppSettings : AppSettings public string GeneratedPath { get; set; } = string.Empty; ///

- /// The path for specs files. + /// The path for input files. /// - public string SpecsPath { get; set; } = string.Empty; + public string InputPath { get; set; } = string.Empty; /// /// Indicates whether the application is running in HTTP mode. diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 0d3f0b9e..73c83a46 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -57,14 +57,14 @@ return Results.BadRequest(new { error = "No file uploaded." }); } - // 2. 입력 파일 저장소 (SpecsPath) 확인 및 생성 + // 2. 입력 파일 저장소 (InputPath) 확인 및 생성 var appSettings = webApp.Services.GetRequiredService(); // AppSettings 주입 - if (!Directory.Exists(appSettings.SpecsPath)) - Directory.CreateDirectory(appSettings.SpecsPath); + if (!Directory.Exists(appSettings.InputPath)) + Directory.CreateDirectory(appSettings.InputPath); // 3. 파일명 추출 및 최종 경로 설정 var fileName = Path.GetFileName(file.FileName); - var filePath = Path.Combine(appSettings.SpecsPath, fileName); + var filePath = Path.Combine(appSettings.InputPath, fileName); try { @@ -99,36 +99,40 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) string baseDirectory; - if (isContainer) + if (isAzure) { - baseDirectory = "/app"; - settings.SpecsPath = Path.Combine(baseDirectory, "files"); - settings.GeneratedPath = Path.Combine(baseDirectory, "workspace", "generated"); + //baseDirectory = "/app"; + baseDirectory = "/workspace"; + settings.InputPath = Path.Combine(baseDirectory); + settings.GeneratedPath = Path.Combine(baseDirectory,"generated"); + settings.WorkspacePath = Path.GetDirectoryName(settings.InputPath) ?? baseDirectory; + } + else if (isContainer) + { + baseDirectory = "/files"; + settings.InputPath = Path.Combine(baseDirectory, "input"); + settings.GeneratedPath = Path.Combine(baseDirectory, "generated"); - // WorkspacePath는 SpecsPath의 상위 개념으로 설정 - settings.WorkspacePath = Path.GetDirectoryName(settings.SpecsPath) ?? baseDirectory; + // WorkspacePath는 InputPath의 상위 개념으로 설정 + settings.WorkspacePath = Path.GetDirectoryName(settings.InputPath) ?? baseDirectory; } - else { // [로컬 환경]: 프로젝트 루트 폴더 찾기 baseDirectory = TryFindProjectRoot(Directory.GetCurrentDirectory()) ?? Directory.GetCurrentDirectory(); + string workspacePath = Path.Combine(baseDirectory, "workspace"); + settings.WorkspacePath = workspacePath; + settings.InputPath = Path.Combine(workspacePath, "input"); // 입력 파일 저장소 + settings.GeneratedPath = Path.Combine(workspacePath, "generated"); // 출력 파일 저장소 } - - // 작업 공간 경로 설정 - string workspacePath = Path.Combine(baseDirectory, "workspace"); - // 설정 객체에 값 주입 - settings.WorkspacePath = workspacePath; - settings.SpecsPath = Path.Combine(workspacePath, "inputs"); // 입력 파일 저장소 - settings.GeneratedPath = Path.Combine(workspacePath, "generated"); // 출력 파일 저장소 settings.IsHttpMode = isHttp; settings.IsContainer = isContainer; settings.IsAzure = isAzure; // 디렉토리 생성 보장 if (!Directory.Exists(settings.WorkspacePath)) Directory.CreateDirectory(settings.WorkspacePath); - if (!Directory.Exists(settings.SpecsPath)) Directory.CreateDirectory(settings.SpecsPath); + if (!Directory.Exists(settings.InputPath)) Directory.CreateDirectory(settings.InputPath); if (!Directory.Exists(settings.GeneratedPath)) Directory.CreateDirectory(settings.GeneratedPath); } @@ -141,7 +145,7 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) // Dockerfile.ppt-font-fix 파일이 있는 곳을 루트로 간주 if (dir.GetFiles("Dockerfile.ppt-font-fix").Length > 0) { - return dir.FullName; + return Path.Combine(dir.FullName, "ppt-font-fix"); } dir = dir.Parent; } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 6ec286f9..3db58a03 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -42,16 +42,18 @@ You are a professional PPT Font Fix helper. - If Tool returns 'curl' command, use the file system tool to download the file from the public URL to the specific path. 2. If the file is opened normally, please analyze the usage status of the font in the PPT file through 'analyze_font' and show the following results. - List of used fonts - - List of inconsistent used fons - 3. If an item exists in the unused fon: + - List of inconsistent used fonts + 3. If an item exists in the unused font: - Ask the user for two answers. A. **Choose a Standard Font** (from UsedFonts) B. **Choose an Action Mode:**: 1. Fix & Clean — Replace fonts and remove unused text boxes 2. Fix Only — Replace fonts only + ** Make sure to enter the font name as it is in the original, not Unicode. ** 4. Ask the user if there is a path they want to save. - If the user did not answer the desired path: Save it as the default path if the file was opened immediately without any problems in No. 1, and specify the outputDirectory as null if you moved the file in the path you suggested. ** If the returned path starts with '/files/', the file is stored within the mounted path. If the user has responded to the desired path, this requires a file system tool to copy it from the mounted folder to the file path between the local and the container. If not, it should be notified that it is stored in the mounted folder. (Exists inside workspace) + ** If result is link, return the link directly to the user. ** 5. Report Provides the download link or file path that the Tool returns. """; diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 5474e739..4bf78db3 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -112,9 +112,9 @@ public PptFontFixService( string safeFileName = Path.GetFileName(filePath.Replace('\\', '/')); // (기존) 컨테이너 내부의 미리 약속된 경로를 탐색 + searchPaths.Add(Path.Combine(_settings.InputPath, safeFileName)); searchPaths.Add(Path.Combine("/app", safeFileName)); searchPaths.Add(Path.Combine("/files", safeFileName)); - searchPaths.Add(Path.Combine("/app/mounts", safeFileName)); // (기존) WebRoot 및 Temp 경로 탐색 string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); @@ -173,7 +173,7 @@ I am running in an Azure environment and cannot access your local file `{filePat else if (_settings.IsContainer) { // [변경] Docker 환경에서는 볼륨 복사(cp) 가이드 반환 - string targetContainerPath = Path.Combine(_settings.SpecsPath, safeFileName); + string targetContainerPath = Path.Combine(_settings.InputPath, safeFileName); string targetHostPath = targetContainerPath; string? hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); @@ -183,7 +183,7 @@ I am running in an Azure environment and cannot access your local file `{filePat string normalizedHostRoot = _hostRootPath.Replace('\\', '/').TrimEnd('/'); - targetHostPath = $"{normalizedHostRoot}/workspace/{safeFileName}"; + targetHostPath = $"{normalizedHostRoot}/{safeFileName}"; } return $""" @@ -366,7 +366,7 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu memoryStream.Position = 0; string finalPhysicalPath = ""; - string baseDirectory; + string baseDirectory = _settings.GeneratedPath; string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); string webGeneratedDir = Path.Combine(webRoot, "generated"); // 웹 서비스 경로 @@ -396,8 +396,7 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu } else if (Directory.Exists("/files")) { - // Stdio Container Volume Mount (/files)를 사용합니다. - baseDirectory = "/files"; + baseDirectory = _settings.GeneratedPath; _logger.LogInformation("Base Path: Stdio Volume Mount (/files) -> {Path}", baseDirectory); } else From 4c16e845672d402758a39d64ac2694fe16a9d8ac Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 8 Dec 2025 05:04:26 +0900 Subject: [PATCH 39/42] fix README --- .vscode/mcp.json | 21 ++++++++++++++++--- ppt-font-fix/.vscode/mcp.stdio.container.json | 6 +++--- ppt-font-fix/README.md | 12 ++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 921e3dad..0df41470 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,8 +1,23 @@ -{ +{ + "inputs": [ + { + "type": "promptString", + "id": "repository-root", + "description": "The absolute path where the your repository is cloned" + } + ], "servers": { "ppt-font-fix": { - "type": "http", - "url": "http://localhost:8080/mcp" + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-v", "${input:repository-root}\\workspace:/files", + "-e", "HOST_ROOT_PATH=${input:repository-root}", + "ppt-font-fix:latest" + ] } } } \ No newline at end of file diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index 7b6d76fb..8d3e0608 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -2,8 +2,8 @@ "inputs": [ { "type": "promptString", - "id": "your-ppt-file-path", - "description": "The absolute path where the PPT file you want to modify is located" + "id": "repository-root", + "description": "The absolute path where the your repository is cloned" } ], "servers": { @@ -14,7 +14,7 @@ "run", "-i", "--rm", - "-v", "${input:your-ppt-file-path}:/files", + "-v", "${input:repository-root}\\workspace:/files", "ppt-font-fix:latest" ] } diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md index 83ae5324..8dd3fb1a 100644 --- a/ppt-font-fix/README.md +++ b/ppt-font-fix/README.md @@ -21,7 +21,8 @@ PPT Font Fix MCP server includes: | Building Block | Name | Description | Usage | |----------------|----------------------------|-------------------------------------|-----------------------------| -| Tools          | `analyze_ppt_file`         | Opens and analyzes fonts used in a PPTX file.       | `#analyze_ppt_file` | +| Tools          | `open_ppt_file`         | Opens a PPTX file.       | `#open_ppt_file` | +| Tools          | `analyze_ppt_file`         | Analyzes fonts used in a PPTX file.       | `#analyze_ppt_file` | | Tools          | `update_ppt_file`          | Replaces inconsistent fonts and saves the modified file.     | `#update_ppt_file` | | Prompts        | `fix_ppt_fonts`            | Structured workflow to guide file upload and repair process. | `/mcp.ppt-font-fix.fix_ppt_fonts ` | @@ -80,17 +81,18 @@ PPT Font Fix MCP server includes: cd $REPOSITORY_ROOT docker build -f Dockerfile.ppt-font-fix -t ppt-font-fix:latest . ``` + > Make sure take note the absolute directory path of the `ppt-font-fix` project. 1. Run the MCP server app in a container. ```bash - docker run -i --rm -p 8080:8080 ppt-font-fix:latest + docker run -i --rm -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ppt-font-fix:latest ``` Alternatively, use the container image from the container registry. ```bash - docker run -i --rm -p 8080:8080 ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest + docker run -i --rm -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest ``` **Parameters**: @@ -101,12 +103,12 @@ PPT Font Fix MCP server includes: ```bash # use local container image - docker run -it --rm -p 8080:8080 -u 0 --name ppt-font-fix ppt-font-fix:latest --http + docker run -i --rm -p 8080:8080 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ppt-font-fix:latest --http ``` ```bash # use container image from the container registry - docker run -it --rm -p 8080:8080 -u 0 --name ppt-font-fix ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest --http + docker run -it --rm -p 8080:8080 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest --http ``` #### On Azure From 21e97a4128953fd76654207af8df37deb2f212cd Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Mon, 8 Dec 2025 05:13:01 +0900 Subject: [PATCH 40/42] fix some comment --- .../Program.cs | 24 ++---------------- .../Prompts/PptFontFixPrompt.cs | 2 +- .../Services/PPTFontFixService.cs | 25 ++----------------- .../Tools/PPTFontFixTool.cs | 19 ++++++-------- 4 files changed, 12 insertions(+), 58 deletions(-) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 73c83a46..73ea18ef 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -31,57 +31,44 @@ if (useStreamableHttp && app is WebApplication webApp) { - // A. 정적 파일 서빙 (다운로드용) - // GeneratedPath(수정된 파일 저장소)가 없으면 생성 string actualGeneratedPath = Path.Combine(webApp.Environment.WebRootPath, "generated"); if (!Directory.Exists(actualGeneratedPath)) { Directory.CreateDirectory(actualGeneratedPath); } - // '/generated' 경로로 들어오는 요청을 WebRootPath의 generated 폴더에 매핑 webApp.UseStaticFiles(new StaticFileOptions { - // 🚨 수정: appSettings.GeneratedPath 대신 실제 wwwroot 경로를 사용 FileProvider = new PhysicalFileProvider(actualGeneratedPath), RequestPath = "/generated", ServeUnknownFileTypes = true }); - - // B. 파일 업로드 엔드포인트 추가 (/upload) webApp.MapPost("/upload", async (IFormFile file, IPptFontFixService service) => { - // 1. 입력 유효성 검사 (오류 시 반환) if (file is null || file.Length == 0) { return Results.BadRequest(new { error = "No file uploaded." }); } - // 2. 입력 파일 저장소 (InputPath) 확인 및 생성 var appSettings = webApp.Services.GetRequiredService(); // AppSettings 주입 if (!Directory.Exists(appSettings.InputPath)) Directory.CreateDirectory(appSettings.InputPath); - // 3. 파일명 추출 및 최종 경로 설정 var fileName = Path.GetFileName(file.FileName); var filePath = Path.Combine(appSettings.InputPath, fileName); try { - // 4. 파일 스트림을 디스크에 직접 저장 using (var stream = file.OpenReadStream()) using (var outputStream = File.Create(filePath)) { await stream.CopyToAsync(outputStream); } - // 5. [수정] 업로드 성공 후, LLM이 참조할 수 있는 최종 파일 경로 반환 - // (Tool이 이 경로를 받아 AnalyzePptFileAsync를 호출함) return Results.Ok(new { message = "File uploaded successfully.", filePath = filePath }); } catch (Exception ex) { - // 6. 예외 발생 시 반환 return Results.Problem($"File upload failed: {ex.Message}"); } }) @@ -92,7 +79,6 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) { - // Docker/Azure 환경 변수 확인 bool isContainer = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; string? azureAppName = Environment.GetEnvironmentVariable("CONTAINER_APP_NAME"); bool isAzure = !string.IsNullOrEmpty(azureAppName); @@ -101,7 +87,6 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) if (isAzure) { - //baseDirectory = "/app"; baseDirectory = "/workspace"; settings.InputPath = Path.Combine(baseDirectory); settings.GeneratedPath = Path.Combine(baseDirectory,"generated"); @@ -113,36 +98,31 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) settings.InputPath = Path.Combine(baseDirectory, "input"); settings.GeneratedPath = Path.Combine(baseDirectory, "generated"); - // WorkspacePath는 InputPath의 상위 개념으로 설정 settings.WorkspacePath = Path.GetDirectoryName(settings.InputPath) ?? baseDirectory; } else { - // [로컬 환경]: 프로젝트 루트 폴더 찾기 baseDirectory = TryFindProjectRoot(Directory.GetCurrentDirectory()) ?? Directory.GetCurrentDirectory(); string workspacePath = Path.Combine(baseDirectory, "workspace"); settings.WorkspacePath = workspacePath; - settings.InputPath = Path.Combine(workspacePath, "input"); // 입력 파일 저장소 - settings.GeneratedPath = Path.Combine(workspacePath, "generated"); // 출력 파일 저장소 + settings.InputPath = Path.Combine(workspacePath, "input"); + settings.GeneratedPath = Path.Combine(workspacePath, "generated"); } settings.IsHttpMode = isHttp; settings.IsContainer = isContainer; settings.IsAzure = isAzure; - // 디렉토리 생성 보장 if (!Directory.Exists(settings.WorkspacePath)) Directory.CreateDirectory(settings.WorkspacePath); if (!Directory.Exists(settings.InputPath)) Directory.CreateDirectory(settings.InputPath); if (!Directory.Exists(settings.GeneratedPath)) Directory.CreateDirectory(settings.GeneratedPath); } -// 프로젝트 루트 탐색 헬퍼 메서드 string? TryFindProjectRoot(string startPath) { var dir = new DirectoryInfo(startPath); while (dir != null) { - // Dockerfile.ppt-font-fix 파일이 있는 곳을 루트로 간주 if (dir.GetFiles("Dockerfile.ppt-font-fix").Length > 0) { return Path.Combine(dir.FullName, "ppt-font-fix"); diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 3db58a03..ffc36fe7 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -3,7 +3,7 @@ using System.IO; using System; using System.Collections.Generic; -using System.Linq; // Path.GetFileName을 위한 Last() 메서드 사용을 위해 필요 +using System.Linq; namespace McpSamples.PptFontFix.HybridApp.Prompts; diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 4bf78db3..8141174e 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -37,7 +37,7 @@ public interface IPptFontFixService /// Save the modified Ppt file. /// /// The desired file name to save as. - /// The directory path on the host machine to save the modified file. // ✅ 신규 추가 + /// The directory path on the host machine to save the modified file. Task SavePptFileAsync(string desiredFileName, string? outputDirectory = null); /// @@ -111,16 +111,13 @@ public PptFontFixService( var searchPaths = new List { filePath }; string safeFileName = Path.GetFileName(filePath.Replace('\\', '/')); - // (기존) 컨테이너 내부의 미리 약속된 경로를 탐색 searchPaths.Add(Path.Combine(_settings.InputPath, safeFileName)); searchPaths.Add(Path.Combine("/app", safeFileName)); searchPaths.Add(Path.Combine("/files", safeFileName)); - // (기존) WebRoot 및 Temp 경로 탐색 string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); searchPaths.Add(Path.Combine(baseDir, "generated", safeFileName)); - // (신규) File Share Mount Path를 기반으로 파일명으로 직접 접근 시도 if (!string.IsNullOrEmpty(_fileShareMountPath)) { searchPaths.Add(Path.Combine(_fileShareMountPath, "generated", safeFileName)); @@ -139,10 +136,8 @@ public PptFontFixService( if (foundPath == null) { - // 2-1. Azure Container Apps (Remote HTTP) 환경 (IsAzure 플래그 사용) if (_settings.IsAzure && _settings.IsHttpMode) { - // [변경] Azure 환경에서는 curl 업로드 가이드 반환 string uploadUrl = "/upload"; var request = _httpContextAccessor?.HttpContext?.Request; if (request != null) @@ -169,10 +164,8 @@ I am running in an Azure environment and cannot access your local file `{filePat After the command completes successfully, please call the `open_ppt_file` tool again with the path returned by the upload. """; } - // 2-2. Docker Container (Stdio/HTTP Local) 환경 (IsContainer 플래그 사용) else if (_settings.IsContainer) { - // [변경] Docker 환경에서는 볼륨 복사(cp) 가이드 반환 string targetContainerPath = Path.Combine(_settings.InputPath, safeFileName); string targetHostPath = targetContainerPath; string? hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); @@ -199,14 +192,11 @@ to the host directory mapped to the container volume. 2. RETRY the `open_ppt_file` tool immediately with the original file path (`{filePath}`). """; } - // 2-3. 로컬 환경 또는 기타 오류 _logger.LogError("❌ File not found. Searched in: {Paths}", string.Join(", ", searchPaths)); - // [변경] 원본 코드의 복사 시도/throw 대신 에러 메시지 반환 return $"[Error] File Not Found: The file '{filePath}' was not found. Please ensure the path is correct and accessible."; } - // 3. 파일 열기 (foundPath 사용) try { _presentation?.Dispose(); @@ -355,7 +345,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu if (this._presentation == null) throw new InvalidOperationException("Ppt file is not opened. Please open a Ppt file before saving."); ArgumentException.ThrowIfNullOrWhiteSpace(desiredFileName, nameof(desiredFileName)); - // 파일 이름 정리 (안전한 파일 이름 추출) string safeFileName = Path.GetFileName(desiredFileName).Replace(":", "").Trim(); _logger.LogInformation("Save process started. Target: {SafeName}", safeFileName); @@ -368,7 +357,7 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu string finalPhysicalPath = ""; string baseDirectory = _settings.GeneratedPath; string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - string webGeneratedDir = Path.Combine(webRoot, "generated"); // 웹 서비스 경로 + string webGeneratedDir = Path.Combine(webRoot, "generated"); bool isContainerEnv = !OperatingSystem.IsWindows() || !string.IsNullOrEmpty(_fileShareMountPath); bool isHttpMode = _httpContextAccessor?.HttpContext?.Request != null; @@ -382,7 +371,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu { if (isHttpMode) { - // 💡 HTTP 환경에서는 마운트 경로를 무시하고 웹 서비스 경로만 사용합니다. baseDirectory = webGeneratedDir; _logger.LogInformation("Base Path: HTTP Mode detected. Using Web Root -> {Path}", baseDirectory); } @@ -390,7 +378,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu { if (!string.IsNullOrEmpty(_fileShareMountPath)) { - // Azure File Share Mount Path를 사용합니다. baseDirectory = Path.Combine(_fileShareMountPath, "generated"); _logger.LogInformation("Base Path: File Share Mount (Non-HTTP) -> {Path}", baseDirectory); } @@ -401,14 +388,12 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu } else { - // 로컬 환경에서는 웹 루트의 generated 폴더를 사용합니다. baseDirectory = webGeneratedDir; _logger.LogInformation("Base Path: Local Environment Web Root -> {Path}", baseDirectory); } } } - // 2. 디렉토리 확인 및 생성 if (!Directory.Exists(baseDirectory)) { try @@ -424,7 +409,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu finalPhysicalPath = Path.Combine(baseDirectory, safeFileName); - // 3. 파일 저장 (마운트 볼륨/웹 루트에 단일 저장) try { memoryStream.Position = 0; @@ -434,7 +418,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu await fs.FlushAsync(); } - // Docker/Linux 환경에서 권한 설정 if (!OperatingSystem.IsWindows() && string.IsNullOrEmpty(this._fileShareMountPath)) { File.SetUnixFileMode(finalPhysicalPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); @@ -448,16 +431,13 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu throw; } - // 4. 최종 반환: HTTP Context가 있다면 웹 URL을, 없다면 물리적 경로를 반환 if (_httpContextAccessor?.HttpContext?.Request != null) { if (!string.IsNullOrEmpty(outputDirectory) && !finalPhysicalPath.StartsWith(webRoot, StringComparison.OrdinalIgnoreCase)) { - // 사용자 지정 경로가 웹으로 접근 불가능할 경우 물리적 경로 반환 _logger.LogWarning("User-specified path is outside of WebRoot. Returning Physical Path: {Path}", finalPhysicalPath); return finalPhysicalPath; } - // 모든 파일이 'generated' 폴더 아래에 저장되었으므로, 웹 URL 경로는 /generated/{filename}으로 통일 string relativePath = Path.GetRelativePath(webRoot, finalPhysicalPath).Replace('\\', '/'); var request = _httpContextAccessor.HttpContext.Request; string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; @@ -466,7 +446,6 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu } else { - // STDIN/STDOUT (stdio) 또는 로컬 실행 환경에서 HTTP Context가 없을 경우 _logger.LogInformation("✅ Returning Physical Path (No HTTP Context): {Path}", finalPhysicalPath); return finalPhysicalPath; } diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs index 49a97cd5..5c9145a0 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Tools/PPTFontFixTool.cs @@ -15,18 +15,18 @@ namespace McpSamples.PptFontFix.HybridApp.Tools; public interface IPptFontFixTool { - ////// + /// /// Opens the specified PPT file and loads it into memory for subsequent analysis. /// /// The path to the PPT file. /// A string message indicating success or an action required instruction for the LLM. - Task OpenPptFileAsync(string filePath); // 🚨 신규 Tool 추가 + Task OpenPptFileAsync(string filePath); /// /// Analyzes fonts in the file currently loaded in memory. /// /// Returns instance. - Task AnalyzeFontsAsync(); // 🚨 기존 AnalyzePptFileAsync를 AnalyzeFontsAsync로 변경 + Task AnalyzeFontsAsync(); /// /// Updates the PPT file by removing unused fonts, replacing inconsistent fonts, and saving to a new path. @@ -34,10 +34,10 @@ public interface IPptFontFixTool /// The font to replace all inconsistent fonts with. /// The list of inconsistent font names to be replaced. /// The list of shape locations to be removed. - /// The directory path on the host machine to save the modified file. // ✅ 신규 추가 + /// The directory path on the host machine to save the modified file. /// The full path to save the new .pptx file. /// Returns a success message with the new file path. - Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string outputDirectory, string newFileName); // ✅ 시그니처 변경 + Task UpdatePptFileAsync(string replacementFont, List inconsistentFontsToReplace, List locationsToRemove, string outputDirectory, string newFileName); } /// @@ -48,22 +48,18 @@ public interface IPptFontFixTool [McpServerToolType] public class PptFontFixTool(IPptFontFixService service, ILogger logger) : IPptFontFixTool { - // 🚨 신규 Tool: open_ppt_file 구현 [McpServerTool(Name = "open_ppt_file", Title = "Open PPT File")] [Description("Opens a Ppt file and loads it into memory. Returns action instructions if the file cannot be accessed.")] public async Task OpenPptFileAsync( [Description("The path of the Ppt file to open and analyze")] string filePath) { - // Service의 OpenPptFileAsync를 호출합니다. (이 메서드는 string?을 반환하도록 수정되었음) string? actionRequiredMessage = await service.OpenPptFileAsync(filePath).ConfigureAwait(false); if (!string.IsNullOrEmpty(actionRequiredMessage)) { - // Service가 string 메시지를 반환했으므로, 예외 없이 바로 반환합니다. return actionRequiredMessage; } - // 성공 시: logger.LogInformation("Ppt file opened successfully: {FilePath}", filePath); return $"PPT file '{filePath}' successfully loaded into memory. You can now call the analyze_fonts tool."; } @@ -72,7 +68,7 @@ public async Task OpenPptFileAsync( /// [McpServerTool(Name = "analyze_fonts", Title = "Analyze Fonts")] [Description("Analyzes fonts used in the PPT file currently loaded in memory, identifying inconsistencies.")] - public async Task AnalyzeFontsAsync() // 🚨 Tool 이름 변경 + public async Task AnalyzeFontsAsync() { try { @@ -91,7 +87,6 @@ public async Task AnalyzeFontsAsync() // 🚨 Tool 이름 } catch (InvalidOperationException ex) { - // PPT 파일이 로드되지 않았을 때 (AnalyzeFontsAsync 내부에서 InvalidOperationException을 던질 경우) logger.LogError(ex, "Analysis failed because the PPT file was not loaded."); throw; } @@ -109,7 +104,7 @@ public async Task UpdatePptFileAsync( [Description("The replacement font")] string replacementFont, [Description("The fonts to be replaced")] List inconsistentFontsToReplace, [Description("A list of shape locations (from analysis result) to be removed")] List locationsToRemove, - [Description("The directory path on the host machine to save the modified file (e.g., C:\\Users\\Downloads)")] string outputDirectory, // ✅ 신규 파라미터 + [Description("The directory path on the host machine to save the modified file (e.g., C:\\Users\\Downloads)")] string outputDirectory, [Description("The filename for the modified Ppt file.")] string newFileName) { try From f2e72fbe9b71b98e25d7c6886983412b5851ad9d Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sat, 13 Dec 2025 01:19:51 +0900 Subject: [PATCH 41/42] Add tags --- .vscode/mcp.json | 21 +-- Dockerfile.ppt-font-fix-azure | 6 +- ppt-font-fix/.vscode/mcp.stdio.container.json | 6 +- ppt-font-fix/README.md | 8 +- .../Configurations/PPTFontFixAppSettings.cs | 17 +++ .../Program.cs | 12 +- .../Prompts/PptFontFixPrompt.cs | 4 +- .../Services/PPTFontFixService.cs | 125 +++--------------- 8 files changed, 54 insertions(+), 145 deletions(-) diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 0df41470..920d570c 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -1,23 +1,8 @@ { - "inputs": [ - { - "type": "promptString", - "id": "repository-root", - "description": "The absolute path where the your repository is cloned" - } - ], "servers": { "ppt-font-fix": { - "type": "stdio", - "command": "docker", - "args": [ - "run", - "-i", - "--rm", - "-v", "${input:repository-root}\\workspace:/files", - "-e", "HOST_ROOT_PATH=${input:repository-root}", - "ppt-font-fix:latest" - ] + "type": "http", + "url": "http://localhost:8080/mcp" } } -} \ No newline at end of file +} diff --git a/Dockerfile.ppt-font-fix-azure b/Dockerfile.ppt-font-fix-azure index 29e2fd1d..68ab0efa 100644 --- a/Dockerfile.ppt-font-fix-azure +++ b/Dockerfile.ppt-font-fix-azure @@ -21,14 +21,10 @@ RUN mkdir -p /app/wwwroot/generated \ ARG UID=$APP_UID -# 3. 중요: 생성된 디렉토리의 소유권을 $APP_UID에게 변경합니다. -# 이렇게 해야 $APP_UID 사용자가 이 디렉토리에 파일을 쓸 수 있습니다. -# chown -R [사용자 ID]:[그룹 ID] [경로] RUN chown -R $UID:$UID /app/wwwroot/generated \ && chown -R $UID:$UID /app/workspace \ && chown -R $UID:$UID /files -# 4. 비-루트 사용자로 전환 (기존 코드와 동일) USER $UID -ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] +ENTRYPOINT ["dotnet", "McpSamples.PptFontFix.HybridApp.dll"] \ No newline at end of file diff --git a/ppt-font-fix/.vscode/mcp.stdio.container.json b/ppt-font-fix/.vscode/mcp.stdio.container.json index 8d3e0608..7b6d76fb 100644 --- a/ppt-font-fix/.vscode/mcp.stdio.container.json +++ b/ppt-font-fix/.vscode/mcp.stdio.container.json @@ -2,8 +2,8 @@ "inputs": [ { "type": "promptString", - "id": "repository-root", - "description": "The absolute path where the your repository is cloned" + "id": "your-ppt-file-path", + "description": "The absolute path where the PPT file you want to modify is located" } ], "servers": { @@ -14,7 +14,7 @@ "run", "-i", "--rm", - "-v", "${input:repository-root}\\workspace:/files", + "-v", "${input:your-ppt-file-path}:/files", "ppt-font-fix:latest" ] } diff --git a/ppt-font-fix/README.md b/ppt-font-fix/README.md index 8dd3fb1a..3e5ec798 100644 --- a/ppt-font-fix/README.md +++ b/ppt-font-fix/README.md @@ -86,13 +86,13 @@ PPT Font Fix MCP server includes: 1. Run the MCP server app in a container. ```bash - docker run -i --rm -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ppt-font-fix:latest + docker run -i --rm -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" ppt-font-fix:latest -c ``` Alternatively, use the container image from the container registry. ```bash - docker run -i --rm -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest + docker run -i --rm -p 8080:8080 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest -c ``` **Parameters**: @@ -103,12 +103,12 @@ PPT Font Fix MCP server includes: ```bash # use local container image - docker run -i --rm -p 8080:8080 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ppt-font-fix:latest --http + docker run -it --rm -p 8080:8080 -u 0 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" ppt-font-fix:latest --http -c ``` ```bash # use container image from the container registry - docker run -it --rm -p 8080:8080 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" -e HOST_ROOT_PATH="$REPOSITORY_ROOT/ppt-font-fix" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest --http + docker run -it --rm -p 8080:8080 -u 0 -v "$REPOSITORY_ROOT/ppt-font-fix/workspace:/files" ghcr.io/microsoft/mcp-dotnet-samples/ppt-font-fix:latest --http -c ``` #### On Azure diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs index fce56428..56c75eeb 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Configurations/PPTFontFixAppSettings.cs @@ -44,4 +44,21 @@ public class PptFontFixAppSettings : AppSettings /// Indicates whether the application is running in an Azure environment. /// public bool IsAzure { get; set; } + + /// + protected override T ParseMore(IConfiguration config, string[] args) + { + var settings = base.ParseMore(config, args); + + for (var i = 0; i < args.Length; i++) + { + var arg = args[i]; + if (args.Contains("-c") || args.Contains("--container")) + { + (settings as PptFontFixAppSettings)!.IsContainer = true; + } + } + + return (settings as T)!; + } } \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs index 73ea18ef..280db379 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Program.cs @@ -31,7 +31,7 @@ if (useStreamableHttp && app is WebApplication webApp) { - string actualGeneratedPath = Path.Combine(webApp.Environment.WebRootPath, "generated"); + string actualGeneratedPath = appSettings.GeneratedPath; if (!Directory.Exists(actualGeneratedPath)) { Directory.CreateDirectory(actualGeneratedPath); @@ -50,7 +50,7 @@ return Results.BadRequest(new { error = "No file uploaded." }); } - var appSettings = webApp.Services.GetRequiredService(); // AppSettings 주입 + var appSettings = webApp.Services.GetRequiredService(); if (!Directory.Exists(appSettings.InputPath)) Directory.CreateDirectory(appSettings.InputPath); @@ -79,7 +79,7 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) { - bool isContainer = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; + bool isContainer = settings.IsContainer || Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; string? azureAppName = Environment.GetEnvironmentVariable("CONTAINER_APP_NAME"); bool isAzure = !string.IsNullOrEmpty(azureAppName); @@ -87,9 +87,9 @@ void InitializeRuntimeSettings(PptFontFixAppSettings settings, bool isHttp) if (isAzure) { - baseDirectory = "/workspace"; - settings.InputPath = Path.Combine(baseDirectory); - settings.GeneratedPath = Path.Combine(baseDirectory,"generated"); + baseDirectory = "/app"; + settings.InputPath = Path.Combine(baseDirectory, "workspace/input"); + settings.GeneratedPath = Path.Combine(baseDirectory,"workspace/generated"); settings.WorkspacePath = Path.GetDirectoryName(settings.InputPath) ?? baseDirectory; } else if (isContainer) diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs index 8faa8007..ffc36fe7 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Prompts/PptFontFixPrompt.cs @@ -3,7 +3,7 @@ using System.IO; using System; using System.Collections.Generic; -using System.Linq; +using System.Linq; namespace McpSamples.PptFontFix.HybridApp.Prompts; @@ -58,4 +58,4 @@ 5. Report Provides the download link or file path that the Tool returns. """; } -} +} \ No newline at end of file diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs index 8141174e..07471106 100644 --- a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs +++ b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/Services/PPTFontFixService.cs @@ -62,13 +62,9 @@ public interface IPptFontFixService public class PptFontFixService : IPptFontFixService { private readonly ILogger _logger; - private readonly IConfiguration _configuration; - private readonly IHostEnvironment _hostEnvironment; - private readonly IWebHostEnvironment? _webHostEnvironment; private readonly IHttpContextAccessor? _httpContextAccessor; private readonly PptFontFixAppSettings _settings; private Presentation? _presentation; - private readonly string? _fileShareMountPath; private HashSet? _analyzedVisibleFonts; @@ -80,16 +76,10 @@ public PptFontFixService( IServiceProvider serviceProvider) { _logger = logger; - _configuration = configuration; - _hostEnvironment = hostEnvironment; - _webHostEnvironment = serviceProvider.GetService(); _httpContextAccessor = serviceProvider.GetService(); - _fileShareMountPath = configuration["AZURE_FILE_SHARE_MOUNT_PATH"]; _settings = settings; } - private readonly string? _hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); - /// @@ -108,20 +98,9 @@ public PptFontFixService( return "[Error] File Access: Direct URL access is not supported. Please ensure the file is placed in the shared volume."; } - var searchPaths = new List { filePath }; string safeFileName = Path.GetFileName(filePath.Replace('\\', '/')); - searchPaths.Add(Path.Combine(_settings.InputPath, safeFileName)); - searchPaths.Add(Path.Combine("/app", safeFileName)); - searchPaths.Add(Path.Combine("/files", safeFileName)); - - string baseDir = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - searchPaths.Add(Path.Combine(baseDir, "generated", safeFileName)); - - if (!string.IsNullOrEmpty(_fileShareMountPath)) - { - searchPaths.Add(Path.Combine(_fileShareMountPath, "generated", safeFileName)); - } + var searchPaths = new List { filePath, Path.Combine(_settings.InputPath, safeFileName) }; string? foundPath = null; foreach (var path in searchPaths) @@ -165,20 +144,7 @@ I am running in an Azure environment and cannot access your local file `{filePat """; } else if (_settings.IsContainer) - { - string targetContainerPath = Path.Combine(_settings.InputPath, safeFileName); - string targetHostPath = targetContainerPath; - string? hostRootPath = Environment.GetEnvironmentVariable("HOST_ROOT_PATH"); - - - if (!string.IsNullOrEmpty(_hostRootPath)) - { - - string normalizedHostRoot = _hostRootPath.Replace('\\', '/').TrimEnd('/'); - - targetHostPath = $"{normalizedHostRoot}/{safeFileName}"; - } - + { return $""" ⚠️ Action Required: File Synchronization Needed (Docker Container) @@ -188,7 +154,7 @@ I am running in an Azure environment and cannot access your local file `{filePat EXECUTION PLAN (Follow Strictly): 1. COPY the file from your local machine path (`{filePath}`) to the host directory mapped to the container volume. - The recommended target path is: `{targetHostPath}` + The recommended target path is: `{_settings.InputPath}/{safeFileName}` 2. RETRY the `open_ppt_file` tool immediately with the original file path (`{filePath}`). """; } @@ -354,101 +320,46 @@ public async Task SavePptFileAsync(string desiredFileName, string? outpu await Task.Run(() => _presentation.Save(memoryStream)); memoryStream.Position = 0; - string finalPhysicalPath = ""; string baseDirectory = _settings.GeneratedPath; - string webRoot = _webHostEnvironment?.WebRootPath ?? Path.Combine(_hostEnvironment.ContentRootPath, "wwwroot"); - string webGeneratedDir = Path.Combine(webRoot, "generated"); - - bool isContainerEnv = !OperatingSystem.IsWindows() || !string.IsNullOrEmpty(_fileShareMountPath); - bool isHttpMode = _httpContextAccessor?.HttpContext?.Request != null; - if (!string.IsNullOrEmpty(outputDirectory) && !isContainerEnv) + if (!string.IsNullOrEmpty(outputDirectory) && !_settings.IsContainer && !_settings.IsAzure) { baseDirectory = outputDirectory; - _logger.LogInformation("Base Path: User Provided Output Directory -> {Path}", baseDirectory); - } - else - { - if (isHttpMode) - { - baseDirectory = webGeneratedDir; - _logger.LogInformation("Base Path: HTTP Mode detected. Using Web Root -> {Path}", baseDirectory); - } - else - { - if (!string.IsNullOrEmpty(_fileShareMountPath)) - { - baseDirectory = Path.Combine(_fileShareMountPath, "generated"); - _logger.LogInformation("Base Path: File Share Mount (Non-HTTP) -> {Path}", baseDirectory); - } - else if (Directory.Exists("/files")) - { - baseDirectory = _settings.GeneratedPath; - _logger.LogInformation("Base Path: Stdio Volume Mount (/files) -> {Path}", baseDirectory); - } - else - { - baseDirectory = webGeneratedDir; - _logger.LogInformation("Base Path: Local Environment Web Root -> {Path}", baseDirectory); - } - } + _logger.LogInformation("Using User Provided Directory: {Path}", baseDirectory); } - if (!Directory.Exists(baseDirectory)) - { - try - { - Directory.CreateDirectory(baseDirectory); - } - catch (Exception ex) - { - _logger.LogError(ex, "FATAL: Could not create base directory {Path}.", baseDirectory); - throw; - } - } + if (!Directory.Exists(baseDirectory)) Directory.CreateDirectory(baseDirectory); - finalPhysicalPath = Path.Combine(baseDirectory, safeFileName); + string finalPhysicalPath = Path.Combine(baseDirectory, safeFileName); try { - memoryStream.Position = 0; using (var fs = new FileStream(finalPhysicalPath, FileMode.Create, FileAccess.Write)) { await memoryStream.CopyToAsync(fs); await fs.FlushAsync(); } - - if (!OperatingSystem.IsWindows() && string.IsNullOrEmpty(this._fileShareMountPath)) - { - File.SetUnixFileMode(finalPhysicalPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite); - } - - _logger.LogInformation("✅ File successfully saved to mount/web path: {Path}", finalPhysicalPath); + + _logger.LogInformation("File saved to: {Path}", finalPhysicalPath); } catch (Exception ex) { - _logger.LogError(ex, "FATAL: Could not save file to the final physical path: {Path}", finalPhysicalPath); + _logger.LogError(ex, "FATAL: Could not save file."); throw; } - if (_httpContextAccessor?.HttpContext?.Request != null) + if (_settings.IsHttpMode) { - if (!string.IsNullOrEmpty(outputDirectory) && !finalPhysicalPath.StartsWith(webRoot, StringComparison.OrdinalIgnoreCase)) + var request = _httpContextAccessor?.HttpContext?.Request; + if (request != null) { - _logger.LogWarning("User-specified path is outside of WebRoot. Returning Physical Path: {Path}", finalPhysicalPath); - return finalPhysicalPath; + string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; + _logger.LogInformation("Returning Web URL: {Url}", url); + return url; } - string relativePath = Path.GetRelativePath(webRoot, finalPhysicalPath).Replace('\\', '/'); - var request = _httpContextAccessor.HttpContext.Request; - string url = $"{request.Scheme}://{request.Host}/generated/{safeFileName}"; - _logger.LogInformation("✅ Returning Web URL: {Url}", url); - return url; - } - else - { - _logger.LogInformation("✅ Returning Physical Path (No HTTP Context): {Path}", finalPhysicalPath); - return finalPhysicalPath; } + + return finalPhysicalPath; } } From 0cf21d24f5fb77848ea508f38b07abcf5215cee7 Mon Sep 17 00:00:00 2001 From: jewelry14 Date: Sat, 13 Dec 2025 01:20:28 +0900 Subject: [PATCH 42/42] remove test file --- .../McpSamples.PptFontFix.HybridApp/test.pptx | Bin 40943 -> 0 bytes ppt-font-fix/test.pptx | Bin 40943 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx delete mode 100644 ppt-font-fix/test.pptx diff --git a/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx b/ppt-font-fix/src/McpSamples.PptFontFix.HybridApp/test.pptx deleted file mode 100644 index eaa90ce5de664fdb99f004e2455eb6b7012d62e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40943 zcmeFZV{|3$zAYZx?l|eFW81cE+crD4osO|$+qP|WoOJBuX21LV$2kAH-#hjh<9<8m z)`zF6)~fpOta|30Kg?S4QlMaHKoCGsKtMo5Kq<~-u>HV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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 diff --git a/ppt-font-fix/test.pptx b/ppt-font-fix/test.pptx deleted file mode 100644 index eaa90ce5de664fdb99f004e2455eb6b7012d62e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40943 zcmeFZV{|3$zAYZx?l|eFW81cE+crD4osO|$+qP|WoOJBuX21LV$2kAH-#hjh<9<8m z)`zF6)~fpOta|30Kg?S4QlMaHKoCGsKtMo5Kq<~-u>HV5K(YuxK&U`aAX-9pw$3KD z&U(ro_9jj`wC*<6g!y0~6uCekU)TS??SJquFp)Yc+fR=aawXm&bUydBWe8GR{4c>j%n!1ADY7>(EB%u^fkV)h0e+3I4MrT>wAViUs1Q z&MbW;IAVG~d-jNVa0N@rjY9g-3i9#;6e_Fo2yrItgp1r0Cwy#=m+25s9a??qQj8@i zhKom4_of9rAi@Y=u&~b|0>y8Y8l5l1cdX@2cYq9w%Kj!mBlMTA$IP=`9qE-G!=wdZ zcO`VE#WgT-4O-TUoV`4laGo2d$Oiq>!nPw)zi+o5B{2A!79_M2H^S`s7en)^Mtmo< zy8{#OXV)p|nchX07psyH+jh`kZbpo<`)6`l2EIy6Sw_`A242;#Vd`sG=P$m6V7$j3 zah~NbmTeE0cX4q{IwGgr@`F2{{^O%Dx-;5Vzc`zD?zBOMuZ#$XLL}4j~7FkYq5gty}TST$onKqlO_;@LHp{2luLQ!jmwx z6(-*M#F>cWz)`w0s&u=CycKYUlkUryn@&HtL?N!_1fI_${6e6`X~;Z6;UeA;Rwhl} zWP&+scp8qLmP;VTL4c}46qJRjnXMKUn(cLMKKw1YTK68i>{G`4*)4CzMRne1hD$8x zsG~UCt^`YCNVpX(_C$%z*+-UWjmbmk_g#TO)GtxT8>URezr{?rPGN2S7hY=Mfq>Ay zuCTXvrn7f6ar%->17{06+kXh=dFrNZCOz8l75N2ToE^F36PbeeVuex0l7zxMk3Xzz zkfpUTm&KgLRhJQH07=FIc=kpCBDDUmMkVqvDa@_&7$mJxM#?QkJidCryUp^Dp zK!UXzY^cGE|kkN0lv#MpDzu6hL6JW-1bWtJJLLy

^jUa2-c19&iGCZW2LV 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