Commit Graph

61 Commits

Author SHA1 Message Date
Barry Walker 87261a0ad1 Merge pull request #8 from elarsson1/fix/runtime-type-serialization
fix(client): send populated request bodies for create/update/bulk-edit
2026-05-05 12:27:33 -04:00
Axel Larsson b0ab0dd5dd fix(client): send populated request bodies for create/update/bulk-edit
Create/update operations were sending empty request bodies to Paperless,
producing two visible failure modes:

1. POST creates (correspondents, tags, document types, storage paths,
   custom fields) returned `400 {"name":["This field is required."]}`
   even when the caller passed a valid name.
2. PATCH updates (documents, correspondents, tags, etc.) returned 200
   and bumped the row's `modified` timestamp, but no fields actually
   changed — server-side this looked like a successful no-op PATCH.
3. Bulk edit operations (`api/documents/bulk_edit/`,
   `api/bulk_edit_objects/`) failed because the inner `parameters` field
   went out as `{}`, so add_tag/remove_tag/etc. arrived without a tag id.

Reproducer: `correspondents.create(name="ACME Corp")` against a real
Paperless instance returns 400 with the body above.

Root causes are two related serialization patterns where the
compile-time type of the value to serialize is `object`:

- `PostWithResultAsync` / `PatchWithResultAsync` accept the request as
  `object` and pass it to `PostAsJsonAsync<TValue>` /
  `JsonContent.Create<T>(value, ...)`. The generic `T` is inferred as
  `object`, and through the configured DI HttpClient pipeline
  (DelegatingHandler + Polly retry policy) the body that reaches the
  wire is empty, even though the same JsonContent's
  `ReadAsStringAsync()` returns the expected JSON.
- `BulkEditDocumentsAsync` / `BulkEditObjectsAsync` wrap the call args
  in an anonymous type whose `parameters` field has compile-time type
  `object?`. System.Text.Json serializes that property against
  `object`, producing `"parameters":{}` regardless of the runtime value.

Fix: serialize against the runtime type explicitly and materialize the
JSON into a `StringContent` before the request leaves this client.
For bulk edits, build the body via `JsonObject` and serialize the
`parameters` payload against its runtime type.

Adds wire-format pinning tests for create / update / bulk_edit /
bulk_edit_objects that capture the outbound request body and assert the
expected payload shape. These do not reproduce the original bug under
MockHttp (the test helper bypasses the DI handler chain), but they pin
the new serialization for future refactors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:52:36 -07:00
Woodpecker CI c348f416f0 chore(release): bump version to 0.1.18 [skip ci] 2026-04-12 16:04:02 +00:00
Barry Walker 215cf0d39a Merge pull request #4 from barryw/fix/tool-names-replace-dots-with-underscores
fix: replace dots with underscores in tool names
2026-04-12 12:01:07 -04:00
Barry Walker a816f5296b test: add tool name validation tests for Anthropic API compliance
Reflection-based tests verify all McpServerTool names match
^[a-zA-Z0-9_-]{1,64}$ and contain no dots, preventing regressions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:57:40 -04:00
Barry Walker 561624bf78 fix: replace dots with underscores in tool names to comply with Anthropic API naming rules
Closes #2

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:55:33 -04:00
Woodpecker CI 9dff0273bc chore(release): bump version to 0.1.17 [skip ci] 2026-01-24 23:37:39 +00:00
Barry Walker c427ed258c docs: add GitHub Sponsors and Ko-fi funding links
- Add FUNDING.yml for sponsor button on repo
- Add support section to README with badges

