feat(ui): declutter dashboard done-recently + MCP-access, add per-project stats
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 31s
CI & Build / Python tests (push) Successful in 49s
CI & Build / Build & push image (push) Successful in 58s

Dashboard:
- 'Done recently' chip-cloud -> compact uniform list (Active-now row style),
  showing 5 with inline expand to the rest (backend already returns up to 8).
- New 'Projects' rail card: each active project with 'N open · M done'.
  Backend already computed done_count (dashboard.py) — now surfaced in the
  /api/dashboard payload per active project.

MCP Access (Connect Claude / Claude Code):
- Progressive disclosure: lead with the pre-filled plugin-install snippet;
  fold server name, scope, marketplace URL, and the MCP-only path into a
  single 'Customize' expander. Desktop tab keeps its own server-name field.
- Marketplace URL now defaults to this instance's own repo via
  config.PLUGIN_MARKETPLACE_URL (env-overridable); /api/plugin/marketplace-url
  falls back to it, so the field + install snippet are pre-filled out of the
  box instead of showing a generic placeholder.

Refs #761

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 11:04:23 -04:00
parent 79aec4f9c1
commit da511fcc9f
5 changed files with 134 additions and 87 deletions
+71 -74
View File
@@ -1550,35 +1550,6 @@ function formatUserDate(iso: string): string {
token value, or copy the snippet now and paste your own where it says <code>&lt;your-token&gt;</code>.
</p>
<!-- Per-client config: server name + scope (persisted to localStorage) -->
<div class="mcp-client-config">
<label class="mcp-config-field">
<span class="mcp-config-label">Server name</span>
<input
v-model="mcpServerName"
type="text"
placeholder="scribe"
class="settings-input"
spellcheck="false"
/>
<span class="mcp-hint">
Local label Claude uses for this server. Examples: <code>scribe</code>, <code>scribe-dev</code>.
</span>
</label>
<label class="mcp-config-field">
<span class="mcp-config-label">Scope</span>
<select v-model="mcpScope" class="settings-input">
<option value="user">user available across all projects</option>
<option value="project">project write to current repo's .mcp.json</option>
<option value="local">local — this machine + repo only</option>
</select>
<span class="mcp-hint">
Where Claude Code stores the server registration. Pick <code>project</code> to commit it
to a specific repo's <code>.mcp.json</code>.
</span>
</label>
</div>
<div class="mcp-client-tabs" role="tablist">
<button
type="button"
@@ -1602,19 +1573,6 @@ function formatUserDate(iso: string): string {
<strong>Recommended install the Scribe plugin.</strong> One install wires up the MCP
connection, a session-start hook that surfaces your rules, and the Scribe process-skills.
</p>
<label class="mcp-config-field">
<span class="mcp-config-label">Scribe plugin marketplace (git URL)</span>
<input
v-model="pluginMarketplaceUrl"
type="text"
placeholder="https://git.example.com/you/Scribe.git"
class="settings-input"
spellcheck="false"
/>
<span class="mcp-hint">
The Scribe app's own git repo — it ships the plugin in lockstep with this instance.
</span>
</label>
<ol>
<li>
Add the marketplace and install the plugin:
@@ -1637,42 +1595,81 @@ function formatUserDate(iso: string): string {
</ol>
<details class="mcp-advanced">
<summary>Advanced: connect the MCP only (no plugin)</summary>
<ol>
<li>
Register just the MCP server:
<div class="mcp-code-row">
<pre class="mcp-code">{{ claudeCodeCommand }}</pre>
<button class="btn btn-secondary btn-sm" @click="copySnippet(claudeCodeCommand, 'cc-add')">
{{ copiedSnippetKey === 'cc-add' ? 'Copied' : 'Copy' }}
</button>
</div>
</li>
<li>
Verify with <code>/mcp</code> — <code>{{ effectiveMcpName }}</code> should appear as connected.
You won't get the session-start rule push or the Scribe skills this way.
</li>
</ol>
<summary>Customize</summary>
<label class="mcp-config-field">
<span class="mcp-config-label">Plugin marketplace (git URL)</span>
<input
v-model="pluginMarketplaceUrl"
type="text"
:placeholder="serverMarketplaceUrl || 'https://git.example.com/you/Scribe.git'"
class="settings-input"
spellcheck="false"
/>
<span class="mcp-hint">
Pre-filled with this instance's repo. Override only if you host the plugin elsewhere.
</span>
</label>
<div class="mcp-client-config">
<label class="mcp-config-field">
<span class="mcp-config-label">Server name</span>
<input v-model="mcpServerName" type="text" placeholder="scribe" class="settings-input" spellcheck="false" />
<span class="mcp-hint">
Local label for the MCP-only path below. Examples: <code>scribe</code>, <code>scribe-dev</code>.
</span>
</label>
<label class="mcp-config-field">
<span class="mcp-config-label">Scope</span>
<select v-model="mcpScope" class="settings-input">
<option value="user">user — available across all projects</option>
<option value="project">project — write to current repo's .mcp.json</option>
<option value="local">local this machine + repo only</option>
</select>
<span class="mcp-hint">Where Claude Code stores the MCP-only registration.</span>
</label>
</div>
<p class="mcp-hint" style="margin-top: 0.75rem;">
<strong>Connect the MCP only (no plugin).</strong> You won't get the session-start rule
push or the Scribe skills this way.
</p>
<div class="mcp-code-row">
<pre class="mcp-code">{{ claudeCodeCommand }}</pre>
<button class="btn btn-secondary btn-sm" @click="copySnippet(claudeCodeCommand, 'cc-add')">
{{ copiedSnippetKey === 'cc-add' ? 'Copied' : 'Copy' }}
</button>
</div>
<p class="mcp-hint">
Verify with <code>/mcp</code> — <code>{{ effectiveMcpName }}</code> should appear as connected.
</p>
</details>
</div>
<!-- Claude Desktop tab -->
<ol v-else-if="mcpClientTab === 'claude-desktop'">
<li>
Add this block to your Claude Desktop MCP config file
(<code>~/Library/Application Support/Claude/claude_desktop_config.json</code> on macOS,
<code>%APPDATA%\Claude\claude_desktop_config.json</code> on Windows):
<div class="mcp-code-row">
<pre class="mcp-code">{{ mcpConfigSnippet }}</pre>
<button class="btn btn-secondary btn-sm" @click="copySnippet(mcpConfigSnippet, 'cd-config')">
{{ copiedSnippetKey === 'cd-config' ? 'Copied' : 'Copy' }}
</button>
</div>
</li>
<li>
Restart Claude Desktop. The Scribe tools should appear in the available tools list.
</li>
</ol>
<div v-else-if="mcpClientTab === 'claude-desktop'">
<label class="mcp-config-field">
<span class="mcp-config-label">Server name</span>
<input v-model="mcpServerName" type="text" placeholder="scribe" class="settings-input" spellcheck="false" />
<span class="mcp-hint">The key used for this server in the config JSON below.</span>
</label>
<ol>
<li>
Add this block to your Claude Desktop MCP config file
(<code>~/Library/Application Support/Claude/claude_desktop_config.json</code> on macOS,
<code>%APPDATA%\Claude\claude_desktop_config.json</code> on Windows):
<div class="mcp-code-row">
<pre class="mcp-code">{{ mcpConfigSnippet }}</pre>
<button class="btn btn-secondary btn-sm" @click="copySnippet(mcpConfigSnippet, 'cd-config')">
{{ copiedSnippetKey === 'cd-config' ? 'Copied' : 'Copy' }}
</button>
</div>
</li>
<li>
Restart Claude Desktop. The Scribe tools should appear in the available tools list.
</li>
</ol>
</div>
</section>
</div>