Releases: groupdocs-metadata/GroupDocs.Metadata.Mcp
26.5.1
26.5.1 — ReadMetadata JSON response no longer truncated mid-document
What changed
ReadMetadataToolnow returns 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: PDFs with rich XMP / image-bearing documents with extensive EXIF / Office documents with many custom properties (any of these can push the metadata JSON past 5 KB), 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.4.4 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 for richly-tagged documents), so removing the wrapping is sufficient — no in-document truncation needed today.
Skip from 26.4.4 to 26.5.1
This release skips the 26.5.0 patch number — that label was used by the sibling Conversion / Comparison / Viewer MCP servers for their initial public release, and bumping Metadata in lockstep with the family fix keeps version-discovery tooling consistent across the four products. CalVer doesn't require contiguous patch numbers within a YY.MM band; no prior consumer pinned =26.5.0 on Metadata because that build never existed.
Migration / impact
Drop-in replacement for 26.4.4. 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.4.4 work cleanly against 26.5.1.
Full Changelog: 26.4.4...26.5.1
26.4.4
Linux runtime fixes (SkiaSharp + libgdiplus), README polish, and Docker image OCI labels
What changed
Linux native asset fix (the real production bug)
- build/dependencies.props — added
<SkiaSharp>3.119.0</SkiaSharp>under "External Dependency Versions" with an inline comment requiring this property to stay in lockstep with whatever SkiaSharp version$(GroupDocsMetadata)transitively pulls (ABI-incompatible otherwise). - src/GroupDocs.Metadata.Mcp/GroupDocs.Metadata.Mcp.csproj — added
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="$(SkiaSharp)" />. Inline comment flags this as a workaround for the upstreamGroupDocs.Metadatanuspec gap and notes it can be dropped once the upstream nuspec declares the platform native asset packages.
Before: the published 26.4.3 nupkg shipped tools/net10.0/any/runtimes/{win-*,osx}/native/libSkiaSharp.{dll,dylib} but no linux-*/native/libSkiaSharp.so — GroupDocs.Metadata's nuspec only declares <dependency id="SkiaSharp" version="3.119.0" /> (managed assembly only), so dnx-installed packages on Ubuntu had nothing to load when SkiaSharp's SKObject..cctor ran. The integration tests crashed with SkiaSharpVersion.CheckNativeLibraryCompatible → unhandled finalizer exception → MCP server process exited unexpectedly on every Ubuntu CI job.
After: the 26.4.4 nupkg ships all 12 Linux native variants (linux-x64, linux-arm64, linux-musl-x64, linux-arm, linux-x86, linux-loongarch64, linux-riscv64, plus the four linux-musl-* siblings). Verified via Expand-Archive of the locally-built nupkg; the previously-empty runtimes/linux-* paths now contain the expected libSkiaSharp.so files (8.8 MB for linux-x64).
libgdiplus / System.Drawing.Common Linux fix (the second Linux production bug)
- docker/Dockerfile — added an
apt-get install -y --no-install-recommends libgdiplus libfontconfig1step in thefinalstage (underUSER root, with cache cleanup after) so the runtime image has the GDI+ implementation thatSystem.Drawing.Common6.0.0 P/Invokes on Linux. - src/GroupDocs.Metadata.Mcp/GroupDocs.Metadata.Mcp.csproj — added
<RuntimeHostConfigurationOption Include="System.Drawing.EnableUnixSupport" Value="true" />. Emitted into the publishedruntimeconfig.json; without it,System.Drawing.Common6.0.0's static initializer throwsPlatformNotSupportedExceptionon first bitmap allocation regardless of whetherlibgdiplusis present.
Before: reading metadata from a JPEG (sample.jpg from the integration tests) through the published Docker image produced this stack:
System.TypeInitializationException: The type initializer for 'Gdip' threw an exception.
---> System.PlatformNotSupportedException: System.Drawing.Common is not supported on non-Windows platforms.
at System.Drawing.LibraryResolver.EnsureRegistered()
at System.Drawing.SafeNativeMethods.Gdip.PlatformInitialize()
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height) ← inside GroupDocs.Metadata
PDF/DOCX/XLSX paths were unaffected (those don't go through Bitmap). Only image formats (JPEG, PNG, image-bearing PDFs) tripped this.
After: the runtime config flag flips the gate, and libgdiplus.so is loadable from the container's /usr/lib/x86_64-linux-gnu/. JPEG/PNG read_metadata calls succeed.
README polish — install snippets default to unpinned
- README.md — three install snippets reworked to lead with the unpinned form and show pinning as the explicit alternative:
- Top install snippet —
dnx GroupDocs.Metadata.Mcp --yesis now the lead, with@26.4.4shown below as the "for shared configs / CI" pinning option. - Claude Desktop config block —
"args": ["GroupDocs.Metadata.Mcp", "--yes"]with a callout explaining how to swap in the pinned form. - VS Code / Copilot config block — same treatment.
- Top install snippet —
- README.md — new "Documentation & guides" section above the License heading, linking to the companion GroupDocs.Metadata.Mcp.Tests repo and its six per-channel how-to guides (NuGet install, Docker, MCP registry verification, Claude Desktop, VS Code / Copilot, integration tests). Includes a one-sentence note that the Tests repo exercises every advertised tool against the published NuGet artifact on Linux / macOS / Windows in CI.
Docker image OCI labels
- docker/Dockerfile — added
ARG VERSION=devand aLABELblock on thefinalstage with seven OCI standard labels:image.title,image.description,image.version,image.source,image.url,image.licenses,image.vendor. - .github/workflows/publish_docker.yml — added
build-args: VERSION=${{ steps.version.outputs.version }}to thedocker/build-push-action@v6step, so each release substitutes the real package version into the label at build time.
Why
Linux native asset fix: the GroupDocs.Metadata published nuspec declares only <dependency id="SkiaSharp"> — neither SkiaSharp.NativeAssets.Linux.NoDependencies nor any other native-asset package is listed. This is fine for normal application consumers (the .NET runtime loads natives from the consumer's resolved package graph), but <PackAsTool>true</PackAsTool> packages a self-contained tool layout — the runtimes/<rid>/native/ content is only copied for RIDs whose native-asset packages are in this project's resolved graph. Win32 and macOS native libs reach the MCP package transitively through some other Aspose dep; Linux doesn't. Adding the explicit SkiaSharp.NativeAssets.Linux.NoDependencies reference here patches the gap until the upstream GroupDocs.Metadata nuspec is fixed to declare it directly. Tied to $(SkiaSharp) so the lock-step is one property edit at every upstream bump rather than scattered.
libgdiplus / System.Drawing.Common Linux fix: Microsoft made System.Drawing.Common Windows-only by default in .NET 6 — non-Windows callers throw PlatformNotSupportedException from the static initializer unless the System.Drawing.EnableUnixSupport runtime config flag is set. The flag must be declared on the entry-point project (the one that emits runtimeconfig.json), not on a referenced library — so even though the upstream GroupDocs.Metadata.csproj source has it, the flag doesn't propagate to consumers. Combined with the missing libgdiplus system package in the Debian-based runtime image (the mcr.microsoft.com/dotnet/aspnet:10.0 base intentionally omits it for image-size reasons), every JPEG/PNG read_metadata call on Linux failed. Both pieces are required: opt-in alone gives DllNotFoundException, libgdiplus alone gives PlatformNotSupportedException. The fix has a hard expiry — the EnableUnixSupport flag was removed in System.Drawing.Common 7.0+; GroupDocs.Metadata 26.x pins 6.0.0 so the flag still works. If upstream ever bumps past 6.0.0 without migrating off System.Drawing, this stops working and the consumer needs a different escape hatch.
README polish: users upgrading the package on their own cadence (every 1–2 months in the typical case) shouldn't have to copy-paste a new version into their MCP client config every release. The unpinned form is the natural default for solo / dev use; pinning is the deliberate choice for committed / CI configs. Mirrors how npx / dnx are typically used elsewhere. The new Documentation & guides section makes the companion test repo (which already provides per-channel walkthroughs) discoverable from the canonical README — previously users hit the package page with no hint that step-by-step guides exist outside this repo.
Docker image OCI labels: the published image inherited org.opencontainers.image.version from the base mcr.microsoft.com/dotnet/aspnet:10.0 image, which sets the label to the Ubuntu OS version (24.04). Verified by inspecting ghcr.io/groupdocs-metadata/metadata-net-mcp:latest:
$ docker inspect ... --format '{{index .Config.Labels "org.opencontainers.image.version"}}'
24.04
Effect: every release pushed to ghcr.io / Docker Hub since the project began carries the same 24.04 version label, regardless of whether the underlying GroupDocs.Metadata.Mcp version is 26.4.0 or 26.4.3. The label is one of the standard ways tooling (Renovate, Dependabot, registry UIs, security scanners) infers what's running, and a wrong/stuck value defeats them.
After this fix, docker inspect ghcr.io/groupdocs-metadata/metadata-net-mcp:26.4.4 will return "version":"26.4.4". Local docker build runs without --build-arg VERSION=... get version=dev — self-identifying as a non-release build instead of inheriting the misleading 24.04.
The other six labels (title, description, source, url, licenses, vendor) are static — they don't need to change between releases — but were missing entirely from the inherited set, so registries and clients couldn't surface basic metadata about what the image is or who publishes it.
Migration / impact
- No API changes, no tool changes, no breaking config changes. The csproj edit produces a larger published nupkg (~8 MB extra for the Linux native libs), the Docker image grows ~3 MB compressed for libgdiplus + libfontconfig1, and consumers see the same MCP tool surface. The Docker label additions are pure metadata — container behaviour is identical.
- For users on Linux: 26.4.3 was effectively broken in two stages —
dnxcrashed during finalization on first SkiaSharp use (server never started), and even when it ran (Docker), JPEG/PNG metadata reads threwPlatformNotSupportedException. 26.4.4 is the first release thednxflow works on Linux at all, *and...
26.4.3
MCP Registry NuGet ownership marker + corrected registry URL
What changed
- README.md — added
<!-- mcp-name: io.github.groupdocs-metadata/groupdocs-metadata-mcp -->footer marker. The MCP Registry reads this from the published NuGet package as the NuGet-side ownership proof, complementing the GitHub OIDC namespace claim. - src/GroupDocs.Metadata.Mcp/.mcp/server.json —
packages[0].registryBaseUrlchanged fromhttps://api.nuget.orgto the fully-qualified V3 indexhttps://api.nuget.org/v3/index.json, which is what the Registry's server-side validation expects forregistryType: nuget. - .github/workflows/publish_prod.yml — removed the
MCP_REGISTRY_PUBLISHopt-in variable gate; thepublish_mcp_registryjob now runs on every release via GitHub OIDC, consistent with how NuGet and Docker publishing work. - RELEASE.md — dropped the opt-in variable from the secrets/variables table, removed the "One-time MCP Registry setup" section (replaced with a shorter namespace-verification note), and synced
main→masterthroughout to match the repo's actual default branch.
Why
26.4.2 reached NuGet and both container registries cleanly but the MCP Registry publish failed twice — first on a URL-format check, then on the missing ownership marker (which NuGet packages treat as immutable, so 26.4.2 couldn't be retro-fixed). 26.4.3 lands all three corrections in one shot so the full four-channel release pipeline (NuGet + ghcr.io + Docker Hub + MCP Registry) publishes end-to-end from a single tag.
Migration / impact
None for consumers. No API changes, no tool changes. The README gains an HTML-comment footer that's invisible when rendered.
Full Changelog: 26.4.2...26.4.3
26.4.2
Fix Docker image + enable MCP Registry publishing
What changed
- docker/Dockerfile — switched from a custom
adduserstep toUSER $APP_UID, the non-root user pre-shipped bymcr.microsoft.com/dotnet/aspnet:10.0(UID 1654). The previousaddusercommand was Debian-specific and broke on the Azure Linux base image that Microsoft now uses for .NET 10. - src/GroupDocs.Metadata.Mcp/.mcp/server.json — shortened
descriptionto fit the MCP schema's 100-character cap and dropped inaccurate "write" wording (the server only exposesReadMetadataandRemoveMetadata, no write tool). - .github/workflows/run_tests.yml — replaced the ajv-cli schema-validation step with
check-jsonschema, which handles the MCP schema's cross-draft$refto the draft-07 meta-schema natively instead of tripping ajv's strict mode. - MCP Registry publishing enabled —
MCP_REGISTRY_PUBLISH=truerepo variable now set, sopublish_prod.yml → publish_mcp_registryruns on every release via GitHub OIDC.
Why
The 26.4.1 release succeeded on NuGet but the Docker image build blew up on the adduser step (Azure Linux base doesn't ship Debian's adduser wrapper), and the MCP Registry step was gated behind an opt-in variable that hadn't been set — so 26.4.1 was never listed at registry.modelcontextprotocol.io. 26.4.2 is the end-to-end verification that all three channels (NuGet + Docker + MCP Registry) publish cleanly from a single release.
Migration / impact
None for consumers. No API changes, no behaviour changes — same two tools, same env vars, same schema.
Full Changelog: 26.4.1...26.4.2
26.4.1
Fix repository URL + bump Core to 26.4.1
What changed
PackageProjectUrl,RepositoryUrl, andPackageReleaseNotesin build/dependencies.props now use the canonical repo URLhttps://github.com/groupdocs-metadata/GroupDocs.Metadata.Mcp. Previous value (groupdocs/groupdocs-metadata-mcp) was wrong on both the org and the casing.- src/GroupDocs.Metadata.Mcp/.mcp/server.json
repository.urlupdated to the same canonical URL and MCP Registrynamealigned toio.github.groupdocs-metadata/groupdocs-metadata-mcpso GitHub OIDC namespace verification succeeds. Bothversionfields bumped to26.4.1. - README.md —
dnx GroupDocs.Metadata.Mcp@…pinned version updated in all three snippets (install, Claude Desktop, VS Code). - Upgraded
GroupDocs.Mcp.Coredependency from26.4.0to26.4.1(which carries the matching URL fix for the Core packages).
Why
git clone against the hyphenated URL redirected, but deep links like /releases/tag/26.4.0 on the NuGet "Project website" button did not — users hit a GitHub 404 instead of the release notes.
Migration / impact
None for consumers upgrading from 26.4.0 to 26.4.1 — no API changes, just metadata corrections. The next nuget.org listing will link correctly.
Full Changelog: https://github.com/groupdocs-metadata/GroupDocs.Metadata.Mcp/commits/26.4.1