{
  "openapi": "3.1.0",
  "info": {
    "title": "MYOPL Personal MCP API",
    "version": "1.0.0",
    "description": "OAuth-protected, consenting-account tools. Available to eligible MYOPL Plus and higher accounts with the required scopes and enabled features. Use the separate public OpenAPI specification for anonymous ratings, rules and directory lookups."
  },
  "servers": [
    {
      "url": "https://api.myopl.net"
    }
  ],
  "externalDocs": {
    "url": "https://myopl.net/auth.md",
    "description": "MYOPL sign-in and scope guide"
  },
  "security": [
    {
      "myoplOAuth": []
    }
  ],
  "paths": {
    "/mcp/personal": {
      "post": {
        "operationId": "callMyoplPersonalMcp",
        "summary": "Call MYOPL tools for the consenting account",
        "description": "Stateless MCP Streamable HTTP, JSON-RPC 2.0. Initialize before subsequent calls. Each tool additionally requires its declared scope. The operation does not require all scopes at once. Read tool metadata for the authorized UI resource. Do not call prepare_my_rsvp unless the user requests RSVP preparation.",
        "security": [
          {
            "myoplOAuth": []
          }
        ],
        "parameters": [
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "description": "Required except for initialize.",
            "schema": {
              "const": "2025-11-25"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "id",
                      "method",
                      "params"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "const": "tools/call"
                      },
                      "params": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "const": "get_my_rating"
                          },
                          "arguments": {
                            "type": "object",
                            "additionalProperties": false,
                            "properties": {},
                            "required": []
                          }
                        }
                      }
                    },
                    "description": "Read the consenting player published OPL ratings",
                    "x-required-oauth-scopes": [
                      "myopl:rating:read"
                    ]
                  },
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "id",
                      "method",
                      "params"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "const": "tools/call"
                      },
                      "params": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "const": "get_my_next_session"
                          },
                          "arguments": {
                            "type": "object",
                            "additionalProperties": false,
                            "properties": {
                              "league": {
                                "type": "string",
                                "pattern": "^[A-Za-z0-9_-]{1,150}$"
                              }
                            },
                            "required": [
                              "league"
                            ]
                          }
                        }
                      }
                    },
                    "description": "Find the consenting player league sessions",
                    "x-required-oauth-scopes": [
                      "myopl:sessions:read"
                    ]
                  },
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "id",
                      "method",
                      "params"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "const": "tools/call"
                      },
                      "params": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "const": "prepare_my_rsvp"
                          },
                          "arguments": {
                            "type": "object",
                            "additionalProperties": false,
                            "properties": {
                              "league": {
                                "type": "string",
                                "pattern": "^[A-Za-z0-9_-]{1,150}$"
                              },
                              "response": {
                                "type": "string",
                                "enum": [
                                  "yes",
                                  "maybe",
                                  "no"
                                ]
                              }
                            },
                            "required": [
                              "league",
                              "response"
                            ]
                          }
                        }
                      }
                    },
                    "description": "Prepare RSVP for explicit confirmation in MYOPL; does not submit attendance",
                    "x-required-oauth-scopes": [
                      "myopl:rsvp:write"
                    ]
                  },
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "id",
                      "method",
                      "params"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "const": "tools/call"
                      },
                      "params": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "const": "get_my_action_status"
                          },
                          "arguments": {
                            "type": "object",
                            "additionalProperties": false,
                            "properties": {
                              "action_id": {
                                "type": "string",
                                "pattern": "^[A-Za-z0-9]{64}$"
                              }
                            },
                            "required": [
                              "action_id"
                            ]
                          }
                        }
                      }
                    },
                    "description": "Prepare RSVP for explicit confirmation in MYOPL; does not submit attendance",
                    "x-required-oauth-scopes": [
                      "myopl:rsvp:write"
                    ]
                  },
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "id",
                      "method",
                      "params"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "const": "tools/call"
                      },
                      "params": {
                        "type": "object",
                        "required": [
                          "name"
                        ],
                        "properties": {
                          "name": {
                            "const": "get_my_statistics_card"
                          },
                          "arguments": {
                            "type": "object",
                            "additionalProperties": false,
                            "properties": {},
                            "required": []
                          }
                        }
                      }
                    },
                    "description": "Read own statistics cards without a paid upgrade",
                    "x-required-oauth-scopes": [
                      "myopl:statistics:read"
                    ]
                  },
                  {
                    "type": "object",
                    "required": [
                      "jsonrpc",
                      "method"
                    ],
                    "properties": {
                      "jsonrpc": {
                        "const": "2.0"
                      },
                      "id": {
                        "type": [
                          "integer",
                          "string"
                        ]
                      },
                      "method": {
                        "enum": [
                          "initialize",
                          "ping",
                          "tools/list",
                          "resources/list",
                          "resources/read",
                          "notifications/initialized"
                        ]
                      },
                      "params": {
                        "type": "object"
                      }
                    },
                    "description": "Initialize with protocolVersion, clientInfo and capabilities. resources/read requires uri. Notifications omit id."
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result or protocol error; tool failures can use result.isError.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "202": {
            "description": "Notification accepted; no body.",
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "description": "Invalid transport request or unsupported protocol version.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired or invalid OAuth access; use the advertised resource metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope or unavailable access.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "405": {
            "description": "Use POST.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "406": {
            "description": "Accept application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "413": {
            "description": "Request exceeds 16384 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "415": {
            "description": "Use application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Temporary request limit; retry after the Retry-After seconds without disconnecting.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "RateLimit-Policy": {
                "description": "IETF structured quota policy (draft-ietf-httpapi-ratelimit-headers-11): q is the request allowance and w the window in seconds. The reported policy is the currently tightest applicable budget.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";q=20;w=60"
              },
              "RateLimit": {
                "description": "IETF structured current quota: r requests remaining and t seconds until reset. Advisory; Retry-After controls a 429 retry. No account, address or token identifiers are included.",
                "schema": {
                  "type": "string"
                },
                "example": "\"myopl\";r=19;t=60"
              },
              "X-RateLimit-Reset": {
                "description": "Compatibility field: Unix timestamp when the reported quota resets.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "myoplOAuth": {
        "type": "oauth2",
        "description": "Authorization code with PKCE S256; discover current registration and renewal behavior from authorization-server metadata.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.myopl.net/oauth/authorize",
            "tokenUrl": "https://api.myopl.net/oauth/token",
            "refreshUrl": "https://api.myopl.net/oauth/token",
            "scopes": {
              "myopl:rating:read": "Read the consenting player published OPL ratings",
              "myopl:sessions:read": "Find the consenting player league sessions",
              "myopl:rsvp:write": "Prepare RSVP for explicit confirmation in MYOPL; does not submit attendance",
              "myopl:statistics:read": "Read own statistics cards without a paid upgrade"
            }
          }
        }
      }
    }
  },
  "x-oauth-protected-resource": "https://api.myopl.net/.well-known/oauth-protected-resource/mcp/personal",
  "x-oauth-authorization-server": "https://api.myopl.net/.well-known/oauth-authorization-server",
  "x-mcp-tools": [
    {
      "name": "get_my_rating",
      "scopes": [
        "myopl:rating:read"
      ],
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      }
    },
    {
      "name": "get_my_next_session",
      "scopes": [
        "myopl:sessions:read"
      ],
      "inputSchema": {
        "type": "object",
        "properties": {
          "league": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{1,150}$"
          }
        },
        "required": [
          "league"
        ],
        "additionalProperties": false
      }
    },
    {
      "name": "prepare_my_rsvp",
      "scopes": [
        "myopl:rsvp:write"
      ],
      "inputSchema": {
        "type": "object",
        "properties": {
          "league": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{1,150}$"
          },
          "response": {
            "type": "string",
            "enum": [
              "yes",
              "maybe",
              "no"
            ]
          }
        },
        "required": [
          "league",
          "response"
        ],
        "additionalProperties": false
      }
    },
    {
      "name": "get_my_action_status",
      "scopes": [
        "myopl:rsvp:write"
      ],
      "inputSchema": {
        "type": "object",
        "properties": {
          "action_id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{64}$"
          }
        },
        "required": [
          "action_id"
        ],
        "additionalProperties": false
      }
    },
    {
      "name": "get_my_statistics_card",
      "scopes": [
        "myopl:statistics:read"
      ],
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      }
    }
  ]
}
