> ## Documentation Index
> Fetch the complete documentation index at: https://tashfiq.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Investigate MCP Findings

> Understand what each MCP safety rule is flagging and how to resolve it.

Use this guide when `charter doctor` reports one of the three MCP safety rules — [`AE-MCP-001`](/rules/AE-MCP-001), [`AE-MCP-002`](/rules/AE-MCP-002), or [`AE-MCP-003`](/rules/AE-MCP-003). MCP findings are often the highest-signal findings in a repo because they touch dependency integrity, origin trust, and remote authentication. For the reasoning behind each rule, see the [MCP Safety Model](/docs/concepts/mcp-safety-model).

```bash theme={null}
charter explain AE-MCP-001   # compact rule metadata + link to full docs
```

<Tabs>
  <Tab title="AE-MCP-001 — Version pinning">
    **What it means:** An MCP server entry is using a floating version (`@latest`, a semver range like `^1.2.3`, a missing version entirely, or a deprecated/archived package). Charter requires exact version pins for supply-chain auditability.

    **Example finding:**

    ```json theme={null}
    {
      "mcpServers": {
        "filesystem": {
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-filesystem@latest"]
        }
      }
    }
    ```

    **Fix pattern — pin to an exact version:**

    <CodeGroup>
      ```json Before theme={null}
      {
        "mcpServers": {
          "filesystem": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem@latest"]
          }
        }
      }
      ```

      ```json After theme={null}
      {
        "mcpServers": {
          "filesystem": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem@0.6.2"]
          }
        }
      }
      ```
    </CodeGroup>

    Or let Charter apply a catalog-aware bump for you:

    ```bash theme={null}
    charter fix --rule AE-MCP-001 --dry-run   # review first
    charter fix --rule AE-MCP-001             # apply
    ```

    <Note>
      Deprecated packages (such as `@modelcontextprotocol/server-github`) cannot be auto-fixed — the migration path is a different package entirely. Charter provides the successor package name in the finding output. You must make that migration manually.
    </Note>

    **Common version problems Charter flags:**

    | Pattern          | Example                 | Status |
    | ---------------- | ----------------------- | ------ |
    | Floating tag     | `@latest`               | Fail   |
    | Semver range     | `^1.2.3` or `~1.2.3`    | Fail   |
    | Missing version  | `npx -y mcp-server-git` | Fail   |
    | Floating git ref | `git+https://...#main`  | Fail   |
    | Exact pin        | `@2026.1.14`            | Pass   |
  </Tab>

  <Tab title="AE-MCP-002 — Trusted remotes">
    **What it means:** A remote MCP server URL's hostname is not in Charter's built-in catalog of known vendor-operated hosts, and it's not in your repo's `charter.yaml` allowlist. Charter flags unknown origins because remote MCP servers receive tool calls from your agent — the origin should be explicitly reviewed.

    **Example finding:** Charter reports a remote server at `api.your-internal-tool.com` that isn't in the catalog.

    **Resolution — add the host to your allowlist:**

    ```yaml theme={null}
    # charter.yaml
    mcp:
      trustedRemotes:
        - "api.your-internal-tool.com"
        - "mcp.your-company.com"
    ```

    Before adding a host, ask:

    * Is this a reviewed vendor host or your own trusted internal endpoint?
    * Should this remote actually be present in this repo at all?
    * Is this an unexpected entry that should be removed instead?

    <Warning>
      If the remote origin is unexpected or unreviewed, the correct resolution is to remove or replace the MCP server entry — not to add it to the allowlist. Only add hosts you have explicitly reviewed.
    </Warning>

    **Hosts that are always exempt:** local origins (`localhost`, `127.0.0.1`, `::1`) are never flagged regardless of allowlist contents.
  </Tab>

  <Tab title="AE-MCP-003 — Auth declaration">
    **What it means:** A remote HTTP or SSE MCP server entry has no recognized auth header declared. Charter requires that remote servers declare authentication metadata so agents don't silently make unauthenticated calls to external services.

    **Example finding:**

    ```json theme={null}
    {
      "mcpServers": {
        "my-service": {
          "type": "http",
          "url": "https://your-mcp-server.com"
        }
      }
    }
    ```

    **Fix — add an auth header to the server entry:**

    ```json theme={null}
    {
      "mcpServers": {
        "my-service": {
          "type": "http",
          "url": "https://your-mcp-server.com",
          "headers": {
            "Authorization": "${YOUR_API_KEY}"
          }
        }
      }
    }
    ```

    <Tip>
      Use environment variable references (`${VAR}`) in headers — never literal credential values. Charter will flag a literal secret value as an `AE-SEC-001` finding.
    </Tip>

    **Accepted auth header names:**

    | Header          | Example           |
    | --------------- | ----------------- |
    | `Authorization` | `Bearer ${TOKEN}` |
    | `X-Api-Key`     | `${API_KEY}`      |
    | `Api-Key`       | `${API_KEY}`      |
    | `X-Auth-Token`  | `${AUTH_TOKEN}`   |

    Any of the four accepted header names satisfies the rule. Charter does not validate the header value — only that a recognized auth header is declared.
  </Tab>
</Tabs>

## Re-scan after changes

After editing your MCP config or `charter.yaml`:

```bash theme={null}
charter doctor
```

To focus on MCP findings only while iterating:

```bash theme={null}
charter doctor --rule AE-MCP-001,AE-MCP-002,AE-MCP-003
```

## Fast investigation loop

```bash theme={null}
charter doctor
charter explain AE-MCP-001
charter fix --rule AE-MCP-001 --dry-run
charter fix --rule AE-MCP-001
charter doctor
```

## When not to suppress MCP findings

MCP findings are high-signal. Do not jump straight to suppression for findings that point at real supply-chain or trust problems.

Suppress only when:

* the repo intentionally carries a reviewed exception (e.g., a vendored test fixture)
* you have a real reason and, for permanent suppressions, an approver

See [Suppress a Finding](/docs/how-to/suppress-a-finding) for the full suppression workflow.

## Next steps

<CardGroup cols={2}>
  <Card title="MCP Safety Model" icon="plug" href="/docs/concepts/mcp-safety-model">
    Why pinning, trusted remotes, and auth declaration are first-class readiness signals.
  </Card>

  <Card title="charter.yaml Reference" icon="settings" href="/docs/config/charter-yaml">
    Declare reviewed remote hosts with `mcp.trustedRemotes`.
  </Card>

  <Card title="Use charter fix Safely" icon="shield-check" href="/docs/how-to/use-charter-fix-safely">
    Apply the AE-MCP-001 pin bump without surprises.
  </Card>

  <Card title="Suppress a Finding" icon="ban" href="/docs/how-to/suppress-a-finding">
    Record a reviewed MCP exception when one is justified.
  </Card>
</CardGroup>
