> ## Documentation Index
> Fetch the complete documentation index at: https://docs.horizon.prefect.io/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub

> Connect GitHub repositories to hosted Horizon servers, then build from commits, pushes, and pull requests.

Connect GitHub when your code lives in GitHub. After a Horizon organization
links a GitHub installation, Horizon can list the repositories that
installation grants, create hosted servers from those repositories, and start
builds when relevant Git events arrive.

The boundary is simple: GitHub owns repository access and source history.
Horizon owns the server record, build record, deployment URL, environment
selection, access policy, and observability once a repository revision is used
for a hosted server.

<CardGroup cols={2}>
  <Card title="Link repositories" icon="github" iconType="brands">
    Connect one or more GitHub accounts or organizations to a Horizon
    organization.
  </Card>

  <Card title="Build from commits" icon="code-branch">
    Resolve a selected repository branch to an exact commit before creating a
    build.
  </Card>

  <Card title="Preview pull requests" icon="code-pull-request">
    Use pull request events to create preview builds and preview deployment
    URLs.
  </Card>

  <Card title="Keep source access separate" icon="shield">
    Use GitHub access only for repository discovery and builds. MCP clients do
    not receive GitHub credentials.
  </Card>
</CardGroup>

## When to use GitHub

Use the GitHub integration when the server source lives in GitHub and Horizon
should build, deploy, and update a hosted Python MCP or FastMCP server from
that source.

GitHub works well when:

* A repository should become a hosted Horizon server.
* Default branch pushes should create new production-ready builds.
* Pull requests should create preview builds before production promotion.
* Operators need the build list to show branch, commit, pull request, and
  repository context.
* Repository permissions should stay in GitHub while Horizon manages the
  deployed MCP endpoint.

If the server already runs outside Horizon and should stay there, register it
as an [external server](/servers/external). If clients should use a composed
endpoint made from multiple servers, create a [remix server](/servers/remix).

## Integration contract

| Area             | What users can expect                                                                                                                                                                     |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Connection       | A Horizon organization can link one or more GitHub installations. Each installation belongs to a GitHub user or organization account.                                                     |
| Repository list  | Horizon lists repositories that the linked installation grants. Repositories outside the installation permission set do not appear in the picker.                                         |
| Source selection | Creating a hosted server stores the selected repository, its GitHub repository ID, full name, default branch, entrypoint, and dependency file setting.                                    |
| Build revision   | Horizon resolves a branch or pull request to a commit SHA before build work begins. Moving the branch later does not change that build.                                                   |
| Credentials      | Horizon uses repository access for discovery and build checkout. GitHub credentials are not exposed to MCP clients.                                                                       |
| Events           | Push, pull request, branch deletion, installation, and repository-permission events update Horizon records when they match a linked installation and tracked repository.                  |
| Removal          | Removing repository access or deleting the installation can make repositories unavailable to Horizon. Builds that need unavailable source access cannot proceed until access is restored. |

<Info>
  A GitHub connection does not make a server public. Hosted server
  authentication, server access, capability policy, and deployment promotion
  still follow the hosted-server contract.
</Info>

## Connect GitHub

You can connect GitHub from onboarding or from organization settings.

<Steps>
  <Step title="Open the GitHub connection flow">
    During onboarding, Horizon sends users without a linked installation to the
    GitHub connection step. In an existing organization, open
    <strong>Settings</strong> and then <strong>Integrations</strong>.
  </Step>

  <Step title="Authorize or choose an existing installation">
    Horizon opens a GitHub authorization window. If the signed-in GitHub user
    already has unlinked Horizon installations available, Horizon asks which
    account to link. Otherwise, GitHub asks the user to install or configure
    the Horizon GitHub App.
  </Step>

  <Step title="Choose repository access">
    In GitHub, select the repositories Horizon should be able to see. You can
    grant access to all repositories in the account or only selected
    repositories.
  </Step>

  <Step title="Return to Horizon">
    After GitHub redirects back, Horizon verifies the request, links the
    installation to the organization, and returns to the repository picker or
    the integrations page that started the flow.
  </Step>
</Steps>

Members and admins can start the GitHub connection flow for an organization.
The GitHub user completing the popup must administer the selected GitHub
account: the owner for a personal account, or an organization admin for a
GitHub organization. Accounts you can see but do not administer appear
disabled in the picker. If a GitHub organization installed the app before it
requested organization member read access, a GitHub organization admin must
accept the updated permissions on GitHub before that organization can be
linked to another Horizon organization.

## Repository picker

The repository picker shows repositories from every GitHub installation linked
to the active Horizon organization. Repositories are sorted by recent update
time, include public or private visibility, and show the repository default
branch.

When you select a repository, Horizon carries this information into the hosted
server setup form:

* repository full name
* repository visibility
* GitHub installation ID
* default branch
* suggested server name

If no GitHub installation is linked, Horizon redirects the repository picker to
the GitHub connection flow. If a repository is missing, edit repository
permissions from <strong>Settings</strong> > <strong>Integrations</strong>,
then refresh the picker.

## Create a hosted server

After selecting a repository, Horizon asks for the server configuration that
turns the repository into a hosted MCP endpoint.

| Field                 | Behavior                                                                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Server name           | Determines the Horizon server name and the deployment slug preview.                                                                                                            |
| Entrypoint            | Points to the Python file, and optional object name, that defines the MCP server. Horizon validates the path format and can check that the file exists in the selected branch. |
| Authentication        | Horizon authentication is enabled by default. Disabling it is available only when the organization plan allows it.                                                             |
| Dependency file       | Optional. Use it when dependencies are not in the file Horizon would otherwise discover.                                                                                       |
| Environment variables | Optional `KEY=value` lines. Names must use uppercase letters, numbers, and underscores, and must start with a letter or underscore.                                            |

