AWS Builder Center

MCP Targets in AgentCore Gateway, Part 1: How Agents Discover Tools

This is Part 1 of a two-part series on MCP server targets in Amazon Bedrock AgentCore Gateway. • Part 1 (this post): How agents discover tools — DEFAULT vs DYNAMIC listing modes. • Part 2: Which data source wins — resolving resource conflicts with resourcePriority.

If you are putting more than a couple of MCP servers into production, you eventually hit the same wall: every server has to handle its own credentials, its own logging, its own network plumbing, and its own access policy. Amazon Bedrock AgentCore Gateway exists to collapse all of that into one managed entry point. It sits between your MCP clients and your backend MCP servers, REST APIs, and Lambda functions, and presents a single unified MCP endpoint to the agent.
When you register an MCP server as a gateway target, one configuration setting shapes everything about how clients see it: the listing mode (ListingMode). It controls when the gateway discovers what a server can do, either cached ahead of time (DEFAULT) or fetched live at request time (DYNAMIC). That single choice drives latency, semantic search, multi-tenancy, and OAuth behavior. This post walks through how each mode actually works, where each breaks down, and gives you a decision matrix you can use without re-reading the docs every time.
(The companion setting, resourcePriority, handles a completely different job, resolving conflicts when two targets expose the same resource URI. It is the subject of Part 2. )
------------------------------------------------------------------------------------------------------

Where listing mode fits: AgentCore Gateway targets

A gateway is the front door. A target is one backend the gateway connects to. A single gateway can host many targets, and AgentCore supports several target types:
·      AWS Lambda functions
·      OpenAPI specifications (REST APIs)
·      Smithy model definitions
·      Amazon API Gateway REST API stages (a direct target type, API_GATEWAY)
·      MCP servers reachable over an HTTPS URL
Listing mode is specific to MCP server targets. The other target types do not expose the MCP listing-mode choice, because the gateway already knows their full schema from the OpenAPI/Smithy/Lambda definition you give it. It is only when you point the gateway at another MCP server (which has its own tools/list, prompts/list, and resources/list methods) that the question "when do we discover what this server offers?" arises.
When you register an MCP server target, the gateway speaks MCP to it. AgentCore Gateway supports MCP protocol versions 2025-06-18, 2025-03-26, and 2025-11-25, and it surfaces all three MCP primitives, tools, prompts, and resources, as first-class objects through their full method set: tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/read, and resources/templates/list.
One naming detail that matters at the client: tools and prompts are returned prefixed with the target name in the format targetName___toolName. Resource URIs are the exception, they are passed through without a prefix, exactly as the downstream server returned them. That difference is what makes resource conflicts possible, and it is exactly the problem Part 2 tackles.
------------------------------------------------------------------------------------------------------

The core question: when does discovery happen?

Both modes behave identically for invoke operations. tools/call, prompts/get, and resources/read always route through the gateway directly to the backend MCP server target, in both modes. There is no caching of execution.
The modes differ only in list operations, the discovery step. That is the whole distinction.

DEFAULT mode: discover ahead of time, serve from cache

DEFAULT is the mode you get if you set nothing. In DEFAULT mode, the gateway discovers the server's capabilities ahead of request time and caches them at the control plane. Discovery happens two ways:
  • Implicit synchronization: calling CreateGatewayTarget or UpdateGatewayTarget automatically triggers the gateway to fetch tools (tools/list), prompts (prompts/list), and resources (resources/list and resources/templates/list) and index them into a unified catalog.
  • Explicit synchronization: you call the SynchronizeGatewayTargets API on demand. You make a PUT request to /gateways/{gatewayIdentifier}/synchronize with the target ID in the body. It returns 202 immediately and processes asynchronously; you poll GetGatewayTarget to watch progress, which can take several minutes for large capability sets.
