Brief orientation for AI coding agents (Claude Code, Copilot, Cursor, Aider, Amp, Codex) working in this repository.
Integration tests for the GroupDocs.Viewer.Mcp NuGet package — an MCP server that exposes GroupDocs.Viewer for .NET as AI-callable tools.
This repo is not the server itself. The server lives at groupdocs-viewer/GroupDocs.Viewer.Mcp. This repo:
- Consumes only the published NuGet artifact (no project references).
- Launches the server via
dnx, connects as an MCP stdio client, and exercises every advertised tool. - Doubles as a copy-pasteable set of example configs and how-to guides for all deployment channels (NuGet, Docker, MCP registry, Claude Desktop, VS Code).
src/GroupDocs.Viewer.Mcp.Tests/
Fixtures/
McpServerFixture.cs ← launches dnx child process, wires stdio MCP client
SampleDocuments.cs ← builds a synthetic PDF with /Contents stream at runtime
ToolCatalog.cs ← keyword-based tool name resolution (render, viewinfo)
ToolResponse.cs ← CallToolResult text/JSON/image extraction
CommandResolver.cs ← cross-platform dnx.cmd resolution on Windows
PackageVersion.cs ← pulls version from env / assembly metadata / default
ToolDiscoveryTests.cs ← handshake, tools/list, schema validation
RenderPageTests.cs ← synthetic + real-sample rendering; verifies BOTH text and image content blocks
GetViewInfoTests.cs ← file type, page count, per-page dimensions for synthetic + real samples
ErrorHandlingTests.cs ← unknown file, corrupted bytes, password parameter
GroupDocs.Viewer.Mcp.Tests.csproj
.github/workflows/integration.yml ← matrix × 3 OS, nightly cron, release-smoke dispatch
changelog/ ← one MD file per change (NNN-slug.md)
how-to/ ← user-facing guides for every deployment channel
examples/ ← claude-desktop.json, vscode-mcp.json, docker-compose.yml
sample-docs/ ← drop real fixture files here; copied to test output
Directory.Build.props ← McpPackageVersion property (overridable)
global.json ← pinned to .NET 10.0.100
| Area | Covered by |
|---|---|
Package installs and starts via dnx |
McpServerFixture |
| MCP handshake, server info, version | ToolDiscoveryTests |
RenderPage — synthetic PDF + real-sample theory; verifies both TextContentBlock and ImageContentBlock in the response |
RenderPageTests |
GetViewInfo — file type, page count, per-page dimensions for synthetic + real samples |
GetViewInfoTests |
| Unknown / corrupted files, password parameter | ErrorHandlingTests |
# Restore + build
dotnet restore
dotnet build -c Release
# Run all tests against the default package version
dotnet test -c Release
# Run against a specific published version
dotnet test -c Release -p:McpPackageVersion=26.7.0
# or
MCP_PACKAGE_VERSION=26.7.0 dotnet test -c Release
# Unlock licensed-mode tests (drops watermarks)
GROUPDOCS_LICENSE_PATH=/path/to/GroupDocs.Total.lic dotnet test -c Release
# Run just the discovery suite (fastest — no tool invocations)
dotnet test -c Release --filter "FullyQualifiedName~ToolDiscovery"-
Keyword-based tool resolution.
ToolCatalog.RenderPageresolves by"render",ToolCatalog.ViewInfoby"viewinfo". The MCP C# SDK currently uses the method name verbatim (PascalCase:RenderPage,GetViewInfo) — keyword resolution keeps tests robust against future renames / casing convention changes. -
Synthetic PDF with real content.
SampleDocuments.csbuilds a minimal PDF with both an Info dict (for the metadata-based assertions) AND a/Contentsstream drawing visible text viaBT /F1 24 Tf … (text) Tj EToperators. This guaranteesRenderPageproduces non-trivial PNG output andGetViewInforeports a real page count + dimensions. -
RenderPagereturnsCallToolResultdirectly. UnlikeGetViewInfo(which returns a JSON string wrapped in aTextContentBlockserver-side),RenderPagebuilds aCallToolResultwith two content blocks: aTextContentBlock(saved file path) and anImageContentBlock(PNG bytes inline). Tests assert on both — seeRenderPageTests.RenderPage_AuthoredPdfPage1_ReturnsTextAndImageContentBlocks. -
Evaluation-mode handling.
GroupDocs.Viewerproduces watermarked output in eval mode, never throws. Tests assert non-error responses + output-file existence in both modes — they don't branch onGROUPDOCS_LICENSE_PATHfor happy-path assertions. -
No project references to the server. The csproj only references
ModelContextProtocol1.1.0. If the server source breaks in the sibling repo, these tests still pass — they validate the shipped NuGet artifact.
- Changelog entries required — any PR that changes behaviour adds
changelog/NNN-slug.md(schema inchangelog/README.md). - How-to guides track deployment reality — if the main repo publishes a new channel (e.g. new Docker registry), add a guide under
how-to/and updateREADME.md. - Version bumps flow through
Directory.Build.props—<McpPackageVersion>is the single source of truth for "what version are we testing." CI overrides it via env var / workflow input. - Tests must not require the main repo's source. If a test needs a server-side change, file an issue there — don't work around it here.
- Target framework is
net10.0only — required bydnxand the MCP SDK.
The main repo's publish_prod.yml should fire a repository_dispatch with event_type=nuget-published after dotnet nuget push succeeds. The workflow in .github/workflows/integration.yml consumes client_payload.package_version and runs the matrix against the just-published version.
- Do not add a
ProjectReferenceto the main repo'sGroupDocs.Viewer.Mcp.csproj. This repo exists to test the shipped NuGet, not the source. - Do not hardcode tool names as string literals (
"render"). UseToolCatalog.RenderPage.Name/ToolCatalog.ViewInfo.Name. - Do not commit real license files or binary fixtures with unclear provenance. License goes through the
GROUPDOCS_LICENSECI secret; fixtures insample-docs/must be self-authored or CC0/Apache-2.0. - Do not assume
RenderPagereturns a string — it returns aCallToolResultwith both text and image content blocks. Tests must useToolResponse.Image(result)to access the PNG.