Skip to main content
Glama

Migrate a repository in

migrate_repo

Copy a repository from another forge or Forgejo instance into this one, including issues, pull requests, labels, milestones, releases, and wiki, to move project data beyond git refs.

Instructions

Migrate (copy) a repository from ANOTHER forge/instance into this one — the only way to move issues and PRs across instances, unlike push mirrors which carry git refs only. Give clone_addr (http/https URL on the source) and repo_name. Set service to the source forge ("gitea" for Forgejo; the default "git" copies refs only) and turn on issues/pull_requests/labels/milestones/releases/wiki, which all default to false. The import runs within the call, which answers with the finished repository (seconds for a small one). A failure can leave an empty repository under repo_name; the error says so, and it must be deleted before retrying under that name. This copies — the source repo is left untouched. Requires write mode. For a private source, the credential comes from the server's FORGEJO_MIGRATE_TOKEN env var — never pass it as an argument. Set authenticate=true to send it; auth_username is only for service git (optional), onedev and codebase, and is refused for gitea, github, gitlab, gogs and gitbucket, whose importers ignore the token when given a username.

Input Schema

NameRequiredDescriptionDefault
lfsNoAlso fetch Git LFS objects. Defaults to false.
wikiNoAlso migrate the wiki. Defaults to false.
issuesNoAlso migrate issues. Requires a non-`git` `service`. Defaults to false.
labelsNoAlso migrate labels. Requires a non-`git` `service`. Defaults to false.
mirrorNoKeep the new repo as a *pull* mirror that periodically re-fetches from the source, instead of taking a one-shot copy. Defaults to false.
privateNoVisibility of the new repository. Defaults to private.
serviceNoSource forge type: `git`, `github`, `gitea` (use this for Forgejo), `gitlab`, `gogs`, `onedev`, `gitbucket`, `codebase`. Defaults to `git`, which copies git refs only — name the real forge to carry issues, PRs and releases across.
releasesNoAlso migrate releases (and their attachments). Requires a non-`git` `service`. Defaults to false.
repo_nameYesName for the new repository on this instance.
clone_addrYesSource clone URL on the *other* instance, e.g. `https://codeberg.org/owner/repo.git`. Must be `http://` or `https://`.
milestonesNoAlso migrate milestones. Requires a non-`git` `service`. Defaults to false.
repo_ownerNoUser or organisation that will own the new repo. Defaults to the authenticated user.
descriptionNoDescription for the new repository.
authenticateNoSend the server's `FORGEJO_MIGRATE_TOKEN` as the source credential: as a token for `github`, `gitea`, `gitlab`, `gogs` and `gitbucket`, as the clone password for `git`. Leave unset for a public source.
lfs_endpointNoCustom LFS endpoint, if the source doesn't serve LFS from the clone URL.
auth_usernameNoUsername on the *source* instance, sent with the token as its password. Only for `git` (optional, defaults to `oauth2`), `onedev` and `codebase` (required); refused for the other services, which authenticate by token alone and ignore the token when given a username. Setting it turns on authentication.
pull_requestsNoAlso migrate pull requests. Requires a non-`git` `service`. Defaults to false.
mirror_intervalNoPull-mirror refresh interval in Forgejo duration form (e.g. `8h0m0s`). Only meaningful with `mirror = true`.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv0.26.0
    • changedInput schema / properties / auth_username / description
      Previous value: -"Username on the *source* instance. Setting it turns on authentication (the token comes\nfrom the server's `FORGEJO_MIGRATE_TOKEN`). Leave unset for a public source, or when the\nsource authenticates by bare token — then set `authenticate = true` instead."New value: +"Username on the *source* instance, sent with the token as its password. Only for `git`\n(optional, defaults to `oauth2`), `onedev` and `codebase` (required); refused for the\nother services, which authenticate by token alone and ignore the token when given a\nusername. Setting it turns on authentication."
    • changedInput schema / properties / authenticate / description
      Previous value: -"Send the server's `FORGEJO_MIGRATE_TOKEN` as the source credential. Implied when\n`auth_username` is set. Needed on its own for token-only auth, and for private\nGitHub/GitLab sources."New value: +"Send the server's `FORGEJO_MIGRATE_TOKEN` as the source credential: as a token for\n`github`, `gitea`, `gitlab`, `gogs` and `gitbucket`, as the clone password for `git`.\nLeave unset for a public source."
  2. First observedv0.22.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: import is synchronous ('runs within the call, which answers with the finished repository'), non-idempotent in a concrete way ('a failure can leave an empty repository... must be deleted before retrying under that name'), source is untouched, and credentials come from a server env var rather than an argument. This is the kind of operational detail annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the what and the push-mirror contrast, then packs credential and error-recovery caveats into short clauses. Dense but every sentence carries a constraint; the auth_username clause is the one place that runs long and partially restates the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 18-parameter, non-idempotent, open-world mutation with no output schema, it covers return behavior (finished repo), failure semantics, auth, and the flag defaults. The remaining parameters (repo_owner, mirror_interval, lfs_endpoint) are fully documented in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds cross-parameter meaning the schema only states per-field: that service defaults to git which silently copies refs only, that all the issue/PR/wiki flags default to false, that authenticate is what actually sends the token, and where auth_username is refused. Some of this duplicates the schema, so not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with explicit scope ('from ANOTHER forge/instance into this one') and immediately distinguishes it from push mirrors, which 'carry git refs only'. An agent can separate this from create_repo or add_push_mirror without consulting either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (push mirrors) and the condition that selects this tool, plus prerequisites: write mode and a non-default service for anything beyond refs. It does not spell out when a plain create_repo or mirror=true would be preferable, so it falls just short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.