Commit Graph

4 Commits

Author SHA1 Message Date
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
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 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 a37630aeac Initial commit: Paperless-ngx MCP Server
A Model Context Protocol (MCP) server for Paperless-ngx document management.

Features:
- Full CRUD operations for documents, tags, correspondents, document types,
  storage paths, and custom fields
- Document upload with retry logic (base64 and file path)
- Bulk operations with dry-run support
- Search with full-text and metadata filtering
- Pagination support across all list operations
- Proper error handling with McpResponse wrapper

Built with .NET 10 and the official MCP SDK.

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

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