Skip to content

Show the outbound IP for servers that only accept approved IPs - #1487

Merged
helpcodeai merged 2 commits into
mainfrom
feat/egress-ip-allowlist
Nov 3, 2026
Merged

helpcodeai merged 2 commits into
mainfrom
feat/egress-ip-allowlist

Conversation

@helpcodeai

Copy link
Copy Markdown
Contributor

Summary

Many servers only accept calls from approved IP addresses: self-hosted ERPs and CRMs behind a firewall, and providers that check every call (eMAG, Shopee, the Korean law API). Their refusal rarely says why. Most send back a 403 web page such as "Access Restricted", so the model reports a broken connector and the user has no idea which address to allow. Until now the address was written by hand in only two adapters' instructions, and Atlassian's instructions said "ask support".

This PR adds one setting for the instance's outbound addresses and shows them wherever a user needs them.

Changes

  • EGRESS_IPS (optional, comma-separated, invalid entries dropped). It is added to .env.example and to the three compose files, and read by connectors/egress.ts. When it is unset, nothing is shown, and the error advice talks about "the public IP address of the server AnythingMCP runs on".
  • Setup page. A note with the address(es) and a copy button. For adapters marked requiresIpAllowlist: true (new adapter field, validated; set on eMAG, Shopee and Korea Law), the note is a step at the top of the page. For other adapters it is a small note at the bottom. GET /api/adapters/:slug now returns egressIps.
  • Connector page. The same note. GET /api/connectors/proxy-availability now also returns egressIps; the change is additive. When the proxy is available, the note says to keep "Proxy" off for allowlisted servers, and the Proxy tooltip says the same.
  • Tool errors. deriveErrorHint gets a new last-resort rule. It fires on a 403 that is a web page, unless the page is a bot wall (Cloudflare, Akamai, DataDome, …). It also fires on Shopee source_ip_undeclared, on eMAG's refusal, and on explicit "IP not allowed/whitelisted" texts. Vendor-specific rules still take precedence. The hint names the addresses to allow, and says to switch the proxy off when the call went through it.
  • Setup check. The same advice is used when the adapter has no verifyHint of its own for the status.
  • Documentation. docs/tool-definition.md (the new field) and docs/connectors/proxy.md (proxied calls use changing addresses). llms-full.txt is regenerated.

The adapter version hash does not change: requiresIpAllowlist is not part of the fingerprint, and no instructions were edited.

Cloud and self-hosted

  • Cloud: the operator sets EGRESS_IPS to the backend's fixed address.
  • Self-hosted: the operator can set it to the server's public IP. When it is unset, the notes are hidden, except the required-allowlist step, which then names "the public IP address of the server AnythingMCP runs on".

Type

  • Bug fix
  • New feature
  • Documentation

Testing

  • Added/updated unit tests:
    • connectors/egress.spec.ts: parsing, refusal detection including bot walls, hint text;
    • error-hints.spec.ts: the new rule, vendor rules still winning, a JSON permission error left alone. One existing expectation changed: a bare 403 "Access Denied" page now gets the firewall hint, still not the Odoo one;
    • adapters.service.spec.ts: the setup check names the address on a 403 "Access Restricted" page, and describe returns egressIps and requiresIpAllowlist.

Commands run, with their results:

Directory Command Result
packages/backend npx tsc --noEmit -p tsconfig.json clean
packages/backend npx jest --maxWorkers=4 994 suites passed, 6 skipped; 30450 tests passed, 1812 skipped
packages/backend npx eslint on the changed files clean
packages/frontend npx tsc --noEmit -p tsconfig.json clean
packages/frontend npx eslint on the changed files 1 existing warning (react-hooks/exhaustive-deps at connectors/[id]/page.tsx:446), none new
repo root node scripts/validate-adapters.mjs --warn no errors; existing warnings only
repo root node scripts/adapter-count.mjs --check OK
repo root node scripts/generate-llms-txt.mjs --check clean after regenerating

Checklist

  • My code follows the existing code style
  • I have tested my changes locally
  • I have updated documentation
  • All existing tests pass
  • This PR has a descriptive title

Read the instance's outbound addresses from EGRESS_IPS and show them on
the connector setup page and the connector page. Adapters marked
requiresIpAllowlist (eMAG, Shopee, Korea Law) show them as a setup step.
A call or setup check refused by a firewall (a 403 web page that is not a
bot wall, Shopee source_ip_undeclared, eMAG's refusal) now gets a hint
naming the address to allow, and says to switch the proxy off when the
call went through it.
@helpcodeai
helpcodeai requested a review from D3nisty as a code owner November 3, 2026 13:49
@helpcodeai
helpcodeai enabled auto-merge (squash) November 3, 2026 13:49
@helpcodeai
helpcodeai merged commit fcf557f into main Nov 3, 2026
14 checks passed
@helpcodeai
helpcodeai deleted the feat/egress-ip-allowlist branch November 3, 2026 14:06
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant