Files
PaperClipAI/server
Devin FoleyandPaperclip 878734a061 fix(tools): treat OAuth sign-in challenges as client errors (#13786)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connected apps can require OAuth sign-in before they list their
tools.
> - Remote discovery recognizes this condition as `oauth_challenge`.
> - Discovery and catalog refresh currently return it as HTTP 502.
> - The server error handler reports that response as a crash.
> - This pull request returns HTTP 422 for the explicit sign-in
challenge.
> - The operator keeps the sign-in instructions, while unexpected
upstream failures remain reportable.

## Linked Issues or Issue Description

**What happened?**

Connecting a remote MCP app that answers with a recognized OAuth
challenge returns HTTP 502. Reading an empty catalog or explicitly
refreshing it does the same. The server error handler then sends the
expected sign-in condition to error monitoring.

**Expected behavior**

A known sign-in requirement returns HTTP 422 with the existing
`oauth_challenge` code, message, and setup/reconnect links. An
unexplained upstream HTTP 400 or an unavailable upstream service still
returns 502 and reaches error monitoring.

**Steps to reproduce**

1. Configure a remote MCP app that returns HTTP 401 with a Bearer
challenge.
2. Connect the app, read its empty catalog, or request a catalog
refresh.
3. Observe HTTP 502 and a server error report before this change.

**Paperclip version or commit**

Reproduced on `6de50ba594b15efaa3eae6ed869cd39b3a436456`.

**Deployment mode**

Server with remote MCP connections. The regression coverage uses local
PostgreSQL and mocked upstream HTTP responses.

Related: #9750 addresses MCP initialization and session recovery. It
does not change the classification of this recognized sign-in condition.
Targeted searches found no duplicate classification PR.

## What Changed

- Return 422 for `oauth_challenge` from discovery and from catalog
health-error normalization.
- Preserve the existing structured error and remediation links.
- Test automatic empty-catalog reads and explicit refreshes. Verify that
OAuth challenges produce no Sentry capture and that upstream 400/503
failures still do.
- Update the direct-connect and blocked-redirect expectations and
document the monitoring behavior.

## Verification

- Before the fix, three sign-in route regressions fail with 502 instead
of 422; all four upstream-error controls pass.
- After the fix, all 339 tool-access and error-handler tests pass,
including authorization and redirect protections.
- These suites ran against disposable Homebrew PostgreSQL 16.14 through
the existing test-constructor seam. The temporary setup and config
remain outside the repository. CI uses the ordinary embedded PostgreSQL
setup.
- Direct server `tsc --noEmit` passes.
- Full build and recursive typecheck were attempted; the Runner Rust
step cannot run because `cargo` is absent on this machine.
- Full `pnpm test:run`: 8,211 passed, 14 failed, 4,759 skipped. The 36
failed files match the existing embedded PostgreSQL startup/cleanup and
macOS runtime-cache `EACCES` limitations. The changed database-backed
service suite passed separately with local PostgreSQL.
- Greptile: 5/5 with no unresolved comments. Seven CI workers received a
simultaneous shutdown signal; the failed jobs are being retried through
the normal workflow. Other completed checks passed.

## Risks

Low risk. Clients now receive 422 instead of 502 for the explicit
`oauth_challenge` condition. The code, message, and remediation links
remain available. No permissions, credential handling, OAuth discovery
rules, retry policy, or schema change. Other upstream failures retain
their existing behavior.

## Model Used

OpenAI GPT-6 via Codex, with reasoning, repository inspection, code
editing, and test execution. The session does not expose an exact model
snapshot or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (339 service and
error-handler tests; full workspace limitations are documented above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-22 00:34:45 +00:00
..