When a client then calls tools/list or resources/list, the gateway answers straight from its cache without contacting the backend server at all. The backend is only touched on invoke.
The catch is freshness. Because the catalog is a cache, you are responsible for refreshing it. Any time a backend server adds, removes, or changes a tool, prompt, or resource, you must call SynchronizeGatewayTargets, otherwise clients will keep seeing the stale catalog.
The payoff for accepting that responsibility is significant: DEFAULT mode is the only mode that supports semantic tool search, because the gateway pre-computes vector embeddings over the indexed catalog. It is also the mode compatible with outbound three-legged OAuth (3LO).

DYNAMIC mode: discover live, at request time

In DYNAMIC mode, the gateway does not call the MCP server during CreateGatewayTarget or UpdateGatewayTarget. Nothing is cached. Instead, when a client issues a list call, the gateway forwards it live to the backend server at request time, using the identity of the calling user.
That last part is the reason DYNAMIC mode exists. Because the list call runs under the end user's identity, a permissions-aware server can return a different capability set per user. A server might expose approve_expense only to managers, or surface HIPAA-compliant tools only to healthcare tenants. The gateway never freezes a single catalog, so the server keeps full control of who sees what.
DYNAMIC mode carries two hard limitations, both documented:
  • No semantic search. DYNAMIC targets are not indexed at the gateway, so the semantic tool search capability cannot be used for them.
  • No outbound 3LO OAuth. DYNAMIC mode is not interoperable with outbound three-legged OAuth.
When you mix modes on one gateway (which is allowed and common), list responses are paginated, and the cached DEFAULT-mode primitives and the live DYNAMIC-mode primitives come back on different pages.
------------------------------------------------------------------------------------------------------

A side door: providing the schema upfront

There is a third behavior worth knowing, because it interacts with both modes. On an MCP server target you can supply the tool schema directly via the mcpToolSchema field instead of letting the gateway fetch it. The gateway parses and caches what you give it.
Two rules apply:
  • mcpToolSchema is supported only when the credential provider uses the authorization code grant type (3LO).
  • Supplying a static schema disables dynamic tool synchronization for that target. You cannot call SynchronizeGatewayTargets on a target that has a static schema; you must first remove the schema via UpdateGatewayTarget to re-enable synchronization.
This is useful when you cannot, or do not want to, let the gateway reach the server during setup (for example, behind a 3LO consent flow), and you already know the tool contract.
------------------------------------------------------------------------------------------------------

Pros and cons


DEFAULT mode

Pros
  • Lowest list latency: list calls are served from the gateway cache without a round trip to the backend.
  • The only mode that supports semantic tool search (pre-computed embeddings over the indexed catalog).
  • Compatible with outbound three-legged OAuth.
  • Resilient to a temporarily unreachable backend for discovery: the cached catalog still answers list calls (invoke still needs the backend).
  • Predictable, stable catalog that you control the refresh timing of.
Cons
  • Staleness is your problem. You must call SynchronizeGatewayTargets whenever capabilities change, or clients see an outdated catalog.
  • Same catalog for every user. It cannot reflect per-user or per-tenant capability differences on its own (you layer that on with AgentCore Policy or Lambda interceptors instead).
  • Synchronization of large capability sets is asynchronous and can take several minutes.

Dynamic Mode

Pros
  • Always fresh: list calls reflect the backend's current capabilities with no sync step.
  • Per-user capability discovery: list calls run under the caller's identity, so the backend server can enforce its own fine-grained access control and return a tailored set.
  • Zero catalog maintenance: no SynchronizeGatewayTargets to remember.
  • Natural fit for multi-tenant servers where the server, not the gateway, is the source of truth for who sees what.
Cons
  • Higher list latency: every list call is a live round trip to the backend.
  • No semantic tool search for that target.
  • No outbound 3LO OAuth.
  • Discovery availability is tied to the backend being reachable at request time.
------------------------------------------------------------------------------------------------------

Decision Matrix

