Skip to content

Self-hosted Executor needs an OAuth callback handoff for loopback-only MCP providers #1439

Description

@salmonumbrella

@RhysSullivan this feels like a core self-hosting gap rather than a provider-specific setup issue.

The value of Executor for me is connecting integrations once in a self-hosted environment, then making them available to any agent or harness through one governed endpoint. That breaks when a remote MCP supports OAuth and dynamic client registration but only permits loopback or vendor-approved callback URLs.

Reproduction

  • Self-hosted Executor v1.5.34 on a remote Linux host with a stable HTTPS origin.
  • Connect the official Airwallex AgentOS MCP at https://mcp.airwallex.com/mcp.
  • OAuth discovery works.
  • Dynamic client registration succeeds when given the self-hosted HTTPS callback.
  • oauth.start correctly generates the configured HTTPS callback.
  • Airwallex authorization then rejects it with: invalid_request: Redirect URI does not match allowed patterns.
  • The same MCP authorizes from a local client using a 127.0.0.1 callback.

No private hostname, account, organization, OAuth state, credentials, or full authorization URL is included here.

Current gap

oauth.clients.createHandoff does not cover this case. It opens the form for a manually registered confidential client; it does not relay a browser callback from a local machine to a remote Executor OAuth session.

Changing the global self-hosted origin to localhost is not a scalable workaround. It disrupts the normal HTTPS deployment and still requires tunneling and lifecycle changes just to authorize one provider.

Ask

Could self-hosted Executor support one of these?

  1. An opt-in Executor-hosted callback broker that securely returns the completed authorization to the self-hosted instance.
  2. A CLI or desktop loopback companion that receives the provider callback and resumes the remote Executor OAuth session.
  3. A paste or relay handoff where a locally completed callback URL can resume the server-side session.

At minimum, detecting this provider restriction and surfacing the supported path would make the failure actionable.

This resembles #770, but dynamic registration succeeds here. The failure happens during authorization because the provider rejects the remote callback pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions