Skip to main content

MCPS: Cryptographic Security Layer for the Model Context Protocol
draft-sharif-mcps-secure-mcp-00

Document Type Active Internet-Draft (individual)
Author Raza Sharif
Last updated 2026-03-14
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-sharif-mcps-secure-mcp-00
Internet Engineering Task Force                               R. Sharif
Internet-Draft                                            CyberSecAI Ltd
Intended status: Standards Track                          March 14, 2026
Expires: September 14, 2026

     MCPS: Cryptographic Security Layer for the Model Context Protocol
                    draft-sharif-mcps-secure-mcp-00

Abstract

   This document specifies MCPS (MCP Secure), a cryptographic
   security layer for the Model Context Protocol (MCP).  MCPS adds
   agent identity verification, per-message signing, tool definition
   integrity, and replay protection to MCP communications without
   modifying the core protocol.

   MCPS operates as an envelope around existing JSON-RPC messages.
   It introduces four primitives: (1) Agent Passports for
   cryptographic identity bound to a specific origin, (2) signed
   message envelopes for integrity and non-repudiation, (3) tool
   definition signatures covering the full tool object for detecting
   poisoning and tampering, and (4) nonce-plus-timestamp replay
   protection with transcript binding to prevent downgrade attacks.

   The design is fully backward-compatible.  MCPS-unaware clients
   and servers continue to function normally.  MCPS-aware endpoints
   progressively negotiate security capabilities through trust
   levels L0 (no verification) through L4 (full mutual
   authentication with revocation checking).

   All cryptographic operations use ECDSA P-256 (NIST FIPS 186-5).
   Signatures use IEEE P1363 fixed-length r||s encoding per
   RFC 7518 Section 3.4 with low-S normalization to prevent
   signature malleability.  Canonical serialization uses JSON
   Canonicalization Scheme (JCS) per RFC 8785.  The Trust Authority
   component is self-hostable with no external service dependency.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current
   Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six
   months and may be updated, replaced, or obsoleted by other
   documents at any time.  It is inappropriate to use Internet-Drafts
   as reference material or to cite them other than as "work in
   progress."

   This Internet-Draft will expire on September 14, 2026.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (https://trustee.ietf.org/license-info) in effect on the date of
   publication of this document.  Please review these documents
   carefully, as they describe your rights and restrictions with
   respect to this document.  Code Components extracted from this
   document must include Revised BSD License text as described in
   Section 4.e of the Trust Legal Provisions and are provided
   without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . .  4
     1.1.  The Problem . . . . . . . . . . . . . . . . . . . . . .  4
     1.2.  Scope and Limitations . . . . . . . . . . . . . . . . .  5
     1.3.  Relationship to Existing MCP Authorization  . . . . . .  5
     1.4.  Relationship to DPoP (RFC 9449) . . . . . . . . . . . .  6
     1.5.  Design Goals  . . . . . . . . . . . . . . . . . . . . .  7
   2.  Terminology . . . . . . . . . . . . . . . . . . . . . . . .  7
   3.  Protocol Overview . . . . . . . . . . . . . . . . . . . . .  8
     3.1.  Architecture  . . . . . . . . . . . . . . . . . . . . .  8
     3.2.  Envelope Model  . . . . . . . . . . . . . . . . . . . .  9
     3.3.  Trust Levels  . . . . . . . . . . . . . . . . . . . . .  9
     3.4.  Trust Level Assignment Rules  . . . . . . . . . . . . . 10
     3.5.  Cryptographic Primitives  . . . . . . . . . . . . . . . 11
     3.6.  Signature Format Details  . . . . . . . . . . . . . . . 12
     3.7.  Low-S Normalization . . . . . . . . . . . . . . . . . . 12
   4.  Agent Passports . . . . . . . . . . . . . . . . . . . . . . 13
     4.1.  Passport Structure  . . . . . . . . . . . . . . . . . . 13
     4.2.  Passport Fields . . . . . . . . . . . . . . . . . . . . 14
     4.3.  Passport Size Limits  . . . . . . . . . . . . . . . . . 15
     4.4.  Origin Binding  . . . . . . . . . . . . . . . . . . . . 16
     4.5.  Key Rotation and Compromise Recovery  . . . . . . . . . 16
     4.6.  Passport Lifecycle  . . . . . . . . . . . . . . . . . . 17
     4.7.  JWK Key Requirements  . . . . . . . . . . . . . . . . . 18
   5.  Message Signing . . . . . . . . . . . . . . . . . . . . . . 19
     5.1.  Envelope Structure  . . . . . . . . . . . . . . . . . . 19
     5.2.  Signing Process . . . . . . . . . . . . . . . . . . . . 19
     5.3.  TLS Channel Binding . . . . . . . . . . . . . . . . . . 21
     5.4.  Verification Process  . . . . . . . . . . . . . . . . . 21
     5.5.  Canonical Serialization (RFC 8785)  . . . . . . . . . . 22
   6.  Tool Definition Signing . . . . . . . . . . . . . . . . . . 23
     6.1.  Signed Tool Structure . . . . . . . . . . . . . . . . . 23
     6.2.  Author Origin Binding . . . . . . . . . . . . . . . . . 24
     6.3.  Signing Process . . . . . . . . . . . . . . . . . . . . 24
     6.4.  Verification and Pinning  . . . . . . . . . . . . . . . 25
     6.5.  Rug Pull Detection  . . . . . . . . . . . . . . . . . . 26
   7.  Replay Protection . . . . . . . . . . . . . . . . . . . . . 26
     7.1.  Nonce Requirements  . . . . . . . . . . . . . . . . . . 26
     7.2.  Timestamp Window  . . . . . . . . . . . . . . . . . . . 27
     7.3.  Nonce Store Requirements  . . . . . . . . . . . . . . . 27
   8.  Trust Authority . . . . . . . . . . . . . . . . . . . . . . 28
     8.1.  Self-Hosting  . . . . . . . . . . . . . . . . . . . . . 28
     8.2.  Public Key Distribution . . . . . . . . . . . . . . . . 28
     8.3.  Issuer Chains . . . . . . . . . . . . . . . . . . . . . 29
     8.4.  Issuer Chain Entry Format . . . . . . . . . . . . . . . 29
     8.5.  Chain Verification Algorithm  . . . . . . . . . . . . . 30
     8.6.  Multi-TA Deployments  . . . . . . . . . . . . . . . . . 31
     8.7.  Revocation  . . . . . . . . . . . . . . . . . . . . . . 32
     8.8.  Revocation Endpoint Discovery . . . . . . . . . . . . . 33
     8.9.  Revocation Failure Policy . . . . . . . . . . . . . . . 33
   9.  Capability Negotiation  . . . . . . . . . . . . . . . . . . 34
     9.1.  Version Negotiation . . . . . . . . . . . . . . . . . . 34
     9.2.  Client Announcement . . . . . . . . . . . . . . . . . . 35
     9.3.  Server Response . . . . . . . . . . . . . . . . . . . . 36
     9.4.  Negotiation Failure . . . . . . . . . . . . . . . . . . 36
     9.5.  Transcript Binding (Anti-Downgrade) . . . . . . . . . . 37
   10. Error Codes . . . . . . . . . . . . . . . . . . . . . . . . 38
   11. Security Considerations . . . . . . . . . . . . . . . . . . 40
     11.1. Threat Model  . . . . . . . . . . . . . . . . . . . . . 40
     11.2. Provenance vs Safety  . . . . . . . . . . . . . . . . . 41
     11.3. Trust Authority Compromise  . . . . . . . . . . . . . . 42
     11.4. Nonce Store Exhaustion  . . . . . . . . . . . . . . . . 42
     11.5. Clock Skew Attacks  . . . . . . . . . . . . . . . . . . 42
     11.6. Algorithm Agility . . . . . . . . . . . . . . . . . . . 43
     11.7. Privacy Considerations  . . . . . . . . . . . . . . . . 43
     11.8. Non-Repudiation Implications  . . . . . . . . . . . . . 43
   12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 44
     12.1. MCPS Error Code Registry  . . . . . . . . . . . . . . . 44
     12.2. MCPS Trust Level Registry . . . . . . . . . . . . . . . 45
     12.3. MCPS Capability Identifier  . . . . . . . . . . . . . . 45
   13. References  . . . . . . . . . . . . . . . . . . . . . . . . 46
     13.1. Normative References  . . . . . . . . . . . . . . . . . 46
     13.2. Informative References  . . . . . . . . . . . . . . . . 47
   Appendix A.  Example Protocol Exchange  . . . . . . . . . . . . 48
   Appendix B.  OWASP Risk Mapping . . . . . . . . . . . . . . . . 51
   Appendix C.  Design Rationale . . . . . . . . . . . . . . . . . 52
   Appendix D.  Changes from draft-sharif-mcps-secure-mcp-01  . . . 54
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . 56

1.  Introduction

   The Model Context Protocol (MCP) defines a standard interface for
   connecting AI agents to external tools and data sources.  MCP uses
   JSON-RPC 2.0 as its message format and supports multiple transport
   mechanisms including standard input/output (stdio), HTTP with
   Server-Sent Events (SSE), and WebSocket.

   While MCP provides a robust framework for agent-tool interaction,
   the current specification lacks cryptographic guarantees for three
   critical security properties: identity, integrity, and tool
   authenticity.

1.1.  The Problem

   MCP in its current form has no built-in mechanism for:

   Identity:  There is no way for an MCP client or server to
      cryptographically verify the identity of its counterpart and
      bind that identity to a specific origin.  A malicious actor
      can impersonate a legitimate MCP server, serving modified tool
      definitions or intercepting sensitive data.

   Integrity:  JSON-RPC messages between client and server are
      unsigned.  There is no way for a recipient to verify that a
      message has not been tampered with in transit, or to prove
      after the fact that a particular message was sent by a
      particular party (non-repudiation).

   Tool Authenticity:  Tool definitions (name, description, input
      schema) are served unsigned.  A compromised or malicious server
      can modify tool descriptions to inject instructions into agent
      prompts (tool poisoning), or silently change tool behavior
      between sessions.

   These are not theoretical concerns:

   o  41% of MCP servers have zero authentication (TapAuth research,
      scanning 518 production MCP servers).

   o  An independent scan of 39 AI agent frameworks against the OWASP
      Top 10 for Agentic Applications found that 13 frameworks had
      no MCP security controls, 17 had partial controls, and only 9
      implemented adequate protections.

   o  Tool poisoning attacks via description injection have been
      demonstrated in research contexts, where modified tool
      descriptions cause agents to execute unintended actions.

1.2.  Scope and Limitations

   This document addresses identity, integrity, and replay
   protection.  It does NOT address:

   Tool Safety Analysis:  Signing a tool proves WHO authored it
      (provenance), not that the tool is safe to execute.  A
      malicious server operator can sign their own poisoned tool
      definitions with a valid signature.  Tool safety analysis
      (detecting malicious descriptions, sandboxing execution) is a
      separate concern that complements this work.

   Authorization:  This document does not replace OAuth-based access
      control.  It provides a cryptographic identity layer that
      operates alongside authorization.

   Confidentiality:  Message encryption is out of scope.
      MCP-over-HTTP already provides transport-level confidentiality
      via TLS.

1.3.  Relationship to Existing MCP Authorization

   Existing MCP authorization work (OAuth 2.1-based) addresses
   session-level authentication, establishing that a client is
   authorized to connect to a server.  This is necessary but not
   sufficient.

   MCPS addresses a different layer: message-level and artifact-level
   cryptographic guarantees.  The distinction is analogous to:

      +------------------+-----------------+-------------------------+
      | Layer            | HTTP Analogy    | Addressed By            |
      +------------------+-----------------+-------------------------+
      | Session auth     | OAuth bearer    | Existing MCP auth       |
      | Transport        | TLS             | Existing (transport)    |
      | Message integrity| HTTP Signatures | MCPS                    |
      | Artifact signing | Code signing    | MCPS                    |
      | Agent identity   | Client certs    | MCPS                    |
      +------------------+-----------------+-------------------------+

   Note: MCP-over-HTTP already uses TLS for transport security.
   MCPS operates at the application layer above TLS, providing
   per-message non-repudiation and artifact integrity that TLS does
   not offer (TLS terminates at the connection, not the message).

   MCPS complements existing OAuth-based authorization.  A server MAY
   require both OAuth credentials (for access control) and MCPS
   signatures (for integrity and non-repudiation).

1.4.  Relationship to DPoP (RFC 9449)

   DPoP (Demonstrating Proof-of-Possession) [RFC9449] provides proof
   that the presenter of an OAuth access token possesses a particular
   key.  MCPS's message signing serves a similar proof-of-possession
   function but extends beyond OAuth token binding:

   1.  Per-message signing (not per-session): Every JSON-RPC message
       is individually signed, enabling non-repudiation of specific
       tool calls and responses.

   2.  Tool definition signing: DPoP does not address artifact
       integrity.

   3.  Trust level negotiation: DPoP does not define progressive
       trust tiers.

   Implementations MAY compose MCPS with DPoP.  Specifically, the
   Agent Passport's public key MAY be the same key used in DPoP
   proofs, providing a unified identity across both OAuth
   authorization and message-level integrity.

1.5.  Design Goals

   The design of MCPS is guided by the following goals:

   1.  Backward compatibility: Non-MCPS endpoints MUST continue to
       function without modification.

   2.  Transport independence: MCPS MUST work over any MCP transport
       (stdio, HTTP SSE, WebSocket).

   3.  Progressive adoption: Organizations MUST be able to adopt
       MCPS incrementally through trust levels.

   4.  Self-sovereignty: No dependency on any centralized service
       MUST be required.

   5.  Standards alignment: Cryptographic operations MUST use
       established NIST and IETF standards.

2.  Terminology

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
   NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED",
   "MAY", and "OPTIONAL" in this document are to be interpreted as
   described in BCP 14 [RFC2119] [RFC8174] when, and only when, they
   appear in all capitals, as shown here.

   The following terms are used throughout this document:

   Agent:  A software entity that communicates over MCP, acting as
      either a client or server.

   Agent Passport:  A signed credential binding an ECDSA P-256 public
      key to an agent identity and a specific origin, issued by a
      Trust Authority or self-signed.

   Trust Authority (TA):  A service that issues, manages, and
      optionally revokes Agent Passports.  Analogous to a Certificate
      Authority in the TLS/PKI ecosystem.

   Trust Level:  An integer (0-4) indicating the degree of
      cryptographic verification applied to an MCPS connection.

   Signed Envelope:  A JSON object wrapping a JSON-RPC message with
      an MCPS header containing a cryptographic signature, nonce, and
      timestamp.

   Tool Signature:  An ECDSA signature over a tool definition,
      binding the tool's name, description, and input schema to its
      author.

   Canonical Serialization:  JSON Canonicalization Scheme (JCS) per
      RFC 8785, used as the deterministic input to all signing
      operations.

   Tool Hash:  The SHA-256 digest of the JCS-canonicalized tool
      signing object (including name, description, input schema, and
      author origin), used for efficient change detection.

   Pin Store:  A persistent mapping from (server_origin, tool_name)
      tuples to tool hashes, maintained by clients for detecting
      tool definition changes.

   Nonce Store:  A data structure maintaining previously observed
      nonce values for replay detection.

   Transcript Binding:  A signed hash of the capability negotiation
      exchange, using ECDSA signatures (asymmetric), used to detect
      downgrade attacks.  Note: Previous drafts used the term
      "Transcript MAC"; this has been corrected because MCPS uses
      asymmetric signatures, not symmetric MACs.

3.  Protocol Overview

3.1.  Architecture

   MCPS operates as a security layer between the application logic
   and the MCP transport.  The architecture consists of four
   components:

   1.  Agent Passports: Cryptographic identity credentials bound to
       an origin.

   2.  Message Signing: Per-message ECDSA signatures in an envelope.

   3.  Tool Signing: Signatures over complete tool definitions.

   4.  Trust Authority: Passport issuance, chain validation, and
       revocation.

   The following diagram illustrates the message flow:

      +-------------------+         +-------------------+
      |   MCP Client      |         |   MCP Server      |
      |                   |         |                   |
      | +---------------+ |         | +---------------+ |
      | | Application   | |         | | Application   | |
      | +-------+-------+ |         | +-------+-------+ |
      |         |         |         |         |         |
      | +-------v-------+ |         | +-------v-------+ |
      | | MCPS Layer    | | <-----> | | MCPS Layer    | |
      | | (sign/verify) | |         | | (sign/verify) | |
      | +-------+-------+ |         | +-------+-------+ |
      |         |         |         |         |         |
      | +-------v-------+ |         | +-------v-------+ |
      | | MCP Transport | |         | | MCP Transport | |
      | +---------------+ |         | +---------------+ |
      +-------------------+         +-------------------+

3.2.  Envelope Model

   MCPS wraps existing JSON-RPC messages in a signed envelope rather
   than modifying the JSON-RPC schema.  The MCPS header is added as
   a top-level "mcps" field alongside the standard JSON-RPC fields.
   Non-MCPS implementations ignore the "mcps" field per standard
   JSON-RPC behavior.

   This approach follows the precedent of HTTP Signatures [RFC9421],
   which add signatures alongside existing HTTP headers rather than
   modifying the HTTP message format.

3.3.  Trust Levels

   MCPS defines five trust levels for progressive security adoption:

      +-------+-----------+------------------------------------------+
      | Level | Name      | Requirements                             |
      +-------+-----------+------------------------------------------+
      | L0    | None      | No MCPS verification.  Equivalent to     |
      |       |           | current MCP behavior.  Self-signed        |
      |       |           | passports.                                |
      +-------+-----------+------------------------------------------+
      | L1    | Signed    | Messages are signed.  Passport signed     |
      |       |           | by ANY Trust Authority.                   |
      +-------+-----------+------------------------------------------+
      | L2    | Verified  | Messages are signed.  Passport signed     |
      |       |           | by a TA whose root key is in the          |
      |       |           | verifier's trust store.                   |
      +-------+-----------+------------------------------------------+
      | L3    | Strict    | L2 plus tool definition signatures        |
      |       |           | MUST be present and valid.  TA has        |
      |       |           | verified origin ownership.                |
      +-------+-----------+------------------------------------------+
      | L4    | Full      | L3 plus mutual authentication and         |
      |       |           | real-time revocation checking.  TA has    |
      |       |           | performed security audit.                 |
      +-------+-----------+------------------------------------------+

   Servers SHOULD declare their minimum required trust level during
   capability negotiation (Section 9).  Clients connecting at a trust
   level below the server minimum MUST be rejected with error code
   -33009 (MCPS_TRUST_LEVEL_INSUFFICIENT).

3.4.  Trust Level Assignment Rules

   Trust levels are NOT self-asserted by passport holders.  They are
   constrained by the issuance process:

   1.  Self-signed passports are ALWAYS L0, regardless of any
       "trust_level" field value.  Implementations MUST cap
       self-signed passports at L0.

   2.  L1-L2 require the passport to be signed by a Trust Authority
       whose public key can be verified through the issuer chain
       (Section 8.3).

   3.  L3 additionally requires the TA to have verified that the
       passport holder controls the "origin" URI (e.g., via HTTP-01
       challenge, DNS-01 challenge, or documented manual
       verification).

   4.  L4 additionally requires the TA to have performed a security
       audit of the agent and to provide real-time revocation
       checking (Section 8.7).

   An implementation receiving a passport claiming L4 but signed by
   an unknown TA MUST treat it as L0.

3.5.  Cryptographic Primitives

   All MCPS cryptographic operations use the following algorithms:

   Key Algorithm:  ECDSA with the P-256 curve (NIST FIPS 186-5
      [FIPS186-5], deterministic signatures per [RFC6979]).

   Hash Algorithm:  SHA-256 (NIST FIPS 180-4).

   Signature Format:  IEEE P1363 fixed-length r||s encoding
      (exactly 64 bytes for P-256), per [RFC7518] Section 3.4.
      All signatures MUST use low-S normalization (see
      Section 3.7).

   Signature Encoding:  Base64 without padding [RFC4648].

   Key Format:  JSON Web Key (JWK) [RFC7517].

   Canonical Serialization:  JSON Canonicalization Scheme (JCS)
      [RFC8785].

   Why JCS (RFC 8785):  Canonical JSON serialization is critical for
      cross-implementation signature verification.  Different
      language runtimes produce different byte representations for
      the same logical JSON value (e.g., Node.js
      JSON.stringify({a:1.0}) produces {"a":1} while Python's
      json.dumps({a:1.0}) produces {"a": 1.0}).  RFC 8785 defines a
      deterministic serialization that guarantees identical bytes
      across all implementations.

   The choice of P-256 provides 128-bit security strength, broad
   platform support (Web Crypto API, OpenSSL, Java KeyStore), and
   hardware security module (HSM) compatibility.  FIPS 186-5 is
   referenced (not the superseded FIPS 186-4).

   Note: RFC 6979 specifies deterministic ECDSA nonce generation.
   Implementations using HSMs that employ internal random number
   generation for nonce generation are compliant provided the HSM
   generates nonces with sufficient entropy per FIPS 186-5.

   Implementations MAY support additional algorithms in future
   versions via algorithm negotiation in the "mcps" capability.

3.6.  Signature Format Details

   Signatures use the IEEE P1363 fixed-length format: the 32-byte
   big-endian encoding of r concatenated with the 32-byte big-endian
   encoding of s, for a total of exactly 64 bytes.  This format is
   unambiguous (unlike variable-length DER encoding) and mandated by
   RFC 7518 Section 3.4 for JWA/JWS compatibility.

   DER encoding produces variable-length signatures (typically 70-72
   bytes for P-256).  IEEE P1363 produces fixed-length signatures
   (exactly 64 bytes for P-256).  Fixed-length format:

   1.  Eliminates ambiguity in signature parsing across
       implementations.

   2.  Is required by RFC 7518 Section 3.4 (JWA) and widely
       supported.

   3.  Simplifies cross-platform interoperability (no DER parsing
       needed).

3.7.  Low-S Normalization

   Given a valid ECDSA signature (r, s), the signature (r, n-s) is
   also valid for the same message and key.  This malleability can
   be exploited to bypass nonce-based replay detection if the nonce
   store keys on full message bytes rather than the nonce string.

   To eliminate this attack:

   1.  All signatures MUST satisfy s <= n/2, where n is the order
       of the P-256 curve.

   2.  If the raw ECDSA signing operation produces s > n/2, the
       signer MUST replace s with n - s before encoding.

   3.  Verifiers SHOULD normalize incoming signatures (replace s
       with n - s if s > n/2) before verification for
       interoperability with implementations that do not perform
       low-S normalization on signing.

   The P-256 curve order n is:

      n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84
          F3B9CAC2FC632551

   The half-order n/2 is:

      n/2 = 0x7FFFFFFF800000007FFFFFFFFFFFFFFFDE737D56D38BCF42
            79DCE5617E3192A8

   Nonce stores MUST key on the nonce string value, NOT on full
   message bytes, to prevent signature malleability from bypassing
   replay detection (see Section 7.3).

4.  Agent Passports

   An Agent Passport is a signed credential that binds an ECDSA
   P-256 key pair to an agent identity and a specific origin.

4.1.  Passport Structure

   A passport is represented as a JSON object with the following
   top-level structure:

      {
        "mcps_version": "1.0",
        "passport": {
          "id": "ap_<uuid-v4>",
          "agent_name": "<string>",
          "agent_version": "<string (semver)>",
          "issuer": "<string>",
          "origin": "<string (URI)>",
          "issued_at": "<string (ISO 8601 UTC)>",
          "expires_at": "<string (ISO 8601 UTC)>",
          "public_key": {
            "kty": "EC",
            "crv": "P-256",
            "x": "<string (base64url)>",
            "y": "<string (base64url)>"
          },
          "capabilities": ["<string>"],
          "trust_level": 0,
          "issuer_chain": [
            "<string (base64-encoded JSON)>"
          ],
          "key_rotation": {
            "previous_key_hash": "<string (hex SHA-256)>",
            "rotated_at": "<string (ISO 8601 UTC)>"
          }
        },
        "signature": "<string (base64, IEEE P1363)>"
      }

4.2.  Passport Fields

   The following fields are defined for Agent Passports:

   mcps_version:  REQUIRED.  String.  The MCPS protocol version.
      MUST be "1.0" for this specification.

   passport.id:  REQUIRED.  String.  A unique identifier for this
      passport.  MUST begin with the prefix "ap_" followed by a
      UUID v4 value.

   passport.agent_name:  REQUIRED.  String.  A human-readable name
      for the agent.

   passport.agent_version:  REQUIRED.  String.  The semantic version
      [SEMVER] of the agent software.

   passport.issuer:  REQUIRED.  String.  An identifier for the Trust
      Authority that issued this passport.  For self-signed passports,
      this MUST be the string "self".

   passport.origin:  REQUIRED.  String.  The authorized origin URI
      this passport is bound to (e.g.,
      "https://api.example.com:443").  Verifiers MUST reject
      passports presented to a different origin.  See Section 4.4.

   passport.issued_at:  REQUIRED.  String.  The issuance timestamp
      in ISO 8601 UTC format (e.g., "2026-03-13T12:00:00Z").

   passport.expires_at:  REQUIRED.  String.  The expiry timestamp
      in ISO 8601 UTC format.

   passport.public_key:  REQUIRED.  Object.  The agent's public key
      in JWK format.  See Section 4.7 for requirements.

   passport.capabilities:  OPTIONAL.  Array of strings.  A list of
      capability identifiers granted to this agent by the Trust
      Authority.  Maximum 64 entries (see Section 4.3).

   passport.trust_level:  OPTIONAL.  Integer (0-4).  The trust level
      assigned by the issuing Trust Authority.  Default value is 0.
      See Section 3.4 for assignment rules.

   passport.issuer_chain:  OPTIONAL.  Array of strings.  Chain of
      base64-encoded JSON intermediate Trust Authority passports.
      Each entry is a complete signed intermediate TA passport.
      Maximum depth: 5 entries (see Section 4.3).
      See Section 8.3 for format and verification.

   passport.key_rotation:  OPTIONAL.  Object.  Key rotation metadata
      for compromise recovery.  See Section 4.5.

   signature:  REQUIRED.  String.  A base64-encoded IEEE P1363
      ECDSA signature (exactly 64 bytes before encoding) computed
      over the JCS-canonicalized (RFC 8785) "passport" object,
      with low-S normalization (Section 3.7).  For Trust Authority-
      issued passports, this signature is produced using the Trust
      Authority's private key.  For self-signed passports, this
      signature is produced using the agent's own private key.

4.3.  Passport Size Limits

   To prevent denial-of-service via oversized passports, the
   following limits are defined:

   MAX_PASSPORT_BYTES:  8192.  The maximum size in bytes of a
      JCS-canonicalized passport.  Implementations MUST reject
      passports exceeding this limit with error code -33013
      (MCPS_PASSPORT_TOO_LARGE).

   MAX_ISSUER_CHAIN_DEPTH:  5.  The maximum number of entries in
      the "issuer_chain" array.  Implementations MUST reject
      passports with chains exceeding this depth with error code
      -33014 (MCPS_CHAIN_TOO_DEEP).

   MAX_CAPABILITIES:  64.  The maximum number of entries in the
      "capabilities" array.

   Implementations MUST enforce all three limits during passport
   validation.

4.4.  Origin Binding

   The "origin" field binds a passport to a specific server URI.
   This prevents passport reuse across domains:

   1.  When a server presents a passport, the client MUST verify
       that the passport's "origin" matches the URI it connected to.

   2.  When a client presents a passport, the server MUST verify
       that the passport's "origin" matches its own published URI.

   3.  Origin comparison MUST use scheme + authority (host + port)
       per RFC 6454 [RFC6454].

   This prevents an attacker from obtaining a valid passport for
   their own server and presenting it when impersonating a different
   server.

   If origin verification fails, the implementation MUST reject the
   passport with error code -33011 (MCPS_ORIGIN_MISMATCH).

4.5.  Key Rotation and Compromise Recovery

   Passports support key rotation for both routine rotation and
   compromise recovery:

   Routine Rotation:  An agent generates a new key pair, requests a
      new passport from the Trust Authority, and the old passport is
      revoked after confirmation that the new passport is in active
      use.

   Compromise Recovery:  When a key is suspected compromised, the
      agent generates a new key pair and includes a "key_rotation"
      field linking to the previous key via its SHA-256 hash.  This
      enables Trust Authorities to verify the rotation request and
      revoke all passports associated with the compromised key.

   The "key_rotation" object contains:

   previous_key_hash:  REQUIRED (within key_rotation).  String.
      SHA-256 hash (hex-encoded) of the PEM-encoded previous
      public key.

   rotated_at:  REQUIRED (within key_rotation).  String.  ISO 8601
      UTC timestamp indicating when the rotation occurred.

   Trust Authorities SHOULD revoke the old passport upon issuing a
   new one with "key_rotation".  Implementations SHOULD support a
   configurable grace period where both old and new passports are
   accepted to allow rolling deployments.

4.6.  Passport Lifecycle

   The lifecycle of an Agent Passport consists of the following
   stages:

   Generation:  The agent generates an ECDSA P-256 key pair locally.
      The private key MUST be stored securely and MUST NOT be
      transmitted.

   Issuance:  The agent submits its public key and requested origin
      to a Trust Authority.  The Trust Authority validates the
      agent's ownership of the origin (e.g., via HTTP challenge,
      DNS TXT record, or manual verification), assigns capabilities
      and a trust level, and signs the passport with the Trust
      Authority's private key.

   Self-Signing:  An agent MAY self-sign its passport.  Self-signed
      passports are ALWAYS Trust Level L0 regardless of any
      "trust_level" field value.  Implementations MUST enforce this.
      Self-signed passports MUST set the "issuer" field to "self".

   Verification:  A receiving party verifies the passport signature
      against the Trust Authority's public key (for TA-issued
      passports) or against the agent's own public key embedded in
      the passport (for self-signed passports).  For self-signed
      passports, the trust level is capped at L0.

   Expiry:  Passports MUST be rejected after the "expires_at"
      timestamp.  Implementations SHOULD allow a configurable clock
      skew tolerance.  The default clock skew tolerance SHOULD be
      60 seconds.

   Key Rotation:  An agent rotates its key by generating a new key
      pair and requesting a new passport from the Trust Authority.
      For compromise recovery, the "key_rotation" field (Section 4.5)
      links the new passport to the old key.  The old passport
      continues to be valid until its "expires_at" or until
      explicitly revoked.

   Revocation:  Trust Authorities MAY publish revocation information
      for passports they have issued.  See Section 8.7.