Time to get paid for doing jack shit

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 18:34:21 -05:00
Woodpecker CI 369e31cca6 chore(release): bump version to 0.1.16 [skip ci] 2026-01-24 22:45:07 +00:00
Barry Walker f66bd18152 docs: add Claude Code installation option
claude mcp add --transport sse paperless http://localhost:5000/mcp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 17:41:55 -05:00
Barry Walker 5c1a73f3ea docs: rewrite README with personality and proper value proposition
- Lead with the problem: you have docs, no time to organize them
- Clear "Is this for you?" section
- Installation options: Docker first, then Claude Desktop, k8s, source
- Full tool reference with collapsible sections
- No more `latest` tag - link to releases badge instead
- Acknowledge this works with any MCP-compatible AI, not just Claude

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 17:39:01 -05:00
Woodpecker CI 4c2aa6910b chore(release): bump version to 0.1.15 [skip ci] 2026-01-24 22:10:03 +00:00
Barry Walker 466b1c6b0c fix(ci): add diagnostic output on deployment failure
Show pod status, events, describe, and logs when k8s rollout fails
instead of just timing out with no context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 17:06:29 -05:00
Woodpecker CI 134565bae0 chore(release): bump version to 0.1.14 [skip ci] 2026-01-24 20:15:24 +00:00
Barry Walker 7aa8fddea8 ci: add cocogitto for conventional commits and automated releases
- Add cog.toml with commit type configs and version bump hooks
- Add .woodpecker.yml pipeline for automated version bumping on main
- Add Version element to csproj for cog to update
- Document cog workflow in CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 15:11:36 -05:00
Woodpecker CI 162033fecf chore(release): bump version to 0.1.13 [skip ci] 2026-01-24 18:19:25 +00:00
Barry Walker b74a73f793 fix: disable MCP session idle timeout completely
The 24-hour timeout was still not being respected - sessions were being
killed after ~14 minutes. Using Timeout.InfiniteTimeSpan completely
disables idle-based session pruning in the SDK's IdleTrackingBackgroundService.

This makes the MCP server bulletproof against session drops during long
periods of inactivity (e.g., when users are discussing/planning before
making tool calls).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 13:15:50 -05:00
Woodpecker CI b94cef4546 chore(release): bump version to 0.1.12 [skip ci] 2026-01-14 03:48:58 +00:00
Barry Walker be44ea12f9 fix: prevent MCP session timeouts and fix JSON serialization
- Add JsonIgnoreCondition.WhenWritingNull to prevent sending null values
- Increase idle session timeout to 24 hours to prevent premature session closure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 22:44:22 -05:00
Woodpecker CI 020c0a318a chore(release): bump version to 0.1.11 [skip ci] 2026-01-14 00:16:35 +00:00
Barry Walker 3aa10461ff fix(ci): use $VAR instead of ${VAR} for shell variables
Woodpecker was interpreting ${VAR} as CI variables and replacing
them with empty strings. Changed to $VAR syntax which gets passed
through to the shell correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 19:13:54 -05:00
Barry Walker 2b479a528c fix(ci): add debugging and fix shallow clone for version detection
- Change clone depth to partial: false
- Add explicit git fetch --tags --unshallow
- Add extensive debugging output to diagnose version detection
- Check for empty commits before pattern matching

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 19:11:32 -05:00
Barry Walker 0a3a835e08 ci: add centralized versioning with conventional commit bumps
- Add Directory.Build.props for consistent version across all projects
- Add version.json to track current version in source control
- Update release pipeline to:
  - Calculate version bumps from conventional commits
  - Pass /p:Version to all build/test/pack commands
  - Commit version.json back before tagging
  - Generate changelog in GitHub releases
- Version bump rules:
  - feat!: or BREAKING CHANGE: → major bump
  - feat: → minor bump
  - fix/perf/refactor/build/ci/docs/style/test: → patch bump

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 19:08:18 -05:00
Barry Walker c67781bac5 feat: add proper error handling with full API error details
- Add ApiResult<T> type to carry success/failure with error details
- Add UpdateDocumentWithResultAsync and CreateTagWithResultAsync methods
- Update DocumentTools.Update and TagTools.Create to return actual
  HTTP status codes and response bodies in error responses
