{"openapi":"3.1.0","info":{"title":"Ebnii API — ابني، منشئ المواقع بالذكاء الاصطناعي (AI Website Builder)","version":"1.1.0","summary":"Create, build and publish Arabic-first websites on Ebnii (ابني) from any AI assistant or agent through an MCP-compatible JSON-RPC API secured with OAuth 2.1 + PKCE.","description":"Ebnii (ابني) is an AI website builder for Arab businesses: a person describes a site in Arabic and Ebnii's agent designs, writes, hosts and publishes it — right-to-left by default, Gulf payment methods (mada, Apple Pay, stc pay, Tabby, Tamara), WhatsApp and marketing pixels built in.\n\nThis API is the ACCOUNT connector: it exposes an Ebnii account (every site the person owns, plus creating, building and publishing) as an MCP server at `POST /api/mcp`. It speaks JSON-RPC 2.0 over HTTP in stateless mode; every tool is a typed `tools/call` request (see the `McpRequest` schema or `x-ebnii-tools`).\n\n**Authentication** — OAuth 2.1 authorization-code flow with PKCE (S256), public clients only (`token_endpoint_auth_method: none`), dynamic client registration (RFC 7591). Discovery: `GET /.well-known/oauth-authorization-server` (RFC 8414) and `GET /.well-known/oauth-protected-resource` (RFC 9728). Scopes: `sites:read` and `sites:write`; the token response's `scope` tells you which the account granted.\n\n**Access** — The account connector is in a private beta: it is enabled per account by Ebnii. Ask for access at https://ebnii.com/support (mention «MCP») — the OAuth discovery, registration and token endpoints are already public, and an unenabled account receives HTTP 404 from the MCP endpoint.\n\n**Errors** — non-RPC failures are JSON (`ApiError`); RPC failures are JSON-RPC error objects. HTTP 401 carries a `WWW-Authenticate: Bearer resource_metadata=\"…\"` challenge. Rate limits: 120 requests/minute per IP, 240/minute per account.\n\nHuman-readable docs: https://ebnii.com/docs. Site index for agents: https://ebnii.com/llms.txt. Markdown rendering of any public page: send `Accept: text/markdown`.","termsOfService":"https://ebnii.com/terms","contact":{"name":"Ebnii support","url":"https://ebnii.com/support","email":"hello@ebnii.com"},"x-logo":{"url":"https://ebnii.com/icon.png","altText":"Ebnii"}},"externalDocs":{"description":"Ebnii developer documentation","url":"https://ebnii.com/docs"},"servers":[{"url":"https://ebnii.com","description":"Production"}],"tags":[{"name":"mcp","description":"The account MCP server (JSON-RPC 2.0)."},{"name":"oauth","description":"OAuth 2.1 authorization server (PKCE, dynamic client registration)."},{"name":"discovery","description":"Machine-readable files that describe this API and this site."}],"security":[{"oauth2":["sites:read"]},{"bearer":[]}],"paths":{"/api/mcp":{"post":{"operationId":"mcpCall","tags":["mcp"],"summary":"Call the Ebnii account MCP server (initialize, tools/list, tools/call, ping)","description":"One JSON-RPC 2.0 request or a batch of up to 20. Start with `initialize`, then `tools/list`, then `tools/call` with one of the typed variants below. Builds (`create_site`, `build_site`) return immediately and keep running — poll `get_build_status`. Up to 300 seconds per call.","security":[{"oauth2":["sites:read"]},{"oauth2":["sites:read","sites:write"]},{"bearer":[]}],"parameters":[{"name":"MCP-Protocol-Version","in":"header","required":false,"schema":{"type":"string","enum":["2025-11-25","2025-06-18","2025-03-26"]},"description":"Negotiated protocol version (after initialize)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/McpRequest"},{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/McpRequest"}}]},"examples":{"initialize":{"value":{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0.0"}}}},"listTools":{"value":{"jsonrpc":"2.0","id":2,"method":"tools/list"}},"listSites":{"value":{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_sites","arguments":{"limit":20}}}},"buildSite":{"value":{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"build_site","arguments":{"site_id":"00000000-0000-0000-0000-000000000000","instruction":"أضف قسم آراء العملاء تحت الهيرو"}}}}}}}},"responses":{"200":{"description":"JSON-RPC response (or an array of them for a batch). A tool's payload is `result` shaped as `ToolResult`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JsonRpcResponse"},{"type":"array","items":{"$ref":"#/components/schemas/JsonRpcResponse"}}]}}}},"400":{"description":"Body is not valid JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"401":{"description":"Missing, expired or revoked token. Follow the `WWW-Authenticate` challenge to the protected-resource metadata.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"description":"Bearer resource_metadata=\"https://ebnii.com/api/mcp/prm\""}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"404":{"description":"The connector is not enabled for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Body over 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited (120/min per IP, 240/min per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mcp/tools":{"get":{"operationId":"listTools","tags":["discovery"],"summary":"The tool catalog as plain function-calling definitions (no auth)","description":"Same tools `tools/list` returns, with the scope each needs — for building function/tool definitions before a user has authorized.","security":[],"responses":{"200":{"description":"Tool catalog.","content":{"application/json":{"schema":{"type":"object","required":["endpoint","tools"],"properties":{"endpoint":{"type":"string","format":"uri"},"protocol":{"type":"string","const":"mcp"},"protocolVersions":{"type":"array","items":{"type":"string"}},"auth":{"type":"object","additionalProperties":true},"tools":{"type":"array","items":{"type":"object","required":["name","description","parameters","scope"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":{"type":"object","additionalProperties":true},"scope":{"type":"string","enum":["sites:read","sites:write"]}}}}}}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"getAuthorizationServerMetadata","tags":["oauth","discovery"],"summary":"OAuth 2.1 Authorization Server metadata (RFC 8414)","security":[],"responses":{"200":{"description":"Issuer, endpoints, PKCE methods and supported scopes.","content":{"application/json":{"schema":{"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"},"response_types_supported":{"type":"array","items":{"type":"string"}},"grant_types_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"getProtectedResourceMetadata","tags":["oauth","discovery"],"summary":"Protected Resource Metadata for the account MCP server (RFC 9728)","security":[],"responses":{"200":{"description":"Resource identifier, its authorization servers and the scopes it understands.","content":{"application/json":{"schema":{"type":"object","required":["resource","authorization_servers","scopes_supported"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string","enum":["sites:read","sites:write"]}},"scope_descriptions":{"type":"object","additionalProperties":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"}},"resource_documentation":{"type":"string","format":"uri"}}}}}}}}},"/api/mcp-oauth/register":{"post":{"operationId":"registerClient","tags":["oauth"],"summary":"Dynamic client registration (RFC 7591) — stateless, no secret","description":"Returns a `client_id` that encodes the redirect URIs. Public clients only; every authorization still needs the owner's consent and PKCE.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"uri"},"description":"https URLs, or http on 127.0.0.1 / localhost / [::1]."},"client_name":{"type":"string","maxLength":120}}},"example":{"redirect_uris":["https://example.com/oauth/callback"],"client_name":"My agent"}}}},"responses":{"201":{"description":"Registered client.","content":{"application/json":{"schema":{"type":"object","required":["client_id","redirect_uris","token_endpoint_auth_method"],"properties":{"client_id":{"type":"string"},"client_id_issued_at":{"type":"integer"},"redirect_uris":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","const":"none"},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"client_name":{"type":"string"}}}}}},"400":{"description":"invalid_client_metadata or invalid_redirect_uri.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/mcp-oauth/authorize":{"get":{"operationId":"authorize","tags":["oauth"],"summary":"Authorization endpoint (consent page — open it in the user's browser)","description":"Renders Ebnii's consent screen; the signed-in owner approves and is redirected to `redirect_uri` with `code` and `state`. PKCE S256 is mandatory; `resource` must be the account MCP URL.","security":[],"parameters":[{"name":"response_type","in":"query","required":true,"schema":{"type":"string","const":"code"}},{"name":"client_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"redirect_uri","in":"query","required":true,"schema":{"type":"string","format":"uri"}},{"name":"code_challenge","in":"query","required":true,"schema":{"type":"string"}},{"name":"code_challenge_method","in":"query","required":true,"schema":{"type":"string","const":"S256"}},{"name":"resource","in":"query","required":true,"schema":{"type":"string","format":"uri","const":"https://ebnii.com/api/mcp"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string"},"description":"Space-separated: sites:read sites:write. Omit for everything the account allows."},{"name":"state","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Consent page (HTML).","content":{"text/html":{"schema":{"type":"string"}}}},"302":{"description":"Redirect back to `redirect_uri` with `code` and `state`, or with `error`."}}}},"/api/mcp-oauth/token":{"post":{"operationId":"exchangeToken","tags":["oauth"],"summary":"Token endpoint — exchange an authorization code or refresh token","security":[],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","client_id"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string"},"code":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"code_verifier":{"type":"string","minLength":43,"maxLength":128},"resource":{"type":"string","format":"uri"},"refresh_token":{"type":"string"}}}}}},"responses":{"200":{"description":"Access token (1 hour) and refresh token (30 days). `scope` is what the account granted.","content":{"application/json":{"schema":{"type":"object","required":["access_token","token_type","expires_in","scope"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string","const":"Bearer"},"expires_in":{"type":"integer","const":3600},"refresh_token":{"type":"string"},"scope":{"type":"string","description":"e.g. \"sites:read sites:write\""}}}}}},"400":{"description":"invalid_request / invalid_grant / invalid_client / invalid_target / unsupported_grant_type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","tags":["discovery"],"summary":"This document","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","tags":["discovery"],"summary":"Curated site index for AI agents (llmstxt.org), with when-to-use guidance","security":[],"responses":{"200":{"description":"Markdown.","content":{"text/markdown":{"schema":{"type":"string"}}}}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.1 authorization code + PKCE (S256). Register a client first (POST /api/mcp-oauth/register), then send the user to the authorize URL with `resource=https://ebnii.com/api/mcp`. Public clients only — no client secret.","flows":{"authorizationCode":{"authorizationUrl":"https://ebnii.com/mcp-oauth/authorize","tokenUrl":"https://ebnii.com/api/mcp-oauth/token","refreshUrl":"https://ebnii.com/api/mcp-oauth/token","scopes":{"sites:read":"List the account's websites, read a site's pages and source files, and see the plan and remaining credits.","sites:write":"Create websites, send build instructions to Ebnii's agent, check build status and publish sites live. Spends the account's credits."}}},"x-pkce-required":"S256","x-dynamic-client-registration":"https://ebnii.com/api/mcp-oauth/register","x-resource-indicator":"https://ebnii.com/api/mcp","x-legacy-scope":"mcp"},"bearer":{"type":"http","scheme":"bearer","bearerFormat":"Ebnii MCP access token","description":"The access token from the token endpoint, as `Authorization: Bearer …`."}},"schemas":{"ApiError":{"type":"object","description":"Error body of every non-JSON-RPC API response.","required":["error"],"properties":{"error":{"type":"object","required":["code","message","status","docs"],"properties":{"code":{"type":"string","description":"Stable machine-readable code, e.g. not_found.","examples":["not_found"]},"message":{"type":"string"},"hint":{"type":"string","description":"What to do instead."},"docs":{"type":"string","format":"uri"},"status":{"type":"integer"}}}}},"JsonRpcError":{"type":"object","required":["jsonrpc","id","error"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","description":"-32700 parse error · -32600 invalid request · -32601 method not found · -32602 invalid params · -32001 authentication required"},"message":{"type":"string"},"data":{}}}}},"JsonRpcResult":{"type":"object","required":["jsonrpc","id","result"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"result":{"type":"object","additionalProperties":true}}},"JsonRpcResponse":{"oneOf":[{"$ref":"#/components/schemas/JsonRpcResult"},{"$ref":"#/components/schemas/JsonRpcError"}]},"ToolResult":{"type":"object","description":"MCP tools/call result. `structuredContent` mirrors the text block as JSON when the tool returns data.","required":["content"],"properties":{"content":{"type":"array","items":{"type":"object","required":["type","text"],"properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"}}}},"structuredContent":{"description":"Parsed JSON of the text block, when the result is data."},"isError":{"type":"boolean","description":"true when the tool refused or failed; `content[0].text` says why."}}},"Initialize":{"type":"object","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"initialize"},"params":{"type":"object","required":["protocolVersion","capabilities","clientInfo"],"properties":{"protocolVersion":{"type":"string","enum":["2025-11-25","2025-06-18","2025-03-26"],"description":"MCP protocol version; the newest supported is first."},"capabilities":{"type":"object","additionalProperties":true},"clientInfo":{"type":"object","required":["name","version"],"properties":{"name":{"type":"string"},"version":{"type":"string"}}}}}}},"ListTools":{"type":"object","required":["jsonrpc","id","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/list"},"params":{"type":"object"}}},"Ping":{"type":"object","required":["jsonrpc","id","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"ping"}}},"ListSitesArguments":{"type":"object","properties":{"limit":{"type":"integer","description":"Max sites to return, 1–100 (default 50)."}},"additionalProperties":false,"description":"List every website on this Ebnii account, newest first: id, name, address, whether it is published, and when it last changed. Start here — every other tool takes a site_id from this list."},"CallListSites":{"type":"object","title":"tools/call → list_sites","description":"List every website on this Ebnii account, newest first: id, name, address, whether it is published, and when it last changed. Start here — every other tool takes a site_id from this list.\n\nRequires scope `sites:read`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"list_sites"},"arguments":{"$ref":"#/components/schemas/ListSitesArguments"}}}},"x-required-scope":"sites:read"},"GetSiteArguments":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false,"description":"Full detail for one website: its pages, preview and live addresses, whether it has changes not yet published, and any outstanding build warnings (for example a contact form that does not deliver anywhere). Read this before suggesting changes."},"CallGetSite":{"type":"object","title":"tools/call → get_site","description":"Full detail for one website: its pages, preview and live addresses, whether it has changes not yet published, and any outstanding build warnings (for example a contact form that does not deliver anywhere). Read this before suggesting changes.\n\nRequires scope `sites:read`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"get_site"},"arguments":{"$ref":"#/components/schemas/GetSiteArguments"}}}},"x-required-scope":"sites:read"},"ReadFileArguments":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."},"path":{"type":"string","description":"File path exactly as listed by get_site, e.g. src/pages/Home.tsx"}},"required":["site_id","path"],"additionalProperties":false,"description":"Read one source file of a website. Use get_site first to see which files exist. Read-only: to CHANGE a site, describe the change to build_site rather than editing code."},"CallReadFile":{"type":"object","title":"tools/call → read_file","description":"Read one source file of a website. Use get_site first to see which files exist. Read-only: to CHANGE a site, describe the change to build_site rather than editing code.\n\nRequires scope `sites:read`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"read_file"},"arguments":{"$ref":"#/components/schemas/ReadFileArguments"}}}},"x-required-scope":"sites:read"},"GetAccountArguments":{"type":"object","properties":{},"additionalProperties":false,"description":"The person's plan and remaining credit balance. Check this before starting a build so you can tell them what it will cost and whether they can afford it."},"CallGetAccount":{"type":"object","title":"tools/call → get_account","description":"The person's plan and remaining credit balance. Check this before starting a build so you can tell them what it will cost and whether they can afford it.\n\nRequires scope `sites:read`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"get_account"},"arguments":{"$ref":"#/components/schemas/GetAccountArguments"}}}},"x-required-scope":"sites:read"},"CreateSiteArguments":{"type":"object","properties":{"prompt":{"type":"string","description":"What to build, in plain language. Arabic is preferred since the site will be Arabic. Include the business type, the sections wanted, and any real details (phone, address, hours) so the agent does not invent them."},"name":{"type":"string","description":"Optional name for the project. Ebnii picks one if omitted."}},"required":["prompt"],"additionalProperties":false,"description":"Create a NEW website from a plain-language description and start building it. Describe the business and what the site needs — Ebnii's agent designs and writes it, in Arabic, right-to-left. Returns a build id immediately; poll get_build_status. Costs credits."},"CallCreateSite":{"type":"object","title":"tools/call → create_site","description":"Create a NEW website from a plain-language description and start building it. Describe the business and what the site needs — Ebnii's agent designs and writes it, in Arabic, right-to-left. Returns a build id immediately; poll get_build_status. Costs credits.\n\nRequires scope `sites:write`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"create_site"},"arguments":{"$ref":"#/components/schemas/CreateSiteArguments"}}}},"x-required-scope":"sites:write"},"BuildSiteArguments":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."},"instruction":{"type":"string","description":"What to change, in plain language. Arabic preferred. Be specific about the outcome wanted."}},"required":["site_id","instruction"],"additionalProperties":false,"description":"Send a build instruction to an existing website's Ebnii agent — for example 'أضف قسم آراء العملاء' or 'اربط نموذج التواصل بواتساب'. This is how a site is CHANGED; describe the outcome, not the code. Returns a build id immediately and keeps running server-side; poll get_build_status. Costs credits."},"CallBuildSite":{"type":"object","title":"tools/call → build_site","description":"Send a build instruction to an existing website's Ebnii agent — for example 'أضف قسم آراء العملاء' or 'اربط نموذج التواصل بواتساب'. This is how a site is CHANGED; describe the outcome, not the code. Returns a build id immediately and keeps running server-side; poll get_build_status. Costs credits.\n\nRequires scope `sites:write`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"build_site"},"arguments":{"$ref":"#/components/schemas/BuildSiteArguments"}}}},"x-required-scope":"sites:write"},"GetBuildStatusArguments":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false,"description":"Whether a build is still running, finished, or failed — with what the agent changed and what it cost. Poll this after create_site or build_site. Builds usually take 2–10 minutes."},"CallGetBuildStatus":{"type":"object","title":"tools/call → get_build_status","description":"Whether a build is still running, finished, or failed — with what the agent changed and what it cost. Poll this after create_site or build_site. Builds usually take 2–10 minutes.\n\nRequires scope `sites:write`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"get_build_status"},"arguments":{"$ref":"#/components/schemas/GetBuildStatusArguments"}}}},"x-required-scope":"sites:write"},"PublishSiteArguments":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false,"description":"Put a website online at its public address and return the link. Runs Ebnii's security check first and refuses with a reason if it fails. Ask the person before publishing — this makes the site visible to everyone."},"CallPublishSite":{"type":"object","title":"tools/call → publish_site","description":"Put a website online at its public address and return the link. Runs Ebnii's security check first and refuses with a reason if it fails. Ask the person before publishing — this makes the site visible to everyone.\n\nRequires scope `sites:write`.","required":["jsonrpc","id","method","params"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}],"description":"Request id, echoed back in the response."},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","required":["name","arguments"],"properties":{"name":{"type":"string","const":"publish_site"},"arguments":{"$ref":"#/components/schemas/PublishSiteArguments"}}}},"x-required-scope":"sites:write"},"McpRequest":{"oneOf":[{"$ref":"#/components/schemas/Initialize"},{"$ref":"#/components/schemas/ListTools"},{"$ref":"#/components/schemas/Ping"},{"$ref":"#/components/schemas/CallListSites"},{"$ref":"#/components/schemas/CallGetSite"},{"$ref":"#/components/schemas/CallReadFile"},{"$ref":"#/components/schemas/CallGetAccount"},{"$ref":"#/components/schemas/CallCreateSite"},{"$ref":"#/components/schemas/CallBuildSite"},{"$ref":"#/components/schemas/CallGetBuildStatus"},{"$ref":"#/components/schemas/CallPublishSite"}],"discriminator":{"propertyName":"method"}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}},"x-ebnii-tools":[{"name":"list_sites","description":"List every website on this Ebnii account, newest first: id, name, address, whether it is published, and when it last changed. Start here — every other tool takes a site_id from this list.","parameters":{"type":"object","properties":{"limit":{"type":"integer","description":"Max sites to return, 1–100 (default 50)."}},"additionalProperties":false},"x-required-scope":"sites:read"},{"name":"get_site","description":"Full detail for one website: its pages, preview and live addresses, whether it has changes not yet published, and any outstanding build warnings (for example a contact form that does not deliver anywhere). Read this before suggesting changes.","parameters":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false},"x-required-scope":"sites:read"},{"name":"read_file","description":"Read one source file of a website. Use get_site first to see which files exist. Read-only: to CHANGE a site, describe the change to build_site rather than editing code.","parameters":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."},"path":{"type":"string","description":"File path exactly as listed by get_site, e.g. src/pages/Home.tsx"}},"required":["site_id","path"],"additionalProperties":false},"x-required-scope":"sites:read"},{"name":"get_account","description":"The person's plan and remaining credit balance. Check this before starting a build so you can tell them what it will cost and whether they can afford it.","parameters":{"type":"object","properties":{},"additionalProperties":false},"x-required-scope":"sites:read"},{"name":"create_site","description":"Create a NEW website from a plain-language description and start building it. Describe the business and what the site needs — Ebnii's agent designs and writes it, in Arabic, right-to-left. Returns a build id immediately; poll get_build_status. Costs credits.","parameters":{"type":"object","properties":{"prompt":{"type":"string","description":"What to build, in plain language. Arabic is preferred since the site will be Arabic. Include the business type, the sections wanted, and any real details (phone, address, hours) so the agent does not invent them."},"name":{"type":"string","description":"Optional name for the project. Ebnii picks one if omitted."}},"required":["prompt"],"additionalProperties":false},"x-required-scope":"sites:write"},{"name":"build_site","description":"Send a build instruction to an existing website's Ebnii agent — for example 'أضف قسم آراء العملاء' or 'اربط نموذج التواصل بواتساب'. This is how a site is CHANGED; describe the outcome, not the code. Returns a build id immediately and keeps running server-side; poll get_build_status. Costs credits.","parameters":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."},"instruction":{"type":"string","description":"What to change, in plain language. Arabic preferred. Be specific about the outcome wanted."}},"required":["site_id","instruction"],"additionalProperties":false},"x-required-scope":"sites:write"},{"name":"get_build_status","description":"Whether a build is still running, finished, or failed — with what the agent changed and what it cost. Poll this after create_site or build_site. Builds usually take 2–10 minutes.","parameters":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false},"x-required-scope":"sites:write"},{"name":"publish_site","description":"Put a website online at its public address and return the link. Runs Ebnii's security check first and refuses with a reason if it fails. Ask the person before publishing — this makes the site visible to everyone.","parameters":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id from list_sites."}},"required":["site_id"],"additionalProperties":false},"x-required-scope":"sites:write"}],"x-ebnii-access":"private-beta"}