Skip to content

feat(neon-auth): make Neon Auth prerequisite explicit and approval-gated in get/configure#262

Open
Shridhad wants to merge 1 commit into
mainfrom
feat/neon-auth-prereq-hints
Open

feat(neon-auth): make Neon Auth prerequisite explicit and approval-gated in get/configure#262
Shridhad wants to merge 1 commit into
mainfrom
feat/neon-auth-prereq-hints

Conversation

@Shridhad
Copy link
Copy Markdown
Collaborator

Summary

Both get_neon_auth_config and configure_neon_auth require Neon Auth to already be provisioned for the target branch. Today, when that prerequisite isn't met, the response leaves the LLM with two bad options:

  1. Chain into provision_neon_auth automatically — but provisioning has side effects (creates the neon_auth schema, deploys an auth service, may incur cost), so silent auto-provisioning is the wrong UX.
  2. Surface a generic per-operation 404 (e.g. Failed to add trusted origin (404 Not Found). Ensure Neon Auth is provisioned…) — but that's ambiguous; on update_oauth_provider a 404 could equally well mean "unknown OAuth provider id".

This PR tightens both layers so the LLM gets a single, actionable message and an explicit approval gate.

What changed

Tool descriptions (landing/mcp-src/tools/definitions.ts)

Added a PREREQUISITES: block to both get_neon_auth_config and configure_neon_auth, in the same prose style as the existing SECURITY: block. Spells out (a) the side effects of provisioning and (b) the requirement to surface the prerequisite to the user and obtain explicit approval before calling provision_neon_auth.

Shared "not provisioned" message (landing/mcp-src/tools/handlers/neon-auth-config.ts)

Added a single canonical NEON_AUTH_NOT_PROVISIONED_MESSAGE constant exported from neon-auth-config.ts so both handlers render exactly the same wording. Wording is deliberately prescriptive about the approval gate.

Pre-flight probe in configure_neon_auth

Added an internal ensureNeonAuthProvisioned() helper that calls getNeonAuth once at the top of handleConfigureNeonAuth. On 404 it returns the canonical message and short-circuits before any per-op SDK call; on 200 it proceeds; on other statuses it returns a generic "Failed to verify Neon Auth provisioning" error so a 5xx outage can't be misrepresented as "not provisioned".

This costs one extra GET per configure_neon_auth call but:

  • avoids ambiguity between "Neon Auth not provisioned" and op-meaningful 404s (e.g. unknown OAuth provider id on update_oauth_provider); and
  • guarantees the LLM sees the same actionable message regardless of which of the 9 operations it tried.

get_neon_auth_config 404 path

Refactored to use the shared constant instead of its previous local string; no extra round-trip (it already calls getNeonAuth).

Tests

  • Tightened the existing get_neon_auth_config 404 test to assert the approval-gate wording (ask the user, explicit approval, side effects, provision_neon_auth).
  • New handleConfigureNeonAuth prerequisite probe describe block:
    • Short-circuits add_trusted_origin (PR1 op) on getNeonAuth: 404 and verifies the per-op SDK mutation was NOT called.
    • Same for add_oauth_provider (PR2 op).
    • On getNeonAuth: 500, returns a generic verify-failed message that does NOT contain approval-gate keywords (defends against misrepresenting an outage as "not provisioned").
  • defaultSnapshotMocks() gains a default getNeonAuth: 200 mock so existing tests stay green.
  • Three pre-existing tests that intentionally hand-roll narrow neonClient mocks (the update_auth_methods schema/handler-skew test, and two send_test_email tests that assert no snapshot reload) now satisfy the prereq probe with a one-line getNeonAuth: 200 addition.

Test plan

  • pnpm run typecheck clean.
  • pnpm run lint clean.
  • pnpm run fmt:check clean.
  • pnpm run knip clean.
  • pnpm run test:unit — 338 passed (was 335; +3 new prereq tests).
  • pnpm run test:integration — 85 passed.

Notes

@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
mcp-server-neon Ignored Ignored Preview May 15, 2026 9:45am

Request Review

Both `get_neon_auth_config` and `configure_neon_auth` operate on a Neon
Auth integration that must already exist on the target branch. When that
prerequisite isn't met, today's responses leave the LLM with two bad
options: chain into `provision_neon_auth` automatically (provisioning
has side effects — schema, service deploy, possible cost) or surface a
generic 404 the user can't act on.

Tighten both layers:

- Tool descriptions: add a PREREQUISITES block to both tools that
  spells out the side effects of provisioning and tells the LLM to
  surface the prerequisite to the user and obtain explicit approval
  before calling `provision_neon_auth`.