4.7.  JWK Key Requirements

   The "public_key" field of an Agent Passport MUST conform to the
   following requirements:

   o  The "kty" field MUST be "EC".

   o  The "crv" field MUST be "P-256".

   o  The "x" and "y" fields MUST contain the base64url-encoded
      coordinates of the public key point on the P-256 curve, without
      padding.

   o  The "d" (private key) parameter MUST NOT be present.

   o  Implementations MUST validate that the public key point lies on
      the P-256 curve before using it for signature verification.

5.  Message Signing

   Every JSON-RPC message exchanged between MCPS-aware endpoints is
   wrapped in a signed envelope.  The envelope adds an "mcps" field
   to the top level of the JSON-RPC message.

5.1.  Envelope Structure

   A signed message envelope has the following structure:

      {
        "mcps": {
          "version": "1.0",
          "passport_id": "ap_<uuid>",
          "timestamp": "<string (ISO 8601 UTC)>",
          "nonce": "<string (hex, 16 random bytes)>",
          "signature": "<string (base64, IEEE P1363)>"
        },
        "jsonrpc": "2.0",
        "method": "<string>",
        "params": { ... },
        "id": 1
      }

   The "mcps" field contains the following sub-fields:

   version:  REQUIRED.  String.  The MCPS protocol version.  MUST
      be "1.0".

   passport_id:  REQUIRED.  String.  The identifier of the Agent
      Passport used to sign this message.

   timestamp:  REQUIRED.  String.  The current UTC time in ISO 8601
      format at which the message was signed.

   nonce:  REQUIRED.  String.  A hex-encoded string of 16
      cryptographically random bytes, unique to this message,
      used for replay protection.

   signature:  REQUIRED.  String.  A base64-encoded IEEE P1363
      ECDSA signature (exactly 64 bytes before encoding, with
      low-S normalization) over the signing payload (see
      Section 5.2).

