Files
nocodb/packages/nc-gui/components/dashboard/settings/base/MCP/Modal.vue
mertmit ccbd648e4a fix: base issues
Signed-off-by: mertmit <mertmit99@gmail.com>
2026-01-10 00:21:03 +03:00

325 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
interface Props {
value: boolean
token: MCPTokenExtendedType
showRegenerateButton?: boolean
showWorkspaceBaseInfo?: boolean
isAccountLevel?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showRegenerateButton: true,
showWorkspaceBaseInfo: false,
isAccountLevel: false,
})
const emits = defineEmits(['close', 'update:value', 'update:token'])
const modalVisible = useVModel(props, 'value')
const { appInfo } = useGlobal()
const { openedProject } = storeToRefs(useBases())
const token = useVModel(props, 'token')
const supportedDocs: SupportedDocsType[] = [
{
title: 'Getting Started with MCP Server',
href: 'https://nocodb.com/docs/product-docs/mcp',
},
{
title: 'Claude Setup',
href: 'https://nocodb.com/docs/product-docs/mcp#claude',
},
{
title: 'Cursor Setup',
href: 'https://nocodb.com/docs/product-docs/mcp#cursor',
},
{
title: 'Windsurf Setup',
href: 'https://nocodb.com/docs/product-docs/mcp#windsurf',
},
]
const { updateMcpToken } = useMcpSettings()
const regenerateToken = async () => {
const newToken = await updateMcpToken(token.value, props.isAccountLevel)
if (newToken) {
token.value = newToken
}
}
const closeModal = () => {
emits('close')
modalVisible.value = false
}
const activeTab = ref<'claude' | 'cursor' | 'windsurf' | 'antigravity'>('claude')
const serverName = computed(() => {
let title = ''
if (props.showWorkspaceBaseInfo) {
title = isEeUI
? `NocoDB ${token.value.workspace?.title || 'Workspace'} - ${token.value.base?.title || 'Base'}`
: `NocoDB - ${token.value.base?.title || 'Base'}`
} else {
title = `NocoDB Base - ${openedProject.value?.title}`
}
if (activeTab.value === 'antigravity') {
title = title.replaceAll(' ', '_').replaceAll('-', '')
}
return title
})
const code = computed(
() => `
{
"mcpServers": {
"${serverName.value}": {
"command": "npx",
"args": [
"mcp-remote",
"${appInfo.value.ncSiteUrl}/mcp/${token.value.id}",
"--header",
"xc-mcp-token: ${token.value?.token ?? 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'}"
]
}
}
}
`,
)
</script>
<template>
<NcModal v-model:visible="modalVisible" :show-separator="true" size="large" wrap-class-name="nc-modal-mcp-token-create-edit">
<template #header>
<div class="flex w-full items-center p-2 justify-between">
<div class="flex items-center gap-3 pl-1 flex-1">
<GeneralIcon class="text-nc-content-gray-emphasis h-5 w-5" icon="mcp" />
<span class="text-nc-content-gray-emphasis truncate font-semibold text-xl">
{{ token.title }}
</span>
</div>
<div class="flex justify-end items-center gap-3 pr-0.5 flex-1">
<NcButton type="text" size="small" data-testid="nc-close-webhook-modal" @click.stop="closeModal">
<GeneralIcon icon="close" />
</NcButton>
</div>
</div>
</template>
<div class="flex bg-nc-bg-default rounded-b-2xl h-[calc(100%_-_66px)]">
<div
ref="containerElem"
class="h-full flex-1 flex flex-col overflow-y-auto scroll-smooth nc-scrollbar-thin px-24 py-6 mx-auto"
>
<div class="flex flex-col max-w-[640px] w-full mx-auto gap-3">
<div class="text-nc-content-gray font-bold leading-6">
{{ $t('labels.mcpSetup') }}
</div>
<!-- Workspace/Base Info (for account-level view) -->
<div v-if="showWorkspaceBaseInfo" class="flex flex-col gap-2 p-4 bg-nc-bg-gray-extralight rounded-lg">
<div v-if="isEeUI" class="flex items-center gap-2">
<span class="text-sm font-semibold text-nc-content-gray-subtle">{{ $t('objects.workspace') }}:</span>
<span class="text-sm text-nc-content-gray-subtle2">{{ token.workspace?.title || '-' }}</span>
</div>
<div class="flex items-center gap-2">
<span class="text-sm font-semibold text-nc-content-gray-subtle">{{ $t('objects.project') }}:</span>
<span class="text-sm text-nc-content-gray-subtle2">{{ token.base?.title || '-' }}</span>
</div>
</div>
<NcAlert type="info" class="mt-3 max-w-[640px] w-full mx-auto">
<template #message>
{{ $t('labels.mcpTokenVisibilityInfo') }}
</template>
<template #description>
{{ $t('labels.mcpTokenVisibilityInfoDescription') }} <br />
{{ $t('labels.mcpTokenVisibilityInfoDescription2') }}
</template>
</NcAlert>
<NcTabs v-model:active-key="activeTab">
<a-tab-pane key="claude" class="!h-full">
<template #tab>
<span
:class="{
'text-nc-content-brand font-medium': activeTab === 'claude',
'text-nc-content-gray-subtle': activeTab !== 'claude',
}"
class="text-sm"
>
Claude
</span>
</template>
<div class="relative flex flex-col leading-6 text-nc-content-gray-subtle2 gap-3 my-3">
Get started with the NocoDB MCP with Claude Desktop in 3 simple steps
<ol class="list-decimal pl-5">
<li>Navigate to Claude Desktop settings from the navigation bar.</li>
<li>Go to the Develop Tab, and click on Edit Config.</li>
<li>Add the JSON configuration thats provided after creating a token in claude_desktop_config.json</li>
</ol>
<NcButton
v-if="showRegenerateButton"
type="secondary"
class="w-39"
size="small"
:loading="token.loading"
@click="regenerateToken(token)"
>
{{ $t('labels.regenerateToken') }}
</NcButton>
<DashboardSettingsBaseMCPCode :key="code" :code="code" />
</div>
</a-tab-pane>
<a-tab-pane key="cursor" class="!h-full">
<template #tab>
<span
:class="{
'text-nc-content-brand font-medium': activeTab === 'cursor',
'text-nc-content-gray-subtle': activeTab !== 'cursor',
}"
class="text-sm"
>
Cursor
</span>
</template>
<div class="relative flex flex-col leading-6 text-nc-content-gray-subtle2 gap-3 my-3">
Get started with the NocoDB MCP with Cursor in 3 simple steps
<ol class="list-decimal pl-5">
<li>Open Cursor Settings (press Shift+Cmd+J)</li>
<li>Select the "MCP" tab and click "Add Custom MCP" .</li>
<li>Add the JSON configuration thats provided after creating a token.</li>
</ol>
<NcButton
v-if="showRegenerateButton"
type="secondary"
class="w-44"
size="small"
:loading="token.loading"
@click="regenerateToken(token)"
>
{{ $t('labels.regenerateToken') }}
</NcButton>
<DashboardSettingsBaseMCPCode :key="code" :code="code" />
</div>
</a-tab-pane>
<a-tab-pane key="windsurf" class="!h-full">
<template #tab>
<span
:class="{
'text-nc-content-brand font-medium': activeTab === 'windsurf',
'text-nc-content-gray-subtle': activeTab !== 'windsurf',
}"
class="text-sm"
>
Windsurf
</span>
</template>
<div class="relative flex flex-col leading-6 text-nc-content-gray-subtle2 gap-3 my-3">
Get started with the NocoDB MCP with Windsurf in 4 simple steps
<ol class="list-decimal pl-5">
<li>Access Windsurf settings and Select Cascade Tab in the left sidebar</li>
<li>Click on Manage MCP.</li>
<li>Now click on View raw config.</li>
<li>Paste the JSON configuration thats provided after creating a token in the opened file</li>
</ol>
<NcButton
v-if="showRegenerateButton"
type="secondary"
class="w-44"
size="small"
:loading="token.loading"
@click="regenerateToken(token)"
>
{{ $t('labels.regenerateToken') }}
</NcButton>
<DashboardSettingsBaseMCPCode :code="code" />
</div>
</a-tab-pane>
<a-tab-pane key="antigravity" class="!h-full">
<template #tab>
<span
:class="{
'text-nc-content-brand font-medium': activeTab === 'antigravity',
'text-nc-content-gray-subtle': activeTab !== 'antigravity',
}"
class="text-sm"
>
AntiGravity
</span>
</template>
<div class="relative flex flex-col leading-6 text-nc-content-gray-subtle2 gap-3 my-3">
Get started with the NocoDB MCP with AntiGravity in 4 simple steps
<ol class="list-decimal pl-5">
<li>Click on the three dots in the top right of the agent window, and click on "MCP Servers"</li>
<li>Click on Manage MCP Servers.</li>
<li>Now click on View raw config.</li>
<li>Paste the JSON configuration thats provided after creating a token in the opened file</li>
</ol>
<NcButton
v-if="showRegenerateButton"
type="secondary"
class="w-44"
size="small"
:loading="token.loading"
@click="regenerateToken(token)"
>
{{ $t('labels.regenerateToken') }}
</NcButton>
<DashboardSettingsBaseMCPCode :code="code" />
</div>
</a-tab-pane>
</NcTabs>
</div>
</div>
<NcModalSupportedDocsSidebar>
<NcModalSupportedDocs :docs="supportedDocs"> </NcModalSupportedDocs>
</NcModalSupportedDocsSidebar>
</div>
</NcModal>
</template>
<style lang="scss">
.nc-modal-mcp-token-create-edit {
z-index: 1050;
a {
@apply !no-underline !text-nc-content-gray-subtle !hover:text-primary;
}
.nc-modal {
@apply !p-0;
height: min(calc(100vh - 100px), 1024px);
max-height: min(calc(100vh - 100px), 1024px) !important;
}
.nc-modal-header {
@apply !mb-0 !pb-0;
}
.ant-tabs-nav {
@apply !pl-0;
}
.ant-tabs-tab {
@apply pt-1 pb-1.5;
}
}
</style>