{
  "openapi": "3.1.0",
  "info": {
    "title": "tonyhughesdesign.com Agent API",
    "description": "Public API for AI agents and developers to interface with Tony Hughes' brand & positioning consultancy: read-only resources (bio, case studies, engagements, contact) and two actions (evaluate client needs, schedule a consultation). A protocol-compliant MCP server exposing the same surface is available at /api/mcp (see /mcp.json).\n\nError model: every error response carries the same envelope — { \"error\": { \"code\", \"message\", \"resolution\" } } — see #/components/schemas/ErrorBody. All paths honour CORS (Access-Control-Allow-Origin: *). Rate limits: see the RateLimit-* response headers (informational; the serving quota is generous).",
    "version": "2.6.0",
    "x-api-versioning": {
      "policy": "stable-path manifest + REST-Version response header",
      "note": "The manifest at /api/agent is the version authority. Breaking changes ship as a new manifest version before any URL change. URL path versioning (/v1/) will only be introduced if needed."
    },
    "contact": {
      "name": "Tony Hughes",
      "email": "info@tonyhughesdesign.com",
      "url": "https://tonyhughesdesign.com"
    }
  },
  "servers": [
    {
      "url": "https://tonyhughesdesign.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/agent": {
      "get": {
        "operationId": "getAgentManifest",
        "summary": "Agent API manifest",
        "description": "Returns the self-describing manifest of resources and tools available on this API. This is the entry point agents should fetch first.",
        "responses": {
          "200": {
            "description": "Manifest",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Manifest"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/agent/resources/{name}": {
      "get": {
        "operationId": "getAgentResource",
        "summary": "Get one read-only resource",
        "description": "Returns a single resource by name. Supported names: bio (markdown biography), case-studies (JSON list of client work), engagements (JSON list of the four engagement types), contact-card (VCF business card data).",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "description": "Resource name to fetch.",
            "schema": {
              "type": "string",
              "enum": [
                "bio",
                "case-studies",
                "engagements",
                "contact-card"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resource content (markdown, JSON, or vCard text depending on the resource).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ResourceMarkdown"
                    },
                    {
                      "$ref": "#/components/schemas/ResourceJson"
                    },
                    {
                      "$ref": "#/components/schemas/ResourceVcard"
                    }
                  ]
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/vcard": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/agent/tools/evaluate-client-needs": {
      "post": {
        "operationId": "evaluateClientNeeds",
        "summary": "Evaluate client needs against the real engagement offerings",
        "description": "Deterministic match of a client's challenges and technology sector against Tony's actual four engagement types. Keyword-scored against real data, never LLM-generated, so it cannot recommend an engagement type that does not exist.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvaluateClientNeedsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recommendation with rationale and next step.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvaluateClientNeedsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/agent/tools/schedule-consultation": {
      "post": {
        "operationId": "scheduleConsultation",
        "summary": "Send a consultation request to Tony's inbox",
        "description": "Sends a real request to Tony via authenticated SMTP. Not an automatic booking — Tony reviews every inquiry personally and replies within 24 hours to confirm an actual time. No calendar slot is reserved by calling this tool.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleConsultationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request accepted and queued for delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleConsultationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "description": "Mail transport failure — the request was not delivered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/mcp": {
      "get": {
        "operationId": "mcpInitialization",
        "summary": "MCP Streamable HTTP server (GET)",
        "description": "Model Context Protocol server using the Streamable HTTP transport (spec 2025-03-26). GET performs the MCP initialization handshake. A sessionless GET returns the server description immediately.",
        "responses": {
          "200": {
            "description": "MCP server description / initialization response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpServerDescription"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "mcpMessage",
        "summary": "MCP Streamable HTTP server (POST)",
        "description": "Sends MCP protocol JSON-RPC messages (resources.read, tools/call, prompts/get).",
        "responses": {
          "200": {
            "description": "MCP JSON-RPC response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "mcpSessionEnd",
        "summary": "End an MCP session",
        "description": "Deletes the session identified by the Mcp-Session-Id header.",
        "responses": {
          "200": {
            "description": "Session ended."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "llms.txt index",
        "description": "Machine-readable site index per the llms.txt convention (llmstxt.org) for LLM agents reading the site directly.",
        "responses": {
          "200": {
            "description": "Markdown index.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/mcp.json": {
      "get": {
        "operationId": "getMcpManifest",
        "summary": "MCP server manifest",
        "description": "MCP-ecosystem server manifest (https://modelcontextprotocol.io) advertising the /api/mcp endpoint and server name/version.",
        "responses": {
          "200": {
            "description": "MCP manifest JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpManifest"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "NotFound": {
        "description": "The requested resource does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      },
      "BadRequest": {
        "description": "The request body was invalid or missing required fields.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      },
      "ServerError": {
        "description": "An unexpected server error occurred.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorBody"
            }
          }
        }
      }
    },
    "schemas": {
      "Manifest": {
        "type": "object",
        "description": "Self-describing list of resources and tools.",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string",
            "description": "Manifest version. Both this spec and every REST-Version header carry the same value."
          },
          "description": {
            "type": "string"
          },
          "resources": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "method",
                "url"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "GET"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "method",
                "url"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "POST"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "body": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                },
                "description": {
                  "type": "string"
                }
              }
            }
          },
          "mcp": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ResourceMarkdown": {
        "type": "object",
        "description": "The bio resource.",
        "properties": {
          "name": {
            "type": "string"
          },
          "content": {
            "type": "string"
          }
        }
      },
      "ResourceJson": {
        "type": "object",
        "description": "The case-studies and engagements resources.",
        "properties": {
          "name": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "ResourceVcard": {
        "type": "object",
        "description": "The contact-card resource.",
        "properties": {
          "name": {
            "type": "string"
          },
          "content": {
            "type": "string"
          }
        }
      },
      "EvaluateClientNeedsRequest": {
        "type": "object",
        "required": [
          "challenges",
          "technology_sector"
        ],
        "properties": {
          "challenges": {
            "type": "string",
            "description": "Current messaging, pitch or scaling challenges."
          },
          "technology_sector": {
            "type": "string",
            "description": "The technical domain, e.g. Sensory AI, Climate Risk, Fusion Energy."
          }
        }
      },
      "EvaluateClientNeedsResponse": {
        "type": "object",
        "description": "Deterministic recommendation derived only from real engagement data.",
        "properties": {
          "recommended": {
            "type": "object",
            "properties": {
              "key": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "tagline": {
                "type": "string"
              },
              "why": {
                "type": "string"
              },
              "includes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "outcomes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "timing": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "alsoConsider": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "key": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "tagline": {
                "type": "string"
              }
            }
          },
          "nextStep": {
            "type": "string"
          }
        }
      },
      "ScheduleConsultationRequest": {
        "type": "object",
        "required": [
          "client_name",
          "client_email"
        ],
        "properties": {
          "client_name": {
            "type": "string",
            "description": "Name of the founder or executive requesting the call."
          },
          "client_email": {
            "type": "string",
            "format": "email",
            "description": "Email address to reply to."
          },
          "preferred_time": {
            "type": "string",
            "description": "Preferred time slot, in any format."
          },
          "project_context": {
            "type": "string",
            "description": "What the company does and what prompted this inquiry."
          },
          "technology_sector": {
            "type": "string",
            "description": "The technical domain."
          }
        }
      },
      "ScheduleConsultationResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "McpServerDescription": {
        "type": "object",
        "description": "Fast description returned for sessionless GET probes.",
        "properties": {
          "jsonrpc": {
            "type": "string"
          },
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "result": {
            "type": "object",
            "properties": {
              "serverInfo": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  }
                }
              },
              "transport": {
                "type": "string"
              },
              "protocolVersion": {
                "type": "string"
              },
              "resources": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "tools": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "prompts": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "McpJsonRpcResponse": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string"
          },
          "id": {
            "type": [
              "string",
              "number",
              "null"
            ]
          },
          "result": {
            "type": "object"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {}
            }
          }
        }
      },
      "McpManifest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "transport": {
            "type": "string"
          },
          "endpoint": {
            "type": "string",
            "format": "uri"
          },
          "restApiFallback": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ErrorBody": {
        "type": "object",
        "description": "Structured error response. Agents should read `code` and `resolution`, never parse an HTML error page.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "resolution"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "NOT_FOUND",
                "description": "Machine-readable error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable description of the failure."
              },
              "resolution": {
                "type": "string",
                "description": "A concrete next step for the agent."
              }
            }
          }
        }
      }
    }
  }
}