5.2.  Signing Process

   To sign a JSON-RPC message, an MCPS implementation MUST perform
   the following steps in order:

   1.  Construct the JSON-RPC message without the "mcps" field.

   2.  Generate 16 cryptographically random bytes, hex-encode them
       as the nonce.

   3.  Record the current UTC timestamp in ISO 8601 format.

   4.  Compute the message hash:

          message_hash = hex(SHA-256(JCS(JSON-RPC message)))

       where JCS is the RFC 8785 canonicalization of the complete
       JSON-RPC message (without the "mcps" field).

   5.  Construct the signing payload by JCS-canonicalizing [RFC8785]
       the following JSON object:

          {
            "message_hash": "<hex SHA-256>",
            "nonce": "<nonce>",
            "passport_id": "<passport_id>",
            "timestamp": "<timestamp>"
          }

       The keys in this object are sorted lexicographically per
       RFC 8785.  The "message_hash" value is the hexadecimal-
       encoded SHA-256 hash of the JCS-canonicalized JSON-RPC
       message.

   6.  Sign the UTF-8 encoding of the JCS-canonicalized signing
       payload using ECDSA P-256 with the agent's private key per
       [RFC6979] (deterministic signature generation), producing
       an IEEE P1363 signature with low-S normalization
       (Section 3.7).

   7.  Base64-encode the 64-byte IEEE P1363 signature without
       padding per [RFC4648].

   8.  Attach the "mcps" object to the JSON-RPC message.

   Design note: The signing payload uses "message_hash" (the
   SHA-256 hash of the JCS-canonicalized message) rather than
   embedding the JCS string directly.  Earlier drafts used
   "jsonrpc_message: JCS(message)" in the signing payload, nesting
   one JCS string inside another JCS object.  This creates
   fragility: the inner JCS string must be JSON-escaped when
   embedded in the outer object, and different JSON libraries handle
   this escaping differently.  Using a hash eliminates this
   ambiguity, is more robust, and is more efficient.

