{"name":"io.github.dappros/ethora-mcp-server","slug":"dappros-ethora-mcp-server","title":null,"description":"Ethora chat platform MCP: apps, users, rooms, AI agents, chat widgets. Hosted or stdio.","url":"https://mcp.market/server/dappros-ethora-mcp-server","grade":"A","score":99,"certified":false,"status":"active","category":"other","tags":[],"transport":"mixed","callable_via_gateway":true,"default_price_micros":0,"repository":"https://github.com/dappros/ethora-mcp-server","website":"https://ethora.com/ai-sdk/mcp-server/","version":"26.9.3","remotes":[{"type":"streamable-http","url":"https://mcp.chat.ethora.com/mcp/oauth"},{"type":"streamable-http","url":"https://mcp.chat.ethora.com/mcp"}],"packages":[{"registryType":"npm","identifier":"@ethora/mcp-server","version":"26.9.3","transport":{"type":"stdio"},"environmentVariables":[{"description":"Full Ethora API URL. Defaults to https://api.chat.ethora.com/v1 if neither ETHORA_API_URL nor ETHORA_BASE_URL is set.","format":"string","name":"ETHORA_API_URL"},{"description":"Base host URL (e.g. https://api.chat.ethora.com). The server appends /v1 automatically. Use ETHORA_API_URL instead if you need a non-/v1 path.","format":"string","name":"ETHORA_BASE_URL"},{"description":"App JWT used for the user-auth bootstrap flow (login/register). Usually starts with 'JWT '. Optional; can also be set at runtime via the ethora-configure tool.","format":"string","isSecret":true,"name":"ETHORA_APP_JWT"},{"description":"B2B server token used for tenant-actor x-custom-token auth (JWT with type=server). Required for B2B / app provisioning flows. Optional; can also be set at runtime.","format":"string","isSecret":true,"name":"ETHORA_B2B_TOKEN"},{"description":"Set to 'true' to expose destructive tools (app deletion, wallet transfers, bulk delete). Disabled by default.","format":"string","name":"ETHORA_MCP_ENABLE_DANGEROUS_TOOLS"}]}],"tools":[{"name":"ethora-agent-invite-to-chat","description":"Invite an Agent into a chat room. Multiple agents can coexist in the same room — call this tool once per agent and they will all appear as members able to converse. Lazily creates a per-App BotInstance (an Ethora user with isBot:true) if one does not already exist for (agent, app). Spawns the XMPP client live; no ai-service restart required. For the full multi-agent recipe see the `ethora-agents-quickstart` prompt.\nRequires: an agent (`ethora-agents-create-v2`) and a room (`ethora-app-create-chat`) in the selected app.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1,"description":"Either Mongo _id (24 hex chars) or EOA-style address."},"appId":{"type":"string","description":"Required in B2B mode unless already selected via ethora-app-select."},"chatId":{"type":"string","description":"Mongo Chat _id (preferred when invoking from admin)."},"chatJid":{"type":"string","description":"Room JID `${appId}_${chatId}` (optionally with `@conference.<host>`), exactly the `jid` returned by `ethora-app-create-chat`. Preferred over `chatId`."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agent-set-visibility","description":"Set an Agent's visibility (private | unlisted | public). Public agents can be invited cross-app by anyone who knows the address.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"visibility":{"type":"string","enum":["private","unlisted","public"]},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["visibility"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agent-soul-append","description":"Append a fragment to an Agent's SOUL.MD (its evolving identity / private notes). Operator-driven; the Agent itself can also self-edit via the same endpoint when called by ai-service.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"append":{"type":"string","minLength":1},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["append"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agent-soul-set","description":"Replace an Agent's SOUL.MD with the provided markdown. Operator-driven; alternative to -append.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"soulMd":{"type":"string","minLength":0,"description":"Replace SOUL.MD contents. Pass empty string to clear."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["soulMd"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-activate-v2","description":"Make an agent the app's ACTIVE widget bot: sets `App.defaultBotInstanceId` (and `botStatus: on`), which is what `POST /v2/widget/sessions` uses to decide who answers website visitors. Required before an embedded widget can answer on an API-created app. Preconditions: the agent was invited into a room of this app with `ethora-agent-invite-to-chat` (that creates its bot instance). Works in user auth (app update route); falls back to the app-token `/v2/agents/:id/activate` route when an appToken is stored.\nRequires: an agent already invited into a room of the selected app (`ethora-agents-create-v2` -> `ethora-app-create-chat` -> `ethora-agent-invite-to-chat`); the invite creates the bot instance this tool binds as the app's default responder.\nAuth: user session (owner of the app). Errors: 404 no bot instance for this agent in the app (invite first); 403 not the app owner. Related: `ethora-widget-embed-snippet` next, `ethora-bot-instances-list` to inspect.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"description":"Id (or address) of the agent to activate. Get it from `ethora-agents-list-v2` / `ethora-agents-create-v2`."},"chatJid":{"type":"string","description":"Room JID `${appId}_${chatId}` (with or without `@conference...`) that becomes the widget chat. Required for API-created apps; omit only for dashboard-created apps that already have an AI Widget chat bound."},"appId":{"type":"string","description":"App to activate the agent for. Defaults to the app from `ethora-app-select`."},"agentIdOrAddress":{"type":"string","minLength":1,"description":"Alias for `agentId` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-clone-v2","description":"Duplicate an existing saved agent into a new agent, optionally overriding its name/slug/summary (`POST /v2/agents/:agentId/clone`). The source agent is unchanged; the new clone becomes the session's current agent context.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.\nAuth: app-token mode (after `ethora-app-select` + `ethora-auth-use-app`). Errors: 401/403 wrong auth; 404 source `agentId` not found; 422 overridden `slug` collides.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"description":"Id of the source agent to clone. Get it from `ethora-agents-list-v2`."},"name":{"type":"string","description":"Name for the clone. Omit to inherit the source agent's name."},"slug":{"type":"string","description":"URL-safe unique slug for the clone. Omit to let the server derive one; must not collide with an existing agent."},"summary":{"type":"string","description":"Summary for the clone. Omit to inherit the source agent's summary."},"agentIdOrAddress":{"type":"string","minLength":1,"description":"Alias for `agentId` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-create-v2","description":"Create a reusable AI agent (POST /v2/apps/:appId/agents). Works in user auth mode (the normal hosted mode) or B2B mode; app-token mode is not accepted by the backend. Each agent is a persona — name, avatar, system prompt, LLM config, plus response-gate settings (responseMode, cooldownSec) that control when it speaks in a room. For multi-agent scenarios (two or more personas conversing in one chat) create each one separately, then `ethora-agent-invite-to-chat` them into the same room. See the `ethora-agents-quickstart` prompt for the end-to-end recipe.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`; the agent is owned by that app.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the agent belongs to (`POST /v2/apps/:appId/agents`). Defaults to the app selected with `ethora-app-select`. Pass it when you just created an app so the agent lands there rather than in the token's own app."},"name":{"type":"string","description":"Short display name. For multi-agent scenarios, prefer single-word names (e.g. 'Hannibal', 'Varro') — the @-mention matcher uses the exact display name with word-boundary matching."},"slug":{"type":"string","description":"URL-safe slug (auto-generated from name if omitted)."},"summary":{"type":"string","description":"Short bio shown in agent lists."},"prompt":{"type":"string","description":"System prompt — the agent's persona, role, style of speech, and behaviour rules. For multi-agent scenarios, instruct the agent to end every message with an @-mention of who speaks next; that's how turn-handoff works through the response gate."},"greetingMessage":{"type":"string","description":"Optional message the agent posts when it first joins a room."},"trigger":{"type":"string","enum":["any_message","/bot"],"description":"Legacy trigger field. Prefer the newer `responseMode` for new agents."},"responseMode":{"type":"string","enum":["always","mentioned","smart","probability"],"description":"When the agent decides to reply. 'always' = every room message; 'mentioned' = only when @-mentioned by display name or via /bot (recommended for multi-agent turn-taking); 'smart' = a mini LLM gate decides per-message; 'probability' = coin-flip per message using `responseProbability`."},"responseProbability":{"type":"number","minimum":0,"maximum":1,"description":"If responseMode='probability', odds (0-1) of replying to each message. Damped 0.6x for bot-to-bot messages."},"cooldownSec":{"type":"integer","minimum":0,"description":"Minimum seconds between this agent's replies in a given room. Damped 2x for bot-to-bot. Set 0 for quick turn-taking in multi-agent scenarios."},"botDisplayName":{"type":"string","description":"Display name used inside the chat UI. Defaults to `name`."},"botAvatarUrl":{"type":"string","description":"URL of the avatar image shown next to bot messages."},"isRAG":{"type":"boolean","description":"Enable retrieval-augmented generation from indexed sources."},"ragTags":{"type":"array","items":{"type":"string","minLength":1},"description":"Optional RAG tag filter — restrict retrieval to sources matching these tags."},"llmProvider":{"type":"string","description":"LLM provider override (e.g. 'openai'). Defaults to the app's configured provider."},"llmModel":{"type":"string","description":"LLM model override (e.g. 'gpt-4o-mini')."},"visibility":{"type":"string","enum":["private","public"],"description":"'private' (only invitable inside the owning app) or 'public' (cross-app invitable)."},"isPublished":{"type":"boolean","description":"Convenience alias for setting visibility='public'."},"categories":{"type":"array","items":{"type":"string","minLength":1},"description":"Free-form category tags for agent directory listings."},"flowsYaml":{"type":"string","description":"Deterministic scripted conversation for this agent, as YAML. Drives the agent through a fixed sequence (opening menu, appointment request, intake questionnaire, survey) instead of leaving every turn to the model. Compiled and validated server-side on save: an invalid script is rejected with code `FLOWS_INVALID` and per-line details, and nothing is stored. A flow named `start` is reserved and fires when a conversation opens. Buttons are authored here (`buttons:` on a `say` step, or `options:` on an `ask` step). Call `fetch` with id `doc:agent-flows` for the full authoring format before writing one. Pass an empty string to clear the script."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-delete-v2","description":"Delete an Agent (DELETE /v2/agents/:idOrAddress). Destructive — removes the saved Agent and its BotInstances. Gated behind ETHORA_MCP_ENABLE_DANGEROUS_TOOLS.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1,"description":"Mongo _id (24 hex chars) or EOA-style address."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-export-v2","description":"Export an Agent as a portable bundle (GET /v2/agents/:idOrAddress/export). format=json returns the bundle object directly; feed it back to `ethora-agents-import-v2` to recreate the Agent in another App/tenant.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"format":{"type":"string","enum":["json","zip"],"description":"Defaults to json. Prefer json for MCP round-trips."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-get-v2","description":"Fetch one reusable saved agent's full config by id (`GET /v2/agents/:agentId`) — prompt, LLM, RAG settings, visibility. Also sets this agent as the session's current agent context (no server-side change).\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.\nAuth: app-token mode (after `ethora-app-select` + `ethora-auth-use-app`). Errors: 401/403 wrong auth; 404 `agentId` not an agent of the current app. Related: get ids from `ethora-agents-list-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"description":"Id of the saved agent to fetch. Get it from `ethora-agents-list-v2`."},"agentIdOrAddress":{"type":"string","minLength":1,"description":"Alias for `agentId` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-import-v2","description":"Import an Agent from a bundle produced by `ethora-agents-export-v2` (POST /v2/agents/import, application/json body IS the bundle). Optionally scope the new Agent to an owning App via ownerAppId.\nRequires: a bundle produced by `ethora-agents-export-v2` with format json.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"bundle":{"type":"object","properties":{"schemaVersion":{"type":"string","minLength":1,"description":"Bundle schema version, e.g. `ethora.agent.bundle.v1`. Every export carries one."},"kind":{"type":"string","description":"Bundle kind: `agent` for agent exports."},"agent":{"type":"object","additionalProperties":{},"description":"The agent definition carried by the bundle: displayName, prompt, llmProvider, llmModel and so on."}},"required":["schemaVersion","agent"],"additionalProperties":true,"description":"The bundle object returned by `ethora-agents-export-v2` with format=json. Pass it through unchanged."},"ownerAppId":{"type":"string","description":"Owning App for the imported Agent (defaults server-side)."}},"required":["bundle"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-list-v2","description":"List the reusable saved agents of an app (`GET /v2/apps/:appId/agents`, or `GET /v2/agents` for the token's own app) — a saved agent is a reusable bot definition. Returns an array of agents with ids, names, and config.\nAuth: app-token mode (after `ethora-app-select` + `ethora-auth-use-app`). Errors: 401/403 not in app-token mode or invalid appToken; empty list if the app has no saved agents.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId whose agents to list (`GET /v2/apps/:appId/agents`). Defaults to the app selected with `ethora-app-select`; without either, lists the agents of the token's own app."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-agents-update-v2","description":"Update a saved AI agent (PUT /v2/agents/:agentId). All fields are optional — only what you pass is updated. Common uses: tune the system `prompt` after a test run, switch `responseMode` to control turn-taking in multi-agent rooms, or adjust `cooldownSec`. See `ethora-agents-quickstart` prompt for the end-to-end recipe.\nRequires: an agent id or address from `ethora-agents-list-v2` or `ethora-agents-create-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"description":"Mongo _id (24 hex chars) of the agent to update."},"name":{"type":"string","description":"New display name. For multi-agent scenarios prefer single-word names — the @-mention matcher uses exact display-name match with word-boundary."},"slug":{"type":"string","description":"URL-safe slug."},"summary":{"type":"string","description":"Short bio."},"prompt":{"type":"string","description":"Updated system prompt (persona + behaviour). For multi-agent rooms instruct the agent to end every message with an @-mention of the next speaker — that's how turn-handoff works through the response gate."},"greetingMessage":{"type":"string","description":"Message the agent posts when it first joins a new room."},"trigger":{"type":"string","enum":["any_message","/bot"],"description":"Legacy trigger field. Prefer `responseMode`."},"responseMode":{"type":"string","enum":["always","mentioned","smart","probability"],"description":"When the agent replies. 'always' = every message; 'mentioned' = only @-mention or /bot (best for multi-agent turn-taking); 'smart' = mini-LLM decides; 'probability' = coin-flip using `responseProbability`."},"responseProbability":{"type":"number","minimum":0,"maximum":1,"description":"If responseMode='probability', odds (0-1) of replying. Damped 0.6x for bot-to-bot."},"cooldownSec":{"type":"integer","minimum":0,"description":"Minimum seconds between this agent's replies in a given room. Damped 2x for bot-to-bot. Set 0 for quick turn-taking."},"botDisplayName":{"type":"string","description":"Display name in chat UI."},"botAvatarUrl":{"type":"string","description":"Avatar image URL."},"isRAG":{"type":"boolean","description":"Enable RAG retrieval."},"ragTags":{"type":"array","items":{"type":"string","minLength":1},"description":"RAG tag filter."},"llmProvider":{"type":"string","description":"LLM provider override."},"llmModel":{"type":"string","description":"LLM model override."},"visibility":{"type":"string","enum":["private","public"],"description":"'private' or 'public' (cross-app invitable)."},"isPublished":{"type":"boolean","description":"Convenience alias for visibility='public'."},"categories":{"type":"array","items":{"type":"string","minLength":1},"description":"Category tags for directory listings."},"flowsYaml":{"type":"string","description":"Deterministic scripted conversation for this agent, as YAML. Drives the agent through a fixed sequence (opening menu, appointment request, intake questionnaire, survey) instead of leaving every turn to the model. Compiled and validated server-side on save: an invalid script is rejected with code `FLOWS_INVALID` and per-line details, and nothing is stored. A flow named `start` is reserved and fires when a conversation opens. Buttons are authored here (`buttons:` on a `say` step, or `options:` on an `ask` step). Call `fetch` with id `doc:agent-flows` for the full authoring format before writing one. Pass an empty string to clear the script."},"agentIdOrAddress":{"type":"string","minLength":1,"description":"Alias for `agentId` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-api-key-create","description":"Mint a long-lived, revocable API key for the currently logged-in user. The key is a user token: send it as `Authorization: Bearer <key>` to the hosted MCP endpoint (or set it in the stdio client) to skip `ethora-user-login`. Shown once.\nAuth: user auth (logged in). Errors: 401 not logged in; 404 on backends without API key support.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"name":{"type":"string","description":"Label to recognise the key later (e.g. `ci-runner`, `claude-desktop`)."},"ttlDays":{"type":"integer","minimum":1,"maximum":365,"description":"Lifetime in days. Server default applies when omitted."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-api-key-list","description":"List the current user's API keys (id, name, createdAt, expiresAt). Token values are never returned.\nAuth: user auth.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-api-key-revoke","description":"Revoke one of the current user's API keys by id. Clients using that key stop working immediately.\nRequires: a key id from `ethora-api-key-list` or `ethora-api-key-create`.\nAuth: user auth. Errors: 404 unknown id.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"id":{"type":"string","description":"API key id as returned by `ethora-api-key-create` / `ethora-api-key-list`."}},"required":["id"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-create","description":"Create a new Ethora app (tenant) owned by the currently logged-in user. Allocates a fresh 24-char hex `appId` and sets the caller as owner; counts against the owner's plan limit. Returns the new app object including `appId`. The returned app has its credential fields redacted; call `ethora-app-credentials { appId, confirm: true }` when a snippet needs the appToken.\nAuth: user-auth mode, active session (`ethora-user-login` first). Errors: 401 not logged in; 402/403 plan limit reached; 422 invalid `displayName`. Related: server-side provisioning uses `ethora-b2b-app-create`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"displayName":{"type":"string","description":"Human-readable app name shown to users in the app picker and on the public landing page. Not required to be unique across accounts."}},"required":["displayName"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-create-chat","description":"Create a new chat room (MUC room) inside an app the caller owns. Every room created this way is listed in the app's rooms (`defaultRooms`); `pinned: true` additionally makes new users auto-join it (existing users are not added), `pinned: false` (default) keeps it opt-in. Returns the new room object including its JID.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: user-auth mode, active session; the caller must own the app. Errors: 401 not logged in; 403 not owner; 404 unknown `appId`; 422 invalid `title`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex ObjectId of the app to create the chat room in. Optional — defaults to the app most recently passed to `ethora-app-select`."},"title":{"type":"string","description":"Display name for the new chat room. Visible to all members; not required to be unique within the app."},"pinned":{"type":"boolean","default":false,"description":"If `true`, the room is added to the app's default rooms list — every new user of the app auto-joins it. If `false`, the room exists but users must be added explicitly."}},"required":["title"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-credentials","description":"Reveal the appToken of an app the caller owns, for a chat-component snippet or a widget config. Every other tool redacts appToken, appSecret and tenantSecret from its results because tool output enters the model's context and client logs; this tool returns exactly { appId, appToken, note } and nothing else. The App Secret is never returned over MCP: it is shown only in the web dashboard (app settings, API tab), and backend integrations should use revocable server tokens from that tab instead of the secret.\nRequires: an app you own (`ethora-app-create` or `ethora-app-list`) and `confirm: true`.\nAuth: user auth (app owner). Errors: 401 not logged in; 403 not the owner; 404 unknown `appId`; validation error unless `confirm` is `true`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex app id. Defaults to the app selected with `ethora-app-select`."},"confirm":{"type":"boolean","const":true,"description":"Must be `true`: acknowledges that the token is a credential and will appear in this conversation."}},"required":["confirm"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-delete","description":"Permanently delete an Ethora app the caller owns — removes its chat rooms, files, indexed RAG sources, and bot config; end users are immediately signed out. Irreversible; gated behind ETHORA_MCP_ENABLE_DANGEROUS_TOOLS=true.\nRequires: an `appId` from `ethora-app-list` or `ethora-app-create`.\nAuth: user-auth mode, active session; the caller must own the app. Errors: 401 not logged in; 403 not owner; 404 unknown `appId`. Related: to just deactivate the bot use `ethora-app-update` with `botStatus: \"off\"`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex MongoDB ObjectId of the app to delete. Obtain from `ethora-app-list` or the response of `ethora-app-create`."}},"required":["appId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-delete-chat","description":"Permanently delete a chat room from an app the caller owns — removes the MUC room, its message archive, and all member affiliations. Irreversible; gated behind ETHORA_MCP_ENABLE_DANGEROUS_TOOLS=true.\nRequires: a room from `ethora-app-get-default-rooms` or `ethora-app-create-chat`.\nAuth: user-auth mode, active session; the caller must own the app. Errors: 401 not logged in; 403 not owner; 404 `chatJid` not a room in the app.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex ObjectId of the app the chat room belongs to. Optional — defaults to the app most recently passed to `ethora-app-select`."},"chatJid":{"type":"string","description":"Room JID (XMPP address) of the chat to delete, e.g. `<roomId>@conference.<host>`. Obtain from `ethora-app-get-default-rooms` or the response of `ethora-app-create-chat`."}},"required":["chatJid"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-export-v2","description":"Export an App as a portable bundle (GET /v2/apps/:appId/export). format=json returns the bundle object directly. Use `include` to select sections (e.g. 'chats,users,sources,botInstances'). Feed the result to `ethora-app-import-v2`.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"Required in B2B mode unless already selected via ethora-app-select."},"format":{"type":"string","enum":["json","zip"]},"include":{"type":"string","description":"Comma-separated sections to include, e.g. 'chats,users,sources,botInstances'."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-get-default-rooms","description":"List the default chat rooms (MUC rooms) of the currently selected Ethora app — every new user auto-joins these. Returns rooms with their JIDs and titles.\nAuth: user-auth mode, active session; operates against the app set via `ethora-app-select`. Errors: 400 no app currently selected; 401 not logged in. Related: `ethora-app-get-default-rooms-with-app-id` to pass `appId` explicitly.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-app-get-default-rooms-with-app-id","description":"List the default chat rooms of a specific Ethora app, passed via `appId` (or the currently selected app). Returns rooms with their JIDs and titles.\nRequires: an `appId` from `ethora-app-list` or `ethora-app-create`.\nAuth: user-auth mode, active session; the caller needs read access (ownership or room membership). Errors: 400 no `appId` and none selected; 401 not logged in; 403 no read access; 404 unknown `appId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex ObjectId of the app whose default rooms you want to read. Optional — defaults to the app most recently passed to `ethora-app-select`."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-import-v2","description":"Import an App from a bundle produced by `ethora-app-export-v2` (POST /v2/apps/import, application/json body IS the bundle). B2B / tenant-actor auth. domainNameOverride renames the imported App's domain.\nRequires: a bundle produced by `ethora-app-export-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"bundle":{"description":"The exported bundle object (the json export output)."},"domainNameOverride":{"type":"string","description":"Rename the imported App's domainName."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-list","description":"List all Ethora apps (tenants) owned by the currently logged-in user. Returns an array with `appId` (24-char hex), `displayName`, `domainName`, ownership and bot-status metadata. Credential fields (appSecret, tenantSecret, appToken, passwords) are redacted in the result; call `ethora-app-credentials { appId, confirm: true }` to reveal an app's appToken.\nAuth: user-auth mode, active session (`ethora-user-login` first). Errors: 401 not logged in; empty list if the user owns no apps. Related: feed `appId` into `ethora-app-update` / `ethora-app-select`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-app-select","description":"Set the current app context for this session so app-scoped tools can omit their `appId` argument. Stores `currentAppId` and, if given, `appToken` (which defaults the auth mode to app-token unless `authMode` overrides).\nAuth: none required to set the context. Errors: effectively none — a non-existent `appId` is not validated here; the first app-scoped API call surfaces the 404. Related: pairs with `ethora-auth-use-app`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex Ethora appId to set as the current context. Get it from `ethora-app-list`, `ethora-app-create`, or a B2B create/provision response."},"appToken":{"type":"string","description":"Per-app appToken to store alongside the appId. If provided, the active auth mode switches to app-token (unless `authMode` says otherwise). Secret."},"authMode":{"type":"string","enum":["app","user","b2b"],"description":"Auth mode to keep after selecting the app. Omit to let the mode default to app-token when an `appToken` is given, or stay unchanged otherwise."}},"required":["appId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-tokens-create-v2","description":"Mint a new app token for an app. The secret token value is returned exactly once and cannot be retrieved again — capture it immediately. Returns the new token including its one-time secret value and `tokenId`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode; 400 no `appId` and none selected; 404 unknown `appId`. Related: manage with `ethora-app-tokens-list-v2` / `-rotate-v2` / `-revoke-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to mint the token for. Optional — defaults to the app set via `ethora-app-select`."},"label":{"type":"string","description":"Human-readable label to identify this token later (e.g. `staging`, `ci`). Shown in `ethora-app-tokens-list-v2`."},"timeoutMs":{"type":"integer","minimum":500,"maximum":60000,"description":"HTTP timeout for this request, in milliseconds. Default 10000."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-tokens-list-v2","description":"List the app tokens issued for an app — metadata only (`tokenId`, label, created/rotated timestamps, status); the secret token values are never returned (only shown once at create/rotate time).\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode; 400 no `appId` and none selected; 404 unknown `appId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to list tokens for. Optional — defaults to the app set via `ethora-app-select`."},"timeoutMs":{"type":"integer","minimum":500,"maximum":60000,"description":"HTTP timeout for this request, in milliseconds. Default 10000."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-tokens-revoke-v2","description":"Permanently revoke an app token by `tokenId` — it stops working immediately; any client, SDK, or MCP session still using it gets auth failures. No replacement is issued.\nRequires: a token id from `ethora-app-tokens-list-v2`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode; 400 no `appId` and none selected; 404 unknown `appId`. Related: get `tokenId` from `ethora-app-tokens-list-v2`; `ethora-app-tokens-rotate-v2` for revoke-and-replace.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the token belongs to. Optional — defaults to the app set via `ethora-app-select`."},"tokenId":{"type":"string","minLength":1,"description":"Id of the token to revoke. Get it from `ethora-app-tokens-list-v2`."},"timeoutMs":{"type":"integer","minimum":500,"maximum":60000,"description":"HTTP timeout for this request, in milliseconds. Default 10000."}},"required":["tokenId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-tokens-rotate-v2","description":"Rotate an app token: revoke an existing token and issue a replacement in one step. The old `tokenId` is revoked immediately — anything using it stops working at once. The new secret value is returned exactly once — capture it immediately.\nRequires: a token id from `ethora-app-tokens-list-v2`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode; 400 no `appId` and none selected; 404 unknown `appId` or `tokenId`. Related: `ethora-app-tokens-revoke-v2` to revoke without a replacement.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the token belongs to. Optional — defaults to the app set via `ethora-app-select`."},"tokenId":{"type":"string","minLength":1,"description":"Id of the token to revoke and replace. Get it from `ethora-app-tokens-list-v2`."},"label":{"type":"string","description":"Label for the replacement token. Omit to inherit the old token's label."},"timeoutMs":{"type":"integer","minimum":500,"maximum":60000,"description":"HTTP timeout for this request, in milliseconds. Default 10000."}},"required":["tokenId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-app-update","description":"Update mutable fields on an app the caller owns (displayName, domainName, appTagline, primaryColor, botStatus). Partial update — omitted fields are left unchanged.\nRequires: an `appId` from `ethora-app-list` or `ethora-app-create`.\nAuth: user-auth mode, active session; the caller must own the app. Errors: 401 not logged in; 403 not owner; 404 unknown `appId`; 422 validation (e.g. `domainName` taken, `primaryColor` not `#RRGGBB`).","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex ObjectId of the app to update. Optional — defaults to the app most recently passed to `ethora-app-select`."},"displayName":{"type":"string","description":"New human-readable app name. Visible in the app picker and on the public landing page."},"domainName":{"type":"string","description":"Subdomain to host the web app at. Setting `abcd` makes the web app available at `abcd.ethora.com`. Must be unique across all Ethora apps; lower-case alphanumerics and dashes only."},"appTagline":{"type":"string","description":"Short tagline shown on the public app landing page."},"appDescription":{"type":"string","description":"Deprecated alias for `appTagline`, kept so older callers keep working. Prefer `appTagline`."},"primaryColor":{"type":"string","description":"Primary brand color in hex `#RRGGBB` format (e.g. `#F54927`). Used throughout the app UI."},"botStatus":{"type":"string","enum":["on","off"],"description":"`on` enables the AI bot for new conversations (requires a configured prompt — see `ethora-bot-update-v2`); `off` disables it. Does not change the bot's configured prompt or sources."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-auth-use-app","description":"Switch this session's active auth mode to app-token, so subsequent app-scoped calls authenticate with the configured `appToken`.\nAuth: requires an `appToken` to already be configured (via `ethora-configure`, ETHORA_APP_TOKEN env, or `ethora-app-select`). Errors: returns an error if no `appToken` is configured. Related: use after `ethora-app-select`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-auth-use-b2b","description":"Switch this session's active auth mode to B2B, so subsequent calls authenticate as a tenant actor via the `x-custom-token` header.\nAuth: requires a `b2bToken` (JWT with `type=server`) to already be configured (via `ethora-configure` or ETHORA_B2B_TOKEN env). Errors: returns an error if no `b2bToken` is configured. Related: server-side automation — pairs with `ethora-b2b-app-create`, `ethora-users-batch-create-v2`, `ethora-app-tokens-*-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-auth-use-user","description":"Switch this session's active auth mode to user-session, so subsequent calls authenticate as a logged-in Ethora user.\nAuth: the switch needs nothing, but user-auth tools only work once `ethora-user-login` stores a user token (login also needs a configured `appJwt`). Errors: none on the switch; downstream tools return 401 until login succeeds. Related: follow with `ethora-user-login`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-b2b-app-bootstrap-ai","description":"One-call B2B orchestrator: create an app, set it as the current context, index RAG sources, then configure and enable its AI bot. Source ingest and bot activation are best-effort (the app is still created if a later step fails); crawl/embedding continues asynchronously after this returns. Returns a per-step log including the new `appId`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`); internally switches to app-token mode for source-ingest steps. Errors: aborts with the partial step log if app creation fails; previous auth mode restored best-effort. Related: rooms+tokens variant is `ethora-b2b-app-provision`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"description":"Display name for the new app."},"setAsCurrent":{"type":"boolean","description":"If true (default), set the new app as the session's current app and switch to app-token auth so follow-up tools can omit appId."},"crawlUrl":{"type":"string","description":"Optional website URL to crawl and index into the new app's RAG sources."},"followLink":{"type":"boolean","description":"For `crawlUrl`: also follow in-domain links (default true). Can ingest many pages."},"docs":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1},"mimeType":{"type":"string","minLength":1},"base64":{"type":"string","minLength":1}},"required":["name","mimeType","base64"],"additionalProperties":false},"description":"Optional docs to ingest (base64)"},"savedAgentId":{"type":"string","description":"Optional saved agent to bind as the active bot for the new app."},"enableBot":{"type":"boolean","description":"If true, enables botStatus=on (best-effort AI service activation)"},"botTrigger":{"type":"string","description":"Optional bot trigger (e.g. '/bot' or 'any_message')"},"llmProvider":{"type":"string","description":"Optional generation provider for the default AI bot (example: 'openai' or 'openai-compatible')."},"llmModel":{"type":"string","description":"Optional generation model for the default AI bot (example: 'gpt-4o-mini')."},"agentDisplayName":{"type":"string","description":"Phase 1: create a new Agent with this display name as part of bootstrap."},"agentPrompt":{"type":"string","description":"Phase 1: persona/instructions for the newly-created Agent."},"agentVisibility":{"type":"string","enum":["private","unlisted","public"],"description":"Phase 1: visibility for the newly-created Agent."},"inviteToDefaultRoom":{"type":"boolean","description":"Phase 1: if true (default), invite the newly-created Agent into the App's first default room."}},"required":["displayName"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-b2b-app-create","description":"Create a new Ethora app (tenant) server-side using B2B auth — the partner/integrator equivalent of `ethora-app-create`. Allocates a fresh 24-char hex `appId`; does not create tokens, rooms, or a bot. Returns the new app object including `appId`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode or invalid `b2bToken`; 422 invalid `displayName`. Related: all-in-one path is `ethora-b2b-app-bootstrap-ai` / `ethora-b2b-app-provision`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"description":"Human-readable app name shown to users in the app picker and on the public landing page."}},"required":["displayName"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-b2b-app-provision","description":"One-call B2B orchestrator: create an app, mint one or more app tokens, provision default chat rooms, then configure and enable its AI bot. Later-step failures don't undo earlier steps. Returns a per-step log including `appId` and the created tokens (returned once — capture them).\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: aborts with the partial step log if app creation fails; previous auth mode restored best-effort. Related: `ethora-b2b-app-bootstrap-ai` does sources+bot but not tokens/rooms.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"description":"Display name for the new app."},"tokenLabels":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":5,"description":"Labels for the app tokens to mint, one token per label. Default: ['default']. 1–5 tokens."},"rooms":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Display name of the room."},"pinned":{"type":"boolean","description":"If true, add the room to the app's default rooms (new users auto-join)."}},"required":["title"],"additionalProperties":false},"maxItems":20,"description":"Default chat rooms to create in the new app. Up to 20."},"enableBot":{"type":"boolean","description":"If true, enable the new app's bot using the first minted app token."},"savedAgentId":{"type":"string","description":"Optional id of an existing saved agent to bind as the new app's active bot, instead of setting prompt fields by hand."},"botTrigger":{"type":"string","enum":["any_message","/bot"],"description":"Bot trigger: `any_message` (every message) or `/bot` (only /bot-prefixed messages)."},"botPrompt":{"type":"string","description":"System prompt for the new app's bot."},"botGreetingMessage":{"type":"string","description":"Greeting message the bot posts when a conversation starts."},"llmProvider":{"type":"string","description":"LLM provider for the bot, e.g. `openai` or `openai-compatible`. Must be enabled in your Ethora backend."},"llmModel":{"type":"string","description":"LLM model id for the bot, e.g. `gpt-4o-mini`. Must be available for the chosen provider."}},"required":["displayName"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-b2b-bot-enable","description":"Enable the LEGACY per-app aiBot (B2B auth). NOTE: apps created via the API/B2B no longer auto-provision a legacy aiBot, so this returns 422 BOT_NOT_INITIALIZED on a clean app. The forward path for B2B AI is the Agents API — use `ethora-b2b-app-bootstrap-ai` or `ethora-agents-create-v2` + `ethora-agent-invite-to-chat`. This tool remains valid for apps that already have a legacy aiBot (e.g. admin-panel apps created with a default chat).\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId whose bot to enable. Optional — defaults to the app set via `ethora-app-select`."},"botTrigger":{"type":"string","description":"When the bot responds: `/bot` (only messages starting with /bot) or `any_message` (every message). Omit to leave the existing trigger unchanged."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-disable-v2","description":"Turn the AI bot off for an app (sets bot `status: \"off\"`) — it stops responding. The configured prompt/LLM/RAG and any activated agent are preserved, so re-enabling restores the same behavior.\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`. Related: `ethora-bot-enable-v2` to turn back on.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-enable-v2","description":"Enable the LEGACY per-app aiBot using app-token or B2B auth. NOTE: clean API/B2B-created apps have no legacy aiBot, so this returns 422 BOT_NOT_INITIALIZED there — use the Agents API (`ethora-agents-create-v2` + `ethora-agent-invite-to-chat`, or `ethora-b2b-app-bootstrap-ai`) for B2B AI. Valid for apps that already have a legacy aiBot.\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"trigger":{"type":"string","enum":["any_message","/bot"],"description":"When the bot responds: `any_message` (every message) or `/bot` (only /bot-prefixed messages). Omit to leave the existing trigger unchanged."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-get-v2","description":"Read the current AI bot configuration for an app: status, trigger, prompt, greeting, LLM provider/model, RAG settings, widget config.\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`. Related: change config with `ethora-bot-update-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode (the token determines the app)."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-instance-diag","description":"Diagnose a specific BotInstance for an Agent (GET /v2/agents/:idOrAddress/bot-instances/:botInstanceId/diag). Returns live XMPP/ai-service status and recent activity for troubleshooting.\nRequires: a bot instance id from `ethora-bot-instances-list` (instances are created by `ethora-agent-invite-to-chat`).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"botInstanceId":{"type":"string","minLength":1},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["botInstanceId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-instance-leave-chat","description":"Remove a BotInstance from a chat room (POST /v2/agents/:idOrAddress/bot-instances/:botInstanceId/leave-chat). The inverse of `ethora-agent-invite-to-chat`.\nRequires: a bot instance id from `ethora-bot-instances-list` (instances are created by `ethora-agent-invite-to-chat`).","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"botInstanceId":{"type":"string","minLength":1},"chatJid":{"type":"string","minLength":1,"description":"Fully-qualified room JID to leave."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["botInstanceId","chatJid"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-instance-status","description":"Turn a specific BotInstance on or off. Off detaches it from XMPP; on re-spawns the XMPP client live.\nRequires: a bot instance id from `ethora-bot-instances-list` (instances are created by `ethora-agent-invite-to-chat`).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"botInstanceId":{"type":"string","minLength":1},"status":{"type":"string","enum":["on","off"]}},"required":["botInstanceId","status"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-instance-test-message","description":"Send a test message from a BotInstance (POST /v2/agents/:idOrAddress/bot-instances/:botInstanceId/test-message). Omit roomJid to fan out to every room the BotInstance is in. Requires the ai-service to be running.\nRequires: a bot instance id from `ethora-bot-instances-list` (instances are created by `ethora-agent-invite-to-chat`).","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"agentIdOrAddress":{"type":"string","minLength":1},"botInstanceId":{"type":"string","minLength":1},"text":{"type":"string","maxLength":2000,"description":"Message body. Optional/empty is allowed."},"roomJid":{"type":"string","description":"Target a specific room JID; omit to broadcast to all the bot's rooms."},"agentId":{"type":"string","minLength":1,"description":"Alias for `agentIdOrAddress` - either name is accepted, pass whichever you have."}},"required":["botInstanceId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-instances-list","description":"List BotInstances. Filter by appId (caller's App by default) and/or agentId.\nRequires: at least one invited agent in the app (`ethora-agent-invite-to-chat`); otherwise the list is empty.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string"},"agentId":{"type":"string"},"agentIdOrAddress":{"type":"string","minLength":1,"description":"Alias for `agentId` - either name is accepted, pass whichever you have."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-update-v2","description":"Configure the AI bot for an app — prompt, LLM, trigger, greeting, RAG behavior, identity, and public widget settings. Partial update — omitted fields are left unchanged. `status: \"on\"` activates the bot (best-effort; needs a prompt + LLM and a backend AI service).\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`; 422 validation (e.g. an `llmProvider`/`llmModel` not enabled). Related: `ethora-bot-get-v2`, `ethora-agents-activate-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"status":{"type":"string","enum":["on","off"],"description":"`on` activates the bot, `off` deactivates it. Omit to leave the current status unchanged."},"savedAgentId":{"type":"string","description":"Id of a saved agent whose config should back this bot. Alternative to setting prompt/LLM/RAG fields individually."},"trigger":{"type":"string","enum":["any_message","/bot"],"description":"When the bot responds: `any_message` (replies to every message) or `/bot` (only messages starting with /bot)."},"prompt":{"type":"string","description":"System prompt that defines the bot's persona and behavior."},"greetingMessage":{"type":"string","description":"Message the bot posts when a conversation starts."},"chatId":{"type":"string","description":"Restrict the bot to a single chat by id. Omit to apply app-wide."},"isRAG":{"type":"boolean","description":"If true, the bot retrieves from the app's indexed RAG sources (see the `ethora-sources-*` tools) when answering."},"botFirstName":{"type":"string","description":"Bot's first name in its user profile."},"botLastName":{"type":"string","description":"Bot's last name in its user profile."},"botDisplayName":{"type":"string","description":"Bot's display name shown in chat."},"botAvatarUrl":{"type":"string","description":"Public URL of the bot's avatar image."},"ragTags":{"type":"array","items":{"type":"string","minLength":1},"description":"Restrict RAG retrieval to sources tagged with these tags (see `ethora-sources-site-tags-update-v2` / `ethora-sources-docs-tags-update-v2`)."},"llmProvider":{"type":"string","description":"LLM provider, e.g. `openai` or `openai-compatible`. Must be enabled in your Ethora backend's AI service config."},"llmModel":{"type":"string","description":"LLM model id, e.g. `gpt-4o-mini`. Must be available for the chosen `llmProvider`."},"widgetPublicEnabled":{"type":"boolean","description":"If true, expose the bot through a public embeddable chat widget."},"widgetPublicUrl":{"type":"string","description":"Public URL for the embeddable widget. Usually read via `ethora-bot-widget-v2` rather than set here."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-bot-widget-v2","description":"LEGACY: read the per-app bot widget config (`GET /v2/bot/widget`); only apps that already have a legacy aiBot have one, API-created apps get 422. For the embeddable AI chat widget use `ethora-widget-embed-snippet` instead — the widget config and public widget URL metadata needed to embed the bot on a website.\nRequires: an app with a legacy per-app aiBot (dashboard-created). API-created apps have none: use `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2` instead.\nAuth: app-token mode (after `ethora-app-select` + `ethora-auth-use-app`). Errors: 401/403 not in app-token mode or invalid appToken. Related: enable/disable via `widgetPublicEnabled` in `ethora-bot-update-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-chats-broadcast-job-v2","description":"Fetch the current status and per-room results of a broadcast job by `jobId` (one-shot, no polling). Returns the job object with its `state` (pending/running/completed/failed).\nRequires: a selected app with at least one room (`ethora-app-create-chat`).\nAuth: app-token mode OR B2B mode with an explicit `appId` — must match the auth used to enqueue the job. Errors: 401/403 wrong auth; 404 unknown `jobId`. Related: `ethora-wait-broadcast-job-v2` for a blocking wait.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the job belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"jobId":{"type":"string","description":"Job id returned by `ethora-chats-broadcast-v2`."}},"required":["jobId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-chats-broadcast-v2","description":"Enqueue an asynchronous broadcast job posting a message to one or more chat rooms of an app — returns a `jobId`; messages are not sent synchronously. Targeting is exclusive: `allRooms`, `chatIds`, or `chatNames`, not a mix.\nRequires: a selected app with at least one room (`ethora-app-create-chat`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 400 no target or conflicting targets; 404 unknown `appId` or room. Related: track with `ethora-wait-broadcast-job-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to broadcast in. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode (the token determines the app)."},"text":{"type":"string","minLength":1,"description":"Plain-text message body to broadcast to the targeted rooms."},"allRooms":{"type":"boolean","description":"If true, broadcast to every room in the app. Mutually exclusive with `chatIds` and `chatNames`."},"chatIds":{"type":"array","items":{"type":"string"},"description":"Explicit list of chat ids to target. Mutually exclusive with `allRooms` and `chatNames`."},"chatNames":{"type":"array","items":{"type":"string"},"description":"Explicit list of chat JIDs or localparts to target. Mutually exclusive with `allRooms` and `chatIds`."}},"required":["text"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-chats-history-v2","description":"Read the archived messages of a chat room (GET /v2/apps/:appId/chats/:chatId/messages, newest last). Returns `results` with `from`, `nick`, `body`, `ts` (ms) plus a `nextBefore` cursor for older pages. Identify the room by `roomJid` (`${appId}_${chatId}`) or bare `chatId` plus the selected app.\nRequires: a room in the selected app (`ethora-app-create-chat`).\nAuth: user auth (default on the hosted server) or B2B; app-token mode is not accepted. Errors: 401 not logged in; 403 not the app owner; 404 unknown app/room; 502 MAM_READ_FAILED or `mamUnavailable: true` when the deployment has no message archive.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"roomJid":{"type":"string","description":"Room JID `${appId}_${chatId}` (optionally with `@conference.<host>`). Either this or `chatId` is required."},"chatId":{"type":"string","description":"Bare chat id. Needs an app: pass `appId` or select one with `ethora-app-select`."},"appId":{"type":"string","description":"24-char hex appId. Optional when `roomJid` carries it or an app is selected."},"limit":{"type":"integer","minimum":1,"maximum":500,"description":"Maximum number of most-recent messages to return (default 100)."},"before":{"type":"integer","minimum":0,"description":"Pagination cursor: only messages older than this timestamp (ms), from a previous `nextBefore`."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-chats-message-v2","description":"Post a message into a chat room of an app (POST /v2/apps/:appId/chats/broadcast targeting one room). The message is attributed to the app's broadcast sender (override the shown name with `senderName`). Use it to seed or test a conversation, e.g. right after `ethora-agent-invite-to-chat`, and set `waitForReplySec` (up to 60) to wait for an AI agent's answer; replies are returned in `replies`. Identify the room by `roomJid` (`${appId}_${chatId}`, exactly what `ethora-app-create-chat` returns as `jid`) or by the bare `chatId` plus the selected app.\nRequires: a room in the selected app (`ethora-app-create-chat`); for `replies`, an agent invited into it (`ethora-agent-invite-to-chat`).\nAuth: user auth (the default on the hosted server) or B2B; app-token mode is not accepted by this route. Errors: 401 not logged in; 403 not the app owner; 404 unknown app/room; 422 empty text. Reply detection needs the message archive (MAM) on the deployment; when it is unavailable `replies` is null and `historyUnavailable` is true.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":4000,"description":"Message body to post (1-4000 chars)."},"roomJid":{"type":"string","description":"Room JID `${appId}_${chatId}` (optionally with `@conference.<host>`), as returned by `ethora-app-create-chat`. Either this or `chatId` is required."},"chatId":{"type":"string","description":"Chat id: either the Mongo chat `_id` (as listed by the app's chat list) or the suffix after `${appId}_` in the room JID. Needs an app: pass `appId` or select one with `ethora-app-select`."},"appId":{"type":"string","description":"24-char hex appId. Optional when `roomJid` carries it or an app is selected."},"senderName":{"type":"string","maxLength":60,"description":"Display name shown as the message sender (defaults to the app's broadcast sender / app name)."},"waitForReplySec":{"type":"integer","minimum":0,"maximum":60,"description":"Seconds to wait for a reply from someone else in the room (an AI agent, typically). 0 (default) returns right after posting."}},"required":["text"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-configure","description":"Set the Ethora API URL and credentials for this MCP session. Stores values in memory only; each call merges with omitted fields kept. Alternative to env vars (ETHORA_API_URL / ETHORA_APP_JWT / ETHORA_APP_TOKEN / ETHORA_B2B_TOKEN). On a hosted server `apiUrl` is fixed and cannot be changed; credentials are per session.\nAuth: none required — this establishes auth material. Errors: only if a value is structurally invalid. Follow with an `ethora-auth-use-*` tool to pick the active mode.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"apiUrl":{"type":"string","description":"Full Ethora API URL including the version path, e.g. `https://api.chat.ethora.com/v1` or `http://localhost:8080/v1`. If you only have the host, set ETHORA_BASE_URL env instead and the server appends `/v1`."},"appJwt":{"type":"string","description":"Ethora App JWT, used only to bootstrap login/register in user-auth mode. Usually starts with `JWT `. Secret — never commit it."},"appToken":{"type":"string","description":"Per-app appToken for app-scoped flows (broadcast, sources, bot). Setting this makes app-token auth available via `ethora-auth-use-app`. Secret."},"b2bToken":{"type":"string","description":"B2B server token for tenant-actor `x-custom-token` auth (a JWT with `type=server`). Required for B2B provisioning flows. Secret."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-doctor","description":"Diagnose the session: validate the config is internally consistent for the active auth mode and ping the Ethora API (`GET /v1/ping`). Returns `{ state, checks, ping, suggestions }`.\nAuth: none required; report is tailored to whatever credentials are set. Errors: rarely throws — instead returns `suggestions` and a `ping.ok: false` block when the API is unreachable.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"timeoutMs":{"type":"integer","minimum":500,"maximum":20000,"description":"HTTP timeout in milliseconds for the ping request. Defaults to 3000. Raise it on slow links, lower it to fail fast."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-feedback-submit","description":"Send feedback about Ethora to the Ethora team: something that does not work, behaves differently from what the tool description promised, is missing, or is badly documented. It reaches the team directly, so prefer it over guessing or silently giving up when a tool fails. Recent failures in this session (tool, error code, request id) are attached automatically when `includeRecentErrors` is true, which is what makes a report from here more useful than a web form: the team can join it to the server-side log. Works whether or not you are signed in, so a problem that blocks sign-up can still be reported. Do not put credentials, API keys or end-user personal data in `message`; credential-shaped values in the attached context are redacted before sending.\nRequires: nothing.\nAuth: none. Works anonymously; when the session is authenticated the report is attributed to that account. Errors: 422 if `message` is shorter than 5 characters or looks like spam; 429 if too many reports were sent from this address.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"category":{"type":"string","enum":["bug","unexpected","feature","docs","other"],"description":"What kind of report this is: `bug` (something is broken), `unexpected` (it works but not as described), `feature` (a request), `docs` (a description or guide is wrong or missing), `other`. Defaults to `other`."},"message":{"type":"string","minLength":5,"maxLength":4000,"description":"What happened, in the user's own words where possible: what was attempted, what was expected, what occurred instead. No credentials or end-user personal data."},"email":{"type":"string","description":"Reply address. Only useful when the session is not signed in; an authenticated report already carries the account, so leave this out unless the user offers an address."},"includeRecentErrors":{"type":"boolean","description":"Attach this session's last few tool failures (tool name, error code, request id) so the team can trace them. Default true; set false if the report is unrelated to a failure."}},"required":["message"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-files-delete-v2","description":"Permanently delete one of the authenticated user's files by id (`DELETE /v2/files/:id`). Removes the record and its stored content; not reversible.\nRequires: a file id from `ethora-files-upload-v2`.\nAuth: user-auth mode with an active user session. Errors: 401 not logged in; 403 not owned by the user; 404 unknown `id`. Related: get ids from `ethora-files-get-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"description":"Id of the file to delete. Get it from `ethora-files-get-v2`."}},"required":["id"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-files-get-v2","description":"List the authenticated user's files, or fetch one file's metadata by id (`GET /v2/files`). Returns an array when `id` is omitted, a single record when given.\nRequires: a file id from `ethora-files-upload-v2`.\nAuth: user-auth mode with an active user session. Errors: 401 not logged in; 404 unknown `id` or not owned by the user.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"id":{"type":"string","description":"File id to fetch a single record. Omit to list all files owned by the logged-in user."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-files-upload-v2","description":"Upload 1–5 files to the authenticated user's Ethora file storage (`POST /v2/files`). Each upload is a new record (no overwrite-by-name); files passed as base64, 50MB max each.\nAuth: user-auth mode with an active user session (`ethora-user-login` first). Errors: 401 not logged in; 413 size limit exceeded; 422 unsupported mime type. Related: manage with `ethora-files-get-v2` / `ethora-files-delete-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"File name including extension, e.g. `report.pdf`."},"mimeType":{"type":"string","minLength":1,"description":"MIME type of the content, e.g. `application/pdf`, `image/png`, `text/plain`."},"base64":{"type":"string","minLength":1,"description":"File content, base64-encoded. A `data:...;base64,` prefix is accepted and stripped. Max 50MB decoded per file."}},"required":["name","mimeType","base64"],"additionalProperties":false},"minItems":1,"maxItems":5,"description":"1 to 5 files to upload in this call."}},"required":["files"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-generate-b2b-bootstrap-runbook","description":"Generate a human-readable runbook listing this server's tool calls in the right order for a B2B bootstrap, with example payloads. Documentation only — does not write any file or execute any step.\nAuth: none required — pure text generator, no API calls. Errors: effectively none. Related: to actually run the sequence use `ethora-run-recipe` or `ethora-b2b-app-bootstrap-ai`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"apiUrl":{"type":"string","description":"Ethora API base URL to show in the runbook's configure step. Omit to emit a placeholder."},"displayName":{"type":"string","description":"App display name to show in the runbook's create-app step. Omit to emit a placeholder."},"crawlUrl":{"type":"string","description":"Website URL to show in the runbook's source-ingest step. Omit to emit a placeholder."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-generate-chat-component-app-tsx","description":"Generate a ready-to-paste React `App.tsx` snippet that mounts `@ethora/chat-component`. Returns `{ filename: \"App.tsx\", snippet }`; unpassed values are emitted as placeholders. Does not write any file. Get the appToken from `ethora-app-credentials { appId, confirm: true }` (other tools redact it).\nAuth: none required — pure code generator, no API calls. Errors: effectively none. Security note: the snippet includes `appToken` inline only as a quickstart convenience — do not ship hardcoded tokens to production.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"apiUrl":{"type":"string","description":"Ethora API base URL to embed in the snippet, e.g. `https://api.chat.ethora.com/v1`. Omit to emit a placeholder."},"appToken":{"type":"string","description":"appToken to embed in the snippet for quickstart testing. Omit to emit a placeholder. Do NOT hardcode real tokens in production source."},"roomJid":{"type":"string","description":"Room JID to open on load. Omit to emit a commented-out placeholder."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-generate-env-examples","description":"Generate `.env.example` templates for the three common Ethora integration targets: the frontend chat component, the backend SDK, and this MCP server. Returns `{ target, template }` when `target` is given, or `{ templates }` with all three. Placeholder values only; does not write any file.\nAuth: none required — pure text generator, no API calls. Errors: effectively none.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"target":{"type":"string","enum":["frontend-chat-component","backend-sdk","mcp"],"description":"Which template to return: `frontend-chat-component` (Vite env), `backend-sdk` (@ethora/sdk-backend env), or `mcp` (this server's env). Omit to return all three."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-help","description":"Task-oriented orientation for this MCP server: explains the three Ethora auth modes (user / app-token / B2B) and recommends next tool calls + recipes based on current session state.\nAuth: none required — inspects state, no API calls. Errors: effectively none. Related: pass a recommended recipe id to `ethora-run-recipe`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"goal":{"type":"string","enum":["auto","b2b-bootstrap-ai","broadcast","sources-ingest","files-upload","bot-manage","chat-test","widget","user-login"],"description":"Goal hint to tailor the recommendations and recipe list. Omit or use `auto` to get recommendations inferred from the current session state."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-messages-context-v2","description":"Fetch the messages surrounding a target message (GET /v2/apps/:appId/chats/:chatId/messages/context). Provide either aroundStanzaId or aroundMessageId; radius controls how many messages before/after.\nRequires: a message id from `ethora-messages-search-v2` or `ethora-chats-history-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"chatId":{"type":"string","minLength":1},"appId":{"type":"string","description":"Required in B2B mode unless already selected via ethora-app-select."},"aroundStanzaId":{"type":"string"},"aroundMessageId":{"type":"string"},"radius":{"type":"integer","minimum":0,"maximum":50}},"required":["chatId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-messages-search-v2","description":"Search an App's chat messages (GET /v2/apps/:appId/messages/search). B2B / tenant-actor auth. Filter by room (chatId), author (fromUserId), and time window.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":500,"description":"Search query."},"appId":{"type":"string","description":"Required in B2B mode unless already selected via ethora-app-select."},"mode":{"type":"string","enum":["substring","fulltext"]},"chatId":{"type":"string"},"fromUserId":{"type":"string"},"since":{"type":"string","description":"ISO date lower bound."},"until":{"type":"string","description":"ISO date upper bound."},"sort":{"type":"string","enum":["relevance","date"]},"limit":{"type":"integer","minimum":1,"maximum":100},"offset":{"type":"integer","minimum":0}},"required":["q"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-run-recipe","description":"Execute a built-in recipe — an ordered sequence of this server's own tool calls — by id. Recipes capture common flows (B2B bootstrap, broadcast, sources ingest). Use `dryRun: true` to preview resolved steps. Omit `recipeId` to list runnable recipes for a `goal`.\nRequires: the inputs the chosen recipe lists; call without `recipeId` first to see the recipes and their required inputs.\nAuth: depends on the recipe's steps — configure those first (see `ethora-help`). Errors: stops at the first failing step and returns the partial log; a missing required `vars` entry fails fast before any step runs.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"recipeId":{"type":"string","minLength":1,"description":"Id of the recipe to run. Omit to instead list the runnable recipes for the selected `goal` (get ids from `ethora-help`)."},"goal":{"type":"string","enum":["auto","b2b-bootstrap-ai","broadcast","sources-ingest","files-upload","bot-manage","chat-test","widget","user-login"],"description":"Goal scope used to look up recipes when `recipeId` is omitted. Defaults to `auto`."},"vars":{"type":"object","additionalProperties":{},"description":"Key/value substitutions injected into recipe steps (e.g. appId, appToken, b2bToken, appJwt, email, password, apiUrl). A recipe declares which vars it requires; missing required vars fail the run before any step executes."},"dryRun":{"type":"boolean","description":"If true, resolve and return the step list with `vars` substituted but execute nothing. Use this to preview a recipe before running it for real."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-delete","description":"Remove a previously ingested document from an app's RAG sources by `docId` (legacy user-auth route). Deletes the document record and its embeddings; not reversible.\nRequires: a document id from `ethora-sources-docs-list-v2`.\nAuth: user-auth mode, active session; the user must own the app. Errors: 401 not logged in; 403 not owner; 404 unknown `docId`. Related: get `docId` from `ethora-sources-docs-list-v2`; app-token/B2B uses `ethora-sources-docs-delete-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the document belongs to. Optional — defaults to the app set via `ethora-app-select`."},"docId":{"type":"string","minLength":1,"description":"Id of the ingested document to delete. Get it from `ethora-sources-docs-list-v2`."}},"required":["docId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-delete-v2","description":"Remove a previously ingested document from an app's RAG sources by `docId` (app-token / B2B variant of `ethora-sources-docs-delete`). Deletes the document record and its embeddings; not reversible.\nRequires: a document id from `ethora-sources-docs-list-v2`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId` or `docId`. Related: get `docId` from `ethora-sources-docs-list-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the document belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"docId":{"type":"string","minLength":1,"description":"Id of the ingested document to delete. Get it from `ethora-sources-docs-list-v2`."}},"required":["docId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-list-v2","description":"List an app's ingested documents, including each document's id, name, and current RAG tags. Their ids feed `ethora-sources-docs-tags-update-v2` and `ethora-sources-docs-delete-v2`.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`; empty list if nothing has been uploaded. Related: website-sources equivalent is `ethora-sources-site-list-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to list documents for. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-tags-update-v2","description":"Set the RAG retrieval tags on an ingested document — replaces the document's tag set with the provided `tags` array (not additive; pass `[]` to clear all). Tags let the bot's `ragTags` narrow retrieval.\nRequires: a document id from `ethora-sources-docs-list-v2`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId` or `docId`. Related: get `docId` from `ethora-sources-docs-list-v2`; website-source equivalent is `ethora-sources-site-tags-update-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the document belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"docId":{"type":"string","minLength":1,"description":"Id of the ingested document to tag. Get it from `ethora-sources-docs-list-v2`."},"tags":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"The complete desired tag set for this document (replaces any existing tags). Up to 50 tags; pass `[]` to clear all."}},"required":["docId","tags"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-upload","description":"Upload documents (1–5; PDF, text, etc.) into an app's RAG sources (legacy user-auth route). Async — content becomes queryable once indexing finishes; files passed as base64, 50MB max each.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: user-auth mode, active session; the user must own the app. Errors: 401 not logged in; 403 not owner; 413 too large; 422 unsupported document type. Related: app-token/B2B flows use `ethora-sources-docs-upload-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to ingest into. Optional — defaults to the app set via `ethora-app-select`."},"files":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Document file name including extension, e.g. `handbook.pdf`."},"mimeType":{"type":"string","minLength":1,"description":"MIME type, e.g. `application/pdf`, `text/plain`, `text/markdown`."},"base64":{"type":"string","minLength":1,"description":"Document content, base64-encoded. A `data:...;base64,` prefix is accepted. Max 50MB decoded per file."}},"required":["name","mimeType","base64"],"additionalProperties":false},"minItems":1,"maxItems":5,"description":"1 to 5 documents to ingest in this call."}},"required":["files"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-docs-upload-v2","description":"Upload documents (1–5; PDF, text, etc.) into an app's RAG sources (app-token / B2B variant of `ethora-sources-docs-upload`). Async — content becomes queryable once indexing finishes; files passed as base64, 50MB max each.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`; 413 too large; 422 unsupported document type. Related: `ethora-sources-docs-list-v2`, `ethora-sources-docs-delete-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to ingest into. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"files":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Document file name including extension, e.g. `handbook.pdf`."},"mimeType":{"type":"string","minLength":1,"description":"MIME type, e.g. `application/pdf`, `text/plain`, `text/markdown`."},"base64":{"type":"string","minLength":1,"description":"Document content, base64-encoded. A `data:...;base64,` prefix is accepted. Max 50MB decoded per file."}},"required":["name","mimeType","base64"],"additionalProperties":false},"minItems":1,"maxItems":5,"description":"1 to 5 documents to ingest in this call."}},"required":["files"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-crawl-v2","description":"Crawl a website URL and ingest its content into an app's RAG sources (app-token / B2B variant of `ethora-sources-site-crawl`). Async — returns once the job is accepted; `followLink: true` follows in-domain links and can ingest many pages.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 400 malformed `url`; 404 unknown `appId`. Related: `ethora-sources-site-crawl-v2-wait` (block until done).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to ingest into. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"url":{"type":"string","minLength":1,"description":"Absolute URL to crawl, e.g. `https://example.com/docs`."},"followLink":{"type":"boolean","description":"If true, also crawl in-domain links reachable from `url`. Can ingest many pages — use with care."}},"required":["url"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-crawl-v2-wait","description":"Crawl a website URL and wait for the crawl to finish: enqueues the job, then polls it until it reports `completed` or `failed`. Returns `{ done, status, jobId, polls, durationMs, result }`; `done: false` with a `note` means the budget ran out while the job was still running (it usually finishes server-side anyway).\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 400 malformed `url`; 504/timeout if it takes longer than `timeoutMs` (the job may still complete server-side — check with `ethora-sources-site-list-v2`).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to ingest into. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"url":{"type":"string","minLength":1,"description":"Absolute URL to crawl, e.g. `https://example.com/docs`."},"followLink":{"type":"boolean","description":"If true, also crawl in-domain links reachable from `url`. Can ingest many pages — use with care."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":600000,"description":"How long to poll for the crawl to finish, in milliseconds. Default 45000, chosen to stay under the ~60s request timeout most MCP clients enforce. Caps at 600000 (10 min) for clients that allow longer calls."}},"required":["url"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-delete-url-v2","description":"Remove a single crawled URL from an app's RAG sources, matched by its exact url string (app-token / B2B variant of `ethora-sources-site-delete-url`). Deletes the source record and its embeddings; not reversible. Matches on the exact stored URL string.\nRequires: an indexed site URL from `ethora-sources-site-list-v2` (crawled with `ethora-sources-site-crawl-v2`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 `url` not a crawled source. Related: get the stored value from `ethora-sources-site-list-v2`; bulk-by-id is `ethora-sources-site-delete-url-v2-batch`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the URL belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"url":{"type":"string","minLength":1,"description":"Exact crawled URL string to remove (must match what was stored — get it from `ethora-sources-site-list-v2`)."}},"required":["url"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-delete-url-v2-batch","description":"Bulk-remove crawled website sources (1–100) from an app in one call, matched by their source record ids. Deletes each matching record and its embeddings; not reversible. Ids not present are skipped.\nRequires: an indexed site URL from `ethora-sources-site-list-v2` (crawled with `ethora-sources-site-crawl-v2`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`. Related: matches on source ids (not URL strings) — get them from `ethora-sources-site-list-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the sources belong to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"ids":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":100,"description":"Site source record ids to delete, 1–100 per call. Get them from `ethora-sources-site-list-v2`."}},"required":["ids"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-list-v2","description":"List an app's crawled website sources, including each source's id, URL, and current RAG tags. Their ids feed `ethora-sources-site-tags-update-v2`, `ethora-sources-site-delete-url-v2-batch`, and `ethora-sources-site-reindex-v2`.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId`; empty list if nothing has been crawled.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId to list sources for. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-reindex-v2","description":"Re-crawl and re-embed a previously crawled URL by its `urlId`, refreshing its RAG content (app-token / B2B variant of `ethora-sources-site-reindex`). Async — the existing source record is updated in place once indexing finishes.\nRequires: an indexed site URL from `ethora-sources-site-list-v2` (crawled with `ethora-sources-site-crawl-v2`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId` or `urlId`. Related: get `urlId` from `ethora-sources-site-list-v2`; `ethora-sources-site-reindex-v2-wait` blocks until done.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the URL belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"urlId":{"type":"string","minLength":1,"description":"Id of a previously crawled URL record. Get it from `ethora-sources-site-list-v2`."}},"required":["urlId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-reindex-v2-wait","description":"Re-crawl and re-embed a previously crawled URL and wait for it to finish: enqueues the job, then polls it until it reports `completed` or `failed`. Returns `{ done, status, jobId, polls, durationMs, result }`; `done: false` with a `note` means the budget ran out while the job was still running.\nRequires: an indexed site URL from `ethora-sources-site-list-v2` (crawled with `ethora-sources-site-crawl-v2`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId` or `urlId`; 504/timeout if it takes longer than `timeoutMs` (the job may still complete server-side). Related: get `urlId` from `ethora-sources-site-list-v2`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the URL belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"urlId":{"type":"string","minLength":1,"description":"Id of a previously crawled URL record. Get it from `ethora-sources-site-list-v2`."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":600000,"description":"How long to poll for the reindex to finish, in milliseconds. Default 45000, chosen to stay under the ~60s request timeout most MCP clients enforce. Caps at 600000 (10 min) for clients that allow longer calls."}},"required":["urlId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-sources-site-tags-update-v2","description":"Set the RAG retrieval tags on a crawled website source — replaces the source's tag set with the provided `tags` array (not additive; pass `[]` to clear all). Tags let the bot's `ragTags` narrow retrieval.\nRequires: an indexed site URL from `ethora-sources-site-list-v2` (crawled with `ethora-sources-site-crawl-v2`).\nAuth: app-token mode OR B2B mode with an explicit `appId`. Errors: 401/403 wrong auth; 404 unknown `appId` or `sourceId`. Related: get `sourceId` from `ethora-sources-site-list-v2`; doc equivalent is `ethora-sources-docs-tags-update-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the source belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"sourceId":{"type":"string","minLength":1,"description":"Id of the crawled site source to tag. Get it from `ethora-sources-site-list-v2`."},"tags":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"The complete desired tag set for this source (replaces any existing tags). Up to 50 tags; pass `[]` to clear all."}},"required":["sourceId","tags"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-status","description":"Report the current Ethora MCP session state: configured API URL, active auth mode, which credentials are present (booleans like `hasAppJwt` — values never echoed), the selected appId/agentId, and `hosted`/`sessionId` on the hosted (Streamable HTTP) server.\nAuth: none required. Errors: effectively none. Related: `ethora-doctor` for an active connectivity check.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{}}},{"name":"ethora-unread-counts-v2","description":"Batch per-room unread message counts for a set of users (POST /v2/apps/:appId/users/unread-counts). mode=count returns numbers (capped); mode=flag returns booleans. Requires Mongo message archiving enabled on the deployment.\nRequires: a selected app (`ethora-app-select`) or an explicit `appId`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"userIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":200,"description":"uuid / Mongo _id / xmppUsername, 1..200."},"appId":{"type":"string","description":"Required in B2B mode unless already selected via ethora-app-select."},"mode":{"type":"string","enum":["count","flag"]},"cap":{"type":"integer","minimum":1,"maximum":1000},"concurrency":{"type":"integer","minimum":1,"maximum":32}},"required":["userIds"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-user-login","description":"Authenticate as an existing Ethora user with email + password. Stores the user session token in this MCP session and unlocks user-auth tools (`ethora-app-list`, `ethora-files-*`, `ethora-wallet-*`).\nAuth: user-auth mode (`ethora-auth-use-user` first) and a configured `appJwt`. Errors: 401/403 bad credentials; 404 email not registered; 429 per-IP rate limit — retry with backoff.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"User's registered email address (RFC 5322). Must match an account created via `ethora-user-register`."},"password":{"type":"string","description":"Plain-text password the user set during registration. Sent over TLS to the Ethora API; never echoed back or logged."},"createApiKey":{"type":"boolean","description":"When true, also mint a long-lived API key for this user and return it once, so headless clients / agents can reconnect with `Authorization: Bearer <key>` instead of logging in again. Default false."},"apiKeyName":{"type":"string","description":"Label for the API key when `createApiKey` is true (e.g. `claude-code-laptop`)."},"apiKeyTtlDays":{"type":"integer","minimum":1,"maximum":365,"description":"Lifetime of the API key in days when `createApiKey` is true. Server default applies when omitted."}},"required":["email","password"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-user-register","description":"Create a new Ethora user account by email + first/last name, then log in and bind the session. A password is generated when omitted and returned once. By default also mints a long-lived API key so an agent can reconnect later with `Authorization: Bearer <key>` (no human step needed).\nAuth: user-auth mode and a configured `appJwt` (on a hosted server this is preset). Errors: 401 no `appJwt`; 422 email already registered or password shorter than 6 chars; 429 rate limited. Related: bulk provisioning uses `ethora-users-batch-create-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address for the new user. Must be RFC-5322 valid and not already registered within this app. No confirmation click is required to log in; the address is used for password reset."},"firstName":{"type":"string","description":"First name shown in the user's profile and message attributions across chat rooms and the app UI."},"lastName":{"type":"string","description":"Last name shown in the user's profile."},"password":{"type":"string","minLength":6,"description":"Password for the account (min 6 chars). Omit to have a strong random password generated and returned once in the result."},"createApiKey":{"type":"boolean","description":"Mint a long-lived API key right after signup and return it once. Default true. Set false if you only need this session."},"apiKeyName":{"type":"string","description":"Label for the API key (default `mcp-signup`)."},"apiKeyTtlDays":{"type":"integer","minimum":1,"maximum":365,"description":"API key lifetime in days. Server default applies when omitted."}},"required":["email","firstName","lastName"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-users-batch-create-v2","description":"Provision many Ethora users (1–100) in one asynchronous batch job — the bulk equivalent of `ethora-user-register`. Enqueues a background job (HTTP 202); the job reports per-user conflicts rather than failing the whole batch. Returns `{ jobId, statusUrl }`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`). Errors: 401/403 not in B2B mode; 422 `usersList` validation. Related: track with `ethora-wait-users-batch-job-v2`.","write_action":true,"price_micros":0,"input_schema":{"type":"object","properties":{"bypassEmailConfirmation":{"type":"boolean","description":"If true, created users skip email verification and are immediately usable. If false/omitted, each user receives a verification link."},"usersList":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"User's email address. Must be RFC-5322 valid."},"firstName":{"type":"string","minLength":1,"description":"User's first name, shown in their profile."},"lastName":{"type":"string","minLength":1,"description":"User's last name, shown in their profile."},"password":{"type":"string","minLength":1,"description":"Optional initial password. If omitted, the server generates one / relies on the verification flow."},"uuid":{"type":"string","minLength":1,"description":"Optional caller-supplied id to correlate this user with your own system in the job results."}},"required":["email","firstName","lastName"],"additionalProperties":false},"minItems":1,"maxItems":100,"description":"The users to create, 1–100 per batch."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":600000,"description":"HTTP timeout for the job-creation request (not the job itself), in milliseconds. Default 30000."}},"required":["usersList"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-users-batch-job-v2","description":"Fetch the current status and per-user results of a users batch job by `jobId` (one-shot, no polling). Returns the job object with its `state` (pending/running/completed/failed) and per-user outcomes.\nRequires: a `jobId` returned by `ethora-users-batch-create-v2`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`) — must match the auth used to create the job. Errors: 401/403 not in B2B mode; 404 unknown `jobId`. Related: `ethora-wait-users-batch-job-v2` for a blocking wait.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"jobId":{"type":"string","minLength":1,"description":"Job id returned by `ethora-users-batch-create-v2`."},"timeoutMs":{"type":"integer","minimum":500,"maximum":60000,"description":"HTTP timeout for this status request, in milliseconds. Default 10000."}},"required":["jobId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-wait-broadcast-job-v2","description":"Block until a broadcast job reaches a terminal state (`completed` or `failed`) or until `timeoutMs` — read-only polling wrapper around `ethora-chats-broadcast-job-v2`. Returns `{ done, state, job }`, or `{ done: false, reason: \"timeout\" }` on timeout.\nRequires: a `jobId` returned by `ethora-chats-broadcast-job-v2`.\nAuth: app-token mode OR B2B mode with an explicit `appId` — must match the auth used to enqueue the job. Errors: 401/403 wrong auth; 404 unknown `jobId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"24-char hex appId the job belongs to. Required in B2B mode unless already set via `ethora-app-select`; ignored in app-token mode."},"jobId":{"type":"string","minLength":1,"description":"Job id returned by `ethora-chats-broadcast-v2`."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":300000,"description":"Maximum time to wait, in milliseconds. Default 60000. Caps at 300000 (5 min)."},"intervalMs":{"type":"integer","minimum":250,"maximum":10000,"description":"Delay between status checks, in milliseconds. Default 1000. Lower = more responsive but more API calls."}},"required":["jobId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-wait-users-batch-job-v2","description":"Block until a users batch job reaches a terminal state (`completed` or `failed`) or `timeoutMs` — read-only polling wrapper around `ethora-users-batch-job-v2`. Returns `{ done, state, job }`, or `{ done: false, reason: \"timeout\" }` on timeout.\nRequires: a `jobId` returned by `ethora-users-batch-create-v2`.\nAuth: B2B mode (`ethora-auth-use-b2b` + a configured `b2bToken`) — must match the auth used to create the job. Errors: 401/403 not in B2B mode; 404 unknown `jobId`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"jobId":{"type":"string","minLength":1,"description":"Job id returned by `ethora-users-batch-create-v2`."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":300000,"description":"Maximum time to wait, in milliseconds. Default 60000. Caps at 300000 (5 min)."},"intervalMs":{"type":"integer","minimum":250,"maximum":10000,"description":"Delay between status checks, in milliseconds. Default 1000."}},"required":["jobId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"ethora-widget-embed-snippet","description":"Generate the <script> tag that embeds the Ethora AI chat widget (the floating launcher + chat panel that website visitors use) for an app, plus the prerequisites that must hold before it answers. No API call; pure generator using this deployment's hosted widget URL and public API base. The widget answers with the app's ACTIVE bot: for API-created apps run `ethora-agents-create-v2` -> `ethora-agent-invite-to-chat` -> `ethora-agents-activate-v2 { agentId, chatJid }` first, otherwise `POST /v2/widget/sessions` returns 422 and the widget stays silent.\nRequires: an activated agent on the app (`ethora-agents-activate-v2`); without it the widget opens but never answers.\nAuth: none required (uses the selected app when `appId` is omitted). Errors: effectively none; when no hosted widget is configured the snippet carries a `<WIDGET_URL>` placeholder. Related: `ethora-agents-activate-v2`, `ethora-bot-widget-v2` (legacy per-app bot only).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"appId":{"type":"string","description":"App the widget belongs to (24-char hex). Defaults to the app from `ethora-app-select`."},"botName":{"type":"string","description":"Display name shown in the widget header (`data-bot-name`), e.g. the agent's name."},"botAvatar":{"type":"string","description":"Avatar image URL shown for the bot (`data-bot-avatar`)."},"botId":{"type":"string","description":"Legacy `data-bot-id` (bot XMPP address); only for old embeds. Prefer `appId`: the backend picks the active agent from the app."},"primaryColor":{"type":"string","description":"Brand colour for launcher and bubbles (`data-primary-color`), e.g. `#0052CC`."},"locale":{"type":"string","description":"UI locale (`data-locale`), e.g. `en`, `fr`, `es`."},"greeting":{"type":"string","description":"Greeting shown when the panel opens (`data-greeting-message`)."},"position":{"type":"string","enum":["right","left"],"description":"Launcher corner (`data-position`)."},"apiBase":{"type":"string","description":"Override the public API base (`data-api-base`). Defaults to this deployment's public API URL."},"widgetUrl":{"type":"string","description":"Override the widget bundle base URL (the script is `<widgetUrl>/assistant.js`)."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"fetch","description":"Fetch the full text of a documentation section or tool reference entry by the id returned from `search` (e.g. `tool:ethora-app-create`, `doc:auth-map#app-jwt`, `doc:hosted-guide`).\nAuth: none required. Errors: unknown id.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"id":{"type":"string","description":"Document id from a `search` result."}},"required":["id"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"search","description":"Search the Ethora documentation and tool reference: auth model (app JWT vs app token vs B2B token vs API keys), hosted-server getting started, chat-component and backend SDK quickstarts, recipes, and a reference entry for every tool with its inputs. Use it for any \"how do I ...\" question about Ethora before guessing; then call `fetch` with a result id to read the full text.\nAuth: none required.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"query":{"type":"string","description":"Free-text query, e.g. 'create an app', 'invite agent to chat', 'api key bearer header'. Empty returns the getting-started guides."}},"required":["query"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}],"scan":{"score":99,"grade":"A","scanned_at":"2026-09-18T00:14:58.322Z","report":{"scannerVersion":"0.1.2","scannedAt":"2026-09-18T00:14:58.263Z","components":{"code":{"score":25,"max":25,"notes":["37 source files scanned"]},"reliability":{"score":20,"max":20,"notes":["remote reachable in 228ms (auth required)"]},"poisoning":{"score":15,"max":15,"notes":["91 tool descriptions checked"]},"auth":{"score":15,"max":15,"notes":["OAuth resource metadata advertised on 401"]},"maintenance":{"score":15,"max":15,"notes":["last push 0 days ago"]},"identity":{"score":9,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[],"inputs":{"probes":[{"url":"https://mcp.chat.ethora.com/mcp/oauth","reachable":true,"authRequired":true,"latencyMs":228,"authScheme":"oauth"},{"url":"https://mcp.chat.ethora.com/mcp","reachable":true,"authRequired":false,"latencyMs":720,"serverInfo":{"name":"Ethora MCP Server","version":"26.9.3"}}],"packages":[{"registryType":"npm","identifier":"@ethora/mcp-server","version":"26.9.3","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":5,"publishedAt":"2026-09-17T22:37:49.283Z","repositoryUrl":"git+https://github.com/dappros/ethora-mcp-server.git","weeklyDownloads":282}],"repo":{"found":true,"owner":"dappros","repo":"ethora-mcp-server","archived":false,"pushedAt":"2026-09-17T22:42:52Z","stars":6,"openIssues":1,"ownerType":"Organization","ownerCreatedAt":"2020-04-18T11:14:56Z","license":"MIT"}}}},"grade_history":[]}