<?xml version="1.0" encoding="UTF-8"?>
<div xmlns:ac="http://atlassian.com/content"
     xmlns:ri="http://atlassian.com/resource/identifier">
  <h1>Model Context Protocol for Agent Framework Developers</h1>

  <ac:structured-macro ac:name="info" ac:schema-version="1">
    <ac:rich-text-body>
      <p>
        This page explains MCP from the perspective of an agent-framework developer,
        walks through an end-to-end agent interaction, summarizes the stable
        <code>2026-07-28</code> protocol revision, and describes how Codex currently
        handles MCP tools, resources, prompts, and server instructions.
      </p>
    </ac:rich-text-body>
  </ac:structured-macro>

  <ac:structured-macro ac:name="toc" ac:schema-version="1">
    <ac:parameter ac:name="maxLevel">3</ac:parameter>
  </ac:structured-macro>

  <h2>Executive Summary</h2>
  <p>
    MCP is an interoperability boundary between an AI host and external systems.
    It standardizes capability discovery, tool invocation, resource retrieval,
    reusable prompt templates, results, errors, user-input requests, notifications,
    caching, versioning, authentication, and transport.
  </p>
  <p>
    MCP does not define the agent loop, planning, reasoning, memory, model selection,
    context ranking, approval policy, or prompt assembly. The host application remains
    responsible for deciding what the model actually sees.
  </p>
  <p>
    The most important distinction is:
    <strong>the agent runtime sees MCP; the model sees the runtime's projection of MCP.</strong>
  </p>

  <h2>Architecture</h2>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">text</ac:parameter>
    <ac:plain-text-body><![CDATA[User
  |
  v
Agent host/runtime
  |-- conversation, planning, approvals, context policy
  |-- LLM adapter --------------------------> Model
  |
  |-- MCP client A --> GitHub MCP server ---> GitHub API
  |-- MCP client B --> Database MCP server -> Database
  `-- MCP client C --> Files MCP server ----> Filesystem]]></ac:plain-text-body>
  </ac:structured-macro>

  <h3>Participants</h3>
  <ul>
    <li>
      <strong>Host:</strong> The application the user interacts with. It owns the
      model call, agent loop, context policy, user experience, permissions, and
      connections to one or more MCP servers.
    </li>
    <li>
      <strong>Client:</strong> A protocol component inside the host that communicates
      with one MCP server.
    </li>
    <li>
      <strong>Server:</strong> A local or remote program that exposes external data
      and capabilities through MCP.
    </li>
  </ul>

  <h3>Layers</h3>
  <ul>
    <li>
      <strong>Data layer:</strong> JSON-RPC 2.0 requests, results, errors,
      capability discovery, primitives, utilities, and extensions.
    </li>
    <li>
      <strong>Transport layer:</strong> Standard input/output for local subprocesses
      or Streamable HTTP for remote services, including framing and authorization.
    </li>
  </ul>

  <h3>What MCP Standardizes</h3>
  <ul>
    <li>Version and capability discovery.</li>
    <li>Typed tool discovery and invocation.</li>
    <li>Addressable contextual data and resource templates.</li>
    <li>Reusable, parameterized prompt templates.</li>
    <li>Results, structured content, errors, progress, and cancellation.</li>
    <li>User elicitation and multi-round-trip interactions.</li>
    <li>Caching and change notifications.</li>
    <li>Local and remote transports and HTTP authorization conventions.</li>
    <li>Negotiation of optional extensions such as Tasks and MCP Apps.</li>
  </ul>

  <h3>What MCP Does Not Standardize</h3>
  <ul>
    <li>Planning, reasoning, or the agent loop.</li>
    <li>Conversation memory or history compaction.</li>
    <li>Which model or provider to call.</li>
    <li>How tools are selected, approved, or presented to users.</li>
    <li>How resources are ranked, chunked, summarized, or injected.</li>
    <li>The instruction priority assigned to server-supplied text.</li>
    <li>How tool results are converted into model messages.</li>
  </ul>

  <h2>Core Primitives</h2>
  <table>
    <thead>
      <tr>
        <th>Primitive</th>
        <th>Purpose</th>
        <th>Typical controller</th>
        <th>What can reach the model</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Tools</td>
        <td>Executable operations such as search, query, create, or modify.</td>
        <td>Model, subject to host policy.</td>
        <td>Name, description, input schema, output schema, and execution result.</td>
      </tr>
      <tr>
        <td>Resources</td>
        <td>Addressable, normally read-only context such as files, schemas, and records.</td>
        <td>Host, user, or model through a host-defined interface.</td>
        <td>Only descriptors and content the host chooses to expose.</td>
      </tr>
      <tr>
        <td>Prompts</td>
        <td>Reusable, parameterized message and workflow templates.</td>
        <td>Normally the user or host.</td>
        <td>The instantiated messages returned by <code>prompts/get</code>.</td>
      </tr>
      <tr>
        <td>Elicitation</td>
        <td>Requests for additional user information or confirmation.</td>
        <td>Server to host to user.</td>
        <td>Usually handled by UI; it does not have to enter model context.</td>
      </tr>
      <tr>
        <td>Extensions</td>
        <td>Optional independently negotiated functionality.</td>
        <td>Host and server.</td>
        <td>Depends on the extension; a task handle may be visible while an app UI may not be.</td>
      </tr>
    </tbody>
  </table>

  <h2>End-to-End Agent Example</h2>
  <p>
    Consider the request: <em>Investigate today's checkout errors, consult our
    runbook, and open a GitHub issue if this is a new regression.</em>
  </p>
  <ol>
    <li>
      The host connects to Sentry, internal-documentation, and GitHub MCP servers.
    </li>
    <li>
      It discovers protocol versions and capabilities, then retrieves tool,
      resource, and prompt catalogs as needed.
    </li>
    <li>
      The host converts selected MCP tools into the model provider's native
      function/tool representation.
    </li>
    <li>
      The host may retrieve a relevant runbook resource and include a bounded
      excerpt in model context.
    </li>
    <li>
      The model calls a Sentry search tool. The host validates the call, applies
      approval policy, and routes <code>tools/call</code> to the correct server.
    </li>
    <li>
      The server calls Sentry and returns text, structured JSON, media, or links
      to additional resources.
    </li>
    <li>
      The host converts the useful result into a model-visible tool-result message.
    </li>
    <li>
      The model searches existing GitHub issues and decides whether to create one.
    </li>
    <li>
      If confirmation is required, the server returns
      <code>resultType: "input_required"</code>. The host gathers user input and
      retries the original operation.
    </li>
    <li>
      A long operation may return a Tasks extension handle, which the host polls
      or updates.
    </li>
    <li>
      Tool or resource change notifications may cause the host to refresh future
      catalogs.
    </li>
  </ol>

  <h2>How Resources Reach an Agent</h2>
  <p>
    Resources use a two-stage process. A list call returns catalog metadata, not
    necessarily the underlying content. A later read call retrieves the content.
    The host then decides whether and how to provide it to the model.
  </p>

  <h3>Resource Discovery</h3>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[// Client -> server
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "resources/list",
  "params": {}
}

// Server -> client
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "resources": [
      {
        "uri": "docs://payments/refund-policy",
        "name": "Refund policy",
        "description": "Current refund rules",
        "mimeType": "text/markdown"
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "private"
  }
}]]></ac:plain-text-body>
  </ac:structured-macro>

  <p>
    At this point the client has a descriptor: URI, name, description, MIME type,
    and optional metadata. The actual policy text has not necessarily entered
    model context.
  </p>

  <h3>Resource Reading</h3>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[// Client -> server
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "resources/read",
  "params": {
    "uri": "docs://payments/refund-policy"
  }
}

// Server -> client
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "contents": [
      {
        "uri": "docs://payments/refund-policy",
        "mimeType": "text/markdown",
        "text": "# Refund policy\nRefunds are available within..."
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "private"
  }
}]]></ac:plain-text-body>
  </ac:structured-macro>

  <h3>Host Choices</h3>
  <p>After reading a resource, a host may:</p>
  <ul>
    <li>Insert all or part of its text into the next model request.</li>
    <li>Present it as a user-selected attachment.</li>
    <li>Index it for retrieval and inject only relevant chunks.</li>
    <li>Summarize or truncate it to meet context limits.</li>
    <li>Display it without making it model-visible.</li>
    <li>Reject it because of permissions, provenance, type, or size.</li>
  </ul>

  <h3>Resource Templates</h3>
  <p>
    <code>resources/templates/list</code> exposes parameterized URIs, for example:
  </p>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">text</ac:parameter>
    <ac:plain-text-body><![CDATA[github://repos/{owner}/{repo}/issues/{number}
database://schemas/{schema}/tables/{table}
weather://forecast/{city}/{date}]]></ac:plain-text-body>
  </ac:structured-macro>

  <h2>How Prompts Reach an Agent</h2>
  <p>
    MCP prompts are reusable, parameterized message templates. Unlike tools,
    prompts are normally user-controlled: a host may render them as slash commands,
    menus, workflow starters, or form-driven actions.
  </p>

  <h3>Prompt Discovery</h3>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[// Client -> server
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "prompts/list",
  "params": {}
}

// Server -> client
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resultType": "complete",
    "prompts": [
      {
        "name": "review_pull_request",
        "title": "Review pull request",
        "description": "Reviews a PR using the team's standards",
        "arguments": [
          {
            "name": "pr_number",
            "description": "Pull request number",
            "required": true
          }
        ]
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}]]></ac:plain-text-body>
  </ac:structured-macro>

  <h3>Prompt Expansion</h3>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[// Client -> server
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "prompts/get",
  "params": {
    "name": "review_pull_request",
    "arguments": {
      "pr_number": "123"
    }
  }
}

// Server -> client
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "resultType": "complete",
    "description": "Review PR #123",
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "Review pull request #123. Check API compatibility..."
        }
      }
    ]
  }
}]]></ac:plain-text-body>
  </ac:structured-macro>

  <p>
    The host can append the returned messages to the conversation and start a
    model turn. Prompt messages may also include embedded resources. MCP defines
    the returned structure but does not require a particular command UI or
    instruction priority.
  </p>

  <ac:structured-macro ac:name="note" ac:schema-version="1">
    <ac:rich-text-body>
      <p>
        A server does not push a prompt into model context merely by advertising
        it. The client must list it, select it, retrieve it, and deliberately add
        the returned messages to a model request.
      </p>
    </ac:rich-text-body>
  </ac:structured-macro>

  <h2>How Codex Implements MCP</h2>

  <h3>Tools</h3>
  <p>
    Codex discovers MCP tools and converts each selected definition into the
    model provider's tool representation. The model sees a callable namespace,
    tool name, description, and schema. When the model emits a tool call, Codex
    routes it to the owning MCP client and returns the server result as a
    model-visible tool result.
  </p>

  <h3>Resources</h3>
  <p>
    Codex maps the MCP resource primitive into three internal model-callable tools:
  </p>
  <ul>
    <li><code>list_mcp_resources</code></li>
    <li><code>list_mcp_resource_templates</code></li>
    <li><code>read_mcp_resource</code></li>
  </ul>

  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">text</ac:parameter>
    <ac:plain-text-body><![CDATA[Model
  |
  | calls list_mcp_resources(server="docs")
  v
Codex internal resource tool
  |
  | sends resources/list
  v
MCP server
  |
  | returns URI descriptors
  v
Model receives descriptors as a tool result
  |
  | calls read_mcp_resource(
  |   server="docs",
  |   uri="docs://payments/refund-policy"
  | )
  v
Codex sends resources/read
  |
  v
Resource content becomes a bounded model-visible tool result]]></ac:plain-text-body>
  </ac:structured-macro>

  <p>
    Resource contents are therefore fetched on demand rather than copied into
    context when the server connects. Codex retains control over authorization,
    serialization, visibility, and truncation.
  </p>
  <p>
    The Codex App Server also exposes <code>mcpServerStatus/list</code> and
    <code>mcpServer/resource/read</code>. A Codex UI can use these operations to
    implement a resource browser or explicit attachment picker without asking
    the model to perform the read.
  </p>

  <h3>Prompts</h3>
  <p>
    Current Codex does not expose MCP <code>prompts/list</code> or
    <code>prompts/get</code> as model tools, slash commands, or documented App
    Server operations. A server may advertise prompts according to MCP, but
    current Codex does not automatically inject or render them.
  </p>
  <p>
    This illustrates an important compatibility rule:
    <strong>a primitive supported by the MCP specification is not necessarily
    implemented by every MCP host.</strong>
  </p>

  <h3>Server Instructions</h3>
  <p>
    Codex consumes the server's top-level <code>instructions</code> value as
    server-wide guidance associated with the server's model-visible tool
    namespace.
  </p>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[{
  "instructions": "Search before reading a full document. Cite document titles and revision dates. Never use write tools unless explicitly requested."
}]]></ac:plain-text-body>
  </ac:structured-macro>
  <p>
    This field is appropriate for cross-tool workflows, constraints, rate limits,
    and high-level usage guidance. Codex documentation recommends keeping the first
    512 characters self-contained so that the most important guidance is available
    during tool selection.
  </p>

  <h3>Prompt-Like Workflows in Codex</h3>
  <table>
    <thead>
      <tr>
        <th>Requirement</th>
        <th>Recommended Codex mechanism</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Short guidance applying to every tool from a server</td>
        <td>MCP server <code>instructions</code></td>
      </tr>
      <tr>
        <td>Reusable multi-step workflow</td>
        <td>Skill</td>
      </tr>
      <tr>
        <td>Repository-specific durable instructions</td>
        <td><code>AGENTS.md</code></td>
      </tr>
      <tr>
        <td>Live contextual data</td>
        <td>MCP resource</td>
      </tr>
      <tr>
        <td>Dynamic operation or lookup</td>
        <td>MCP tool</td>
      </tr>
      <tr>
        <td>Server-generated dynamic instructions when a skill is unsuitable</td>
        <td>A narrowly scoped read-only MCP tool whose result is treated as untrusted content</td>
      </tr>
    </tbody>
  </table>

  <h2>MCP 2026-07-28 Revision</h2>
  <p>
    The stable <code>2026-07-28</code> revision is a breaking revision relative
    to <code>2025-11-25</code>. Its central architectural change is a move from
    connection-oriented protocol sessions to self-contained, stateless requests.
  </p>

  <h3>Stateless and Sessionless Core</h3>
  <ul>
    <li>The <code>initialize</code>/<code>notifications/initialized</code> handshake is removed.</li>
    <li>The <code>Mcp-Session-Id</code> HTTP header is removed.</li>
    <li>Every request carries protocol version and client capabilities in <code>_meta</code>.</li>
    <li>Clients should identify themselves on each request.</li>
    <li>Servers should identify themselves in response <code>_meta</code>.</li>
    <li>
      Servers must implement <code>server/discover</code> so clients can discover
      supported versions, capabilities, identity, and optional instructions.
    </li>
    <li>
      Version mismatches return <code>UnsupportedProtocolVersionError</code>.
    </li>
  </ul>

  <h3>Explicit Stateful Workflows</h3>
  <p>
    Application state is still allowed, but it is represented by explicit handles
    instead of hidden connection state.
  </p>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">text</ac:parameter>
    <ac:plain-text-body><![CDATA[create_basket()
  -> { "basket_id": "bsk_123" }

add_item(
  basket_id = "bsk_123",
  sku = "ABC"
)]]></ac:plain-text-body>
  </ac:structured-macro>
  <p>
    This makes state handles visible to the model or host and allows any stateless
    server replica to process the next request.
  </p>

  <h3>Multi Round-Trip Requests</h3>
  <p>
    Server-to-client requests such as elicitation are represented by an interim
    result. The client gathers the requested information and retries the original
    request with a new JSON-RPC request ID.
  </p>
  <ac:structured-macro ac:name="code" ac:schema-version="1">
    <ac:parameter ac:name="language">json</ac:parameter>
    <ac:plain-text-body><![CDATA[{
  "resultType": "input_required",
  "inputRequests": {
    "confirmation": {
      "method": "elicitation/create",
      "params": {
        "message": "Create the issue?"
      }
    }
  },
  "requestState": "opaque-server-state"
}]]></ac:plain-text-body>
  </ac:structured-macro>
  <p>
    All successful results now include a <code>resultType</code>, normally
    <code>complete</code> or <code>input_required</code>.
  </p>

  <h3>Notification Redesign</h3>
  <ul>
    <li>
      The standalone HTTP GET stream and resource subscribe/unsubscribe methods
      are replaced by <code>subscriptions/listen</code>.
    </li>
    <li>
      Clients explicitly subscribe to tool, prompt, resource-list, or individual
      resource changes.
    </li>
    <li>Notifications are tagged with a subscription identifier.</li>
    <li>
      Request-specific progress and messages remain on the response stream of the
      related request.
    </li>
  </ul>

  <h3>Retry and Idempotency</h3>
  <p>
    SSE event IDs, <code>Last-Event-ID</code>, and protocol-level stream resumption
    are removed. If a response stream breaks, the client reissues the operation
    with a new request ID.
  </p>
  <ac:structured-macro ac:name="warning" ac:schema-version="1">
    <ac:rich-text-body>
      <p>
        Agent frameworks should protect side-effecting tools with application-level
        idempotency keys or outcome lookup. Retrying a search is harmless; blindly
        retrying a payment or issue creation can duplicate an action.
      </p>
    </ac:rich-text-body>
  </ac:structured-macro>

  <h3>Caching and Deterministic Catalogs</h3>
  <ul>
    <li>
      Tool, prompt, and resource lists and resource reads include
      <code>ttlMs</code> and <code>cacheScope</code>.
    </li>
    <li>
      Tool lists should be returned in deterministic order to improve client and
      model prompt-cache behavior.
    </li>
    <li>
      A host may use cached catalogs or resource contents until their freshness
      window expires.
    </li>
  </ul>

  <h3>Richer Tool Schemas</h3>
  <ul>
    <li>Tool schemas support substantially more JSON Schema 2020-12 features.</li>
    <li>Composition, conditionals, <code>$ref</code>, and <code>$defs</code> are supported.</li>
    <li><code>outputSchema</code> is less restricted.</li>
    <li>
      <code>structuredContent</code> can be any JSON value, including an array,
      scalar, or null.
    </li>
    <li>
      Frameworks may need to simplify MCP schemas for model providers whose native
      function-calling schema supports only a subset.
    </li>
  </ul>

  <h3>First-Class Extensions</h3>
  <p>
    Clients and servers negotiate optional extensions through the
    <code>capabilities.extensions</code> map using reverse-DNS identifiers.
  </p>
  <ul>
    <li>
      <code>io.modelcontextprotocol/tasks</code>: durable long-running operations
      using task handles and get, update, and cancel operations.
    </li>
    <li>
      <code>io.modelcontextprotocol/ui</code>: MCP Apps, in which a server can
      provide interactive UI rendered by a compatible host.
    </li>
  </ul>

  <h3>Deprecated Features</h3>
  <table>
    <thead>
      <tr>
        <th>Deprecated feature</th>
        <th>Recommended migration</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Roots</td>
        <td>Use explicit tool parameters, resource URIs, or server configuration.</td>
      </tr>
      <tr>
        <td>Sampling</td>
        <td>Integrate the server directly with an LLM provider when server-side inference is required.</td>
      </tr>
      <tr>
        <td>Logging</td>
        <td>Use standard error for local servers or OpenTelemetry for structured observability.</td>
      </tr>
      <tr>
        <td>HTTP plus SSE transport</td>
        <td>Use Streamable HTTP.</td>
      </tr>
      <tr>
        <td>OAuth Dynamic Client Registration</td>
        <td>Use Client ID Metadata Documents where supported.</td>
      </tr>
    </tbody>
  </table>

  <h3>HTTP, Observability, and Authorization</h3>
  <ul>
    <li>Standard <code>Mcp-Method</code> and <code>Mcp-Name</code> routing headers.</li>
    <li>Optional tool-parameter-to-header mapping through <code>x-mcp-header</code>.</li>
    <li>W3C trace-context propagation in <code>_meta</code>.</li>
    <li>OAuth authorization-response issuer validation.</li>
    <li>Binding persisted client credentials to the issuing authorization server.</li>
    <li>More explicit OpenID Connect application-type registration.</li>
  </ul>

  <h2>What the Model Sees</h2>
  <p>The following protocol details are normally runtime-only:</p>
  <ul>
    <li>Protocol version and <code>server/discover</code>.</li>
    <li>Capability and extension negotiation.</li>
    <li>JSON-RPC IDs and HTTP routing headers.</li>
    <li>OAuth tokens and authorization-server metadata.</li>
    <li>Cache TTLs and cache scope.</li>
    <li>Subscription identifiers and trace context.</li>
    <li>Connection identity or server replica.</li>
  </ul>

  <p>The principal model-visible effects of the new revision are:</p>
  <ol>
    <li>
      <strong>Explicit state handles:</strong> State that was hidden in a connection
      may now appear in tool results and subsequent tool arguments.
    </li>
    <li>
      <strong>More stable tool definitions:</strong> Deterministic ordering and
      caching make tool sections more stable across model calls.
    </li>
    <li>
      <strong>Richer schemas and output shapes:</strong> Models may receive more
      expressive constraints and array or scalar structured outputs.
    </li>
    <li>
      <strong>Cleaner interruption handling:</strong> Hosts can handle
      <code>input_required</code> and expose only the final result to the model.
    </li>
    <li>
      <strong>More explicit scope:</strong> Replacing Roots with parameters and
      resource URIs can make scope visible in tool calls.
    </li>
    <li>
      <strong>Less nested access to the host model:</strong> Deprecating Sampling
      reduces implicit server-initiated model completions and cross-server context.
    </li>
    <li>
      <strong>Dynamic tool changes:</strong> Notifications may cause future model
      calls to receive a different tool registry.
    </li>
  </ol>

  <h2>Framework Design Recommendations</h2>
  <ol>
    <li>
      Keep the MCP protocol adapter separate from the model-provider tool adapter.
    </li>
    <li>
      Support both the modern <code>2026-07-28</code> protocol and legacy
      initialization-based servers during migration.
    </li>
    <li>
      Treat every request as self-contained and avoid connection-scoped application
      state.
    </li>
    <li>
      Design explicit, opaque, authorized, expiring handles for stateful workflows.
    </li>
    <li>
      Add idempotency controls to side-effecting tools.
    </li>
    <li>
      Validate full MCP JSON Schema but normalize it for model-provider limitations.
    </li>
    <li>
      Cache catalogs and resource contents according to <code>ttlMs</code> and
      <code>cacheScope</code>.
    </li>
    <li>
      Handle elicitation and task polling outside the main model loop when the
      model does not need to see the intermediate protocol exchange.
    </li>
    <li>
      Never expose authentication tokens, trace metadata, or transport details to
      the model unless there is an explicit, safe reason.
    </li>
    <li>
      Treat server instructions, prompt templates, resource contents, tool
      descriptions, and tool results as untrusted external content.
    </li>
    <li>
      Apply explicit size bounds, provenance labels, and instruction-priority
      rules before adding server-supplied content to model context.
    </li>
  </ol>

  <h2>Sources</h2>
  <ul>
    <li>
      <a href="https://modelcontextprotocol.io/docs/2026-07-28/getting-started/intro">
        MCP introduction
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/docs/2026-07-28/learn/architecture">
        MCP architecture overview
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/specification/2026-07-28/changelog">
        MCP 2026-07-28 changelog
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/resources">
        MCP resources specification
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/prompts">
        MCP prompts specification
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/specification/2026-07-28/server/tools">
        MCP tools specification
      </a>
    </li>
    <li>
      <a href="https://modelcontextprotocol.io/specification/2026-07-28/deprecated">
        MCP deprecated feature registry
      </a>
    </li>
    <li>
      <a href="https://github.com/modelcontextprotocol/modelcontextprotocol/releases/tag/2026-07-28">
        MCP 2026-07-28 stable release
      </a>
    </li>
    <li>
      <a href="https://learn.chatgpt.com/docs/extend/mcp">
        Codex MCP documentation
      </a>
    </li>
    <li>
      <a href="https://learn.chatgpt.com/docs/app-server#api-overview">
        Codex App Server API overview
      </a>
    </li>
    <li>
      <a href="https://github.com/openai/codex/blob/d06c7ac055920c7cb140c25ebda3f3db20197b45/codex-rs/core/src/tools/handlers/mcp_resource_spec.rs">
        Codex MCP resource tool definitions
      </a>
    </li>
    <li>
      <a href="https://github.com/openai/codex/blob/d06c7ac055920c7cb140c25ebda3f3db20197b45/codex-rs/codex-mcp/src/rmcp_client.rs">
        Codex MCP client and server-instruction mapping
      </a>
    </li>
    <li>
      <a href="https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html">
        Atlassian Confluence storage format
      </a>
    </li>
  </ul>
</div>