- Handlers: add a single shared `NEON_AUTH_NOT_PROVISIONED_MESSAGE` and
  use it on the 404 path of `handleGetNeonAuthConfig`. Pre-flight
  `configure_neon_auth` with `ensureNeonAuthProvisioned` (one extra GET
  on `getNeonAuth`) so the handler returns the same actionable message
  before invoking any per-op SDK call. The probe also disambiguates
  "Neon Auth not provisioned" from op-meaningful 404s such as an
  unknown OAuth provider id on `update_oauth_provider`.

Tests:
- Existing `get_neon_auth_config` 404 test tightened to assert the
  approval-gate wording.
- New `handleConfigureNeonAuth prerequisite probe` block: short-circuit
  on a PR1 op (`add_trusted_origin`) and a PR2 op (`add_oauth_provider`)
  with both wording and "mutation SDK not called" assertions, plus a
  non-404 upstream failure that returns a generic verify-failed message
  so it can't be conflated with the provisioning prerequisite.
- `defaultSnapshotMocks()` gains a default `getNeonAuth: 200` so
  existing tests stay green; three tests that intentionally hand-roll
  narrow `neonClient` mocks now satisfy the prereq probe explicitly.
@Shridhad Shridhad force-pushed the feat/neon-auth-prereq-hints branch from d944d71 to 231b9eb Compare May 15, 2026 09:44
@Shridhad Shridhad requested a review from vadim2404 May 20, 2026 11:17
thekauer added a commit that referenced this pull request May 20, 2026
…ating tools

Ports the prerequisite-probe pattern from `#262`
(by @Shridhad) onto the restructured 8-tool surface. Without it, calling any
mutating Neon Auth tool against a branch where Neon Auth is not provisioned
yields an opaque per-op 404 — and on tools like `neon_auth_oauth_provider_update`
or `neon_auth_oauth_provider_delete` the per-op 404 is genuinely ambiguous
(unknown provider id vs auth not provisioned).

Pattern, mirrors PR #262:

- `ensureNeonAuthProvisioned()` helper in `neon-auth-utils.ts` issues a single
  `getNeonAuth()` probe up front. 200 → return null and let the handler
  proceed; 404 → short-circuit with the canonical
  `NEON_AUTH_NOT_PROVISIONED_MESSAGE` (worded to gate the LLM's next action:
  surface the prerequisite to the user, explain side effects, ask for
  explicit approval before calling `neon_auth_provision`); other status →
  generic "Failed to verify Neon Auth provisioning" so a 5xx outage cannot
  be misrepresented as "not provisioned".
- All seven non-provision handlers (methods_update, oauth_provider_*,
  domain_update, webhook_update, send_test_email) call the helper after
  branch resolution and before any per-op SDK call.
- All seven tool descriptions in `definitions.ts` gain a PREREQUISITES block
  matching the wording used by PR #262.
- Tests: integration suite gains a "Neon Auth preflight" describe block —
  404 short-circuits each major handler family without invoking the per-op
  SDK, and 5xx returns the verify-failed message (NOT the
  approval-gate message).

Cost: one extra GET per non-provision tool call. Worth it to avoid
ambiguous 404s and silent auto-provisioning.

Co-authored-by: Isaac
thekauer added a commit that referenced this pull request May 22, 2026
…ating tools

Ports the prerequisite-probe pattern from `#262`
(by @Shridhad) onto the restructured 8-tool surface. Without it, calling any
mutating Neon Auth tool against a branch where Neon Auth is not provisioned
yields an opaque per-op 404 — and on tools like `neon_auth_oauth_provider_update`
or `neon_auth_oauth_provider_delete` the per-op 404 is genuinely ambiguous
(unknown provider id vs auth not provisioned).

Pattern, mirrors PR #262:

- `ensureNeonAuthProvisioned()` helper in `neon-auth-utils.ts` issues a single
  `getNeonAuth()` probe up front. 200 → return null and let the handler
  proceed; 404 → short-circuit with the canonical
  `NEON_AUTH_NOT_PROVISIONED_MESSAGE` (worded to gate the LLM's next action:
  surface the prerequisite to the user, explain side effects, ask for
  explicit approval before calling `neon_auth_provision`); other status →
  generic "Failed to verify Neon Auth provisioning" so a 5xx outage cannot
  be misrepresented as "not provisioned".
- All seven non-provision handlers (methods_update, oauth_provider_*,
  domain_update, webhook_update, send_test_email) call the helper after
  branch resolution and before any per-op SDK call.
- All seven tool descriptions in `definitions.ts` gain a PREREQUISITES block
  matching the wording used by PR #262.
- Tests: integration suite gains a "Neon Auth preflight" describe block —
  404 short-circuits each major handler family without invoking the per-op
  SDK, and 5xx returns the verify-failed message (NOT the
  approval-gate message).

Cost: one extra GET per non-provision tool call. Worth it to avoid
ambiguous 404s and silent auto-provisioning.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant