{"ok":true,"site":{"host":"bandarra.me","url":"https://bandarra.me/apps/webmcp-text-editor/","desc":"WebMCP-enabled text editor with imperative tools for document I/O, workspace CRUD, on-device translation, and sub-agent (planner / researcher / writer / reviewer) delegation.","type":"demo","category":"Developer Tools","tools":[{"name":"list_skills","kind":"read","impl":"imperative","description":"Lists all skills available in this workspace. Returns an array of { id, name, description } entries. Use read_skill to fetch the full instructions for a skill, or delegate_to_skill to run one.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"read_skill","kind":"read","impl":"imperative","description":"Returns the full definition of a skill (id, name, description, instructions, optional model) given its id or name. Use this before delegate_to_skill to inspect what a skill does.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The skill id. Either id or name must be provided."},"name":{"type":"string","description":"The skill name (case-insensitive). Either id or name must be provided."}}},"page":"/"},{"name":"read","kind":"read","impl":"imperative","description":"Reads the complete current editor content.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"read_selection","kind":"read","impl":"imperative","description":"Reads the currently selected text in the editor.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"search","kind":"read","impl":"imperative","description":"Finds all occurrences of a query string in the document. Returns the line and column of each match.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"The text to search for."}},"required":["query"]},"page":"/"},{"name":"get_metadata","kind":"read","impl":"imperative","description":"Returns metadata about the current document: character count, word count, and line count.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"get_current_mode","kind":"read","impl":"imperative","description":"Returns the current UI mode: 'editor' (Monaco editor is visible) or 'preview' (Markdown preview is visible). Check this before making edits to ensure the editor is accessible.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"request_switch_to_editor","kind":"action","impl":"imperative","description":"Requests the user to switch from Preview mode to Editor mode. This will display a prompt to the user and pause until they accept or decline. Call this before attempting edits when in preview mode.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"edit","kind":"write","impl":"imperative","description":"Proposes a targeted edit. This tool pauses and waits for user approval. ONLY use this for small, localized changes (e.g., 1-2 sentences). Never pass the entire document.","inputSchema":{"type":"object","properties":{"originalText":{"type":"string","description":"The exact, minimal string of text to replace. Must be short. Do NOT pass the whole document."},"replacementText":{"type":"string","description":"The new text to replace the originalText with."}},"required":["originalText","replacementText"]},"page":"/"},{"name":"write","kind":"action","impl":"imperative","description":"Proposes a complete rewrite. This tool pauses and waits for user approval. ONLY use this when the user explicitly requests a total rewrite of the entire document.","inputSchema":{"type":"object","properties":{"content":{"type":"string","description":"The full new document content."}},"required":["content"]},"page":"/"},{"name":"get_active_doc_info","kind":"read","impl":"imperative","description":"Returns the id and title of the document currently open in the editor.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"list_workspace_docs","kind":"read","impl":"imperative","description":"Lists all documents in the workspace. Returns an array of { id, title } objects.","inputSchema":{"type":"object","properties":{}},"page":"/"},{"name":"read_workspace_doc","kind":"read","impl":"imperative","description":"Reads the full content of a specific document. Returns { title, content } or { error }.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The document ID to read."}},"required":["id"]},"page":"/"},{"name":"query_workspace_doc","kind":"read","impl":"imperative","description":"Asks a question about a specific document using a sub-agent. Returns { summary, excerpt } where excerpt is the most relevant verbatim passage.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The document ID to query."},"query":{"type":"string","description":"The question about the document."}},"required":["id","query"]},"page":"/"},{"name":"query_workspace","kind":"read","impl":"imperative","description":"Asks a question spanning all workspace documents and synthesizes the results. Returns { summary, sources: [{ id, title, excerpt }] }.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"The question to answer across all documents."}},"required":["query"]},"page":"/"},{"name":"create_document","kind":"write","impl":"imperative","description":"Creates a new document in the workspace with the given title and optional initial content. Providing content avoids a separate write step. Pauses for user authorization before creating.","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"The title for the new document."},"content":{"type":"string","description":"Optional initial content for the new document. If omitted the document is created blank."}},"required":["title"]},"page":"/"},{"name":"rename_document","kind":"action","impl":"imperative","description":"Renames an existing document in the workspace. Pauses for user authorization before renaming.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The document ID to rename."},"title":{"type":"string","description":"The new title for the document."}},"required":["id","title"]},"page":"/"},{"name":"delete_document","kind":"write","impl":"imperative","description":"Deletes a document from the workspace. Pauses for user authorization before deleting. If the deleted document was active, a different document becomes active.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The document ID to delete."}},"required":["id"]},"page":"/"},{"name":"switch_active_document","kind":"action","impl":"imperative","description":"Switches the active document in the editor. Saves the current document content before switching. Does not require user authorization.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"The document ID to switch to."}},"required":["id"]},"page":"/"},{"name":"translate","kind":"action","impl":"imperative","description":"Translate a piece of text from one language to another using an on-device AI model. Languages are specified as BCP 47 tags (e.g. 'en', 'fr', 'ja').","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The text to translate."},"sourceLanguage":{"type":"string","description":"BCP 47 language tag of the source language (e.g. \"en\")."},"targetLanguage":{"type":"string","description":"BCP 47 language tag of the target language (e.g. \"fr\")."}},"required":["text","sourceLanguage","targetLanguage"]},"page":"/"},{"name":"delegate_to_skill","kind":"action","impl":"imperative","description":"Delegates a task to a named skill (sub-agent). The skill runs with read-only access and returns its response as a string. Interpret the response and act on it accordingly.","inputSchema":{"type":"object","properties":{"skillName":{"type":"string","description":"The exact name of the skill to invoke."},"task":{"type":"string","description":"The specific task or instructions to pass to the skill."}},"required":["skillName","task"]},"page":"/"},{"name":"invoke_agent","kind":"action","impl":"imperative","description":"Delegates an ad-hoc task to a generic sub-agent. The sub-agent runs with the given system prompt and optional tool groups. Returns { result: string } with the sub-agent's final response.","inputSchema":{"type":"object","properties":{"systemPrompt":{"type":"string","description":"The system prompt / instructions for the sub-agent."},"task":{"type":"string","description":"The task or question to send to the sub-agent."},"tools":{"type":"array","items":{"type":"string"},"description":"Optional tool group names to give the sub-agent. Supported: 'workspace_readonly'."}},"required":["systemPrompt","task"]},"page":"/"},{"name":"invoke_planner","kind":"action","impl":"imperative","description":"Decomposes a high-level task into a structured step-by-step Plan. Returns a JSON string: { goal, steps: [{ id, instruction, dependsOn }] }. The Orchestrator reads the plan and dispatches each step using the appropriate tools.","inputSchema":{"type":"object","properties":{"task":{"type":"string","description":"The high-level task to decompose into a plan."},"context":{"type":"string","description":"Optional additional context (e.g. current document summary, workspace doc list)."}},"required":["task"]},"page":"/"},{"name":"invoke_researcher","kind":"action","impl":"imperative","description":"Queries workspace documents and synthesizes a structured answer. Returns JSON: { summary, sources: [{ id, title, excerpt }] }. Use this when the task requires finding information across workspace documents before writing or reviewing.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"The question or information need to research."},"docIds":{"type":"array","items":{"type":"string"},"description":"Optional list of document IDs to restrict the search to. If omitted, all workspace documents are queried."}},"required":["query"]},"page":"/"},{"name":"invoke_writer","kind":"action","impl":"imperative","description":"Generates draft text for a single targeted section from an instruction and optional research/style context. Returns { draft: string } — raw text only, no edits applied. After receiving the draft, apply it using edit() for the target section. Do NOT use this to rewrite the whole document at once — use invoke_planner to break full-document tasks into per-section steps.","inputSchema":{"type":"object","properties":{"instruction":{"type":"string","description":"What to write. Be explicit: specify the target section, desired length, and any constraints."},"researchContext":{"type":"string","description":"JSON-encoded ResearchResult from invoke_researcher. Inject when the draft should cite workspace sources."},"styleContext":{"type":"string","description":"A verbatim excerpt from the document the Writer should match in tone, voice, and formatting."}},"required":["instruction"]},"page":"/"},{"name":"invoke_reviewer","kind":"action","impl":"imperative","description":"Evaluates a draft against explicit criteria and returns structured feedback. Returns JSON: { passed: boolean, issues: [{ severity, location?, description, fix? }], summary }. Use after invoke_writer to check a draft before applying it. If passed is false and error-severity issues remain after 3 Writer→Reviewer cycles, present the best available draft via edit() or write() and summarise remaining issues in your response.","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The draft text to review."},"criteria":{"type":"array","items":{"type":"string"},"description":"Review criteria to check against (e.g. 'grammatical correctness', 'consistent use of past tense', 'no unsupported factual claims')."}},"required":["text","criteria"]},"page":"/"},{"name":"post_comment","kind":"action","impl":"declarative","description":"Leave a blog post comment","inputSchema":{"type":"object","properties":{"slug":{"type":"string"},"website":{"type":"string"},"author_name":{"type":"string"},"author_email":{"type":"string"},"text":{"type":"string"}},"required":["author_name","text"]},"page":"/posts/bringing-the-agent-loop-to-the-web"}],"_scrape":{"etag":null,"lastModified":"Thu, 28 May 2026 13:40:01 GMT","scrapedAt":"2026-05-28T13:40:23.945Z"},"apiSurface":"spec","prominence":3,"favicon":"/favicons/bandarra.me.png","toolCount":27}}