5.3.  TLS Channel Binding

   Implementations MAY include a TLS channel binding token (per
   [RFC9266], tls-exporter type) in the signing payload to bind MCPS
   signatures to the TLS session:

      {
        "channel_binding": "<base64 tls-exporter binding>",
        "message_hash": "<hex SHA-256>",
        "nonce": "<nonce>",
        "passport_id": "<passport_id>",
        "timestamp": "<timestamp>"
      }

   When present, the verifier MUST verify that the "channel_binding"
   value matches the tls-exporter binding of the current TLS session.
   This prevents relay attacks where a man-in-the-middle with a valid
   TLS certificate for a different domain forwards signed messages
   between the legitimate client and server.

   The "channel_binding" field is OPTIONAL.  When absent, the signing
   payload uses the four-field format defined in Section 5.2.

5.4.  Verification Process

   To verify a signed message, an MCPS implementation MUST perform
   the following steps in order:

   1.  Extract the "mcps" field from the received message.

   2.  Verify that all required "mcps" sub-fields are present.

   3.  Verify that the "timestamp" is within the acceptable window
       (see Section 7.2).  If the timestamp is outside the window,
       reject the message with error code -33006.

   4.  Verify that the "nonce" has not been previously observed (see
       Section 7.1).  If the nonce is a duplicate, reject the
       message with error code -33005.

   5.  Look up the Agent Passport by "passport_id".  Verify that the
       passport is valid, has not expired, is bound to the correct
       origin (Section 4.4), and (for L4) has not been revoked.  If
       the passport format is invalid, reject with error code
       -33001.  If expired, reject with -33002.  If revoked, reject
       with -33003.  If origin mismatches, reject with -33011.

   6.  Determine the effective trust level using the rules in
       Section 3.4.  If the effective trust level is below the
       server's minimum, reject with -33009.

   7.  Reconstruct the signing payload: compute the message hash
       from the received JSON-RPC message (with the "mcps" field
       removed), combine with received nonce, passport_id, and
       timestamp.  If "channel_binding" is present, include it.

   8.  JCS-canonicalize the reconstructed signing payload.

   9.  Verify the IEEE P1363 ECDSA signature against the public key
       from the Agent Passport.  Normalize s to low-S before
       verification (Section 3.7).  If verification fails, reject
       with error code -33004.

   10. Store the nonce (keyed on the nonce string) in the nonce
       store to prevent future replay.

   If any step fails, the message MUST be rejected with the
   appropriate error code defined in Section 10.

5.5.  Canonical Serialization (RFC 8785)

   All MCPS signing operations use the JSON Canonicalization Scheme
   (JCS) defined in RFC 8785 [RFC8785] for deterministic
   serialization.  This ensures that implementations in different
   programming languages produce identical byte sequences for the
   same logical JSON value.

   Key JCS requirements relevant to MCPS:

   1.  Object keys MUST be sorted lexicographically by their Unicode
       code point values.

   2.  No extraneous whitespace (spaces, tabs, newlines) SHALL be
       present between tokens.

   3.  String values MUST use the shortest possible JSON escape
       sequences.

   4.  Numbers MUST be serialized according to ECMAScript number
       serialization: no unnecessary leading zeros, no trailing
       decimal zeros, integer-valued floats serialized as integers
       (1.0 becomes 1).

   5.  Negative zero (-0) MUST be serialized as 0.

   Implementers MUST test their JCS implementation against the
   RFC 8785 test vectors to ensure cross-platform compatibility.
   In particular, number serialization differences between
   JavaScript and Python runtimes are a common source of
   interoperability failures.

6.  Tool Definition Signing

   Tool definitions MAY be signed by their author to prevent
   poisoning attacks and to detect unauthorized modifications.

6.1.  Signed Tool Structure

   A signed tool definition has the following structure:

      {
        "tool": {
          "name": "read_file",
          "description": "Read contents of a file at the
                          given path",
          "inputSchema": {
            "type": "object",
            "properties": {
              "path": {
                "type": "string",
                "description": "File path to read"
              }
            },
            "required": ["path"]
          }
        },
        "tool_signature": {
          "author_passport_id": "ap_<uuid>",
          "author_origin": "https://author.example.com",
          "signed_at": "<string (ISO 8601 UTC)>",
          "signature": "<string (base64, IEEE P1363)>",
          "tool_hash": "<string (hex-encoded SHA-256)>"
        }
      }

   The "tool_signature" field contains:

   author_passport_id:  REQUIRED.  String.  The passport identifier
      of the tool author.

   author_origin:  OPTIONAL.  String.  The origin URI of the tool
      author.  When present, enables tool-server origin binding
      (see Section 6.2).

   signed_at:  REQUIRED.  String.  ISO 8601 UTC timestamp of when
      the tool definition was signed.

   signature:  REQUIRED.  String.  Base64-encoded IEEE P1363 ECDSA
      signature (with low-S normalization) over the JCS-
      canonicalized tool signing object (see Section 6.3).

   tool_hash:  REQUIRED.  String.  Hexadecimal-encoded SHA-256
      digest of the JCS-canonicalized tool signing object.  This
      enables efficient change detection without re-verifying the
      full signature.

6.2.  Author Origin Binding

   The "author_origin" field in the tool signature binds the signed
   tool to a specific serving origin.  This prevents tool relaying
   attacks where a validly signed tool is served from an unauthorized
   server.

   When "author_origin" is present in the tool signature:

   1.  Clients SHOULD verify that the "author_origin" matches the
       origin of the server currently serving the tool.

   2.  If the origin does not match, the client SHOULD alert the
       user or reject the tool according to its configured policy.

   When "author_origin" is null or absent, origin binding is not
   enforced.  This supports cases where a tool author intentionally
   distributes tools for use on third-party servers.

6.3.  Signing Process

   To sign a tool definition:

   1.  Construct the signing object:

          {
            "author_origin": "<author's origin URI or null>",
            "description": "<tool description>",
            "inputSchema": { ... },
            "name": "<tool name>"
          }

       Note: The signing object keys are ordered lexicographically
       per RFC 8785 conventions.

   2.  JCS-canonicalize [RFC8785] the signing object.

   3.  Compute the SHA-256 hash of the JCS-canonicalized output.
       Record this as the "tool_hash" field (hex-encoded).

   4.  Sign the JCS-canonicalized output with the tool author's
       private key using ECDSA P-256, producing an IEEE P1363
       signature with low-S normalization (Section 3.7).

   Important: The hash covers the entire signing object, including
   the "description" field.  This is critical because tool poisoning
   attacks primarily target the description field (injecting
   instructions into agent prompts), not the inputSchema.  A hash
   covering only the schema would not detect description-based
   poisoning attacks.

6.4.  Verification and Pinning

   Clients SHOULD maintain a persistent pin store mapping
   (server_origin, tool_name) tuples to the last known tool_hash
   value.  On each connection:

   1.  Verify the tool signature against the author's Agent Passport
       public key.

   2.  Verify the author's passport is bound to the correct origin
       (Section 4.4).

   3.  If "author_origin" is present in the tool signature, verify
       it matches the origin of the server serving the tool
       (Section 6.2).

   4.  Compare the received "tool_hash" against the pinned value
       in the local pin store.

   5.  If no pinned value exists, store the current tool_hash
       (trust on first use).

   6.  If the hash has changed since the last pinned value, the
       client MUST take action according to its configured policy
       (see Section 6.5).

6.5.  Rug Pull Detection

   When a tool's tool_hash changes between sessions, a "rug pull"
   may have occurred: the tool's name, description, or schema has
   been modified without the user's knowledge.

   Implementations MUST support at least one of the following
   policies for handling tool hash changes:

   Alert:  Notify the user that the tool definition has changed and
      request confirmation before proceeding.

   Reject:  Reject the tool and return error code -33008.

   Accept:  Accept the new definition and update the pin store.
      This policy is NOT RECOMMENDED for Trust Levels L3 and L4.

   The default policy SHOULD be "alert" for Trust Levels L1 and L2,
   and "reject" for Trust Levels L3 and L4.

7.  Replay Protection

   MCPS uses a dual mechanism for replay protection combining nonce
   uniqueness with timestamp windowing.

7.1.  Nonce Requirements

   Each signed message MUST include a nonce in the "mcps" header.
   The nonce MUST be generated as 16 cryptographically random bytes,
   hex-encoded (producing a 32-character hexadecimal string).

   Recipients MUST maintain a nonce store and MUST reject any
   message whose nonce has been previously observed.  A duplicate
   nonce MUST result in error code -33005.

7.2.  Timestamp Window

   Messages with timestamps older than the configurable timestamp
   window MUST be rejected with error code -33006.  The default
   timestamp window is 300 seconds (5 minutes).

   Implementations SHOULD allow the timestamp window to be
   configured.  The minimum permitted timestamp window is 30 seconds.
   The maximum permitted timestamp window is 3600 seconds (1 hour).

   Implementations SHOULD allow a configurable clock skew tolerance
   to account for imprecise system clocks.  The default clock skew
   tolerance is 60 seconds.  The effective acceptance window is
   therefore (timestamp_window + clock_skew_tolerance).

