fix(settings): separate MCP connections from models (#522)

- Add a dedicated MCP connections destination to Settings navigation
- Keep ModelsPanel focused on model profiles and assignments
- Update documentation, changelog, and browser coverage for the new location
This commit is contained in:
Danila Poyarkov 2026-08-14 20:39:29 +03:00 committed by GitHub
parent 90f2498bcf
commit a29f609dd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 27 additions and 5 deletions

View file

@ -33,6 +33,10 @@
- Allow supported AI model profiles to set a provider-specific reasoning effort. (#454)
- Show unavailable or substituted document fonts with affected-layer selection and retry actions, and expose font fidelity through the Figma API and MCP tooling. (#503)
### Changed
- Move MCP connections into their own Settings destination instead of presenting them as part of model configuration.
### Performance
- Defer JSX generation and syntax highlighting until the Code panel is active, keeping large canvas selections responsive. (#500)

View file

@ -33,7 +33,7 @@ No backend, no subscription — your key talks directly to the provider. Browser
### External MCP connections
Desktop ACP agents can also use trusted remote [Model Context Protocol](https://modelcontextprotocol.io/) servers. In **Settings → AI & agents → MCP connections**, add a named Streamable HTTP endpoint, optionally save a bearer token, and enable the connection. OpenPencil stores the token in the configured credential backend rather than ordinary settings and resolves it only when starting the ACP session.
Desktop ACP agents can also use trusted remote [Model Context Protocol](https://modelcontextprotocol.io/) servers. In **Settings → MCP connections**, add a named Streamable HTTP endpoint, optionally save a bearer token, and enable the connection. OpenPencil stores the token in the configured credential backend rather than ordinary settings and resolves it only when starting the ACP session.
Remote servers must use HTTPS. Loopback HTTP endpoints are accepted for local development. Review and trust a server before enabling it: its tools may read external data or perform actions with the credentials you provide. OpenPencil's built-in design MCP server remains attached automatically and does not need to be added here.

View file

@ -1,6 +1,6 @@
import { ref } from 'vue'
export type SettingsSection = 'ai' | 'media' | 'storage'
export type SettingsSection = 'ai' | 'mcp' | 'media' | 'storage'
export const settingsDialogOpen = ref(false)
export const settingsDialogSection = ref<SettingsSection>('ai')

View file

@ -7,6 +7,7 @@ import { IS_TAURI } from '@open-pencil/core/constants'
import { useAIChat } from '@/app/ai/chat/use'
import { appCredentialServices } from '@/app/settings/credentials/app'
import { settingsDialogOpen, settingsDialogSection } from '@/app/settings/dialog'
import MCPConnectionsSection from '@/components/settings/mcp/MCPConnectionsSection.vue'
import ModelsPanel from '@/components/settings/models/ModelsPanel.vue'
import StockPhotoKeysSection from '@/components/settings/provider/StockPhotoKeysSection.vue'
import StorageSettingsPanel from '@/components/settings/storage/StorageSettingsPanel.vue'
@ -67,6 +68,16 @@ const navigationClass =
<icon-lucide-sparkles class="size-3.5" />
{{ dialogs.settingsAIAndAgents }}
</button>
<button
type="button"
:class="navigationClass"
:data-state="settingsDialogSection === 'mcp' ? 'active' : 'inactive'"
data-test-id="settings-section-mcp"
@click="settingsDialogSection = 'mcp'"
>
<icon-lucide-plug class="size-3.5" />
{{ dialogs.mcpConnections }}
</button>
<button
type="button"
:class="navigationClass"
@ -98,6 +109,14 @@ const navigationClass =
<ModelsPanel />
</section>
<section
v-else-if="settingsDialogSection === 'mcp'"
class="flex flex-col"
data-test-id="settings-mcp-panel"
>
<MCPConnectionsSection />
</section>
<section
v-else-if="settingsDialogSection === 'media'"
class="flex flex-col gap-2.5"

View file

@ -6,7 +6,6 @@ import { ACP_AGENTS, AI_PROVIDERS } from '@open-pencil/core/constants'
import { aiModelSettings, modelConnection, modelConnectionCredentialStatus } from '@/app/ai/models'
import type { CredentialStatus } from '@/app/settings/credentials/types'
import MCPConnectionsSection from '@/components/settings/mcp/MCPConnectionsSection.vue'
import ProfileEditor from '@/components/settings/models/ProfileEditor.vue'
import RoleAssignments from '@/components/settings/models/RoleAssignments.vue'
@ -158,8 +157,6 @@ watch(
</div>
</section>
<MCPConnectionsSection />
<section class="mt-5 border-t border-border pt-4">
<div class="mb-3">
<h3 class="text-xs font-semibold text-surface">{{ dialogs.modelAssignments }}</h3>

View file

@ -40,6 +40,7 @@ test('MCP connections keep bearer tokens out of ordinary settings', async ({ pag
await canvas.waitForInit()
await page.getByTestId('app-settings-trigger').click()
await page.getByTestId('settings-section-mcp').click()
const section = page.locator('[data-mcp-connections]')
await section.getByRole('button', { name: 'Add connection' }).click()
await section.getByLabel('Connection name').fill('GitHub')
@ -61,6 +62,7 @@ test('MCP connections keep bearer tokens out of ordinary settings', async ({ pag
await page.reload()
await canvas.waitForInit()
await page.getByTestId('app-settings-trigger').click()
await page.getByTestId('settings-section-mcp').click()
await expect(section).toContainText('https://example.com/mcp')
await expect(section).toContainText('Enabled')
await section.getByRole('button', { name: /GitHub/ }).click()