Skip to content

(feat): add --console-url testing flag for OAuth against alternative consoles#81

Merged
ChiragAgg5k merged 2 commits into
mainfrom
feat/console-url-testing-flag
Jul 16, 2026
Merged

(feat): add --console-url testing flag for OAuth against alternative consoles#81
ChiragAgg5k merged 2 commits into
mainfrom
feat/console-url-testing-flag

Conversation

@ChiragAgg5k

Copy link
Copy Markdown
Member

What

Adds a centralized testing-flag registry and its first flag, --console-url / MCP_CONSOLE_URL, so testers can run the hosted OAuth flow through a pre-release console (e.g. the new console at new.appwrite.io) instead of the production console.

Why

The Appwrite authorization server hard-codes its login/consent redirect to the production console (_APP_CONSOLE_OAUTH2_AUTHORIZATION_URL server-side), so testers had no way to exercise MCP OAuth against the new console.

How

  • flags.py (new) — central registry: each flag declares CLI name, env var, and help once, and automatically gets the --<name> argument and $<ENV> variable. The environment is the runtime source of truth; values are read at request time so tests toggle them via os.environ.
  • auth.py — with the flag set, protected-resource metadata names the MCP server itself as the authorization server, and the mirrored discovery document rewrites only authorization_endpoint to a local proxy. Token/registration/JWKS endpoints stay upstream, so token validation is unchanged.
  • http_app.py — new /oauth2/authorize proxy (404 when the flag is off): forwards the request to the real authorize endpoint (keeping upstream validation), rewrites the …/console/oauth2/consent redirect to <console-url>/oauth2/consent, and passes error redirects / non-redirect responses through verbatim. Also adds a /.well-known/openid-configuration alias for clients that discover via OIDC.
  • docs/flags.md (new) — how to add a flag, enable it (CLI or env), and verify it (curl checks per hop + full claude mcp add flow). Linked from AGENTS.md.

Verification

Verified end to end against new.appwrite.io: discovery → local authorize proxy → new-console sign-in + consent → authorization code → PKCE token exchange (with RFC 8707 resource) → authenticated MCP initialize, tools/list, and tools/call against the flag-enabled server.

New console sign-in Consent
reached via the local authorize proxy approved, code delivered to local callback

Found during testing (separate issue, new console repo): the new console's consent page drops the RFC 8707 resource query parameter when replaying the authorize call, so grants are created without resource indicators and spec-compliant MCP clients fail token exchange with invalid_target. Reproduced with this flag on vs. off; the full chain works when resource is preserved.

Unit tests: 173 pass; ruff/black/pyright clean.

…consoles

Introduces a central testing-flag registry (flags.py): each flag declares
its CLI name, env var, and help text once, and gets the --<name> argument
and $<ENV> variable automatically, with the environment as the runtime
source of truth.

First flag: --console-url / MCP_CONSOLE_URL. The upstream authorization
server hard-codes its consent redirect to the production console, so when
the flag is set the MCP server advertises itself as the authorization
server, mirrors the upstream discovery document with authorization_endpoint
pointing at a local /oauth2/authorize proxy, and the proxy forwards to the
real authorize endpoint and rewrites the consent redirect to the override
console (e.g. https://new.appwrite.io). Token, registration, and JWKS
endpoints stay upstream, so token validation is unchanged.

Verified end to end against new.appwrite.io: discovery -> local proxy ->
new console login/consent -> code -> PKCE token exchange -> authenticated
MCP initialize/tools/call. docs/flags.md documents how to add, enable, and
test flags.
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a centralized testing-flag registry (flags.py) and its first flag, --console-url / MCP_CONSOLE_URL, so testers can run the hosted OAuth flow through a pre-release Appwrite Console without modifying production configuration.

  • flags.py: Declares each flag once (CLI name + env var + help); apply_cli_args uses an is not None guard so --console-url \"\" correctly clears a shell-exported env var, and value() normalizes trailing slashes.
  • http_app.py: New /oauth2/authorize proxy (404 when the flag is off) forwards authorize requests to the real Appwrite endpoint, rewrites only the consent redirect to <console-url>/oauth2/consent (guarding the empty-query case to avoid a trailing bare ?), and passes error redirects through verbatim; also adds /.well-known/openid-configuration as a discovery alias.
  • auth.py: When the flag is active, protected-resource metadata advertises the MCP server as the authorization server and the mirrored discovery document rewrites only authorization_endpoint; token validation in AppwriteTokenVerifier continues to use the un-proxied cached metadata so JWKS/issuer checks remain against the real Appwrite server.

Confidence Score: 5/5

Safe to merge — the flag is opt-in and off by default, all three concerns raised in the prior review round are addressed, and the core token-validation path is untouched.

The change is well-scoped: production behavior is unchanged when MCP_CONSOLE_URL is unset, the proxy 404s cleanly when the flag is off, and AppwriteTokenVerifier reads the un-proxied discovery cache so JWKS/issuer validation continues against the real Appwrite server. The empty-query bare-? fix and the CLI-empty-value-clears-env behavior are both present and covered by new tests.

No files require special attention.

Important Files Changed

Filename Overview
src/mcp_server_appwrite/flags.py New central registry for testing flags; value() normalizes correctly so --console-url "" clears an env-set flag via the is not None guard in apply_cli_args
src/mcp_server_appwrite/auth.py Adds console-override helpers; token validation in AppwriteTokenVerifier still reads the un-proxied cached metadata so issuer/JWKS validation remains against the real Appwrite server
src/mcp_server_appwrite/http_app.py Adds authorize proxy and OIDC alias; consent-URL rewrite correctly guards the empty-query case, error redirects pass through verbatim, and the endpoint 404s when the flag is unset
tests/unit/test_http_app.py New ConsoleOverrideTests covers discovery rewrite, consent-redirect with and without query params, error-redirect pass-through, 404 when flag unset, and CLI-empty-value clearing
src/mcp_server_appwrite/server.py Wires flag CLI registration and env application correctly; apply_cli_args is called after the stdio early-return so flags correctly apply only in HTTP mode

Reviews (2): Last reviewed commit: "(fix): address review — no bare '?' on q..." | Re-trigger Greptile

Comment thread src/mcp_server_appwrite/http_app.py Outdated
Comment thread src/mcp_server_appwrite/flags.py
Comment thread tests/unit/test_http_app.py
…CLI can clear env-set flags

- The consent-redirect rewrite no longer emits a trailing bare '?' when the
  upstream Location has no query string.
- Flag CLI arguments now default to None instead of mirroring the env var, so
  an explicit --console-url "" clears a flag exported in the shell while an
  omitted argument leaves the environment untouched.
- Tests: query-less consent redirect, 404 when the flag is unset, and CLI
  clear-vs-omit semantics.
@ChiragAgg5k
ChiragAgg5k merged commit 4087a93 into main Jul 16, 2026
5 checks passed
@ChiragAgg5k
ChiragAgg5k deleted the feat/console-url-testing-flag branch July 16, 2026 03:52
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