Releases: groupdocs-conversion/GroupDocs.Conversion.Mcp
Release list
26.7.2
26.7.2 — Full configuration surface in install snippets (docs/infra only)
What changed
No server code changes — the bump republishes so the refreshed README (install
buttons above the fold, Codex/Windsurf guides, fixed one-click links) reaches the
NuGet package page, Docker/GHCR, and the MCP Registry.
- Every install snippet and one-click deeplink (VS Code / Cursor buttons, Claude
Desktop/Code, VS Code, VS 2022, Cursor, Windsurf, Cline, Rider, Codex) now
pre-fills all supported environment variables so users see the full
configuration surface in the install dialog:GROUPDOCS_MCP_STORAGE_PATH— placeholder documents folderGROUPDOCS_MCP_OUTPUT_PATH— same folder as storage by defaultGROUPDOCS_LICENSE_PATH— empty by default (evaluation mode)
- Verified in
GroupDocs.Mcp.Core'sLicenseManager: an empty license path is
handled identically to an unset one (string.IsNullOrEmptyguard → evaluation
mode with a log warning; a wrong path only logs;SetLicenseFromPathis wrapped
in try/catch) — an empty value can never fail the server.
Migration / impact
Drop-in — the server binary is identical apart from the version stamp.
Full Changelog: 26.7.1...26.7.2
26.7.1
26.7.1 — Discoverability & one-click install uplift (docs/infra only)
What changed
Pilot of the org-wide MCP repo improvement plan (assets/mcp-improve-plan.md in the
Metadata repo). No server code changes — the bump ships the new README to the NuGet
package page.
- README restructured top-loaded: value prop → badge row (NuGet version/downloads,
Docker pulls, MCP Registry, Tests-repo CI status, MIT) → demo placeholder →
"Install in 60 seconds" with one-click VS Code/Cursor buttons and per-client snippets
(Claude Desktop, Claude Code, VS Code/Copilot, Visual Studio 2022.mcp.json,
Cursor, Windsurf, Cline, JetBrains Rider, Docker, global tool) → tools table →
new Licensing section (evaluation limits: watermark + 15-document cap, temporary
license + purchase links) → the rest. install/config.json— canonical install config; the ONE source for every snippet
and deeplink. Version is read frombuild/dependencies.propsat generation time.install/generate-install-links.ps1— emitsinstall/generated/(per-client
mcp.json snippets, Claude Code / Rider how-tos, VS Code + Cursor deeplinks) and rewrites
the README<!-- install-buttons -->block idempotently. Byte-stable output (UTF-8
no-BOM, LF) across Windows PowerShell 5.1 and pwsh.- CI drift guard in
build_packages.yml:generate-install-links.ps1 -Checkfails
the build if generated snippets or the README block are out of sync with the config. .vscode/mcp.json— added a published-package (dnx) server entry alongside the
existing from-source dev entry.- Repo hygiene:
SECURITY.md(local-only data handling, private reporting),
CONTRIBUTING.md, issue templates (bug report asks client/install method/OS/license
mode; feature request),smithery.yaml(publish is manual),docker/README.hub.md
(Docker Hub overview),llms.txtlicensing + how-to links. - GitHub topics set on the repo (mcp, mcp-server, model-context-protocol, ai-agents,
claude, cursor, github-copilot, dotnet, document-processing, document-conversion, pdf, docx).
Why
AI-agent users find MCP servers through registries, GitHub topics, and READMEs; installers
copy the first snippet they see. One canonical config guarantees every rendered snippet
stays correct, and the drift guard makes that permanent. Licensing up front removes the
main evaluation-mode surprise (the 15-document cap).
Migration / impact
Drop-in — the server binary is identical to 26.7.0 apart from the version stamp. Cursor's
deeplink format is marked TODO(verify) in the generator pending confirmation against
current Cursor docs (improvement-plan M9).
Full Changelog: 26.7.0...26.7.1
26.7.0
26.7.0 — engine 26.6.0 + shared descriptive-error contract across all tools
What changed
- Bumped the
GroupDocs.Conversionengine from 26.3.0 → 26.6.0. Engine 26.6.0 introduces a dedicatednet10.0runtime sub-package (GroupDocs.Conversion.Net100) that the MCP'snet10.0target now resolves directly (previouslynet10.0fell back to thenet8.0runtime). SkiaSharp pin is unchanged at 3.119.2 (the versionNet100transitively declares). - Bumped the MCP package version 26.5.2 → 26.7.0 (CalVer).
- Extracted a shared
Tools/ToolError.cs(ToolError.Format(op, file, ex, subjectSuffix = null)) and routed every tool's failure path through it.ConvertToolpreviously carried a privateFormatExceptionhelper;GetDocumentInfoToolandGetSupportedFormatsToolhad no exception handling at all — an engine failure in either (e.g. a missing native dependency on Linux, or a malformed document) bubbled up toModelContextProtocol.Server's genericAn error occurred invoking '<tool>'.wrapper, discarding the cause. - All three tools now catch engine exceptions and return a descriptive string that starts with
"<op> failed for '<file>'[ <suffix>]: <ExceptionType>: <message> | inner(0): …":Convert→Conversion failed for '<input>' -> <ext>: …GetDocumentInfo→Document-info lookup failed for '<input>': …GetSupportedFormats→Supported-formats lookup failed for '<input>': …
Why
ConvertTool already surfaced engine exceptions (26.5.2), but the two read-only inspection tools did not — a native-deps regression that broke get_document_info / get_supported_formats on Linux would have looked identical to any other failure from the client's perspective. Consolidating the formatter removes the duplicated helper and gives the whole tool surface one consistent, testable error prefix.
Migration / impact
- Tool callers:
isErrorisfalseeven on engine failure for all three tools now; the cause surfaces in the response text. Detectors should substring-match the per-tool prefix ("Conversion failed for","Document-info lookup failed for","Supported-formats lookup failed for"). - File-not-found behaviour is unchanged — the resolver runs before the try/catch, exactly as in
ConvertTool. - Successful calls: identical output to 26.5.2. No wire-name or schema changes; the tool surface is still the same three tools.
Full Changelog: 26.5.2...26.7.0
26.5.2
26.5.2 — convert surfaces underlying engine exceptions
What changed
-
ConvertTool.Convertnow catches all exceptions from the underlyingGroupDocs.Conversionengine and returns a descriptive error string that includes the exception type, message, and inner-exception chain (up to 5 levels deep). Format:Conversion failed for '<input>' -> <target-ext>: <ExceptionType>: <message> | inner(0): <InnerType>: <message> | …Before 26.5.2, any engine exception bubbled up to
ModelContextProtocol.Server's default tool-invocation handler, which replaces all exception detail with a single canned line:An error occurred invoking 'convert'.. That made native-deps issues on Linux (missing fonts,DllNotFoundException,PlatformNotSupportedException, etc.) indistinguishable from corrupted-input issues from invalid-format issues. AI agents and human operators had no way to act on the failure without re-running with stdio/strace.
Why
Tracking down the Conversion-MCP-Tests Ubuntu nightly failure (Convert_AuthoredPdf_ToHtml_ProducesOutputFile, Convert_RealSample_ProducesExpectedOutputFile(sample.pdf → html)) was blocked by the framework's exception wrapping. Surfacing engine exceptions directly:
- Lets future native-deps regressions be diagnosed from a single failed test run instead of requiring local Docker reproduction.
- Makes the
converttool's error responses actionable for AI agents — they can reason about "DllNotFoundException: libfoo.so" vs. "DocumentReaderException: corrupted input" and respond appropriately. - Matches the contract
GetSupportedFormatsalready establishes for format-incompatible inputs (graceful descriptive response, not a crash).
Migration / impact
- Tool callers:
isErroron theCallToolResultis nowfalseeven on engine failure; the failure surfaces in the response text. Test fixtures that branched onresult.IsError == trueshould switch to substring-matching the response text ("Conversion failed for") to detect failures. The two existing error-handling tests (Convert_CorruptedFile_DoesNotCrashServer,PasswordParameter_IsAcceptedByConvert) already match this pattern and are unaffected. - AI agents: error responses now contain more text than before; clients that pattern-match on the old canned "An error occurred invoking 'convert'" string will need to update their detectors. Unlikely to be load-bearing.
- Successful conversions: identical behaviour to 26.5.1.
Drop-in replacement for 26.5.1 otherwise. No public-API or wire-name changes.
Full Changelog: 26.5.1...26.5.2
26.5.1
26.5.1 — JSON tool responses no longer truncated mid-document
What changed
GetSupportedFormatsToolandGetDocumentInfoToolnow return raw JSON directly instead of routing it throughOutputHelper.TruncateText.OutputHelper.TruncateTextis intended for plain-text output: when the input exceedsMcpConfig.MaxOutputCharacters(default 5000), it appends a[Output truncated — showing first X of Y characters. ...]marker on a new line. That marker is non-JSON and breaks any consumer usingJsonDocument.Parse/JsonSerializer.Deserializeon the response.- Affected callers in practice: the integration test suite's
GetSupportedFormats_PlainJpeg_ReturnsImageTargets(JPEG → 60+ target formats produces ~6 KB JSON, exceeding 5 KB cap), plus any client that strict-parses the tool response. Lenient consumers (Claude, Cursor, VS Code Copilot) tolerate the trailing marker, so user-visible AI-agent flows in 26.5.0 are unaffected.
Why
Tools that emit structured JSON should always return valid JSON regardless of size. Truncation should be expressed inside the JSON document (e.g. capped inner array + truncated: true flag) rather than by appending a non-JSON marker line. In practice the response is bounded by API realities (a few KB to ~30 KB), so removing the wrapping is sufficient — no in-document truncation needed today.
Migration / impact
Drop-in replacement for 26.5.0. No public-API or wire-name changes. Tool responses now contain only the JSON document; previous trailing marker line for ~5KB+ responses is gone. Strict-JSON parsers that broke against 26.5.0 work cleanly against 26.5.1.
Full Changelog: 26.5.0...26.5.1
26.5.0
Initial public release of GroupDocs.Conversion MCP Server
What changed
- NuGet package
GroupDocs.Conversion.Mcppublished withMcpServerpackage type. - Three MCP tools exposed:
Convert— convert a document to a different format (PDF, DOCX, XLSX, PPTX, HTML, PNG, JPG, and 70+ more) and save the result to storage.GetSupportedFormats— list every target format the source document can be converted to, with primary/secondary indicators.GetDocumentInfo— return file type, page count, and basic properties (author, title, dates, password-protected) for a source document.
- Installable via
dnx GroupDocs.Conversion.Mcp@26.5.0 --yes(.NET 10 SDK required) ordotnet tool install -g. - Docker image published to
ghcr.io/groupdocs-conversion/conversion-net-mcpanddocker.io/groupdocs/conversion-net-mcp. - Environment variables:
GROUPDOCS_MCP_STORAGE_PATH, optionalGROUPDOCS_MCP_OUTPUT_PATH,GROUPDOCS_LICENSE_PATH. - Linux native graphics deps wired up:
SkiaSharp.NativeAssets.Linux.NoDependencies(3.119.2) is referenced becauseGroupDocs.Conversionuses SkiaSharp internally;libgdiplus+libfontconfig1are installed in the Docker image and theSystem.Drawing.EnableUnixSupportruntime flag is set because Conversion's image-format paths still callSystem.Drawing.Common.
Why
Second product MCP server in the GroupDocs MCP framework (after Metadata). Exposes
GroupDocs.Conversion for .NET as AI-callable tools for Claude, Cursor,
VS Code / GitHub Copilot, and other MCP-compatible agents.
Migration / impact
First release — no migration required.
Full Changelog: https://github.com/groupdocs-conversion/GroupDocs.Conversion.Mcp/commits/26.5.0