{
  "openapi": "3.1.0",
  "info": {
    "title": "DForge Operations MCP API",
    "version": "1.0.0",
    "summary": "HTTP surface of the DForge Operations MCP server.",
    "description": "The DForge Operations MCP server exposes DForge operations tooling to AI agents over the Model Context Protocol (Streamable HTTP transport). Tool discovery and invocation use MCP JSON-RPC messages posted to `/mcp`. Every call carries a client-specific bearer token that maps to one or more scopes:\n\n- `support`: Read users, sites, tickets and commission records; manage support tickets.\n- `operations`: Update allowlisted site configuration, Vercel project assignment and trigger deployments.\n- `finance_request`: Create pending Finance requests only; never executes a payout.\n- `marketing`: Create draft email campaigns, send test copies and capped campaign sends; draft and publish Platform Updates and site announcements.\n- `admin`: All of the above plus audited admin console writes. Still no payout execution.\n\nThe server holds no payment-provider credentials and exposes no payout tool. Request a scoped token from support@dforge.site.",
    "contact": {
      "name": "DForge support",
      "email": "support@dforge.site",
      "url": "https://dforge.site/contact"
    },
    "termsOfService": "https://dforge.site/terms"
  },
  "externalDocs": {
    "description": "Developer resources",
    "url": "https://dforge.site/developers"
  },
  "servers": [
    {
      "url": "https://mcp.dforge.site",
      "description": "Production MCP server"
    }
  ],
  "security": [
    {
      "mcpBearer": []
    }
  ],
  "x-scopes-supported": [
    "support",
    "operations",
    "finance_request",
    "marketing",
    "admin"
  ],
  "x-protected-resource-metadata": "https://dforge.site/.well-known/oauth-protected-resource",
  "tags": [
    {
      "name": "mcp",
      "description": "Model Context Protocol endpoint"
    },
    {
      "name": "health",
      "description": "Liveness"
    }
  ],
  "paths": {
    "/mcp": {
      "post": {
        "tags": [
          "mcp"
        ],
        "operationId": "mcpRequest",
        "summary": "Send an MCP JSON-RPC message (initialize, tools/list, tools/call, …)",
        "description": "Stateless Streamable HTTP transport: each POST carries one JSON-RPC request or notification. Call `tools/list` to discover the tools available to your token, then `tools/call`. A call outside the token's scopes is refused and audited.",
        "security": [
          {
            "mcpBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "examples": {
                "listTools": {
                  "summary": "List tools",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "tools/list",
                    "params": {}
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (application/json) or event stream (text/event-stream)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed (only POST is accepted in stateless mode)"
          }
        }
      },
      "get": {
        "tags": [
          "mcp"
        ],
        "operationId": "mcpGetNotSupported",
        "summary": "Not supported: the server runs in stateless mode",
        "responses": {
          "405": {
            "description": "Method not allowed"
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "tags": [
          "health"
        ],
        "operationId": "health",
        "summary": "Liveness check (no authentication)",
        "security": [],
        "responses": {
          "200": {
            "description": "Server is up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "service": {
                      "type": "string"
                    },
                    "financialBoundary": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "service"
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "mcpBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Client-specific token issued by DForge and mapped to one or more scopes. Scopes: support, operations, finance_request, marketing, admin. Scope semantics are published at /.well-known/oauth-protected-resource.",
        "x-scopes": {
          "support": "Read users, sites, tickets and commission records; manage support tickets.",
          "operations": "Update allowlisted site configuration, Vercel project assignment and trigger deployments.",
          "finance_request": "Create pending Finance requests only; never executes a payout.",
          "marketing": "Create draft email campaigns, send test copies and capped campaign sends; draft and publish Platform Updates and site announcements.",
          "admin": "All of the above plus audited admin console writes. Still no payout execution."
        }
      }
    },
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "method": {
            "type": "string",
            "examples": [
              "initialize",
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "$ref": "#/components/schemas/JsonRpcError"
          }
        }
      },
      "JsonRpcError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "data": {}
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