7.3.  Nonce Store Requirements

   Implementations MUST store nonces for at least the duration of
   the timestamp window plus the clock skew tolerance.

   Nonce stores MUST key on the nonce string value, NOT on full
   message bytes.  This is critical for preventing ECDSA signature
   malleability from bypassing replay detection: given a valid
   signature (r, s), the signature (r, n-s) is also valid for the
   same message, producing different message bytes but containing
   the same nonce.  Keying on the nonce string ensures that both
   the original and the malleable variant are detected as replays.

   Implementations SHOULD periodically garbage-collect nonces whose
   associated timestamps fall outside the acceptance window.

   The nonce store MAY be implemented as:

   o  An in-memory data structure for single-process deployments.

   o  A shared data store (e.g., Redis, database table) for
      distributed deployments.

   o  A Bloom filter for memory-constrained environments, accepting
      a configurable false-positive rate (which results in
      legitimate messages being incorrectly rejected as replays).

8.  Trust Authority

   A Trust Authority (TA) is a service that issues and manages Agent
   Passports.  The TA role is analogous to a Certificate Authority
   in the TLS/PKI ecosystem.

8.1.  Self-Hosting

   Any organization MAY operate its own Trust Authority.  A Trust
   Authority is defined by:

   1.  An ECDSA P-256 key pair (the TA's signing key).

   2.  A public key distribution mechanism (see Section 8.2).

   3.  For L3+ passports: a documented origin verification process.

   4.  For L4 passports: a revocation endpoint and audit process.

   There is no requirement to use any specific Trust Authority
   service.  Implementations MUST support configuring one or more
   custom TA public keys as trust anchors.

8.2.  Public Key Distribution

   Trust Authority public keys MAY be distributed via any of the
   following mechanisms:

   o  An HTTPS endpoint serving the TA's public key in JWK format.

   o  A JWK Set endpoint conforming to [RFC7517].

   o  Static configuration in the client or server application.

   Implementations MUST support at least one of these mechanisms.
   HTTPS-based distribution SHOULD use TLS with certificate
   validation.

8.3.  Issuer Chains

   Trust delegation follows X.509-style chains:

   1.  A root TA signs intermediate TA passports.

   2.  Intermediate TAs sign agent passports.

   3.  Verifiers walk the chain from agent passport to a root key
       in their configured trust store.

   4.  If no chain leads to a trusted root, the passport MUST be
       treated as L0.

   The "issuer_chain" field in the passport contains a chain of
   base64-encoded JSON intermediate Trust Authority passports,
   ordered from the agent's immediate issuer to the root.  Each
   entry is a complete signed intermediate TA passport.  The chain
   MUST NOT exceed MAX_ISSUER_CHAIN_DEPTH (5) entries.

8.4.  Issuer Chain Entry Format

   Each entry in the "issuer_chain" array is a base64-encoded JSON
   string representing a complete signed intermediate Trust Authority
   passport.  When decoded from base64, each entry contains:

      {
        "mcps_version": "1.0",
        "passport_id": "ap_<intermediate-uuid>",
        "agent": {
          "name": "Intermediate TA Name",
          "version": "1.0.0",
          "capabilities": []
        },
        "public_key": {
          "kty": "EC",
          "crv": "P-256",
          "x": "<base64url>",
          "y": "<base64url>"
        },
        "origin": "https://intermediate-ta.example.com",
        "trust_level": 2,
        "issued_at": "<ISO 8601 UTC>",
        "expires_at": "<ISO 8601 UTC>",
        "issuer": "<parent-ta-id>",
        "issuer_chain": [],
        "signature": "<base64, IEEE P1363>"
      }

   The intermediate passport contains its own signature, public key,
   and issuer fields.  The "signature" is produced by the parent TA
   (the TA that issued this intermediate), and the "public_key" is
   the intermediate TA's own key which was used to sign the next
   passport down the chain.

8.5.  Chain Verification Algorithm

   Verifiers MUST implement the following algorithm to validate an
   issuer chain:

   1.  Let P be the agent passport to verify.

   2.  Check that the length of P.issuer_chain does not exceed
       MAX_ISSUER_CHAIN_DEPTH (5).  If it does, reject with error
       code -33014 (MCPS_CHAIN_TOO_DEEP).

   3.  If P.issuer is directly present in the verifier's trust
       store, verify P.signature against that TA's public key.
       If verification succeeds, the chain is valid.  Done.

   4.  If P.issuer_chain is empty or absent, treat the passport
       as L0.  Done.

   5.  Set i = 0 (index into issuer_chain).

   6.  Decode issuer_chain[i] from base64, parse as JSON.
       Let IC = the decoded intermediate passport.

   7.  Verify P.signature against IC.public_key (the intermediate
       TA's public key).  If verification fails, treat the
       passport as L0.

   8.  Verify that IC has not expired (check IC.expires_at).

   9.  If IC.issuer is in the verifier's trust store, verify
       IC.signature against the trust store's public key for that
       issuer.  If verification succeeds, the chain is valid.
       Done.

   10. If i+1 < length of issuer_chain, set P = IC, increment i,
       and go to step 6.

   11. If the chain is exhausted without reaching a trusted root,
       treat the passport as L0.

   At each step, signature verification MUST use IEEE P1363 format
   with low-S normalization (Section 3.7).

8.6.  Multi-TA Deployments

   Implementations SHOULD support multiple Trust Authorities
   simultaneously:

   1.  The trust store MAY contain public keys from multiple TAs.

   2.  When verifying an issuer chain, the verifier checks each
       configured TA in the trust store for a matching issuer
       identifier.

   3.  When checking revocation, implementations SHOULD try each
       configured TA that could have issued the passport until a
       reachable one responds.

   4.  Cross-TA trust (where TA-A trusts passports issued by TA-B)
       is established explicitly by including TA-B's signing key
       in TA-A's trust store.  There is no implicit cross-TA trust.

   5.  Implementations MUST NOT assume any trust relationship
       between TAs unless explicitly configured.

8.7.  Revocation

   Trust Authorities providing L4 passports MUST publish signed
   revocation information using one or both of the following
   mechanisms:

8.7.1.  Revocation List (CRL-style)

   An HTTP GET endpoint returning a signed JSON object:

      {
        "revoked": ["ap_<uuid>", "ap_<uuid>"],
        "updated_at": "<string (ISO 8601 UTC)>",
        "signature": "<string (base64, IEEE P1363)>"
      }

   The "revoked" array contains the passport identifiers of all
   revoked passports.  The "updated_at" field indicates when the
   list was last modified.

   The "signature" field MUST contain a base64-encoded IEEE P1363
   ECDSA signature (with low-S normalization) computed over the
   JCS-canonicalized JSON object containing only the "revoked" and
   "updated_at" fields.  This signature MUST be produced by the
   issuing Trust Authority's private key.

   Clients SHOULD cache the revocation list and refresh it
   periodically.  The refresh interval SHOULD be configurable with
   a default of 300 seconds.

8.7.2.  Per-Passport Status Check (OCSP-style)

   An HTTP GET endpoint at the path "/{passport_id}/status"
   returning a signed JSON object:

      {
        "passport_id": "ap_<uuid>",
        "status": "<string>",
        "checked_at": "<string (ISO 8601 UTC)>",
        "signature": "<string (base64, IEEE P1363)>"
      }

   The "status" field MUST be one of:

   o  "active" - The passport is valid and has not been revoked.

   o  "revoked" - The passport has been revoked by the Trust
      Authority.

   o  "expired" - The passport has passed its "expires_at" timestamp.

   o  "unknown" - The passport identifier is not recognized by this
      Trust Authority.

   The "signature" field MUST contain a base64-encoded IEEE P1363
   ECDSA signature (with low-S normalization) computed over the
   JCS-canonicalized JSON object containing only the "passport_id",
   "status", and "checked_at" fields.  This signature MUST be
   produced by the issuing Trust Authority's private key.

   Revocation responses MUST be signed by the issuing Trust
   Authority.  Unsigned revocation responses MUST be rejected.

8.8.  Revocation Endpoint Discovery

   The revocation endpoint URL MUST NOT be supplied by the party
   being verified.  Instead:

   1.  The revocation endpoint is discovered from the Trust
       Authority's published metadata (JWK Set document or
       well-known endpoint).

   2.  Alternatively, the verifier configures the revocation endpoint
       out-of-band when adding the TA to its trust store.

   This prevents an attacker from directing revocation checks to a
   server they control, which could return fraudulent "active"
   responses for revoked passports.

8.9.  Revocation Failure Policy

   If the revocation endpoint is unreachable, implementations MUST
   behave as follows:

   For Trust Level L4:  Implementations MUST fail-closed (reject
      the passport).  Revocation checking is mandatory at L4;
      proceeding without it violates the L4 guarantee.

   For L1-L3 with optional revocation configured:  If a deployment
      enables optional revocation checking at L1-L3 and the endpoint
      is unreachable, implementations MUST fail-closed (reject the
      passport).  If the operator wants fail-open behavior, they
      SHOULD disable revocation checking rather than relying on
      silent fallback.

   For L1-L3 without revocation configured:  Revocation checking is
      skipped entirely (default for L1-L3).

   Implementations SHOULD cache the last successful revocation
   response and apply a configurable maximum cache age (default:
   300 seconds).  A valid cached response MAY be used when the
   endpoint is temporarily unreachable, provided the cache has not
   expired.

9.  Capability Negotiation

   MCPS capabilities are negotiated during the MCP "initialize"
   handshake, using the standard MCP capability extension mechanism.

9.1.  Version Negotiation

   The "mcps" capability includes a "version" field for protocol
   version negotiation.  Implementations MUST support version
   negotiation:

   1.  The client announces its supported MCPS version(s) in the
       "mcps.version" field.  The value MAY be a single version
       string (e.g., "1.0") or an array of version strings
       (e.g., ["1.0", "2.0"]) for forward compatibility.

   2.  The server responds with the highest mutually supported
       version in its "mcps.version" field (always a single string).

   3.  If no mutually supported version exists, the server MUST
       reject the connection with error code -33015
       (MCPS_VERSION_MISMATCH).

   4.  After version negotiation, all subsequent MCPS operations
       MUST use the negotiated version.

   This mechanism enables forward compatibility as new MCPS protocol
   versions are introduced.

9.2.  Client Announcement

   An MCPS-capable client announces its support by including an
   "mcps" object within the "capabilities" field of the "initialize"
   request:

      {
        "jsonrpc": "2.0",
        "method": "initialize",
        "params": {
          "protocolVersion": "2025-03-26",
          "capabilities": {
            "mcps": {
              "version": "1.0",
              "trust_level": 2,
              "passport": { ... }
            }
          },
          "clientInfo": {
            "name": "my-agent",
            "version": "1.0.0"
          }
        },
        "id": 1
      }

   The "mcps" capability object contains:

   version:  REQUIRED.  The MCPS protocol version(s) supported.
      String or array of strings.

   trust_level:  REQUIRED.  The maximum trust level the client
      supports.

   passport:  REQUIRED.  The client's Agent Passport.

9.3.  Server Response

   An MCPS-capable server responds with its own MCPS capabilities:

      {
        "jsonrpc": "2.0",
        "result": {
          "protocolVersion": "2025-03-26",
          "capabilities": {
            "mcps": {
              "version": "1.0",
              "min_trust_level": 2,
              "passport": { ... }
            }
          },
          "serverInfo": {
            "name": "secure-server",
            "version": "2.0.0"
          }
        },
        "id": 1
      }

   The server's "mcps" capability object contains:

   version:  REQUIRED.  The negotiated MCPS protocol version
      (single string).

   min_trust_level:  REQUIRED.  The minimum trust level required
      for connections to this server.

   passport:  REQUIRED.  The server's Agent Passport.

   Note: The server's capability response MUST NOT include a
   revocation_endpoint field.  Revocation endpoints are discovered
   via Trust Authority metadata (Section 8.8), not supplied by the
   party being verified.

9.4.  Negotiation Failure

   If the client's trust level is below the server's
   "min_trust_level", the server MUST reject the connection with
   JSON-RPC error code -33009 (MCPS_TRUST_LEVEL_INSUFFICIENT).

   If the MCPS versions are incompatible (no mutual version), the
   server MUST reject the connection with error code -33015
   (MCPS_VERSION_MISMATCH).

   If the server does not include an "mcps" capability in its
   response, the client MUST operate without MCPS verification
   (Trust Level L0) or disconnect, depending on its configured
   minimum trust level requirement.

9.5.  Transcript Binding (Anti-Downgrade)

   After capability negotiation, both parties MUST exchange a
   transcript binding to confirm they agree on the negotiated
   security parameters.  This prevents an active attacker from
   stripping the "mcps" capability during the handshake (downgrade
   attack).

   Note: This mechanism uses ECDSA signatures (asymmetric), not
   MAC (symmetric).  Previous drafts used the term "transcript MAC";
   this has been corrected to "transcript binding" for accuracy.

   Transcript scope: The transcript covers the "params" field from
   the client's initialize request and the "result" field from the
   server's initialize response -- NOT the full JSON-RPC envelope
   (which includes the jsonrpc version string, method name, and
   message id that are not security-relevant).

   The procedure is as follows:

   1.  Both parties compute:

       transcript_hash = SHA-256(
         JCS(client_initialize_params) ||
         JCS(server_initialize_result)
       )

       where "||" denotes byte concatenation, and JCS is the
       RFC 8785 canonicalization.  "client_initialize_params" is the
       value of the "params" field from the client's initialize
       request.  "server_initialize_result" is the value of the
       "result" field from the server's initialize response.

   2.  Each party signs the transcript_hash with their private key
       using ECDSA P-256, producing an IEEE P1363 signature with
       low-S normalization (Section 3.7).

   3.  The signed transcript is exchanged as the first signed
       message after the "initialize" handshake, using the method
       "mcps/transcript_verify":

          {
            "mcps": {
              "version": "1.0",
              "passport_id": "ap_<uuid>",
              "timestamp": "<ISO 8601 UTC>",
              "nonce": "<hex, 16 random bytes>",
              "signature": "<base64, IEEE P1363>"
            },
            "jsonrpc": "2.0",
            "method": "mcps/transcript_verify",
            "params": {
              "transcript_hash": "<hex SHA-256>",
              "transcript_signature": "<base64, IEEE P1363>"
            },
            "id": 2
          }

   4.  Each party verifies the other's transcript binding by:
       a.  Recomputing the transcript_hash from their own records.
       b.  Verifying the received transcript_hash matches.
       c.  Verifying the transcript_signature against the other
           party's passport public key.

   5.  If the transcript bindings do not match, the connection MUST
       be terminated with error code -33012
       (MCPS_TRANSCRIPT_MISMATCH).

   This mechanism is analogous to the TLS Finished message, which
   prevents downgrade attacks by binding both parties to the same
   view of the negotiated parameters.

10.  Error Codes

   MCPS defines the following JSON-RPC error codes in the -33xxx
   range, avoiding collision with JSON-RPC's reserved
   implementation-defined range (-32000 to -32099).  Each error has
   both a numeric code and a string code for programmatic handling:

      +--------+---------+-------------------------------+
      | Code   | String  | Name                          |
      +--------+---------+-------------------------------+
      | -33001 | MCPS-001| MCPS_INVALID_PASSPORT         |
      |        |         | Passport format invalid.      |
      +--------+---------+-------------------------------+
      | -33002 | MCPS-002| MCPS_PASSPORT_EXPIRED         |
      |        |         | Passport has expired.         |
      +--------+---------+-------------------------------+
      | -33003 | MCPS-003| MCPS_PASSPORT_REVOKED         |
      |        |         | Passport has been revoked.    |
      +--------+---------+-------------------------------+
      | -33004 | MCPS-004| MCPS_INVALID_SIGNATURE        |
      |        |         | Message signature             |
      |        |         | verification failed.          |
      +--------+---------+-------------------------------+
      | -33005 | MCPS-005| MCPS_REPLAY_DETECTED          |
      |        |         | Duplicate nonce detected.     |
      +--------+---------+-------------------------------+
      | -33006 | MCPS-006| MCPS_TIMESTAMP_EXPIRED        |
      |        |         | Message timestamp outside     |
      |        |         | acceptable window.            |
      +--------+---------+-------------------------------+
      | -33007 | MCPS-007| MCPS_AUTHORITY_UNREACHABLE    |
      |        |         | Trust Authority unreachable   |
      |        |         | (fail-closed).                |
      +--------+---------+-------------------------------+
      | -33008 | MCPS-008| MCPS_TOOL_INTEGRITY_FAILED    |
      |        |         | Tool definition signature     |
      |        |         | invalid or hash changed.      |
      +--------+---------+-------------------------------+
      | -33009 | MCPS-009| MCPS_TRUST_LEVEL_INSUFFICIENT |
      |        |         | Client trust level below      |
      |        |         | server minimum.               |
      +--------+---------+-------------------------------+
      | -33010 | MCPS-010| MCPS_RATE_LIMITED              |
      |        |         | Rate limit exceeded.          |
      +--------+---------+-------------------------------+
      | -33011 | MCPS-011| MCPS_ORIGIN_MISMATCH          |
      |        |         | Passport origin does not      |
      |        |         | match server URI.             |
      +--------+---------+-------------------------------+
      | -33012 | MCPS-012| MCPS_TRANSCRIPT_MISMATCH      |
      |        |         | Transcript binding            |
      |        |         | verification failed           |
      |        |         | (downgrade detected).         |
      +--------+---------+-------------------------------+
      | -33013 | MCPS-013| MCPS_PASSPORT_TOO_LARGE       |
      |        |         | Passport exceeds maximum      |
      |        |         | size (8192 bytes).            |
      +--------+---------+-------------------------------+
      | -33014 | MCPS-014| MCPS_CHAIN_TOO_DEEP           |
      |        |         | Issuer chain exceeds          |
      |        |         | maximum depth (5).            |
      +--------+---------+-------------------------------+
      | -33015 | MCPS-015| MCPS_VERSION_MISMATCH         |
      |        |         | No mutually supported MCPS    |
      |        |         | version.                      |
      +--------+---------+-------------------------------+

   Error responses MUST include the standard JSON-RPC error format
   with a "data" object providing additional context:

      {
        "jsonrpc": "2.0",
        "error": {
          "code": -33004,
          "message": "MCPS_INVALID_SIGNATURE",
          "data": {
            "string_code": "MCPS-004",
            "passport_id": "ap_<uuid>",
            "reason": "Signature does not match message
                       content"
          }
        },
        "id": 1
      }

   The "data" object SHOULD include:

   string_code:  The MCPS string code (e.g., "MCPS-004") for
      programmatic error handling across implementations that may
      use different numeric error code conventions.

   passport_id:  The passport identifier associated with the error,
      if applicable.

   reason:  A human-readable description of the failure cause.

   Design note: The -33xxx range is used because JSON-RPC 2.0
   reserves error codes -32000 to -32099 for "implementation-defined
   server errors."  The previous draft (01) incorrectly placed MCPS
   error codes in the -32001 to -32009 range, which collides with
   this reserved range.  The -33xxx range is outside all JSON-RPC
   reserved ranges, providing a clean namespace for MCPS errors.

11.  Security Considerations

11.1.  Threat Model

   MCPS defends against the following threats:

      +---------------------------+-----------------------------------+
      | Threat                    | Mitigation                        |
      +---------------------------+-----------------------------------+
      | Server impersonation      | Origin-bound passports (Sec 4.4)  |
      +---------------------------+-----------------------------------+
      | Message tampering         | Per-message signatures (Sec 5)    |
      +---------------------------+-----------------------------------+
      | Tool description poisoning| Full-tool-object hashing          |
      |                           | including description (Sec 6)     |
      +---------------------------+-----------------------------------+
      | Replay attacks            | Nonce + timestamp (Sec 7)         |
      +---------------------------+-----------------------------------+
      | Signature malleability    | Low-S normalization (Sec 3.7)     |
      +---------------------------+-----------------------------------+
      | Capability downgrade      | Transcript binding (Sec 9.5)      |
      +---------------------------+-----------------------------------+
      | Revocation bypass         | Signed revocation responses,      |
      |                           | fail-closed default (Sec 8.7-8.9) |
      +---------------------------+-----------------------------------+
      | Trust level inflation     | Issuer chain validation,          |
      |                           | self-signed capped at L0 (Sec 3.4)|
      +---------------------------+-----------------------------------+
      | Oversized passport DoS    | Size limits (Sec 4.3)             |
      +---------------------------+-----------------------------------+
      | Tool relaying             | Author origin binding (Sec 6.2)   |
      +---------------------------+-----------------------------------+
      | Agent key compromise      | Key rotation with                 |
      |                           | previous_key_hash (Sec 4.5)       |
      +---------------------------+-----------------------------------+
      | TLS relay (MITM)          | Optional channel binding          |
      |                           | (Sec 5.3)                         |
      +---------------------------+-----------------------------------+

   MCPS does NOT defend against:

      +---------------------------+-----------------------------------+
      | Threat                    | Why Not                           |
      +---------------------------+-----------------------------------+
      | Malicious tool authored   | Provenance proves WHO, not safety.|
      | by legitimate server      | See Section 11.2.                 |
      +---------------------------+-----------------------------------+
      | Compromised Trust         | Same as X.509: TA compromise is   |
      | Authority                 | catastrophic.  Mitigated by key   |
      |                           | rotation, multiple TAs (Sec 8.6). |
      +---------------------------+-----------------------------------+
      | Compromised agent key     | Agent must protect its key.  HSM  |
      |                           | recommended for L4.  Key rotation |
      |                           | provides recovery (Sec 4.5).      |
      +---------------------------+-----------------------------------+

11.2.  Provenance vs Safety

   MCPS provides provenance (WHO authored a tool or sent a message),
   not safety analysis.  A malicious server operator can sign their
   own poisoned tool definitions with a valid MCPS signature.

   Tool safety analysis -- detecting malicious descriptions,
   sandboxing execution, and input validation -- is a separate
   concern that complements MCPS.  Implementations SHOULD NOT
   treat a valid MCPS signature as evidence that a tool is safe
   to execute.

11.3.  Trust Authority Compromise

   If a Trust Authority's signing key is compromised, an attacker
   can issue fraudulent Agent Passports.  To mitigate this risk:

   o  Trust Authority private keys SHOULD be stored in hardware
      security modules (HSMs) or equivalent tamper-resistant
      hardware.

   o  Trust Authorities SHOULD implement key rotation procedures
      with documented key ceremony practices.

   o  Trust Authorities MUST publish revocation lists promptly upon
      detecting key compromise.

   o  Clients SHOULD support pinning Trust Authority public keys to
      detect unauthorized key changes.

   o  Deployments SHOULD configure multiple TAs (Section 8.6) to
      reduce single-point-of-failure risk.

   This is the same risk model as X.509 Certificate Authority
   compromise.  Mitigations are well-understood from the TLS/PKI
   ecosystem.

11.4.  Nonce Store Exhaustion

   An attacker could flood a server with messages containing unique
   nonces to exhaust the nonce store's memory.  Implementations
   MUST mitigate this by:

   o  Garbage-collecting nonces whose associated timestamps have
      fallen outside the acceptance window.

   o  Implementing rate limiting on incoming messages.

   o  Setting a maximum nonce store size with a least-recently-used
      eviction policy as a last resort.

11.5.  Clock Skew Attacks

   An attacker with the ability to manipulate system clocks on
   either the sender or receiver could bypass timestamp validation.
   Mitigations include:

   o  Implementations at Trust Level L3 and above SHOULD require
      NTP synchronization or equivalent time source.

   o  The configurable clock skew tolerance limits the exploitable
      window.

   o  The nonce mechanism provides a secondary protection layer
      independent of timestamps.

11.6.  Algorithm Agility

   This specification mandates ECDSA P-256 as the sole algorithm.
   Future versions of MCPS MAY introduce algorithm negotiation to
   support additional curves or signature schemes via the version
   negotiation mechanism defined in Section 9.1.

   Implementations SHOULD be designed to accommodate future algorithm
   changes by parameterizing the signature algorithm rather than
   hard-coding P-256.

   If algorithm negotiation is introduced in future versions, the
   "mcps" header MUST include an "alg" field indicating the
   algorithm used, and both parties MUST agree on a common algorithm
   during capability negotiation.

11.7.  Privacy Considerations

   Agent Passports contain an agent name, origin, and public key.
   The origin reveals the server the agent is authorized to
   communicate with.

   Passport identifiers are pseudonymous (UUID-based).  They do not
   reveal the agent operator's identity without Trust Authority
   cooperation.

   Signed messages enable non-repudiation: it is possible to prove
   cryptographically that a specific agent sent a specific message.
   This property may conflict with privacy requirements in certain
   jurisdictions.  Operators SHOULD consider data retention policies
   for signed message logs.

   Implementations SHOULD NOT include sensitive or personally
   identifiable information in the "agent_name" or "capabilities"
   fields of Agent Passports.

11.8.  Non-Repudiation Implications

   Because MCPS signatures are produced using long-lived agent keys,
   signed messages provide strong non-repudiation properties.  This
   means that a signed message can be presented as evidence that a
   particular agent sent a particular message at a particular time.

   Operators deploying MCPS SHOULD be aware that signed message logs
   may have legal implications, particularly in regulated industries.
   Message retention and disposal policies SHOULD be established as
   part of MCPS deployment planning.

12.  IANA Considerations

12.1.  MCPS Error Code Registry

   This document requests IANA to create a new registry titled
   "MCPS Error Codes" with the following initial entries:

      +--------+---------+-------------------------------+-----------+
      | Code   | String  | Name                          | Reference |
      +--------+---------+-------------------------------+-----------+
      | -33001 | MCPS-001| MCPS_INVALID_PASSPORT         | [this doc]|
      | -33002 | MCPS-002| MCPS_PASSPORT_EXPIRED         | [this doc]|
      | -33003 | MCPS-003| MCPS_PASSPORT_REVOKED         | [this doc]|
      | -33004 | MCPS-004| MCPS_INVALID_SIGNATURE        | [this doc]|
      | -33005 | MCPS-005| MCPS_REPLAY_DETECTED          | [this doc]|
      | -33006 | MCPS-006| MCPS_TIMESTAMP_EXPIRED        | [this doc]|
      | -33007 | MCPS-007| MCPS_AUTHORITY_UNREACHABLE    | [this doc]|
      | -33008 | MCPS-008| MCPS_TOOL_INTEGRITY_FAILED    | [this doc]|
      | -33009 | MCPS-009| MCPS_TRUST_LEVEL_INSUFFICIENT | [this doc]|
      | -33010 | MCPS-010| MCPS_RATE_LIMITED              | [this doc]|
      | -33011 | MCPS-011| MCPS_ORIGIN_MISMATCH          | [this doc]|
      | -33012 | MCPS-012| MCPS_TRANSCRIPT_MISMATCH      | [this doc]|
      | -33013 | MCPS-013| MCPS_PASSPORT_TOO_LARGE       | [this doc]|
      | -33014 | MCPS-014| MCPS_CHAIN_TOO_DEEP           | [this doc]|
      | -33015 | MCPS-015| MCPS_VERSION_MISMATCH         | [this doc]|
      +--------+---------+-------------------------------+-----------+

   New entries in this registry require Standards Action [RFC8126].

12.2.  MCPS Trust Level Registry

   This document requests IANA to create a new registry titled
   "MCPS Trust Levels" with the following initial entries:

      +-------+----------+------+-----------------------------------+
      | Level | Name     | Ref  | Description                       |
      +-------+----------+------+-----------------------------------+
      | 0     | None     | [td] | No MCPS verification              |
      | 1     | Signed   | [td] | Signed, any TA                    |
      | 2     | Verified | [td] | Signed, recognized TA required    |
      | 3     | Strict   | [td] | L2 + tool sigs + origin verified  |
      | 4     | Full     | [td] | L3 + mutual auth + revocation     |
      +-------+----------+------+-----------------------------------+

      [td] = [this document]

   New entries in this registry require Specification Required
   [RFC8126].

12.3.  MCPS Capability Identifier

   This document registers the capability identifier "mcps" for use
   within the MCP capabilities negotiation framework.  Implementations
   using this capability identifier MUST conform to the negotiation
   procedures defined in Section 9 of this document.

13.  References

13.1.  Normative References

   [FIPS186-5]
              National Institute of Standards and Technology, "Digital
              Signature Standard (DSS)", FIPS PUB 186-5,
              DOI 10.6028/NIST.FIPS.186-5, February 2023.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/info/rfc2119>.

   [RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
              Encodings", RFC 4648, DOI 10.17487/RFC4648,
              October 2006,
              <https://www.rfc-editor.org/info/rfc4648>.

   [RFC6454]  Barth, A., "The Web Origin Concept", RFC 6454,
              DOI 10.17487/RFC6454, December 2011,
              <https://www.rfc-editor.org/info/rfc6454>.

   [RFC6979]  Pornin, T., "Deterministic Usage of the Digital
              Signature Algorithm (DSA) and Elliptic Curve Digital
              Signature Algorithm (ECDSA)", RFC 6979,
              DOI 10.17487/RFC6979, August 2013,
              <https://www.rfc-editor.org/info/rfc6979>.

   [RFC7517]  Jones, M., "JSON Web Key (JWK)", RFC 7517,
              DOI 10.17487/RFC7517, May 2015,
              <https://www.rfc-editor.org/info/rfc7517>.

   [RFC7518]  Jones, M., "JSON Web Algorithms (JWA)", RFC 7518,
              DOI 10.17487/RFC7518, May 2015,
              <https://www.rfc-editor.org/info/rfc7518>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
              RFC 2119 Key Words", BCP 14, RFC 8174,
              DOI 10.17487/RFC8174, May 2017,
              <https://www.rfc-editor.org/info/rfc8174>.

   [RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
              Writing an IANA Considerations Section in RFCs",
              BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
              <https://www.rfc-editor.org/info/rfc8126>.

   [RFC8785]  Rundgren, A., Jordan, B., and S. Erdtman, "JSON
              Canonicalization Scheme (JCS)", RFC 8785,
              DOI 10.17487/RFC8785, June 2020,
              <https://www.rfc-editor.org/info/rfc8785>.

   [RFC9266]  Shoemaker, R., "Channel Bindings for TLS 1.3",
              RFC 9266, DOI 10.17487/RFC9266, July 2022,
              <https://www.rfc-editor.org/info/rfc9266>.

13.2.  Informative References

   [RFC9421]  Backman, A., Richer, J., and M. Sporny, "HTTP
              Message Signatures", RFC 9421, DOI 10.17487/RFC9421,
              February 2024,
              <https://www.rfc-editor.org/info/rfc9421>.

   [RFC9449]  Fett, D., Campbell, B., Bradley, J., Lodderstedt, T.,
              Jones, M., and D. Waite, "OAuth 2.0 Demonstrating
              Proof of Possession (DPoP)", RFC 9449,
              DOI 10.17487/RFC9449, September 2023,
              <https://www.rfc-editor.org/info/rfc9449>.

   [JSONRPC]  JSON-RPC Working Group, "JSON-RPC 2.0 Specification",
              January 2013, <https://www.jsonrpc.org/specification>.

   [SEMVER]   Preston-Werner, T., "Semantic Versioning 2.0.0",
              <https://semver.org/>.

Appendix A.  Example Protocol Exchange

   This appendix provides a complete example of an MCPS-secured MCP
   session, illustrating capability negotiation, transcript binding
   verification, and signed tool invocation.

A.1.  Capability Negotiation

   Client sends initialize request with MCPS capability:

      {
        "jsonrpc": "2.0",
        "method": "initialize",
        "params": {
          "protocolVersion": "2025-03-26",
          "capabilities": {
            "mcps": {
              "version": "1.0",
              "trust_level": 2,
              "passport": {
                "mcps_version": "1.0",
                "passport": {
                  "id":
                    "ap_550e8400-e29b-41d4-a716-446655440000",
                  "agent_name": "research-agent",
                  "agent_version": "1.2.0",
                  "issuer": "ta.example.com",
                  "origin": "https://api.example.com",
                  "issued_at": "2026-03-01T00:00:00Z",
                  "expires_at": "2026-09-01T00:00:00Z",
                  "public_key": {
                    "kty": "EC",
                    "crv": "P-256",
                    "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8T
                          us9uPHvRVEU",
                    "y": "x_FEzRu9m36HLN_tue659LNpXW6pCySt
                          ikYjKIWI5a0"
                  },
                  "capabilities": [
                    "tools/call",
                    "tools/list"
                  ],
                  "trust_level": 2,
                  "issuer_chain": []
                },
                "signature": "MEUCIQC...base64..."
              }
            }
          },
          "clientInfo": {
            "name": "research-agent",
            "version": "1.2.0"
          }
        },
        "id": 1
      }

   Server responds with its MCPS capabilities and passport:

      {
        "jsonrpc": "2.0",
        "result": {
          "protocolVersion": "2025-03-26",
          "capabilities": {
            "mcps": {
              "version": "1.0",
              "min_trust_level": 2,
              "passport": {
                "mcps_version": "1.0",
                "passport": {
                  "id":
                    "ap_660f9511-f30c-52e5-b827-557766551111",
                  "agent_name": "file-server",
                  "agent_version": "2.0.0",
                  "issuer": "ta.example.com",
                  "origin": "https://api.example.com",
                  "issued_at": "2026-02-15T00:00:00Z",
                  "expires_at": "2026-08-15T00:00:00Z",
                  "public_key": {
                    "kty": "EC",
                    "crv": "P-256",
                    "x": "2ygLm3slRf6MtoN_-D2bLMMq_10eCMei
                          -yLAbFYmPFE",
                    "y": "4PUOD5BNzGMIAnvMjMVHRwZ3XwGBJjB0
                          NJEwPHLJDjg"
                  },
                  "capabilities": ["tools/call"],
                  "trust_level": 2,
                  "issuer_chain": []
                },
                "signature": "MEQCIAo...base64..."
              }
            }
          },
          "serverInfo": {
            "name": "file-server",
            "version": "2.0.0"
          }
        },
        "id": 1
      }

A.2.  Transcript Binding Verification

   Both parties exchange transcript bindings after initialize.
   The transcript hash is computed over the "params" field of the
   client's initialize request and the "result" field of the
   server's initialize response (NOT the full JSON-RPC envelopes):

      {
        "mcps": {
          "version": "1.0",
          "passport_id":
            "ap_550e8400-e29b-41d4-a716-446655440000",
          "timestamp": "2026-03-13T14:29:55Z",
          "nonce":
            "b2c3d4e5f6a748b90c1d2e3f4a5b6c7d",
          "signature": "MEQCIBx...base64..."
        },
        "jsonrpc": "2.0",
        "method": "mcps/transcript_verify",
        "params": {
          "transcript_hash":
            "a1b2c3...64-char-hex-sha256...",
          "transcript_signature":
            "MEUCIQDk...base64..."
        },
        "id": 2
      }

A.3.  Signed Tool Call

   Client invokes a tool with MCPS signature:

      {
        "mcps": {
          "version": "1.0",
          "passport_id":
            "ap_550e8400-e29b-41d4-a716-446655440000",
          "timestamp": "2026-03-13T14:30:00Z",
          "nonce":
            "a1b2c3d4e5f647a89b0c1d2e3f4a5b6c",
          "signature": "MEUCIQDr...base64..."
        },
        "jsonrpc": "2.0",
        "method": "tools/call",
        "params": {
          "name": "read_file",
          "arguments": {
            "path": "/etc/hostname"
          }
        },
        "id": 3
      }

Appendix B.  OWASP Risk Mapping

   The following table maps MCPS features to risks identified by the
   OWASP Top 10 for Agentic Applications (2026) and the OWASP MCP
   Top 10:

      +-----------------------------+---------------------------------+
      | Risk                        | MCPS Mitigation                 |
      +-----------------------------+---------------------------------+
      | Inadequate Agent Identity   | Origin-bound Agent Passports    |
      | (ASI02)                     | with issuer chain validation    |
      +-----------------------------+---------------------------------+
      | Inadequate Tool Validation  | Full tool definition signing    |
      | (ASI03)                     | with description coverage       |
      +-----------------------------+---------------------------------+
      | Delegated Trust Boundaries  | Trust levels enforce minimum    |
      | (ASI04)                     | security per connection         |
      +-----------------------------+---------------------------------+
      | Tool Poisoning (MCP03)      | Signed tool definitions with    |
      |                             | pinned tool_hash detection      |
      +-----------------------------+---------------------------------+
      | Server Impersonation        | Origin-bound passport-based     |
      |                             | mutual authentication           |
      +-----------------------------+---------------------------------+
      | Message Tampering           | Per-message ECDSA signatures    |
      |                             | with JCS canonicalization       |
      +-----------------------------+---------------------------------+
      | Replay Attacks              | Nonce + timestamp window        |
      +-----------------------------+---------------------------------+
      | Capability Downgrade        | Transcript binding              |
      |                             | (Section 9.5)                   |
      +-----------------------------+---------------------------------+
      | Insufficient Authorization  | Trust level gating with         |
      | (MCP07)                     | capability lists                |
      +-----------------------------+---------------------------------+

Appendix C.  Design Rationale

C.1.  Why a Separate Envelope (Not Modifying JSON-RPC)

   MCPS wraps existing JSON-RPC messages rather than modifying the
   protocol schema.  This ensures backward compatibility, transport
   independence, and composability with existing OAuth authorization
   and DPoP.

C.2.  Why ECDSA P-256 (Not Ed25519 or RSA)

   P-256 is mandated by FIPS 186-5, required for government and
   enterprise compliance, and supported by Web Crypto API.  Ed25519
   has superior performance but lacks FIPS certification.  RSA key
   sizes create larger signatures.

C.3.  Why IEEE P1363 (Not DER)

   DER encoding produces variable-length signatures (typically 70-72
   bytes for P-256).  IEEE P1363 produces fixed-length signatures
   (exactly 64 bytes for P-256).  Fixed-length format eliminates
   parsing ambiguity, is required by RFC 7518 Section 3.4, and
   simplifies cross-platform interoperability.

C.4.  Why message_hash (Not Nested JCS)

   Earlier drafts used "jsonrpc_message: JCS(message)" in the
   signing payload, nesting one JCS string inside another JCS
   object.  This creates fragility: the inner JCS string must be
   JSON-escaped when embedded in the outer object, and different
   JSON libraries handle this escaping differently.  Using
   "message_hash: SHA-256(JCS(message))" eliminates this ambiguity,
   is more robust, and is more efficient.

C.5.  Why -33xxx Error Codes (Not -32xxx)

   JSON-RPC 2.0 reserves error codes -32000 to -32099 for
   "implementation-defined server errors."  Using this range for
   MCPS-specific codes would risk collisions with other JSON-RPC
   extensions.  The -33xxx range is outside all reserved ranges,
   providing a clean namespace for MCPS errors.

C.6.  Why a Lightweight Passport Format (Not Raw X.509)

   Agent Passports serve a similar role to X.509 certificates but
   use a JSON-native format because: (1) MCP is JSON-RPC, so JSON
   credentials avoid ASN.1/DER complexity; (2) the chain model is
   simpler than X.509 path validation; (3) JSON is familiar to the
   MCP developer ecosystem.

   However, the passport model deliberately borrows proven concepts
   from X.509: issuer chains, validity periods, key usage
   constraints, and revocation checking.  Implementations MAY bridge
   to X.509 by embedding a certificate reference in the passport.

C.7.  Why Not JWS (RFC 7515) for Message Signing

   The per-message envelope is comparable in size to JWS compact
   serialization (~280 bytes vs ~200 bytes for JWS).  The primary
   motivation for a purpose-built envelope is explicitness: the
   "mcps" field contains exactly the fields needed for MCP
   verification (passport_id, nonce, timestamp) without requiring
   implementers to parse JWS headers and map them to MCP semantics.

   An alternative formulation using JWS as the signing container
   is viable and could be explored if the community prefers
   standards composition over a purpose-built format.

C.8.  Why Self-Hostable Trust Authority

   A centralized TA would create a single point of failure.  The
   self-hostable design ensures no vendor lock-in, air-gapped
   deployment support, regulatory compliance, and resilience.

Appendix D.  Changes from draft-sharif-mcps-secure-mcp-01

   This section summarizes the changes from version 01 to version 02:

   CRITICAL changes:

   o  Specified IEEE P1363 signature format (r||s concatenation,
      exactly 64 bytes for P-256) per RFC 7518 Section 3.4.
      Explicitly prohibits DER encoding.  Added low-S normalization
      requirement (s <= n/2) with the P-256 curve order constant.
      (Section 3.6, Section 3.7)

   o  Added ECDSA malleability defense: low-S normalization prevents
      (r, n-s) from being accepted as valid alternative.  Nonce
      stores MUST key on nonce string, not full message bytes.
      (Section 3.7, Section 7.3)

   o  Defined issuer chain entry format: each entry is a base64-
      encoded JSON intermediate TA passport with its own signature,
      public_key, and issuer fields.  Added step-by-step chain
      verification algorithm.  Max depth: 5.
      (Section 8.4, Section 8.5)

   o  Changed error code range from -32001..-32009 (which collides
      with JSON-RPC reserved range -32000..-32099) to
      -33001..-33015.  Added string codes MCPS-001 through MCPS-015.
      (Section 10)

   HIGH changes:

   o  Renamed "Transcript MAC" to "Transcript Binding" throughout.
      MCPS uses ECDSA signatures (asymmetric), not MAC (symmetric).
      (Section 2, Section 9.5)

   o  Added version negotiation mechanism during initialize.
      Client may announce single version or array of versions.
      Server responds with highest mutual version or -33015 error.
      (Section 9.1)

   o  Added passport size limits: MAX_PASSPORT_BYTES = 8192,
      MAX_ISSUER_CHAIN_DEPTH = 5, MAX_CAPABILITIES = 64.  Added
      corresponding error codes -33013 and -33014.
      (Section 4.3)

   o  Changed signing payload from "jsonrpc_message: JCS(msg)"
      to "message_hash: SHA-256(JCS(msg))" to avoid double-
      canonicalization fragility.
      (Section 5.2)

   o  Added optional TLS channel binding field (RFC 9266
      tls-exporter) to signing payload.
      (Section 5.3)

   o  Added multi-TA deployment support with documented cross-TA
      trust model.
      (Section 8.6)

   o  Added key_rotation field with previous_key_hash and
      rotated_at for agent key compromise recovery.
      (Section 4.5)

   o  Clarified transcript hash boundary: covers "params" (client)
      and "result" (server), NOT full JSON-RPC envelope.
      (Section 9.5)

   o  Added author_origin to tool signing payload for tool-server
      origin binding.
      (Section 6.1, Section 6.2)

   o  Updated all references from FIPS 186-4 to FIPS 186-5.
      Added note on RFC 6979 vs HSM compatibility with FIPS 186-5
      nonce generation.
      (Section 3.5)

   Additional changes:

   o  Added RFC 7518 and RFC 9266 to normative references.

   o  Updated reference implementation test counts: Node.js 75
      tests, Python 53 tests.

   o  Added six new error codes: MCPS_AUTHORITY_UNREACHABLE (-33007),
      MCPS_RATE_LIMITED (-33010), MCPS_ORIGIN_MISMATCH (-33011),
      MCPS_PASSPORT_TOO_LARGE (-33013), MCPS_CHAIN_TOO_DEEP
      (-33014), MCPS_VERSION_MISMATCH (-33015).

Author's Address

   Raza Sharif
   CyberSecAI Ltd

   Email: contact@agentsign.dev