- Add comprehensive tests for error handling (18 new tests)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:59:16 -05:00
Barry Walker 39768fdd45 ci: add local git hook for conventional commit validation
Run `git config core.hooksPath .githooks` to enable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:28:31 -05:00
Barry Walker de0a3c5d84 ci: add commitlint to enforce conventional commits on PRs
Validates all commit messages in a PR follow the conventional commits
format before allowing build/test to proceed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:22:44 -05:00
Barry Walker 6cac693e9c feat: add k8s deployment pipeline and code quality improvements
- Add deploy step to Woodpecker CI release pipeline
- Create ParsingHelpers utility to deduplicate ParseIntArray/ParseDate
- Add ConfigureAwait(false) to all async calls (library best practice)
- Fix resource disposal in UploadDocumentInternalAsync
- Configure HttpClient default 30s timeout
- Remove unused GetAllPagesAsync method

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:21:00 -05:00
Barry Walker dba6c453c4 fix: use /api/status/ for ping instead of /api/
The /api/ endpoint returns HTML (Swagger UI), not JSON.
Changed ping to use /api/status/ which returns JSON with version info.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:38:26 -05:00
Barry Walker 5230dd126a fix: use TCP probes instead of HTTP for MCP endpoint
MCP endpoints return 406 for plain GET requests since they use SSE.
TCP socket probes check if the port is open without protocol issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:33:02 -05:00
Barry Walker 35f3120bad fix: restore /mcp path for MapMcp endpoint
The health probes expect the endpoint at /mcp.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:23:05 -05:00
Barry Walker eed1e4535c fix: add WithHttpTransport() for HTTP mode and add k8s manifests
HTTP transport mode was missing the required WithHttpTransport() call,
causing MapMcp() to fail. Also adds Kubernetes manifests for deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:17:02 -05:00
Barry Walker 2b7d9eaa95 docs: add CLAUDE.md for Claude Code guidance
Provides build commands, architecture overview, and development
conventions for AI-assisted development.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:08:12 -05:00
Barry Walker 0d6a73e6fb docs: add Woodpecker CI build status badge
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:49:06 -05:00
Barry Walker 30496d8e49 fix: use GitHub API directly instead of deprecated plugin
The old plugin only works on tag events. Using curl to call
GitHub API directly to create releases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:44:23 -05:00
Barry Walker 3ce5ef3897 fix: escape variables with $$ for Woodpecker preprocessing
Woodpecker evaluates ${VAR} before the shell runs. Using $$ escaping
so variables are passed to the shell properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:38:43 -05:00
Barry Walker c3d23c992d fix: try secrets directive instead of environment
Testing if secrets directive injects the token properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:37:58 -05:00
Barry Walker 60ba630824 fix: revert to github_* secret names
User has github_token and github_username configured.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:29:13 -05:00
Barry Walker cf113b75b1 fix: use ghcr_* secret names to match Woodpecker config
WeightTracker uses ghcr_username/ghcr_token, not github_*.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:28:03 -05:00
Barry Walker 6ed551f2d4 fix: add debug output and quote git URL
Check if GITHUB_TOKEN is being injected properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:23:21 -05:00
Barry Walker e12e095a82 fix: use single-line kaniko command with proper quoting
Multiline backslash continuation may have shell expansion issues.
Using single line with quoted arguments instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:18:12 -05:00
Barry Walker 627b9fdf6c fix: consolidate all multi-command steps into script blocks
Each command runs in separate shell - variables don't persist.
All steps with variable dependencies now use single script blocks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:10:44 -05:00
Barry Walker 23e7b6da2f feat: enable NuGet packaging
Add IsPackable and package metadata to csproj for NuGet package
generation in CI pipeline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:03:03 -05:00
Barry Walker 0d922b185c fix: put entire version script in single shell block
Each command runs in separate shell - variables don't persist.
Moving everything into one script block.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:55:57 -05:00
Barry Walker 7d17582fe7 fix: use POSIX-compatible shell syntax in version script
The multiline script runs in sh, not bash. Using sed instead of
bash parameter expansion for stripping the v prefix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:49:22 -05:00
Barry Walker 85aecd5b13 fix: consolidate build steps to share NuGet cache
Each step runs in a fresh container, so NuGet packages restored in one
step aren't available in the next. Consolidating restore/build/test
into single steps.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:47:19 -05:00
Barry Walker b77e5baf08 fix: target Linux runners instead of macOS
Add platform label to run on Linux runners with Docker support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:36:03 -05:00
Barry Walker 1e5d54ebb4 fix: update to .NET 10 GA images
.NET 10 is now generally available - the -preview tags no longer exist.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:48:51 -05:00
Barry Walker 31e6529bbe fix: configure clone plugin with lfs disabled
Use woodpeckerci/plugin-git with lfs: false setting instead of
skipping clone entirely.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:46:28 -05:00
Barry Walker 5cd4ef8401 fix: skip default clone to avoid LFS failure
Woodpecker's default clone step fails when git-lfs isn't installed.
Using manual clone with alpine/git instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:41:54 -05:00
Barry Walker 45ad30c0b4 fix: remove invalid clone configuration
The LFS warning is non-fatal. Removing the incorrect clone config
that was causing linter errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:36:32 -05:00