{
  "openapi": "3.1.0",
  "info": {
    "title": "Peetchr Agent & OAuth API",
    "version": "1.0.0",
    "summary": "OAuth 2.1 + MCP entry points for AI agents.",
    "description": "Peetchr is a Talent Intelligence platform that plugs into an existing ATS and uses AI to evaluate candidates on hard skills, soft skills, culture fit, and team fit - no candidate test required - so recruiters get an explainable, ranked shortlist for every role across their new applicants, their existing ATS talent pool, and their employees.\n\nPeetchr's programmatic surface is a Model Context Protocol (MCP) server protected by OAuth 2.1. This specification documents the OAuth authorization server and the MCP transport so agents can authenticate and connect. The typed tool catalog is published by the MCP server itself via `tools/list`; see https://peetchr.com/agents.md.",
    "contact": {
      "name": "Peetchr SAS",
      "email": "hello@peetchr.ai",
      "url": "https://peetchr.com"
    }
  },
  "externalDocs": {
    "description": "Agent guide and auth walkthrough",
    "url": "https://peetchr.com/agents.md"
  },
  "servers": [
    {
      "url": "https://app.peetchr.com",
      "description": "Peetchr recruiter app (MCP + OAuth host)"
    }
  ],
  "security": [
    {
      "peetchrOAuth": [
        "peetchr:recruiter"
      ]
    }
  ],
  "paths": {
    "/api/mcp": {
      "post": {
        "operationId": "mcpInvoke",
        "summary": "MCP Streamable HTTP transport (JSON-RPC 2.0).",
        "description": "Model Context Protocol endpoint. Send JSON-RPC 2.0 requests (initialize, tools/list, tools/call) with an OAuth bearer token. Read tools require the peetchr:recruiter scope; write tools require peetchr:recruiter:write.",
        "security": [
          {
            "peetchrOAuth": [
              "peetchr:recruiter"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC or SSE response from the MCP server.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid token. Includes a `WWW-Authenticate: Bearer resource_metadata=\"...\"` header pointing at the RFC 9728 metadata.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "Bearer challenge with resource_metadata URL."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Structured JSON error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/api/mcp": {
      "get": {
        "operationId": "getProtectedResourceMetadata",
        "summary": "RFC 9728 protected-resource metadata for the MCP resource.",
        "security": [],
        "responses": {
          "200": {
            "description": "Protected-resource metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedResourceMetadata"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "getAuthorizationServerMetadata",
        "summary": "RFC 8414 authorization-server metadata.",
        "security": [],
        "responses": {
          "200": {
            "description": "Authorization-server metadata (issuer, endpoints, scopes).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/mcp/register": {
      "post": {
        "operationId": "registerClient",
        "summary": "Dynamic client registration (RFC 7591).",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "client_name": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Registered client credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/mcp/authorize": {
      "get": {
        "operationId": "authorize",
        "summary": "OAuth 2.1 authorization endpoint (code + PKCE).",
        "security": [],
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "const": "code"
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "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": {
              "const": "S256"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect back to redirect_uri with an authorization code."
          }
        }
      }
    },
    "/api/auth/mcp/token": {
      "post": {
        "operationId": "token",
        "summary": "OAuth 2.1 token endpoint.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access token response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Structured JSON error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "peetchrOAuth": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code with PKCE and RFC 7591 dynamic client registration.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://app.peetchr.com/api/auth/mcp/authorize",
            "tokenUrl": "https://app.peetchr.com/api/auth/mcp/token",
            "refreshUrl": "https://app.peetchr.com/api/auth/mcp/token",
            "scopes": {
              "openid": "Authenticate the recruiter granting access (OpenID Connect).",
              "profile": "Read the granting recruiter profile.",
              "email": "Read the granting recruiter email.",
              "offline_access": "Obtain a refresh token for long-running sessions.",
              "peetchr:recruiter": "Read-only recruiter access: jobs, candidates, scorecards, credits.",
              "peetchr:recruiter:write": "Write recruiter access: create jobs/candidates, generate and save scorecards, accept/reject candidates.",
              "peetchr:admin:recruiter": "Peetchr-admin cross-organization recruiter actions (e.g. invite recruiters).",
              "peetchr:admin:sql": "Peetchr-admin read-only SQL access. Highly privileged; rarely granted."
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Structured error an agent can parse without scraping HTML.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code."
          },
          "error_description": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "number"
            ]
          },
          "method": {
            "type": "string",
            "examples": [
              "initialize",
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "const": "Bearer"
          },
          "expires_in": {
            "type": "integer"
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          }
        }
      },
      "ProtectedResourceMetadata": {
        "type": "object",
        "properties": {
          "resource": {
            "type": "string",
            "format": "uri",
            "examples": [
              "https://app.peetchr.com/api/mcp"
            ]
          },
          "authorization_servers": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "resource_name": {
            "type": "string"
          }
        }
      }
    }
  }
}