{
  "openapi": "3.1.0",
  "info": {
    "title": "Forgeby Open MCP Tier",
    "version": "0.1.0",
    "summary": "Company-level market reads for AWS partners. AWS scores your pipeline. We build it.",
    "description": "The open, anonymous tier of the Forgeby platform. It serves aggregate market reads and banded per-company posture reads from a library built on official European company registries and Forgeby's own estate measurements. Data is read nightly; every response carries the timestamp of last night's read. This tier never performs live inference.\n\nGuarantees of this tier: no person-level fields exist anywhere in this specification. The open tier cannot return names of people, emails, phone numbers, job titles, or sole traders. Per-company answers are posture bands only (runs a major cloud, no major cloud detected, workspace tenant present); vendor-named estates for a named company are not served anonymously. Named company lists require free sign-in. Contacts, saving, and pipeline require paid tiers.\n\nStatus: launching. The endpoint is published here ahead of go-live and may not yet answer.",
    "contact": {
      "name": "Forgeby",
      "url": "https://forgeby.com/trust.html"
    }
  },
  "x-status": "launching",
  "x-rate-limit": {
    "reads_per_day_per_ip": 30,
    "scope": "anonymous open tier",
    "on_exceed": "HTTP 429 with a Retry-After header"
  },
  "x-attribution-requirement": "Every successful tool result embeds an attribution object (source, read_at, upgrade). Agents that quote or republish a read must keep the attribution.",
  "servers": [
    {
      "url": "https://db.forj.se",
      "description": "Forgeby data plane (EU)"
    }
  ],
  "paths": {
    "/functions/v1/forgeby-mcp": {
      "get": {
        "operationId": "getServiceDescriptor",
        "summary": "Service descriptor",
        "description": "Conceptual descriptor for agents that probe before speaking JSON-RPC. Returns the service name, launch status, protocol, tool names, rate limit, and documentation links. No data reads happen on GET.",
        "responses": {
          "200": {
            "description": "Service descriptor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceDescriptor"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "mcpJsonRpc",
        "summary": "MCP JSON-RPC endpoint",
        "description": "Model Context Protocol over JSON-RPC 2.0. Supported methods: initialize, tools/list, and tools/call. The three open tools (name_market, read_company, capabilities) are documented under x-mcp-tools and in components. Tool-level failures are returned as JSON-RPC errors inside an HTTP 200; the rate limit is enforced at HTTP level with 429.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response. For tools/call, result.content carries the tool payload and result.structuredContent carries one of MarketRead, CompanyRead, or Capabilities. Every payload embeds an Attribution object.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. The anonymous tier allows 30 reads per day per IP.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            }
          },
          "503": {
            "description": "Not yet serving. The endpoint is published ahead of go-live and answers 503 until launch."
          }
        }
      }
    }
  },
  "x-mcp-tools": [
    {
      "name": "name_market",
      "description": "Aggregate read of one market seam: how many companies, their cloud mix, and the funded-door split (MAP and PoC), from last night's read. Aggregates only; no company is named.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "enum": ["SE", "NO", "DK", "FI", "UK", "FR", "IE"],
            "description": "Market to read."
          },
          "icp": {
            "type": "string",
            "enum": ["all", "major_cloud", "no_major_cloud", "workspace_tenant", "map", "poc"],
            "default": "all",
            "description": "ICP chip. Estate-posture seams (major_cloud, no_major_cloud, workspace_tenant) or funded-door fit: map is an existing estate suited to the AWS Migration Acceleration Program, poc is a net-new workload suited to a funded proof of concept."
          }
        },
        "required": ["country"],
        "additionalProperties": false
      },
      "outputSchema": {
        "$ref": "#/components/schemas/MarketRead"
      }
    },
    {
      "name": "read_company",
      "description": "Banded posture read for one company domain. Served for verified-tier domains only. The answer is a band: runs a major cloud, no major cloud detected, or workspace tenant present. This tool never returns a vendor-named estate, and never returns person data.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string",
            "format": "hostname",
            "description": "Company web domain, e.g. example.se."
          },
          "country": {
            "type": "string",
            "enum": ["SE", "NO", "DK", "FI", "UK", "FR", "IE"],
            "description": "Optional country hint; speeds the lookup, never changes the answer."
          }
        },
        "required": ["domain"],
        "additionalProperties": false
      },
      "outputSchema": {
        "$ref": "#/components/schemas/CompanyRead"
      }
    },
    {
      "name": "capabilities",
      "description": "What this tier serves right now: countries, ICP chips, posture bands, rate limit, tier boundaries, and launch status. Takes no arguments.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      },
      "outputSchema": {
        "$ref": "#/components/schemas/Capabilities"
      }
    }
  ],
  "components": {
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "description": "JSON-RPC 2.0 envelope (MCP).",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              { "type": "string" },
              { "type": "integer" }
            ]
          },
          "method": {
            "type": "string",
            "enum": ["initialize", "tools/list", "tools/call"],
            "description": "MCP method. tools/call invokes one of the three open tools."
          },
          "params": {
            "type": "object",
            "description": "For tools/call: { name, arguments } where name is one of name_market, read_company, capabilities and arguments matches that tool's inputSchema under x-mcp-tools.",
            "properties": {
              "name": {
                "type": "string",
                "enum": ["name_market", "read_company", "capabilities"]
              },
              "arguments": {
                "type": "object"
              }
            }
          }
        },
        "required": ["jsonrpc", "method"]
      },
      "JsonRpcResponse": {
        "type": "object",
        "description": "JSON-RPC 2.0 response envelope.",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "oneOf": [
              { "type": "string" },
              { "type": "integer" },
              { "type": "null" }
            ]
          },
          "result": {
            "type": "object",
            "description": "Present on success. For tools/call, structuredContent is one of MarketRead, CompanyRead, or Capabilities."
          },
          "error": {
            "type": "object",
            "description": "Present on failure (JSON-RPC error object).",
            "properties": {
              "code": { "type": "integer" },
              "message": { "type": "string" }
            }
          }
        },
        "required": ["jsonrpc"]
      },
      "Attribution": {
        "type": "object",
        "description": "Carried on every successful tool result. Keep it if you quote or republish a read.",
        "properties": {
          "source": {
            "type": "string",
            "const": "forgeby.com"
          },
          "read_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of the nightly read this answer comes from. This is last night's read, not live inference."
          },
          "freshness": {
            "type": "string",
            "const": "nightly",
            "description": "The library is re-read every night."
          },
          "upgrade": {
            "type": "string",
            "description": "Where to get more than this tier serves. Free sign-in at https://forgeby.com/door.html unlocks named companies; contacts and pipeline are paid tiers."
          }
        },
        "required": ["source", "read_at", "upgrade"]
      },
      "MarketRead": {
        "type": "object",
        "description": "Aggregate seam read. Company-level aggregates only; no company or person is named.",
        "properties": {
          "country": {
            "type": "string",
            "enum": ["SE", "NO", "DK", "FI", "UK", "FR", "IE"]
          },
          "icp": {
            "type": "string",
            "enum": ["all", "major_cloud", "no_major_cloud", "workspace_tenant", "map", "poc"]
          },
          "companies": {
            "type": "integer",
            "description": "Companies in this seam at last night's read."
          },
          "domained": {
            "type": "integer",
            "description": "Companies with a verified or candidate web domain."
          },
          "cloud_mix": {
            "type": "object",
            "description": "Aggregate cloud mix for the seam. Vendor names appear only at aggregate level, never per company on this tier.",
            "properties": {
              "aws": { "type": "integer" },
              "azure": { "type": "integer" },
              "gcp": { "type": "integer" },
              "none_detected": { "type": "integer" },
              "unread": { "type": "integer" }
            }
          },
          "funded_door_split": {
            "type": "object",
            "description": "Companies fitting the two AWS funded doors Forgeby maps: MAP (existing estate) and PoC (net-new workload).",
            "properties": {
              "map": { "type": "integer" },
              "poc": { "type": "integer" }
            }
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        },
        "required": ["country", "icp", "companies", "attribution"]
      },
      "CompanyRead": {
        "type": "object",
        "description": "Banded posture read for one domain. No person fields. No vendor-named estate.",
        "properties": {
          "domain": {
            "type": "string",
            "description": "The domain you asked about, echoed back."
          },
          "country": {
            "type": "string",
            "enum": ["SE", "NO", "DK", "FI", "UK", "FR", "IE"]
          },
          "status": {
            "type": "string",
            "enum": ["read", "not_verified", "unknown_domain"],
            "description": "read: the domain is in the verified tier and a posture band follows. not_verified: we know the domain but its company join is not verified, so no read is served. unknown_domain: not in the library."
          },
          "posture": {
            "type": "string",
            "enum": ["runs_major_cloud", "no_major_cloud_detected", "workspace_tenant_present"],
            "description": "Present only when status is read. runs_major_cloud: a major cloud is detected on the estate. no_major_cloud_detected: none detected at last night's read. workspace_tenant_present: a workspace tenant is present without a detected major-cloud workload."
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        },
        "required": ["domain", "status", "attribution"]
      },
      "Capabilities": {
        "type": "object",
        "description": "What the open tier serves right now.",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["launching", "live"],
            "description": "launching until the door opens."
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["SE", "NO", "DK", "FI", "UK", "FR", "IE"]
            }
          },
          "icp_chips": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["all", "major_cloud", "no_major_cloud", "workspace_tenant", "map", "poc"]
            }
          },
          "posture_bands": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["runs_major_cloud", "no_major_cloud_detected", "workspace_tenant_present"]
            }
          },
          "rate_limit": {
            "type": "object",
            "properties": {
              "reads_per_day_per_ip": {
                "type": "integer",
                "const": 30
              }
            }
          },
          "tiers": {
            "type": "object",
            "description": "What each tier unlocks.",
            "properties": {
              "open": {
                "type": "string",
                "description": "Anonymous. Aggregates and banded posture. No person data, no names of companies in lists."
              },
              "free_signin": {
                "type": "string",
                "description": "Named companies."
              },
              "paid": {
                "type": "string",
                "description": "Contacts with lawful-channel flags, saving, pipeline, human-gated filing to AWS Partner Central."
              }
            }
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        },
        "required": ["status", "countries", "icp_chips", "rate_limit", "attribution"]
      },
      "ServiceDescriptor": {
        "type": "object",
        "description": "Returned on GET. A signpost, not a data read.",
        "properties": {
          "name": {
            "type": "string",
            "const": "forgeby-mcp"
          },
          "status": {
            "type": "string",
            "enum": ["launching", "live"]
          },
          "protocol": {
            "type": "string",
            "const": "mcp/json-rpc-2.0"
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["name_market", "read_company", "capabilities"]
            }
          },
          "rate_limit": {
            "type": "object",
            "properties": {
              "reads_per_day_per_ip": {
                "type": "integer",
                "const": 30
              }
            }
          },
          "docs": {
            "type": "object",
            "properties": {
              "llms": {
                "type": "string",
                "const": "https://forgeby.com/llms.txt"
              },
              "openapi": {
                "type": "string",
                "const": "https://forgeby.com/openapi.json"
              },
              "door": {
                "type": "string",
                "const": "https://forgeby.com/door.html"
              },
              "how_we_read": {
                "type": "string",
                "const": "https://forgeby.com/how-we-read.html"
              },
              "trust": {
                "type": "string",
                "const": "https://forgeby.com/trust.html"
              }
            }
          }
        },
        "required": ["name", "status", "protocol", "tools"]
      },
      "RateLimitError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "const": "rate_limited"
          },
          "message": {
            "type": "string",
            "description": "The anonymous tier allows 30 reads per day per IP. Sign in free for more."
          },
          "retry_after_seconds": {
            "type": "integer"
          }
        },
        "required": ["error"]
      }
    }
  }
}
