From 7fcd3172056aee033c2b482bf589cd479ab9b0e3 Mon Sep 17 00:00:00 2001 From: davegilligan Date: Tue, 2 Jun 2026 07:45:17 +0200 Subject: [PATCH] feat(tools): reposition as Do Better Legal two-track Norwegian-law MCP De-family-ify shared JSON tools (persona-aware routing + neutral base prompt), make the verification review pick its engine per track (family/child-welfare -> dbn-legal-agent-v3, others -> gpt-4o interim), and route product-name strings through dbnToolsProductName(). Rebrand the MCP/tools surface (mcp.php + i18n mcp_* strings) to Do Better Legal. Co-Authored-By: Claude Opus 4.7 --- api/korrespond-refine.php | 6 ++- api/legal-analysis.php | 6 ++- includes/BvjAnalyzerAgent.php | 8 ++-- includes/DbnMcpRuntime.php | 2 +- includes/DeepResearchAgent.php | 13 +++--- includes/DiscrepancyAgent.php | 5 ++- includes/KorrespondAgent.php | 7 ++-- includes/LegalAnalysisAgent.php | 24 ++++++++--- includes/LegalTools.php | 54 +++++++++++++++---------- includes/bootstrap.php | 71 +++++++++++++++++++++++++++------ includes/i18n.php | 32 +++++++-------- mcp.php | 2 +- 12 files changed, 158 insertions(+), 72 deletions(-) diff --git a/api/korrespond-refine.php b/api/korrespond-refine.php index 80c5946..efae15a 100644 --- a/api/korrespond-refine.php +++ b/api/korrespond-refine.php @@ -75,8 +75,12 @@ try { 'language' => $language, ]); + $personaSlug = (isset($input['profile']) && is_string($input['profile']) && trim($input['profile']) !== '') + ? trim($input['profile']) + : null; + $agent = new DbnKorrespondAgent(); - $result = $agent->refine($intake, $classify, $originalDraftNo, $jurisdiction, $emit); + $result = $agent->refine($intake, $classify, $originalDraftNo, $jurisdiction, $emit, $personaSlug); $ftRemaining = dbnToolsFreeTierDeduct($ftUid, 'korrespond_refine'); $result['ok'] = true; $result['latency_ms'] = (int)round((microtime(true) - $startTime) * 1000); diff --git a/api/legal-analysis.php b/api/legal-analysis.php index 05b96e2..f9fe63a 100644 --- a/api/legal-analysis.php +++ b/api/legal-analysis.php @@ -64,7 +64,8 @@ try { $personaResolved = dbnToolsResolvePersona((int)$client['id'], $personaSlug); $agent = (new DbnLegalAnalysisAgent()) - ->withPersonaPrompt($personaResolved['system_prompt'] ?? null); + ->withPersonaPrompt($personaResolved['system_prompt'] ?? null) + ->withPersonaSlug($personaResolved['slug'] ?? $personaSlug); // Pass 1 — extract issues (Azure, fast); deduct credit AFTER this succeeds $emit('progress', ['step' => 'extracting_issues', 'detail' => 'Identifying distinct legal issues…']); @@ -132,7 +133,8 @@ try { $legalCheck = dbnToolsRunLegalCheck( mb_strimwidth((string)($synth['overall_assessment'] ?? ''), 0, 800), $docType, - $personaResolved['system_prompt'] ?? null + $personaResolved['system_prompt'] ?? null, + $personaResolved['slug'] ?? $personaSlug ); } catch (Throwable) {} diff --git a/includes/BvjAnalyzerAgent.php b/includes/BvjAnalyzerAgent.php index 0b260f1..65d1546 100644 --- a/includes/BvjAnalyzerAgent.php +++ b/includes/BvjAnalyzerAgent.php @@ -847,9 +847,10 @@ PROMPT; : ''; $docExcerpt = mb_substr($docText, 0, 8000, 'UTF-8'); + $product = dbnToolsProductName(); $prompt = <<resolvedPersonaPrompt + $this->resolvedPersonaPrompt, + $this->personaSlug ); if (!empty($checkFindings)) { if (!is_array($json['procedural_red_flags'] ?? null)) { @@ -1379,7 +1381,7 @@ PROMPT; dbnToolsAbort('The family-legal corpus package is not active.', 503, 'package_unavailable'); } if (!dbnToolsHasActiveSubscription($clientId, (int)$package['id'])) { - dbnToolsAbort('Do Better Norge does not have an active family-legal subscription.', 503, 'subscription_missing'); + dbnToolsAbort(dbnToolsProductName() . ' does not have an active family-legal subscription.', 503, 'subscription_missing'); } return $package; } diff --git a/includes/DbnMcpRuntime.php b/includes/DbnMcpRuntime.php index 18ea0dc..4d517d6 100644 --- a/includes/DbnMcpRuntime.php +++ b/includes/DbnMcpRuntime.php @@ -56,7 +56,7 @@ final class DbnMcpRuntime 'mode' => ['type' => 'string', 'enum' => ['standard', 'strict']], 'output_format' => ['type' => 'string', 'enum' => ['contextual', 'generic', 'pseudonym']], ], ['text']), - self::tool('dbn.translate', 'Translate legal document', 'Translate Norwegian family-law text with legal terminology annotations.', [ + self::tool('dbn.translate', 'Translate legal document', 'Translate Norwegian legal text with legal terminology annotations.', [ 'text' => $text, 'source_lang' => $lang, 'target_lang' => $lang, diff --git a/includes/DeepResearchAgent.php b/includes/DeepResearchAgent.php index 300a4d0..b16ac37 100644 --- a/includes/DeepResearchAgent.php +++ b/includes/DeepResearchAgent.php @@ -440,7 +440,7 @@ final class DbnDeepResearchAgent dbnToolsAbort('The family-legal corpus package is not active.', 503, 'package_unavailable'); } if (!dbnToolsHasActiveSubscription($clientId, (int)$package['id'])) { - dbnToolsAbort('Do Better Norge does not have an active family-legal subscription.', 503, 'subscription_missing'); + dbnToolsAbort(dbnToolsProductName() . ' does not have an active family-legal subscription.', 503, 'subscription_missing'); } return $package; } @@ -487,8 +487,9 @@ final class DbnDeepResearchAgent $priorContextBlock = implode("\n", $parts) . "\n\nNow investigate this branch:\n"; } + $product = dbnToolsProductName(); $prompt = << self::L('legal_check', $userLang)]); } $legalCheck = []; try { - $legalCheck = dbnToolsRunLegalCheck($checked['draft'], $body); + $legalCheck = dbnToolsRunLegalCheck($checked['draft'], $body, null, $persona); } catch (Throwable $e) { /* silent — non-critical */ } // ── Translate to user language (if not Norwegian) ─────────────────────── @@ -777,7 +777,8 @@ EOT, array $classify, string $originalDraftNo, string $jurisdiction, - ?callable $emit = null + ?callable $emit = null, + ?string $persona = null ): array { $body = $intake['recipient_body'] ?? 'other'; $outputType = $intake['output_type'] ?? 'email'; @@ -808,7 +809,7 @@ EOT, if ($emit) { $emit('progress', ['detail' => self::L('legal_check', $userLang)]); } $legalCheckRefine = []; try { - $legalCheckRefine = dbnToolsRunLegalCheck($checked['draft'], $body); + $legalCheckRefine = dbnToolsRunLegalCheck($checked['draft'], $body, null, $persona); } catch (Throwable $e) { /* silent — non-critical */ } $draftUser = $checked['draft']; diff --git a/includes/LegalAnalysisAgent.php b/includes/LegalAnalysisAgent.php index 76f909e..b152efa 100644 --- a/includes/LegalAnalysisAgent.php +++ b/includes/LegalAnalysisAgent.php @@ -28,6 +28,8 @@ final class DbnLegalAnalysisAgent /** Persona system prompt (from the resolved chat profile); null ⇒ use the built-in barnevern prompt. */ private ?string $personaPrompt = null; + /** Persona slug driving the per-track reviewer model; default = child-welfare (family track). */ + private string $personaSlug = 'child-welfare'; public function withPersonaPrompt(?string $prompt): self { @@ -36,6 +38,15 @@ final class DbnLegalAnalysisAgent return $this; } + public function withPersonaSlug(?string $slug): self + { + $slug = is_string($slug) ? trim($slug) : ''; + if ($slug !== '') { + $this->personaSlug = $slug; + } + return $this; + } + public function __construct() { // On Azure: gpt-4o-mini for extraction/synthesis. On Bedrock: factory picks Haiku/Sonnet. @@ -408,11 +419,12 @@ PROMPT; $userMsg .= "\n\n" . $ctxLabel . ': ' . $issue['brief_context']; } if ($corpusContext !== '') { + $product = dbnToolsProductName(); $srcLabel = match ($language) { - 'no' => 'Relevante kilder fra Do Better Norge-korpuset', - 'pl' => 'Istotne źródła z korpusu Do Better Norge', - 'uk' => 'Релевантні джерела з корпусу Do Better Norge', - default => 'Relevant sources from the Do Better Norge corpus', + 'no' => 'Relevante kilder fra ' . $product . '-korpuset', + 'pl' => 'Istotne źródła z korpusu ' . $product, + 'uk' => 'Релевантні джерела з корпусу ' . $product, + default => 'Relevant sources from the ' . $product . ' corpus', }; $userMsg .= "\n\n" . $srcLabel . ":\n" . $corpusContext; } @@ -613,7 +625,9 @@ PROMPT; try { $legalCheck = dbnToolsRunLegalCheck( mb_strimwidth($synth['overall_assessment'], 0, 800), - $docType + $docType, + $this->personaPrompt, + $this->personaSlug ); } catch (Throwable) {} diff --git a/includes/LegalTools.php b/includes/LegalTools.php index b8deb40..8b0a3b5 100644 --- a/includes/LegalTools.php +++ b/includes/LegalTools.php @@ -39,8 +39,9 @@ final class DbnLegalToolsService 'shared' => 'Legal Library only', default => 'Legal Library + personal corpus', }; + $product = dbnToolsProductName(); $trace = [ - $this->trace('Query interpretation', "Searching Do Better Norge {$scopeLabel}.", 'complete'), + $this->trace('Query interpretation', "Searching {$product} {$scopeLabel}.", 'complete'), $this->trace('Search tools used', 'ClientRagPipeline::searchAll with keyword mode.', 'running'), ]; @@ -252,12 +253,9 @@ Return JSON only with these keys: } PROMPT; - // Persona voice/domain prepended to the JSON-enforcing scaffold (keeps the + // Persona voice/domain folded into the JSON-enforcing scaffold (keeps the // structured-output contract while applying the persona's legal framing). - $system = $this->legalJsonSystemPrompt($language); - if (!empty($personaResolved['system_prompt'])) { - $system = $personaResolved['system_prompt'] . "\n\n" . $system; - } + $system = $this->legalJsonSystemPrompt($language, $personaResolved['system_prompt'] ?? null); $askDeployment = $personaModel; $raw = $gateway->withDeployment($askDeployment)->chatText([ ['role' => 'system', 'content' => $system], @@ -1166,7 +1164,7 @@ PROMPT; dbnToolsAbort('The family-legal corpus package is not active.', 503, 'package_unavailable'); } if (!dbnToolsHasActiveSubscription($clientId, (int)$package['id'])) { - dbnToolsAbort('Do Better Norge does not have an active family-legal subscription.', 503, 'subscription_missing'); + dbnToolsAbort(dbnToolsProductName() . ' does not have an active family-legal subscription.', 503, 'subscription_missing'); } return $package; } @@ -1191,30 +1189,44 @@ PROMPT; return [$this->azure, ($engine === 'azure_full') ? 'gpt-4o' : 'gpt-4o-mini']; } - private function runJsonTool(string $prompt, string $language, int $maxTokens): array + private function runJsonTool(string $prompt, string $language, int $maxTokens, ?array $persona = null): array { - $raw = $this->azure->chatText([ - ['role' => 'system', 'content' => $this->legalJsonSystemPrompt($language)], + // With a persona, route to its pinned engine (Track-1 → tuned Qwen, Track-2 → gpt-4o) + // and fold its domain framing into the system prompt. Without one (e.g. pasted-text + // tools), keep the default Azure routing with the neutral base prompt. + $personaPrompt = $persona['system_prompt'] ?? null; + if ($persona !== null) { + [$gateway, $model] = $this->personaGateway($persona, 'azure_mini'); + $gateway = $gateway->withDeployment($model); + } else { + $gateway = $this->azure; + } + $raw = $gateway->chatText([ + ['role' => 'system', 'content' => $this->legalJsonSystemPrompt($language, $personaPrompt)], ['role' => 'user', 'content' => $prompt], ], [ 'json' => true, 'temperature' => 0.1, 'max_tokens' => $maxTokens, ]); - $json = $this->azure->decodeJsonObject($raw); + $json = $gateway->decodeJsonObject($raw); if (!$json) { - dbnToolsAbort('Azure OpenAI did not return valid structured JSON.', 502, 'azure_invalid_json'); + dbnToolsAbort('The model did not return valid structured JSON.', 502, 'invalid_json'); } return $json; } - private function legalJsonSystemPrompt(string $language): string + private function legalJsonSystemPrompt(string $language, ?string $personaPrompt = null): string { - $locale = dbnToolsLanguageName($language); + $locale = dbnToolsLanguageName($language); + $product = dbnToolsProductName(); + $personaPrompt = is_string($personaPrompt) ? trim($personaPrompt) : ''; + // The persona (family, immigration, labour, …) supplies the domain framing; the + // base prompt stays domain-neutral so non-family tracks are not cast as child-welfare. + $personaBlock = $personaPrompt !== '' ? ($personaPrompt . "\n") : ''; return << $title, 'excerpt' => $docSummary ?? $rawExcerpt, 'chunk_text' => $rawExcerpt, - 'package_or_corpus' => (string)($chunk['source_name'] ?? $chunk['source_type'] ?? 'Do Better Norge'), + 'package_or_corpus' => (string)($chunk['source_name'] ?? $chunk['source_type'] ?? dbnToolsProductName()), 'score' => $score, 'document_id' => isset($chunk['document_id']) ? (int)$chunk['document_id'] : null, 'chunk_id' => isset($chunk['id']) ? (int)$chunk['id'] : null, @@ -1354,7 +1366,7 @@ PROMPT; $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as &$row) { $row['similarity'] = 0.25; - $row['source_name'] = 'Do Better Norge private corpus'; + $row['source_name'] = dbnToolsProductName() . ' private corpus'; $row['source_type'] = 'private'; } return $rows; @@ -1819,7 +1831,7 @@ PROMPT; $enriched = $text; $corpusUsed = $corpusContext !== ''; if ($corpusUsed) { - $enriched = "[Relevant legal context from Do Better Norge corpus]\n" + $enriched = '[Relevant legal context from ' . dbnToolsProductName() . " corpus]\n" . $corpusContext . "\n\n---\n\nDocument to summarise:\n" . $text; @@ -1874,7 +1886,7 @@ PROMPT; } $corpusNote = $corpusUsed - ? 'Summary enriched with ' . count(array_filter(explode('=== ', $corpusContext))) . ' passage(s) from the Do Better Norge legal corpus.' + ? 'Summary enriched with ' . count(array_filter(explode('=== ', $corpusContext))) . ' passage(s) from the ' . dbnToolsProductName() . ' legal corpus.' : 'No corpus search performed; summarised from document text only.'; $trace = [ diff --git a/includes/bootstrap.php b/includes/bootstrap.php index f011b3e..35ffb8e 100644 --- a/includes/bootstrap.php +++ b/includes/bootstrap.php @@ -479,6 +479,39 @@ function dbnToolsDefaultPersonaSlug(): string return $v !== '' ? $v : 'family'; } +/** Product display name for tool-facing copy. Override via .env DBN_PRODUCT_NAME. */ +function dbnToolsProductName(): string +{ + $v = trim((string)(dbnToolsEnv('DBN_PRODUCT_NAME', 'Do Better Legal') ?? 'Do Better Legal')); + return $v !== '' ? $v : 'Do Better Legal'; +} + +/** + * Engine track for a persona slug: + * 'family' → family + child-welfare, served/verified by the fine-tuned Qwen. + * 'general' → all other Norwegian-law personas, served/verified by the interim engine. + */ +function dbnToolsPersonaTrack(?string $slug): string +{ + $slug = strtolower(trim((string)$slug)); + return in_array($slug, ['family', 'child-welfare'], true) ? 'family' : 'general'; +} + +/** + * Reviewer/verification model for a persona's track. + * Family track → fine-tuned Qwen (dbn-legal-agent-v3). + * General track → interim gpt-4o; swap to the 2nd fine-tune later via .env + * DBN_REVIEW_MODEL_GENERAL with no code change. + */ +function dbnToolsReviewerModel(?string $slug = null): string +{ + if (dbnToolsPersonaTrack($slug) === 'family') { + return trim((string)(dbnToolsEnv('DBN_REVIEW_MODEL_FAMILY', 'dbn-legal-agent-v3') ?? 'dbn-legal-agent-v3')) + ?: 'dbn-legal-agent-v3'; + } + return trim((string)(dbnToolsEnv('DBN_REVIEW_MODEL_GENERAL', 'gpt-4o') ?? 'gpt-4o')) ?: 'gpt-4o'; +} + /** * Resolve a DBN persona (a caveauAI chat profile for client 57) into a normalized * runtime bundle the tools can act on: @@ -544,7 +577,7 @@ function dbnToolsResolvePersona(int $clientId, ?string $slug = null): array dbnToolsAbort('No persona profile and the family-legal corpus package is not active.', 503, 'package_unavailable'); } if (!dbnToolsHasActiveSubscription($clientId, (int)$package['id'])) { - dbnToolsAbort('Do Better Norge does not have an active corpus subscription.', 503, 'subscription_missing'); + dbnToolsAbort(dbnToolsProductName() . ' does not have an active corpus subscription.', 503, 'subscription_missing'); } $resolved = [ 'slug' => 'family', @@ -938,7 +971,7 @@ function dbnToolsRequireClient(): array { $client = dbnToolsFetchClient(); if (!$client || empty($client['is_active'])) { - dbnToolsAbort('Do Better Norge client tenant is not active or was not found.', 503, 'client_unavailable'); + dbnToolsAbort(dbnToolsProductName() . ' client tenant is not active or was not found.', 503, 'client_unavailable'); } return $client; } @@ -1304,26 +1337,33 @@ function dbnToolsLiteLLMEmbedBatch(array $texts, string $model = 'nomic-embed-te // Strategy: ask ONE targeted question per document type, cap tokens at 350 to cut // off before the tool-planning loop kicks in, parse the answer for legal findings. -function dbnToolsRunLegalCheck(string $brief, string $docType, ?string $personaPrompt = null): array +function dbnToolsRunLegalCheck(string $brief, string $docType, ?string $personaPrompt = null, ?string $personaSlug = null): array { - $question = dbnToolsSelectCheckQuestion($docType, $brief); + $track = dbnToolsPersonaTrack($personaSlug); + $model = dbnToolsReviewerModel($personaSlug); + + $question = dbnToolsSelectCheckQuestion($docType, $brief, $track); if ($question === null) { return []; } $opts = [ - 'model' => 'dbn-legal-agent-v3', + 'model' => $model, 'temperature' => 0.1, 'max_tokens' => 350, 'timeout' => 45, // No 'json' key — plain narrative, no response_format flag ]; - // Base prompt from the resolved persona (default = Child-welfare/barnevern). + // Base prompt: resolved persona prompt wins; otherwise a track-appropriate default. $personaPrompt = is_string($personaPrompt) ? trim($personaPrompt) : ''; - $sysMsg = $personaPrompt !== '' - ? $personaPrompt - : 'Du er en ekspert på norsk barnevernsloven og EMD-praksis. Svar alltid på norsk med korrekt juridisk terminologi. Bruk terskler fra barnevernsloven 2021: § 4-25 krever «klar nødvendighet». Strand Lobben mot Norge (37283/13) setter krav om rehabiliteringsplan før adopsjon. Aldri oppfinn paragrafnumre, saksnumre eller dommernavn.'; + if ($personaPrompt !== '') { + $sysMsg = $personaPrompt; + } elseif ($track === 'family') { + $sysMsg = 'Du er en ekspert på norsk barnevernsloven og EMD-praksis. Svar alltid på norsk med korrekt juridisk terminologi. Bruk terskler fra barnevernsloven 2021: § 4-25 krever «klar nødvendighet». Strand Lobben mot Norge (37283/13) setter krav om rehabiliteringsplan før adopsjon. Aldri oppfinn paragrafnumre, saksnumre eller dommernavn.'; + } else { + $sysMsg = 'Du er en erfaren norsk jurist med bred kompetanse i norsk rett (forvaltningsrett, utlendingsrett, arbeidsrett, husleie- og forbrukerrett). Svar alltid på norsk med korrekt juridisk terminologi. Aldri oppfinn paragrafnumre, saksnumre, dommernavn eller kilder. Hvis du er usikker, si det tydelig.'; + } // Prepend a short snippet of the actual synthesis text so v3 answers in context, // not just as a general law quiz. Strip HTML tags and cap at 350 chars. @@ -1360,16 +1400,23 @@ function dbnToolsRunLegalCheck(string $brief, string $docType, ?string $personaP 'severity' => dbnToolsInferCheckSeverity($clean), 'legal_basis' => dbnToolsExtractCheckLegalBasis($clean), 'source_refs' => [], - 'what_to_check'=> 'Verifiser med norsk familieretsadvokat', - 'check_model' => 'dbn-legal-agent-v3', + 'what_to_check'=> $track === 'family' ? 'Verifiser med norsk familieretsadvokat' : 'Verifiser med norsk advokat', + 'check_model' => $model, ]]; } -function dbnToolsSelectCheckQuestion(string $docType, string $brief): ?string +function dbnToolsSelectCheckQuestion(string $docType, string $brief, string $track = 'family'): ?string { $t = mb_strtolower($docType); $b = mb_strtolower($brief); + // Track 2 (other Norwegian law): neutral verification question, always fires. + if ($track !== 'family') { + return 'Vurder teksten ovenfor opp mot gjeldende norsk rett: er de rettslige påstandene korrekte, ' + . 'er det vist til riktige lover og paragrafer, og mangler det viktige rettslige vilkår, frister ' + . 'eller prosessuelle krav som burde vært nevnt?'; + } + if (str_contains($t, 'akutt') || str_contains($t, 'emergency')) { return 'Hva er den korrekte rettslige terskelen for midlertidig plassering utenfor hjemmet ' . 'etter barnevernsloven § 4-25 (2021-loven)? Er det forskjell mellom § 4-6 (1992-loven) ' diff --git a/includes/i18n.php b/includes/i18n.php index aaf5ebc..ec02daa 100644 --- a/includes/i18n.php +++ b/includes/i18n.php @@ -470,11 +470,11 @@ function dbnToolsTranslations(): array 'doc_picker_modal_title' => 'Select from My Docs', // MCP setup page + tool detail pages - 'mcp_page_title' => 'MCP — Do Better Norge', - 'mcp_meta_desc' => 'Connect Claude, Cursor, and other AI tools to all 19 DBN legal preparation tools via MCP.', + 'mcp_page_title' => 'MCP — Do Better Legal', + 'mcp_meta_desc' => 'Connect Claude, Cursor, and other AI tools to all Do Better Legal Norwegian-law preparation tools via MCP.', 'mcp_hero_badge' => '✦ Plus & Pro', - 'mcp_hero_h1' => 'Use DBN tools from Claude, Cursor & Copilot', - 'mcp_hero_sub' => 'Connect any MCP client to all 19 Do Better Norge tools — transcription, legal analysis, timelines, redaction, and more.', + 'mcp_hero_h1' => 'Use Do Better Legal tools from Claude, Cursor & Copilot', + 'mcp_hero_sub' => 'Connect any MCP client to the full Do Better Legal toolset — transcription, legal analysis, timelines, redaction, and more.', 'mcp_token_section_title' => 'Your MCP token', 'mcp_gate_guest_p' => 'Sign in to create your personal MCP token. Available to Plus and Pro members.', 'mcp_gate_guest_btn' => 'Sign in', @@ -928,11 +928,11 @@ function dbnToolsTranslations(): array 'doc_picker_modal_title' => 'Velg fra Mine dokumenter', // MCP setup page + tool detail pages - 'mcp_page_title' => 'MCP — Do Better Norge', - 'mcp_meta_desc' => 'Koble Claude, Cursor og andre AI-verktøy til alle 19 DBN juridiske forberedelsesverktøy via MCP.', + 'mcp_page_title' => 'MCP — Do Better Legal', + 'mcp_meta_desc' => 'Koble Claude, Cursor og andre AI-verktøy til alle Do Better Legal-verktøy for norsk juridisk forberedelse via MCP.', 'mcp_hero_badge' => '✦ Plus & Pro', - 'mcp_hero_h1' => 'Bruk DBN-verktøy fra Claude, Cursor & Copilot', - 'mcp_hero_sub' => 'Koble enhver MCP-klient til alle 19 Do Better Norge-verktøy — transkripsjon, juridisk analyse, tidslinjer, redigering og mer.', + 'mcp_hero_h1' => 'Bruk Do Better Legal-verktøy fra Claude, Cursor & Copilot', + 'mcp_hero_sub' => 'Koble enhver MCP-klient til hele Do Better Legal-verktøysettet — transkripsjon, juridisk analyse, tidslinjer, redigering og mer.', 'mcp_token_section_title' => 'Din MCP-token', 'mcp_gate_guest_p' => 'Logg inn for å opprette din personlige MCP-token. Tilgjengelig for Plus- og Pro-medlemmer.', 'mcp_gate_guest_btn' => 'Logg inn', @@ -1386,11 +1386,11 @@ function dbnToolsTranslations(): array 'doc_picker_modal_title' => 'Вибрати з Моїх документів', // MCP setup page + tool detail pages - 'mcp_page_title' => 'MCP — Do Better Norge', - 'mcp_meta_desc' => 'Підключіть Claude, Cursor та інші інструменти ШІ до всіх 19 юридичних підготовчих інструментів DBN через MCP.', + 'mcp_page_title' => 'MCP — Do Better Legal', + 'mcp_meta_desc' => 'Підключіть Claude, Cursor та інші інструменти ШІ до всіх інструментів Do Better Legal для підготовки за нормами норвезького права через MCP.', 'mcp_hero_badge' => '✦ Плюс та Профі', - 'mcp_hero_h1' => 'Використовуйте інструменти DBN від Claude, Cursor та Copilot', - 'mcp_hero_sub' => 'Підключіть будь-якого клієнта MCP до всіх 19 інструментів Do Better Norge — транскрипція, юридичний аналіз, часові лінії, редагування та інше.', + 'mcp_hero_h1' => 'Використовуйте інструменти Do Better Legal від Claude, Cursor та Copilot', + 'mcp_hero_sub' => 'Підключіть будь-якого клієнта MCP до повного набору інструментів Do Better Legal — транскрипція, юридичний аналіз, часові лінії, редагування та інше.', 'mcp_token_section_title' => 'Ваш токен MCP', 'mcp_gate_guest_p' => 'Увійдіть, щоб створити свій особистий токен MCP. Доступно для учасників Плюс та Профі.', 'mcp_gate_guest_btn' => 'Увійти', @@ -1844,11 +1844,11 @@ function dbnToolsTranslations(): array 'doc_picker_modal_title' => 'Wybierz z Moich dokumentów', // MCP setup page + tool detail pages - 'mcp_page_title' => 'MCP — Do Better Norge', - 'mcp_meta_desc' => 'Połącz Claude, Cursor i inne narzędzia AI z wszystkimi 19 narzędziami przygotowania prawnego DBN za pośrednictwem MCP.', + 'mcp_page_title' => 'MCP — Do Better Legal', + 'mcp_meta_desc' => 'Połącz Claude, Cursor i inne narzędzia AI z wszystkimi narzędziami Do Better Legal do przygotowania w zakresie prawa norweskiego za pośrednictwem MCP.', 'mcp_hero_badge' => '✦ Plus & Pro', - 'mcp_hero_h1' => 'Użyj narzędzi DBN z Claude, Cursor i Copilot', - 'mcp_hero_sub' => 'Połącz dowolnego klienta MCP ze wszystkimi 19 narzędziami Do Better Norge — transkrypcja, analiza prawna, harmonogramy, redakcja i inne.', + 'mcp_hero_h1' => 'Użyj narzędzi Do Better Legal z Claude, Cursor i Copilot', + 'mcp_hero_sub' => 'Połącz dowolnego klienta MCP z pełnym zestawem narzędzi Do Better Legal — transkrypcja, analiza prawna, harmonogramy, redakcja i inne.', 'mcp_token_section_title' => 'Twój token MCP', 'mcp_gate_guest_p' => 'Zaloguj się, aby utworzyć swój osobisty token MCP. Dostępny dla członków Plus i Pro.', 'mcp_gate_guest_btn' => 'Zaloguj się', diff --git a/mcp.php b/mcp.php index 06b0115..d141dbf 100644 --- a/mcp.php +++ b/mcp.php @@ -411,7 +411,7 @@ export DBN_MCP_TOKEN=dbn_user_mcp_... { "type": "promptString", "id": "dbn-token", - "description": "Do Better Norge MCP token", + "description": "Do Better Legal MCP token", "password": true } ],