Your
situation
Recommended
mode
Why
Capabilities
are stable and change rarely
DEFAULTCache
cost is paid once; refresh only on change.
You want agents to find tools by
meaning (semantic tool search)
DEFAULT (required)Semantic search only works over the
indexed catalog.
You
use outbound three-legged OAuth to the backend
DEFAULT (required)DYNAMIC
is not interoperable with outbound 3LO.
The server personalizes capabilities
per user/role
DYNAMICList runs under the caller's identity;
server returns a tailored set.
Multi-tenant
server that enforces its own access control
DYNAMICKeeps
the server as the authority for visibility.
Tools/prompts change frequently and
unpredictably
DYNAMICAvoids constant re-synchronization.
You
cannot reach the server at setup time (e.g., 3LO consent) but know the
contract
DEFAULT + mcpToolSchemaProvide
schema upfront; note this disables sync.
Lowest possible list latency at scaleDEFAULTServed from cache, no backend round
trip.
Backend
may be intermittently reachable, but you still want discovery to work
DEFAULTCached
catalog answers list calls independently.
A useful default heuristic: start with DEFAULT unless you specifically need per-user capability sets or you cannot tolerate any catalog staleness. DEFAULT gives you the performance and the semantic search and OAuth features; reach for DYNAMIC when the server's own identity-aware logic must drive what each user sees.
You do not have to pick one mode for the whole gateway. A common pattern is DEFAULT for stable, shared catalogs (a corporate "knowledge" MCP server) and DYNAMIC for a permission-sensitive one (an internal operations server), all behind the same gateway. Just remember their primitives come back on separate pages of the list response.
A note on tenancy regardless of mode: you can enforce capability filtering centrally for both modes using AgentCore Policy or AWS Lambda response interceptors, for example restricting a tenant to read-only tools. DYNAMIC additionally lets the backend server itself do that filtering under the user's identity. So "I need per-tenant filtering" does not automatically force DYNAMIC; it forces DYNAMIC only when you want the backend server to own that decision rather than the gateway.
------------------------------------------------------------------------------------------------------

A few Operational gotchas

  • Latency tip for invoke. If your MCP server runs on AgentCore Runtime, enable MCP sessions on the gateway (or allow Mcp-Session-Id as a header in the target's metadataConfiguration). The gateway then reuses the initialized backend connection across calls instead of re-initializing each time, which avoids cold-starting a new micro-VM per request and lowers latency for subsequent tool calls. Session timeout is configurable from 15 minutes to 8 hours, defaulting to 1 hour.
  • Auth strategies. MCP server targets support no-auth (not recommended), OAuth (2LO client credentials and 3LO authorization code), IAM SigV4, and API key. IAM SigV4 outbound only works behind services that actually verify SigV4: AgentCore Gateway, AgentCore Runtime, Amazon API Gateway, and Lambda Function URLs. It will not work behind an Application Load Balancer or a direct EC2 endpoint, use OAuth or API key there.
  • Pending auth states. A target mid-3LO-consent sits in CREATE_PENDING_AUTH, UPDATE_PENDING_AUTH, or SYNCHRONIZE_PENDING_AUTH. You cannot delete, update, or synchronize it until the authorization completes or fails.
------------------------------------------------------------------------------------------------------

Bottom Line

Listing mode is a small field with a large blast radius. DEFAULT buys you cached, low-latency discovery plus semantic search and 3LO OAuth, at the cost of remembering to synchronize when things change. DYNAMIC buys you always-fresh, identity-aware discovery driven by the backend server, at the cost of per-call latency and losing semantic search and 3LO. Start with DEFAULT, move a target to DYNAMIC only when the server itself must decide what each user sees.
Next in this series: Part 2 covers what happens when two targets expose the same resource URI, and the resourcePriority rule that decides which one wins (with a precedence direction that is the opposite of what most people guess).
------------------------------------------------------------------------------------------------------
Sources
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article