description: Uses Embrapa4Dev snippets for BootstrapBlazor UI work. Invoke when implementing, creating, modifying, or troubleshooting any .NET / Blazor / BootstrapBlazor UI component or page across razor, csharp, javascript, and json feature parts. alwaysApply: true --- # Embrapa4Dev — BootstrapBlazor Snippet Assistant ## When to activate Activate this workflow when the developer asks about **implementing, creating, modifying, or troubleshooting** any **.NET / Blazor / BootstrapBlazor** UI component or page — across **all four snippet languages** (`razor`, `csharp`, `javascript`, `json`) that make up a feature. Examples: - "How do I build a table with server-side pagination?" (razor) - "Create a form with validation" (razor + csharp) - "Implement a modal dialog with confirmation" (razor) - "Add a dropdown with async data loading" (razor + csharp) - "How to show a loading spinner while fetching data?" (razor) - "How to call ToastService from code-behind?" (csharp) - "How to use IDbContextFactory inside a Blazor page?" (csharp) - "How to invoke a BootstrapBlazor component method via @ref?" (csharp) - "How to handle OnQueryAsync or OnClickTabItemAsync callbacks?" (csharp) - "JSInterop helper to open a URL / focus an element" (javascript) - "appsettings or localization JSON for a component/feature" (json) > The snippet library contains validated snippets in **four languages** — `razor`, `csharp`, `javascript`, `json` — all targeting **the BootstrapBlazor version installed in this project**. Never hardcode a version from memory: each search result carries a `bootstrapBlazorVersion` field, and the project's own `.csproj` / baseline setting is the source of truth. When a feature touches more than one language (e.g. a Razor page + its C# callback + a JSInterop helper + a JSON config), **search for each language**. Always search before assuming a pattern. See **Snippet languages** below. **Do NOT activate** for: - Pure C# backend logic with zero connection to a Blazor component: domain models, EF migrations, infrastructure services, pure data-access code - Database migrations, EF Core queries unrelated to a Blazor page - Architecture or design pattern discussions - Questions about other frontend frameworks (React, Angular, Vue) --- ## Snippet languages (4 — all first-class) Every snippet carries a `language` field. The library has **four** values, and all four are **priority sources** when implementing a feature — do not limit the search to Razor: | `language` | Cobre | Quando buscar | |---|---|---| | `razor` | Markup Blazor/BootstrapBlazor. **Trechos de HTML e CSS puro também são `razor`, mas só podem ser usados se expressamente solicitados no prompt** (ver regra `Html/` abaixo) | Página, componente, layout, template | | `csharp` | Code-behind, `@code`, services, callbacks de componente (`OnQueryAsync`, `OnClickTabItemAsync`), `@ref`, padrões de `ToastService` / `IDbContextFactory` em página | Lógica que dá suporte ao componente | | `javascript` | JSInterop, arquivos `.js`, helpers chamados via `IJSRuntime` (ex.: `window.open`, foco, scroll) | Qualquer interação que exija JS | | `json` | Configuração e dados: `appsettings`, localização (`Locales/*.json`), seed, opções de componente | Config/i18n que acompanha o componente | > **Uma funcionalidade quase sempre cruza linguagens.** Ex.: uma página Razor (`razor`) + seu callback (`csharp`) + um helper JSInterop (`javascript`) + chaves de i18n (`json`). **Faça uma busca por linguagem relevante** — não pare na primeira que retornar markup. > ⚠️ **HTML/CSS puro dentro de `razor`:** snippets cujo `componentName` começa com `Html/` (ex.: `Html/Table`, `Html/Select`) ou que tenham a tag `html` são `language: razor` mas representam HTML/CSS puro. **Só podem ser utilizados se o prompt do desenvolvedor solicitar HTML/CSS puro de forma expressa.** Fora desse caso, descarte-os e use sempre o componente BootstrapBlazor nativo equivalente — mesmo que isso exija buscar outro snippet ou implementar via documentação oficial da versão instalada. Não há exceção por "ausência de componente BB". --- ## Workflow (execute in order, every time) ### 1 — Recall similar past sessions Call `recall_similar_sessions` as the very first action. This tool uses a high similarity threshold (0.75), so **zero results is normal for new topics** — proceed to step 2 regardless. ``` recall_similar_sessions( query: , top_k: 3 ) ``` Use returned sessions to: reuse validated patterns, avoid already-rejected approaches, and adapt project-specific conventions from prior work. ### 1b — Retrieve institutional conventions (parallel with step 1) Call `get_project_conventions` to fetch the curated institutional rules — architectural decisions, naming standards, integration patterns — that the Architect maintains. Run it **in parallel with step 1** (and with `list_components`, step 2a). ``` get_project_conventions( topic: ) ``` - **Always pass `topic`.** Pick the 1–2 topics relevant to the scenario (UI feature → `ui-patterns` + possibly `i18n`; API/integration → `http`; login/roles → `auth`/`security`; EF/queries → `data-access`). Make one call per topic, in parallel. - ⚠️ **Never call without `topic`:** the full payload is ~64 KB and exceeds the tool-result token limit of most harnesses — the call fails or gets dumped to a file you then have to slice manually. - **Unknown/misspelled `topic`:** returns an empty result plus `availableTopics` — pick the right one from that list and call again. It is never an error. - **Conventions outrank snippets.** A snippet shows *how* a component is used; a convention states what this institution *requires*. If a snippet contradicts an active convention, follow the convention and say so explicitly in your answer. ### 2 — Discover components (if needed) + search snippets **Step 2a — If you do not know the exact BootstrapBlazor component name,** call `list_components` to see the full catalogue. This call can run **in parallel with step 1** to save time. ``` list_components() ``` **Step 2b — Search the snippet library** with a **behavior-first** query that descreve o que o usuário faz e o que acontece — não apenas o nome do componente. - ❌ Genérico: `"Table com checkbox"` - ✅ Comportamento: `"Table com coluna de seleção por checkbox controlada externamente via HashSet, HeaderTemplate para select-all, reload ao trocar papel via @key"` > 🔎 **Inclua os nomes exatos** de componente, método, callback ou API que você já conhece (`Table`, `OnQueryAsync`, `ToastService`, `IJSRuntime`). O ranking é **híbrido — semântico + lexical** —, então o nome literal presente no snippet **eleva o resultado certo ao topo**. `"Table OnQueryAsync paginação server-side"` supera `"tabela com paginação"`. ``` search_snippets( query: , component: , category: , top_k: 5 ) ``` **Se o componente tiver ≥ 5 snippets** (conforme `list_components`), execute **uma segunda query complementar** que capture um ângulo diferente do cenário (ex.: se a primeira buscou o modelo de interação, a segunda busca o modelo de carga de dados). Faça as duas chamadas em paralelo. **Busca multilíngue (obrigatória quando a funcionalidade cruza linguagens):** se a feature precisa de mais de uma linguagem (ver **Snippet languages**), faça **uma query por linguagem relevante**, em paralelo. Inclua o termo da linguagem na query para enviesar o resultado — ex.: `"JSInterop window.open para abrir URL em nova aba"` (javascript), `"chaves de localização JSON para a tela X"` (json), `"callback OnQueryAsync com IDbContextFactory"` (csharp). Não conclua a busca apenas com o snippet `razor`. #### Formato da resposta — duas formas possíveis | Situação | Formato | O que significa | |---|---|---| | **Algum snippet passou do limiar** | **Array puro** de resultados | Snippets **validados**. Fonte primária legítima. | | **Nenhum snippet passou do limiar** | **Objeto** `{ message, results[] }` com cada item marcado `partial_match: true` | ⚠️ **NÃO são exemplos validados** — são apenas os vizinhos mais próximos abaixo do limiar. | > 🚨 **`partial_match: true` = zero resultados.** Itens com essa flag **nunca** podem ser usados como fonte primária de implementação, por mais que tragam código. Trate-os apenas como **inspiração** para refinar a query. Leia o campo `message`: ele confirma que nenhum snippet validado atende à query e que o termo foi registrado como lacuna de conhecimento para a equipe de curadoria. **Se a resposta vier com `partial_match: true` (ou vazia):** 1. **Refine a query uma vez** — inclua o nome exato do componente/método (ver dica de ranking híbrido acima), remova os filtros `component`/`category`, ou tente sinônimos. 2. **Se ainda assim vier `partial_match`,** vá para o **step 2d** (gate de fallback HTML/CSS) antes de qualquer implementação. 3. Ao concluir sem snippet validado, **informe ao desenvolvedor** que não há exemplo validado para essa necessidade e que ele pode contribuir com o snippet faltante pela Admin UI em `/admin/snippets/new`. > ⚠️ **HTML/CSS puro (`Html/`):** ver a regra completa na seção **Snippet languages** — `componentName` `Html/*` / tag `html` **só** se o prompt pedir HTML/CSS puro expressamente; caso contrário, descartar e usar o componente BootstrapBlazor nativo. ### 2c — Avaliar resultados contra o cenário > **`search_snippets` já retorna o campo `code` completo** de cada resultado, além de `title`, `description` e `tags`. Avalie a aderência primeiro por `title` + `description` + `tags`; confirme no `code` do próprio resultado quando necessário. **Não há necessidade de chamadas extras para obter o código.** **Extraia os requisitos-chave do cenário** da story ou pedido do desenvolvedor. Para cada resultado de 2b, avalie usando apenas `title` + `description` + `tags`: | Critério | O que verificar | |---|---| | **Modelo de interação** | O snippet descreve o mesmo padrão de uso? (ex.: seleção via HashSet vs. SelectedRows nativo) | | **Modelo de carga** | O snippet usa o mesmo gatilho de carga? (ex.: `OnQueryAsync` disparado por `@key` vs. carga no `OnInitializedAsync`) | | **Gestão de estado** | O snippet controla estado da mesma forma? (ex.: estado externo ao componente vs. interno) | | **Linguagem certa** | O `language` do snippet corresponde à parte da feature em questão (`razor`/`csharp`/`javascript`/`json`)? Cada linguagem necessária deve ter seu próprio candidato. | | **Componente nativo** | `componentName` é BootstrapBlazor puro? Descartar `Html/*` (HTML/CSS puro) a menos que o prompt o solicite expressamente — ver **Snippet languages** | | **Pontuação** | Cada item traz `similarityScore` (semântico), `lexicalScore` (casamento textual) e `combinedScore` — **é o `combinedScore` que define a ordem**. Alta pontuação ajuda, mas **não decide**: um snippet com `combinedScore` 0.61 que atende todos os critérios acima vence um com 0.68 que só casa o nome do componente | | **Não é partial match** | O item **não** pode ter `partial_match: true` — esses são descartados aqui por definição (ver 2b) | **Selecione os 1–2 snippets com melhor aderência ao cenário, por linguagem necessária** e avance direto para o passo 4 (implementação) — o `code` já está no resultado do search; o passo 3 só é necessário para metadados. Documente brevemente por que cada candidato foi escolhido ou descartado. **Se nenhum candidato aderir ao cenário** (todos descartados, ou só sobraram snippets `Html/*` que o prompt não autorizou), vá para **step 2d** antes de implementar. ### 2d — Gate de fallback HTML/CSS (quando nenhum snippet nativo serve) Acione este passo **apenas** quando, após 2b + 2c, **não houver snippet compatível** (zero resultados, ou nenhum aderente ao cenário). 1. **Pergunte ao usuário**, de forma explícita, se ele quer que você faça uma busca de snippets em **HTML e CSS** para resolver a necessidade. Ex.: *"Não encontrei snippet de componente BootstrapBlazor compatível com X. Quer que eu busque snippets em HTML/CSS puro para essa parte?"* - **NÃO** prossiga com HTML/CSS sem essa confirmação — a resposta afirmativa do usuário **é** a "solicitação expressa" exigida pela regra de **Snippet languages**. 2. **Se o usuário confirmar (sim):** volte ao `search_snippets` mirando HTML/CSS — inclua termos como `html`/`css` na query e considere `componentName` `Html/*` — e avalie os resultados pelos mesmos critérios do passo 2c. Os snippets `Html/*` deixam de ser descartados **para esta necessidade específica**. Depois siga ao passo 4 normalmente. 3. **Se o usuário recusar (não), ou não houver snippet HTML/CSS adequado:** siga ao **passo 4 fallback** (implementar via documentação oficial da versão de BootstrapBlazor instalada no projeto), declarando explicitamente que nenhum snippet foi reutilizado. ### 3 — (Opcional) Get snippet detail > **Na maioria das sessões este passo é desnecessário** — o `code` completo já veio no resultado do `search_snippets` (passo 2b). Use o código de lá diretamente. Chame `get_snippet_detail` **apenas** quando precisar de algo que o search não traz: - metadados extras: `embeddingStatus`, `createdAt`/`updatedAt`, `createdBy`; - confirmar a versão/autoria de um snippet antes de reportar divergência; - o `code` do resultado do search chegou visivelmente truncado pelo harness. ``` get_snippet_detail(id: ) ``` ### 4 — Implement using snippets as primary source - **Priorize os snippets validados das 4 linguagens** (`razor`, `csharp`, `javascript`, `json`) como fonte primária para cada parte da implementação — markup, code-behind, JSInterop e config/i18n. Snippet correspondente disponível ⇒ siga-o; não improvise um padrão paralelo. - Follow the retrieved snippet patterns **exactly** — do not adapt to other BootstrapBlazor versions. - Target **the BootstrapBlazor version this project actually uses** — read it from the project's `.csproj` (package reference) or from the `bootstrapBlazorVersion` field on the retrieved snippets. Patterns from older major/minor releases are frequently incompatible: **never** assume a version from memory, and never carry an API over from an older-version example. - Preserve project-specific base classes, services, and DI registrations found in snippets. - **No relevant snippet found** (para uma dada linguagem): só chegue aqui **após** o gate do passo 2d (oferecer busca HTML/CSS ao usuário). Então declare explicitamente que nenhum snippet foi reutilizado e implemente usando os padrões da documentação oficial de BootstrapBlazor **na versão instalada no projeto**. Do not guess from older-version examples or generic Blazor patterns. - **Snippets `Html/` ou com tag `html` (HTML/CSS puro): use apenas se o prompt solicitar HTML/CSS puro expressamente — ou se o usuário confirmar a busca HTML/CSS no gate do passo 2d.** Caso contrário, descarte e implemente com o componente BootstrapBlazor nativo (ver **Snippet languages**). ### 5 — Rate the session (mandatory — end of every session) At the end of any session where `search_snippets` or `get_snippet_detail` was called, call `rate_interaction` automatically. **Do not wait for the developer to ask.** ``` rate_interaction( score: <1–5>, comment: ) ``` **Scoring guide:** | Score | Meaning | |-------|---------| | 5 | Snippet found, used directly, implementation was correct | | 4 | Snippet found, minor adaptation needed | | 3 | Snippet partially useful; significant adaptation required | | 2 | Snippet found but misleading or outdated; had to ignore it | | 1 | No relevant snippet found; MCP did not help this session | --- ## Tool reference | Tool | Purpose | Call when | |------|---------|-----------| | `recall_similar_sessions` | Prior session context — patterns, corrections, project decisions | Step 1 — always, before anything else | | `get_project_conventions` | Institutional rules curated by the Architect. **Always pass `topic`** (`ui-patterns`, `http`, `i18n`, `config`, `audit`, `auth`, `security`, `data-access`) — the unfiltered payload (~64 KB) blows the tool-result limit | Step 1b — always, in parallel with step 1. **Conventions outrank snippets on conflict** | | `list_components` | Full catalogue of components with snippet counts | Step 2a — when component name is unknown (parallel with step 1) | | `search_snippets` | **Hybrid search (semantic + lexical)** over the validated snippet library. Results include the **full `code`** plus scores. Returns a bare array when snippets clear the threshold, or `{ message, results[] }` with `partial_match: true` when none do | Step 2b — always (2 queries em paralelo se componente ≥ 5 snippets) | | `get_snippet_detail` | Extra metadata (`embeddingStatus`, timestamps, author) for one snippet by UUID — the `code` is the same one search already returned | Step 3 — only when metadata is needed or search `code` was truncated | | `list_snippets` | Paginated inventory (id, component, language, title, tags) with `componentName`/`language` filters — no relevance ranking | Exhaustive inventory or de-duplication checks (e.g. before contributing a new snippet) | | `ping` | Returns pong | Only to diagnose MCP transport issues | | `rate_interaction` | Usefulness feedback for continuous library improvement | Step 5 — end of every MCP session, mandatory | ## MCP server Server name: `e4devia-mcp` Endpoint: `https://mcp-e4devia-d.nuvem.ti.embrapa.br/mcp`