When you submit the form, Horizon runs through these steps:

<Steps>
  <Step title="Fetch repository metadata and default branch" />

  <Step title="Resolve the default branch to a commit" />

  <Step title="Create the server record" />

  <Step title="Create a default branch record" />

  <Step title="Queue the first build" />

  <Step title="Create the first deployment record" />

  <Step title="Run the build in the background" />
</Steps>

<Note>
  The first build uses the repository default branch at the time Horizon creates
  the server. Later changes to the default branch create later builds; they do
  not rewrite the first build.
</Note>

## What GitHub events do

Horizon processes GitHub events only when they match a linked installation and
a repository already tracked by a hosted server.

| Event                             | Horizon behavior                                                                                                                                    |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default branch push               | Creates a queued build and deployment record for the tracked default branch, unless the same commit already has a build for that server and branch. |
| Non-default branch push           | Creates a preview build only when Horizon is already tracking that branch for an open pull request.                                                 |
| Pull request opened or reopened   | Creates a branch record, queued build, and preview deployment for each matching hosted server.                                                      |
| Pull request synchronized         | Creates a new queued build and preview deployment for the updated pull request head commit.                                                         |
| Pull request closed without merge | Removes the preview branch record for the matching server and repository.                                                                           |
| Branch deleted                    | Removes the matching branch record from Horizon.                                                                                                    |
| Repository access added           | Makes the repository available to linked Horizon organizations after repository data refreshes.                                                     |
| Repository access removed         | Removes the repository from Horizon's authorized source records and starts cleanup for related deployment resources.                                |
| Installation deleted              | Removes the linked installation record from Horizon.                                                                                                |

A repository can back more than one hosted server. On a matching push or pull
request event, Horizon queues a build for every hosted server that tracks that
repository and branch. In a monorepo, changing files for one server does not
currently skip builds for the other matching servers.

If a pull request existed before the hosted server was created, Horizon may not
create an automatic preview for that older pull request. Create a new pull
request after the server exists, or use the dashboard workflow for the revision
you want to test.

## Production and preview behavior

Default branch builds and pull request builds use different deployment
contexts.

| Context              | Source                             | Environment scope                                      | Deployment behavior                                                                  |
| -------------------- | ---------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| Production candidate | The tracked default branch commit. | Production variables.                                  | The build can become the live deployment through the production deployment workflow. |
| Pull request preview | The pull request head commit.      | Preview variables, with optional deployment overrides. | Horizon creates or updates a preview deployment URL for that branch.                 |

Successful preview builds do not automatically change production traffic. A
successful default branch build also does not mean clients changed endpoints;
confirm which build the live deployment currently selects on the
[Deployments](/deployments) page.

## Repository access and missing source

Repository access can change outside Horizon. The most common symptoms are a
missing repository in the picker, a build that cannot read source, or a private
repository build that cannot start.

<AccordionGroup>
  <Accordion title="The repository is missing from the picker">
    Open <strong>Settings</strong> > <strong>Integrations</strong>, choose
    the GitHub installation, and edit repository permissions in GitHub. After
    the repository is granted to the installation, refresh the picker.
  </Accordion>

  <Accordion title="The entrypoint or dependency file cannot be verified">
    Confirm the file path is relative to the repository root, does not include
    parent-directory references, and exists on the selected branch. For an
    entrypoint with an object name, use <code>server.py:object\_name</code>.
  </Accordion>

  <Accordion title="A pull request did not create a preview">
    Confirm the server was already tracking the repository when the pull
    request was opened, the pull request branch is still open, and the branch
    has not been removed from Horizon.
  </Accordion>

  <Accordion title="A build uses an older commit than the branch tip">
    Builds are tied to the commit SHA resolved when the build was queued. Open
    the build details and compare the recorded commit with the current branch
    tip.
  </Accordion>

  <Accordion title="A connected installation shows no repositories">
    The installation may have no selected repositories, access may have been
    removed, or GitHub may not be returning repositories for that installation.
    Edit permissions from the integrations page and try again.
  </Accordion>
</AccordionGroup>

## Security boundary

GitHub source access is separate from Horizon endpoint access.

* GitHub permissions decide which repositories Horizon can discover and build.
* GitHub installation administration decides who can link an installation: the
  account owner for a personal account, or an organization admin for a GitHub
  organization.
* Horizon organization membership decides who can start the integration flow in
  Horizon.
* Server access and capability policies decide who can use the deployed MCP
  endpoint.
* Build-time repository access is not returned to MCP clients.
* Environment variables and secrets are scoped through Horizon deployment
  settings, not through GitHub repository visibility.

This separation means a user can have access to a deployed Horizon endpoint
without having access to the underlying GitHub repository, and a GitHub
collaborator does not automatically receive access to the Horizon server.

## Related docs

<CardGroup cols={2}>
  <Card title="Hosted servers" icon="server" href="/servers/hosted">
    Understand the hosted-server contract across source, builds, deployments,
    gateway access, runtime, and observability.
  </Card>

  <Card title="Build system" icon="hammer" href="/platform/build-system">
    See how Horizon packages Python MCP and FastMCP source into build
    artifacts.
  </Card>

  <Card title="Builds" icon="code-branch" href="/builds">
    Review build states, inputs, outputs, and troubleshooting boundaries.
  </Card>

  <Card title="Deployments" icon="cloud-arrow-up" href="/deployments">
    Learn how successful builds become live or preview deployment URLs.
  </Card>

  <Card title="Environment variables" icon="lock" href="/environment-variables">
    Configure production and preview environment variables.
  </Card>

  <Card title="Authentication" icon="key" href="/platform/authentication">
    Choose how MCP clients authenticate to hosted endpoints.
  </Card>
</CardGroup>
