I am looking for the supported configuration for a private OAuth authorization server on a different origin from the MCP server. Local discovery succeeds, but ChatGPT does not reach the AS through the tunnel. Custom target labels below are anonymized; URLs and observed behavior are unchanged.
Environment and expected contract
- Official tunnel-client 0.0.14, commit 0f870e5, Linux in WSL.
- Existing OpenAI Secure MCP Tunnel, ready.
- Private Streamable HTTP MCP: http://127.0.0.1:5197/mcp.
- Separate HTTPS authorization server issuer: https://127.0.0.1:5207/.
- Explicit trust of the existing local public AS certificate, hostname verification enabled.
- Redirects disabled; payload capture and raw HTTP logging disabled.
- Explicit private pre-registered public OAuth client mode in ChatGPT, token endpoint auth none, authorization-code + PKCE S256. No DCR, CIMD, OIDC identity scopes or refresh-token flow.
- The AS advertises authorization_response_iss_parameter_supported=true. Existing local regression tests pin the exact unchanged issuer in authorization responses; no ChatGPT login was performed in this trial. Issuer/audience checks must remain enabled.
Local observations
GET /mcp anonymously returns 401 with:
Bearer resource_metadata="http://127.0.0.1:5197/.well-known/oauth-protected-resource/mcp", scope="events:read"
GET that PRM URL returns 200:
{"resource":"http://127.0.0.1:5197/mcp","authorization_servers":["https://127.0.0.1:5207/"],"scopes_supported":["events:read"],"bearer_methods_supported":["header"]}
GET https://127.0.0.1:5207/.well-known/oauth-authorization-server/ returns 200 with issuer https://127.0.0.1:5207/, local browser authorization_endpoint /connect/authorize and token_endpoint /connect/token. The tunnel client's own startup AS discovery also succeeds. GET the issuer root anonymously returns 401 with no response body.
Configurations compared
Automatic private and loopback host classification are disabled. Plaintext HTTP is enabled for the exact local MCP targets. No redirect following.
The four-target registry contains:
For one specifically approved discovery-only trial, exactly this fifth target was added:
These are exact URL targets, not path prefixes. Browser authorize/account routes and JWKS were not registered. Harpoon's generic method set is GET/POST/PUT; application route/method and authentication controls remain at the local AS. No token POST, login, consent or app creation was performed in this trial.
Actual product observation
In the ChatGPT Create Plugin dialog, select the existing tunnel and OAuth, then open the advanced OAuth settings to trigger discovery.
With either registry, the product invokes Harpoon GET oauth-prmd-source-0 and gets HTTP 200. With the five-target registry, this refresh produced two successful PRM requests at 2026-09-07T21:24:30.818805752Z and 2026-09-07T21:24:31.91567641Z.
No call to the AS metadata, issuer root or token target followed. The OAuth authorization URL, token URL, AS base, resource and scope fields remained empty. No OAuth-specific warning/error was captured by the browser console inspection.
An earlier connector attempt showed the generic “does not implement OAuth” error. App creation was not submitted or reproduced in this trial; the directly observed boundary is successful PRM fetch followed by no AS call and empty discovery fields.
Source evidence and unresolved question
In v0.0.14:
- runtimeharpoon/transform.go rewrites only exact known URLs. Adding the issuer-root target makes authorization_servers[0] eligible for rewriting.
- runtimeharpoon/shared_wiring.go ConvertTargets assigns config category/source and no tags to manual targets.
- runtimeconfig/file_config.go and the public CLI target syntax have no OAuth category/role/group fields.
- oauth/hostbundle.go sets DisallowPrivateHostRegistration for the off-origin AS. runtimeharpoon/host_registration.go does not promote this separate HTTPS origin through the MCP-origin rule.
- docs/architecture.md says AS metadata uses Tunnel when its issuer is rewritten to a Harpoon-backed route; browser authorization stays direct.
What supported configuration maps this separately hosted private AS into the official OAuth shim using only explicitly registered URLs, with the required OAuth role/group association?
What exact issuer does ChatGPT retain from shimmed AS metadata, and how does it preserve equality with the browser-direct RFC-9207 iss response? Please provide a supported configuration or identify the client/service change required. Adding a root mapping alone did not make the AS request occur. We are not requesting a validation bypass, a broad AS-origin exposure, or an arbitrary proxy.
Primary sources
I am looking for the supported configuration for a private OAuth authorization server on a different origin from the MCP server. Local discovery succeeds, but ChatGPT does not reach the AS through the tunnel. Custom target labels below are anonymized; URLs and observed behavior are unchanged.
Environment and expected contract
Local observations
GET /mcp anonymously returns 401 with:
GET that PRM URL returns 200:
GET https://127.0.0.1:5207/.well-known/oauth-authorization-server/ returns 200 with issuer https://127.0.0.1:5207/, local browser authorization_endpoint /connect/authorize and token_endpoint /connect/token. The tunnel client's own startup AS discovery also succeeds. GET the issuer root anonymously returns 401 with no response body.
Configurations compared
Automatic private and loopback host classification are disabled. Plaintext HTTP is enabled for the exact local MCP targets. No redirect following.
The four-target registry contains:
For one specifically approved discovery-only trial, exactly this fifth target was added:
These are exact URL targets, not path prefixes. Browser authorize/account routes and JWKS were not registered. Harpoon's generic method set is GET/POST/PUT; application route/method and authentication controls remain at the local AS. No token POST, login, consent or app creation was performed in this trial.
Actual product observation
In the ChatGPT Create Plugin dialog, select the existing tunnel and OAuth, then open the advanced OAuth settings to trigger discovery.
With either registry, the product invokes Harpoon GET oauth-prmd-source-0 and gets HTTP 200. With the five-target registry, this refresh produced two successful PRM requests at 2026-09-07T21:24:30.818805752Z and 2026-09-07T21:24:31.91567641Z.
No call to the AS metadata, issuer root or token target followed. The OAuth authorization URL, token URL, AS base, resource and scope fields remained empty. No OAuth-specific warning/error was captured by the browser console inspection.
An earlier connector attempt showed the generic “does not implement OAuth” error. App creation was not submitted or reproduced in this trial; the directly observed boundary is successful PRM fetch followed by no AS call and empty discovery fields.
Source evidence and unresolved question
In v0.0.14:
What supported configuration maps this separately hosted private AS into the official OAuth shim using only explicitly registered URLs, with the required OAuth role/group association?
What exact issuer does ChatGPT retain from shimmed AS metadata, and how does it preserve equality with the browser-direct RFC-9207 iss response? Please provide a supported configuration or identify the client/service change required. Adding a root mapping alone did not make the AS request occur. We are not requesting a validation bypass, a broad AS-origin exposure, or an arbitrary proxy.
Primary sources