{
 "openapi": "3.1.0",
 "info": {
  "title": "Agent Rails public MCP and OAuth HTTP API",
  "version": "2026-09-25",
  "description": "Public HTTP envelope for admitted agent apps. OAuth issuer is rails.so; each MCP resource has its own audience. Tool names and schemas are release-bound and come from authenticated tools/list, not this static document.",
  "x-release": {
   "sha": "f51a9efc2490816e05814671daf744823bbf68f1"
  }
 },
 "externalDocs": {
  "url": "https://rails.so/docs"
 },
 "servers": [
  {
   "url": "https://rails.so"
  }
 ],
 "tags": [
  {
   "name": "Discovery"
  },
  {
   "name": "OAuth"
  },
  {
   "name": "MCP"
  },
  {
   "name": "Health"
  }
 ],
 "paths": {
  "/.well-known/oauth-authorization-server": {
   "get": {
    "tags": [
     "Discovery"
    ],
    "summary": "Authorization server metadata",
    "operationId": "authorizationServerMetadata",
    "responses": {
     "200": {
      "description": "RFC 8414 authorization server metadata",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/AuthorizationServerMetadata"
        }
       }
      }
     }
    }
   }
  },
  "/oauth/register": {
   "post": {
    "tags": [
     "OAuth"
    ],
    "summary": "Dynamic public-client registration (RFC 7591)",
    "description": "No client secret is issued. Client ID Metadata Documents are not supported on the source floor of this document.",
    "operationId": "registerClient",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RegistrationRequest"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Registered public client",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/RegistrationResponse"
        }
       }
      }
     },
     "400": {
      "description": "OAuth error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OAuthError"
        }
       }
      }
     },
     "429": {
      "description": "OAuth error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OAuthError"
        }
       }
      }
     }
    }
   }
  },
  "/oauth/authorize": {
   "get": {
    "tags": [
     "OAuth"
    ],
    "summary": "Begin authorization-code + PKCE consent",
    "description": "Browser navigation. A signed-out user is redirected to sign-in. The selected resource is bound to the issued code. Errors the registered redirect_uri can receive are returned as a 303 redirect to it with error, error_description, state and iss.",
    "operationId": "authorize",
    "parameters": [
     {
      "name": "client_id",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "redirect_uri",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "response_type",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "code_challenge",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "code_challenge_method",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "resource",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "HTML consent page"
     },
     "303": {
      "description": "Redirect: to sign-in (signed out or re-verification needed), or an OAuth error redirect to the exact registered redirect_uri with error, error_description, state and iss."
     },
     "400": {
      "description": "Error the client cannot be sent back for (unknown client, unregistered redirect_uri, stale or invalid form): an HTML error page, not JSON.",
      "content": {
       "text/html": {
        "schema": {
         "type": "string"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "OAuth"
    ],
    "summary": "Submit signed-in consent decision",
    "description": "Same-origin, CSRF-protected browser form; not a machine approval endpoint. On allow, redirects to the exact registered redirect_uri with code, state and iss.",
    "operationId": "submitAuthorizationDecision",
    "responses": {
     "303": {
      "description": "Redirect to the exact registered redirect_uri: code, state and iss on allow; error, error_description, state and iss on deny or a redirectable error. Also a redirect to sign-in when the session lapsed."
     },
     "400": {
      "description": "Error the client cannot be sent back for (unknown client, unregistered redirect_uri, stale or invalid form): an HTML error page, not JSON.",
      "content": {
       "text/html": {
        "schema": {
         "type": "string"
        }
       }
      }
     }
    }
   }
  },
  "/oauth/token": {
   "post": {
    "tags": [
     "OAuth"
    ],
    "summary": "Redeem authorization code or rotate refresh token",
    "operationId": "token",
    "requestBody": {
     "required": true,
     "content": {
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object",
        "properties": {
         "grant_type": {
          "type": "string",
          "enum": [
           "authorization_code",
           "refresh_token"
          ]
         },
         "client_id": {
          "type": "string"
         },
         "code": {
          "type": "string"
         },
         "redirect_uri": {
          "type": "string"
         },
         "code_verifier": {
          "type": "string"
         },
         "refresh_token": {
          "type": "string"
         },
         "resource": {
          "type": "string"
         },
         "scope": {
          "type": "string"
         }
        },
        "required": [
         "grant_type",
         "client_id"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Resource-bound token response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TokenResponse"
        }
       }
      }
     },
     "400": {
      "description": "OAuth error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OAuthError"
        }
       }
      }
     },
     "401": {
      "description": "OAuth error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OAuthError"
        }
       }
      }
     }
    }
   }
  },
  "/oauth/revoke": {
   "post": {
    "tags": [
     "OAuth"
    ],
    "summary": "Revoke an access or refresh token",
    "description": "Unknown tokens also return 200 to avoid existence disclosure.",
    "operationId": "revokeToken",
    "requestBody": {
     "required": true,
     "content": {
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object",
        "properties": {
         "token": {
          "type": "string"
         },
         "client_id": {
          "type": "string"
         }
        },
        "required": [
         "token"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Empty JSON object",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "maxProperties": 0
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "BearerAuth": {
    "type": "http",
    "scheme": "bearer"
   }
  },
  "schemas": {
   "ProtectedResourceMetadata": {
    "type": "object",
    "required": [
     "resource",
     "authorization_servers"
    ],
    "properties": {
     "resource": {
      "type": "string",
      "format": "uri"
     },
     "authorization_servers": {
      "type": "array",
      "items": {
       "type": "string",
       "format": "uri"
      }
     },
     "scopes_supported": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    },
    "additionalProperties": true
   },
   "AuthorizationServerMetadata": {
    "type": "object",
    "required": [
     "issuer",
     "authorization_endpoint",
     "token_endpoint",
     "registration_endpoint"
    ],
    "properties": {
     "issuer": {
      "type": "string",
      "format": "uri"
     },
     "authorization_endpoint": {
      "type": "string",
      "format": "uri"
     },
     "token_endpoint": {
      "type": "string",
      "format": "uri"
     },
     "registration_endpoint": {
      "type": "string",
      "format": "uri"
     },
     "revocation_endpoint": {
      "type": "string",
      "format": "uri"
     }
    },
    "additionalProperties": true
   },
   "RegistrationRequest": {
    "type": "object",
    "required": [
     "redirect_uris"
    ],
    "properties": {
     "client_name": {
      "type": "string"
     },
     "redirect_uris": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10,
      "items": {
       "type": "string",
       "format": "uri"
      }
     },
     "grant_types": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "response_types": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "token_endpoint_auth_method": {
      "type": "string",
      "const": "none"
     },
     "scope": {
      "type": "string"
     }
    },
    "additionalProperties": true
   },
   "RegistrationResponse": {
    "type": "object",
    "required": [
     "client_id",
     "redirect_uris",
     "token_endpoint_auth_method"
    ],
    "properties": {
     "client_id": {
      "type": "string"
     },
     "client_id_issued_at": {
      "type": "integer"
     },
     "client_name": {
      "type": "string"
     },
     "redirect_uris": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "token_endpoint_auth_method": {
      "type": "string",
      "const": "none"
     }
    },
    "additionalProperties": true
   },
   "TokenResponse": {
    "type": "object",
    "required": [
     "access_token",
     "token_type",
     "expires_in"
    ],
    "properties": {
     "access_token": {
      "type": "string"
     },
     "token_type": {
      "type": "string"
     },
     "expires_in": {
      "type": "integer"
     },
     "refresh_token": {
      "type": "string"
     },
     "scope": {
      "type": "string"
     }
    },
    "additionalProperties": true
   },
   "OAuthError": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "string"
     },
     "error_description": {
      "type": "string"
     }
    },
    "additionalProperties": true
   },
   "JsonRpcRequest": {
    "type": "object",
    "required": [
     "jsonrpc",
     "method"
    ],
    "properties": {
     "jsonrpc": {
      "type": "string",
      "const": "2.0"
     },
     "id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ]
     },
     "method": {
      "type": "string"
     },
     "params": {
      "type": "object",
      "additionalProperties": true
     }
    },
    "additionalProperties": true
   },
   "JsonRpcResponse": {
    "type": "object",
    "required": [
     "jsonrpc",
     "id"
    ],
    "properties": {
     "jsonrpc": {
      "type": "string",
      "const": "2.0"
     },
     "id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ]
     },
     "result": {},
     "error": {
      "type": "object",
      "properties": {
       "code": {
        "type": "integer"
       },
       "message": {
        "type": "string"
       }
      },
      "required": [
       "code",
       "message"
      ]
     }
    },
    "additionalProperties": true
   },
   "Version": {
    "type": "object",
    "required": [
     "sha",
     "packages",
     "env"
    ],
    "properties": {
     "sha": {
      "type": "string"
     },
     "short": {
      "type": "string"
     },
     "at": {
      "type": "string"
     },
     "env": {
      "type": "string"
     },
     "packages": {
      "type": "object",
      "additionalProperties": {
       "type": "string"
      }
     },
     "verified": {
      "type": [
       "string",
       "null"
      ]
     },
     "verified_at": {
      "type": [
       "string",
       "null"
      ]
     }
    },
    "additionalProperties": true
   },
   "Health": {
    "type": "object",
    "required": [
     "ok",
     "apps_not_admitted"
    ],
    "properties": {
     "ok": {
      "type": "boolean"
     },
     "apps_not_admitted": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "env": {
      "type": "string"
     }
    },
    "additionalProperties": true
   }
  }
 }
}