# MCP servers

Your agents and code call tools on MCP servers. When a vendor renames or
removes a tool, or changes its arguments, the tool name in your MCP config,
your agent instructions or your code stops working. Upseam watches these
servers like any other provider: it finds the places in your repository that
name a changed tool and, for a rename the vendor announced, proposes a pull
request that changes only the tool name.

## Tracked servers

| Id                    | Server                     | Where changes come from                                                                         |
| --------------------- | -------------------------- | ----------------------------------------------------------------------------------------------- |
| `github-mcp`          | GitHub MCP server          | The tool list in each release's README and the renamed-tools table the GitHub team publishes    |
| `microsoft-learn-mcp` | Microsoft Learn MCP server | The server's own `tools/list`, `prompts/list` and `resources/list`, read every hour             |

The id is what you write in [`ignore.providers`](configuration.md#ignore).

Upseam never runs a local MCP server to list its tools and never uses your
tokens to call one. A server that needs a token to list its tools is watched
only through what its vendor publishes: the remote GitHub MCP server through
its releases. Stripe's MCP server publishes no tool list as data, so it is
not watched yet.

## What Upseam detects

A repository uses a server when one of these files names it at the
repository root:

- MCP configs: `.mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`,
  `.gemini/settings.json`, `.roo/mcp.json`, `.kiro/settings/mcp.json`,
  `.amazonq/mcp.json`, `.zed/settings.json`, `opencode.json`,
  `opencode.jsonc`, `claude_desktop_config.json` and `.codex/config.toml`.
  The server is recognised by its URL (for GitHub,
  `https://api.githubcopilot.com/mcp` and any path under it), its Docker
  image (`ghcr.io/github/github-mcp-server`, with the tag shown as the
  version) or its command (`github-mcp-server`).
- Code: the server URL in a source file of a repository that depends on
  `@modelcontextprotocol/sdk` or the Python `mcp` package.

Inside those repositories, a changed tool is matched in:

- **Tool lists in that server's config entry**: `X-MCP-Tools`,
  `GITHUB_TOOLS`, `tools`, `enabled_tools`, `includeTools`, and the value after
  `--tools` in `args`. Other servers' entries are never touched.
- **Permission rules**: Claude Code rules such as
  `mcp__github__list_workflows` in `.claude/settings.json` and
  `.claude/settings.local.json`, and the auto-approve and deny lists in the
  server's entry (`alwaysAllow`, `autoApprove`, `disabled_tools`,
  `excludeTools`).
- **Agent instructions**: `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`,
  `.github/copilot-instructions.md`, `.github/prompts/*.prompt.md`,
  `.github/instructions/*.instructions.md`, `.cursor/rules/*.md`,
  `.cursor/rules/*.mdc`,
  `.claude/commands/*.md` and `.claude/agents/*.md`, where the tool is named
  in backticks or as `mcp__<server>__<tool>`. A one-word name such as
  `search` counts only in the `mcp__…` form.
- **Code**: the tool, prompt or resource name as a whole quoted string in a
  file that uses an MCP SDK (`callTool`, `call_tool`), outside comments.

## What gets patched and what goes to you

| Change                                                                                   | Breaking | Pull request                                                                    |
| ---------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------- |
| Tool renamed by the vendor, same arguments                                               | yes      | configs, permission rules, instructions and calls                               |
| Tool renamed by the vendor, different arguments                                          | yes      | configs, permission rules and instructions; calls need you                      |
| Several tools merged into one                                                            | yes      | configs and instructions; permission rules and calls need you                   |
| Tool, prompt or resource removed                                                         | yes      | needs you                                                                        |
| Required parameter added, parameter removed, type changed, allowed values narrowed       | yes      | needs you                                                                        |
| Tool added, description changed, tool no longer read-only, protocol version changed      | no       | not sent to your repositories                                                   |

Only the vendor decides what replaces a tool: a tool that disappears while
another with the same arguments appears is reported as a removal, not a
rename.

Merged tools are never renamed in permission rules. Allowing or
auto-approving the new tool in place of one of the old ones would also allow
every other tool merged into it, and a renamed deny rule would change what
you chose to block, so Upseam shows the rule and leaves it to you.

When any change in a group needs you, the whole group waits for you, as for
other providers. Files under `.github/` are never patched.

## How a patch is checked

The pull request is written by your model, like every Upseam patch, and then
checked before anything is pushed. For an MCP server the only accepted edit is
switching a matched tool name to the vendor's new name. The check rejects a
patch that adds or removes lines, edits another server or its rules, adds a
server, command, argument, environment variable, header or URL, changes an
image or version pin, changes JSON keys or adds invisible characters. See
[Patch gates](security.md#patch-gates) for the checks that apply to every
patch.

## Limits

- A remote server that briefly lists fewer tools, for example during a
  partial deploy, shows up as a removal and then an addition.
- Upseam does not know which server a line of code calls: a quoted tool name
  matches if the repository uses the server at all.
- Only root-level config and instruction files are read. Codex tool lists
  are read only from one-line arrays outside multi-line strings.
- A pinned image or package version is shown, but Upseam does not open pull
  requests that bump it.
